How do you assign processor pins to board functions?

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm working on the board design of a shield for an Arduino Zero. It needs all 23 processor pins which are connected to the shield. After a lot of laborious attempts it was possible to assign the processor pins to chip pins on the shield.

This was done on paper using the section "I/O Multiplexing and Considerations" in the SAMD21 datasheet and the project spec.

Are there any ways to automate or simplify the procedure? It would be a nice recursive search to match the I/O multiplexing configuration with the pin requirements

Best wishes, Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I will tend to create spreadsheets like https://docs.google.com/spreadsheets/d/1OucZjXE_gFDut9k4IkOgwdQ4IuXx76SgJJhuwig68Y0/edit?usp=sharing

This is essentially a transcription of the "IO Multiplexing" section from the datasheet, with the Arduino "variant.cpp" mapping added, but:

  1. You can re-sort the spreadsheet on a particular column.  Want to see all the pins on an Arduino shield - sort by the appropriate Arduino board pin number.  Want to see which ports have 8 consecutive bits brought out - sort by IOPin.  Want to see where all your SERCOMs go - sort by that column.
  2. You can add additional columns (like UART and I2C) to identify the realities of pad selection (i2C needs these particular 2 pins of the Sercom...)
  3. Typing it all in is a bit helpful in terms of figuring out what is actually present...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the spreadsheet, very useful in that you list the pinouts for various boards

I made a Word document derived from the "I/O multiplexing" table and the requirements, then juggled the pins until they fulfilled the requirements. It's good that one use the MISO SPI pin freely for other purposes. The shield implements a HUB75 LED matrix driver, GPS receiver, Bluetooth/USART converter and BLDC motor controller

Best wishes, Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So I have found that Arduino drivers are really bad as well as the ASF ones, too many while() loops with no time out or error reporting.  Thus I have resorted to bare metal programming and create d my own framework. 

 

I have create a pin structure:

 

typedef struct {
    uint32_t pinNum;
    void *ptrPeriheral;
    pinMuxType_t type;
    uint32_t param; //pad pin waveform
    pinMuxType_t sleepType;
}pin_t;
 

 

Where I define each pin like:

#define PIN_LED_RED            ((const pin_t){PIN_PB06, NULL, PERPIHERAL_GPIO_OUTPUT_HIGH, 0, PERPIHERAL_GPIO_OUTPUT_HIGH})

#define PIN_UART_TX            ((const pin_t){PIN_PA24, SERCOM5, PERPIHERAL_SERCOM_ALT_OUTPUT, PAD_2, PERPIHERAL_GPIO_INPUT_PULLED_LOW})
#define PIN_UART_RX            ((const pin_t){PIN_PB31, SERCOM5, PERPIHERAL_SERCOM_ALT_INPUT, PAD_1, PERPIHERAL_GPIO_INPUT_PULLED_LOW})

 

Then I have functions like:

static inline bool PinRead (const pin_t pin) __attribute__((always_inline));
static inline bool PinRead(const pin_t pin)
{
    if (pin.pinNum == (uint32_t)-1 )
    {
        return 0;
    }
    return (PORT->Group[PIN_GET_PORT(pin.pinNum)].IN.reg & (1<<PIN_GET_PIN(pin.pinNum))) != 0;
}
 

tatic inline void PinHigh (const pin_t pin) __attribute__((always_inline));
static inline void PinHigh (const pin_t pin)
{
    if (pin.pinNum == (uint32_t)-1 )
    {
        return;
    }
    PORT->Group[PIN_GET_PORT(pin.pinNum)].OUTSET.reg=(1<<PIN_GET_PIN(pin.pinNum));
}

static inline void PinLow (const pin_t pin) __attribute__((always_inline));
static inline void PinLow (const pin_t pin)
{
    if (pin.pinNum == (uint32_t)-1 )
    {
        return;
    }
    PORT->Group[PIN_GET_PORT(pin.pinNum)].OUTCLR.reg=(1<<PIN_GET_PIN(pin.pinNum));
}

 

These functions and the const definition of the pins allows the compiler to optimize the GPIO functions of the pins. 

 

Additionally for drivers I can now pass in the pin, like the UART driver I pass in the TX and RX pin and then based on that I configure the correct SERCOM, pin mux and pads for the pins.   I find this much better than Arduino's table mess, as I can change my #define as I change board layouts without changing the underlying code.   Also when I sleep the peripheral I can set the pin to GPIO with the correct pullup/down for the lowest power consumption. 

 

I will be publishing more details and example code in a few weeks. 

 

Trampas

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear Trampas,

   Your method for setting up the pins is very useful, but this is done after you've assigned a function to each pin - which was the original problem

Jerry