How does SAMD work? (GPIO Multiplexing?)

So I’m looking at developing on the SAMD21 and then maybe the 51 after that but I’ve discovered that all the GPIO pins can be multiplexed and change the pinouts.

It seems some pins can only have certain functions, like there are 4 sets of pins that are i2c capable…

But how do you configure all this?

I’m looking at this documentation to using the adafruit u2 bootloader:

But I don’t know how to reconfigure the pins? If anyone has any good links to guides for this would be much appreciated!

See section 7.1 of the datasheet.

Each pin can be assigned to one of up to eight special peripheral functions, labelled A to H, as given in table 7-1.

First you have to specify that the pin is to be used for a special function, by setting the PMUXEN bit in the PINCFGn register corresponding to the pin. Then you have to select which function, A to H, you want that pin to perform by setting the PMUXE/O bits in the PMUXn register corresponding to the pin.

1 Like

Oh hah, found the adafruit guide for it too:

I already read the data sheet, I’m more looking for “how to actually do it” not the theory behind it.

Looks like it’s actually defined at compile time by your tool chain? It looks like these configurations are made either within the board package or you can actually define it at the top of your sketch?

The default ones that Arduino is using are on the inside of the BGA package, so for convenience sake I’d like to use GPIO that are on the outer edge of the BGA package so hopefully I can avoid using vias to make the fanout.

You can do it, and redo it, any time you like. These registers are set through software, not by fuses or compile options.


For example, how would I define these pins, PB22 and PB23 for use in arduino as some digital input pins?

The pins I want are in green. The red box shows the pins I don’t want to use. The red circles are currently defined for the arduino zero, so I’d want to know how to change those to pads on the outside too.

Also if anyone is interested in developing games for 64x32 display on this chip that would also be super helpful and cool and I’d be able to reward for your time!

The variant.cpp file for the Arduino Zero defines PB22 (pad A8) as Arduino pin 30 and PB23 (pad A7) as Arduino pin 31. So, for digital control of these pins you could use, for example:

pinMode(30, INPUT);
pinMode(31, OUTPUT);

uint8_t input = digitalRead(30);
digitalWrite(31, HIGH);

Oh ok! That makes things easy. I guess I’ll have to dig through the variant and check all the pins I need are there.


I guess also related, has anyone ever made a board with 3mil traces before?

Nope, back to being confused. I look at the variant.cpp but where is it actually defining the pin numbers?

I see this:

  // 30/31 - EDBG/UART

I see it getting initialized but I don’t see it defined. Excuse me if I’m wrong but when you look at PA14 which would be “zero pin 2” is defined like this:


So it looks like you’d really want the third and fourth variables to be “PIO_DIGITAL, (PIN_ATTR_DIGITAL)” respectively?

And still confused on how we still get to “arduino pin 2” from that.


I guess the pin numbers are derived from the order they are in that array.

And to get the analog pin names it’s coming from variant.h

 * Analog pins
#define PIN_A0               (14ul)
#define PIN_A1               (15ul)
#define PIN_A2               (16ul)
#define PIN_A3               (17ul)
#define PIN_A4               (18ul)
#define PIN_A5               (19ul)
#define PIN_DAC0             (14ul)

static const uint8_t A0  = PIN_A0;
static const uint8_t A1  = PIN_A1;
static const uint8_t A2  = PIN_A2;
static const uint8_t A3  = PIN_A3;
static const uint8_t A4  = PIN_A4;
static const uint8_t A5  = PIN_A5;

Now I need to figure out where “14ul” is defined???


I have just discovered (14ul) is a compiler macro for unsigned long 14… right?

They didn’t make it as obvious as they could have done but the comments actually hint at that fact.

E.g. if you look at the top:

The 0..13 is supposed to mean that pins 0 to 13 (inclusive) are the digital pins, 0/1 means that the following two entries are the first two pin definitions.

Following that logic the PinDescriptions you quoted are for pins 30, 31 and 2 in that order.

14ul is an integer constant.
The ul suffix just means it has a type of unsigned long.

It’s not a macro, it’s actually part of the language’s syntax.

1 Like

Yeah I see the way they comment it, but it’s not explicit that the pin numbers are generated from the array order, I found the answer here:

Halfway down the page:

“Note that the Arduino pin numbers are the pin order in the PinDescription array in variant.cpp.”

Learn something every day!

Why so low res?

To confuse you, clearly.

Some games like Pong, for example could be very quick to adapt to any resolutions.

I’m betting it’s going to be a CHIP-8 machine.

Original CHIP-8 Display resolution is 64×32 pixels, and color is monochrome.

(Note to self: yell at the Wikipedia people for not using proper sentences.)

1 Like

If not, you could create your own board package with a variant file with your desired mappings.

Or as a possible alternative:

Do you want whatever you’re developing to appear to have a regular Arduino type interface, where sketch developers will use Arduino functions like pinMode(), digitalRead(), digitalWrite()?

Or, do you plan to provide a library that is specifically targeted towards your product and makes things higher level and more abstract, like the Arduboy and Arduboy2 libraries do, with functions like pressed() and digitalWriteRGB()?

If it’s the latter, then you may wish to bypass the Arduino functions that use the g_APinDescription[] array in variant.cpp, and other related arrays, to control the pins.

Instead, in your library you could initialise and control the pins by directly manipulating the required hardware registers using pre-defined constant values. This is how the Arudoby2 library does things now. (Previously, Arduboy2 did use pinMode(), digitalRead(), etc.)

For instance, to test if pin PB22 is high (assuming it has previously been set as a digital input), you could do:

if (PORT->Group[PORTB].IN.reg & bit(22)) {
  // do something

You could also include the equivalent of the g_APinDescription[] array within your library itself, to provide an equivalent layer of abstraction without needing to create a board package.


You don’t need an SAMD21 or 51 to run CHIP8 lol. I almost wrote one for the Arduboy and I would have had room for quite a library of small CHIP8 games as well. Are the SAMD* chips like the same cost to acquire as the Amtel ones? You could certainly fit a larger library of games on a SAMD chip… but you don’t need all that processor power for CHIP8. :slight_smile:

I found them to be cheaper.

I was looking at the SAMD21 because it included a RTC module, and I found a package that was only 50 cents so I was like, wheeee! But then ran into two problems:

1: The BGA package precludes using PCB features that would almost certainly make up for the cheaper part, needing either 3mil traces or via-in-pad with 5 mil traces.

2: The cheap part seems to actually just be digikey liquidating a specific sku, it seems like it’s closer to $1.50

But I’ve been pointed in the direction of STM8 which is kind of my new target, but it lacks an RTC so, that would be worth considering.

Trying to find the cheapest microcontroller that can support i2c 64x32 pixel display, 6 buttons, speaker and be able to play retro games.

If you are interested in developing for a minimal system then let me know, but it would be a closed-source project so I know that means a number of you wouldn’t be interested.