Contents[Hide]

Just for nerds

This article is a comprehensive description of Arduino SAMD21 installation packages. Note that for the use of the SAM 15x15 board, you don't have to read this. Just read the quick start guide.

Pinout

SAMD21G development board 15x15mm (Arduino compatible)
SAMD21G development board 15x15mm (Arduino compatible)

Package installation

To use non standard Arduino boards, such as the Arduino Zero, we have to install an appropriate package, which describes the processor and pins. 

Arduino Zero package deficiency

The Arduino Zero board is pin-compatible with older boards, such as the Arduino Uno. The drawback of this compatibility is that just a part of the SAMD21 pins is connected to the three pin headers; the rest of the pins is not used. Not all pin functions are declared in the Arduino Zero variant.cpp file. For instance, besides A0...A5, pin 3 has an analog input too, but it can't be used.

SAM 15x15 package

In order to make all SAMD21G pins available, install the SAM 15x15 package. This package is derived from the Arduino Zero (package: Arduino SAMD Boards (32-bit ARM Cortex-M0+) where these 6 files are modified:

  1. variant.cpp
  2. variant.h
  3. WVariant.h
  4. wiring_analog.c
  5. samd21_host.c
  6. boards.txt

In contrast to the Arduino Zero, all functions of a pin, such as INT, ADC and PWM are declared also and can be used. 

1 variant.cpp

This files describe the pin functions and is located here:
C:\Users\your-name\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\variants\arduino_zero\variant.cpp

// 29-8-2015 15x15 van Dalen, added extra pins D25..D33, not Arduino compatible
// 29-8-2015 15x15 van Dalen, added INT, ADC, PWM and timer where possible
#include "variant.h"
const PinDescription g_APinDescription[]= 
{ // ----------------------------------- Arduino compatible pins -----------------------------------
  // Digital low D0..D7
  { PORTA, 11, PIO_SERCOM, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel19, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_11 }, // p16 Serial1 RX 
  { PORTA, 10, PIO_SERCOM, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel18, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_10 }, // p15 Serial1 TX
  { PORTA, 14, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_14 }, // p13
  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // p14
  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI }, // p23
  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 }, // p14
  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, // p29
  { PORTA, 21, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH7, TCC0_CH7, EXTERNAL_INT_5 }, // p30
  
  // Digital high D8..D13
  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // p11
  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // p12
  { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // p27
  { PORTA, 16, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // p25 MOSI
  { PORTA, 19, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_3 }, // p28 MISO
  { PORTA, 17, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH1, TCC2_CH1, EXTERNAL_INT_1 }, // p26 SCK
  
  // D14..D19, analog A0..A5 
  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // p3 10bit DAC
  { PORTB,  8, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel2, PWM4_CH0, TC4_CH0, EXTERNAL_INT_8 }, // p7
  { PORTB,  9, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel3, PWM4_CH1, TC4_CH1, EXTERNAL_INT_9 }, // p8
  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel4, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 }, // p9
  { PORTA,  5, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel5, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 }, // p10
  { PORTB,  2, PIO_ANALOG, 0, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // p47
  
  // SDA/SCL, I2C D20..D21
  { PORTA, 22, PIO_SERCOM, (PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM4_CH0, TC4_CH0, EXTERNAL_INT_6 }, // p31 SDA
  { PORTA, 23, PIO_SERCOM, (PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM4_CH1, TC4_CH1, EXTERNAL_INT_7 }, // p32 SCL
  // SPI D22..D24
  { PORTA, 12, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_12 }, // p21
  { PORTB, 10, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM5_CH0, TC5_CH0, EXTERNAL_INT_10 }, // p19
  { PORTB, 11, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM5_CH1, TC5_CH1, EXTERNAL_INT_11 }, // p20
  
  // ----------------------------------- Extra pins, Arduino compatible numbering D25..D26 -----------------------------------  
  { PORTB,  3, PIO_TIMER, PIN_ATTR_DIGITAL, ADC_Channel11, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // p48 previously RX LED
  { PORTA, 27, PIO_TIMER, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 }, // p39 previously TX LED
  
  // ----------------------------------- Extra pins, no Arduino compatible numbering D27..D33 --------------------------------  
  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // p4 AREF, problem with analogRead and digitalRead 
  { PORTA, 13, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH1, TCC2_CH1, EXTERNAL_INT_13 }, // p22
  { PORTB, 22, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // p37
  { PORTB, 23, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // p38
  { PORTA, 28, PIO_TIMER, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // p41 
  { PORTA, 30, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_10 }, // p45 
  { PORTA, 31, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_11 }, // p46 
} ;

Protection of native USB port

In order to make the native USB port invulnerable to the native USB port virus, the USB pins 45 and 46 on the SAMD21 are not included in the variant.cpp file.

2 variant.h

This file contains definitions and is located here:
C:\Users\your-name\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\variants\arduino_zero\variant.cpp

Pin sequence

Because of compatibility with the Arduino Zero, the pin numbering is mixed up, as you can see in the 2 columns "No": 14
27, 15... For clarity, the Arduino pin numbers are used as e.g. digitalRead(14). Note that the Arduino pin numbers are the pin order in the PinDescription array in variant.cpp.

To create a pin sequence from 0,1, 2 ... 33, a pin number conversion array is created with d[], see the 2 columns "I/O".
Example:
digitalRead(d[0]) is equal to digitalRead(14).

 //SAM 15x15 pin sequence
 static const int d[]={ 14, 27, 15, 16, 17, 18,  8,  9,
                   4,  3,  1,  0, 23, 24, 22, 28, 2, 5,
                  11, 13, 10, 12,  6,  7, 20, 21,
                  29, 30, 26, 31, 32, 33, 19, 25 };
 static const int pinCount = 34;
// LEDs
#define PIN_LED_RXL          (25u) // 15x15 can be comment out if unused
#define PIN_LED_TXL          (25u) // (26u) 15x15 combine RXL and TXL to one LED
/*
 * USB
 */
//#define PIN_USB_HOST_ENABLE (27ul) 15x15 the SAM 15x15 doesn't use PIN_USB_HOST_ENABLE

3 WVariant.h

This file contains definitions and is located here:
C:\Users\ your-name \AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\cores\arduino

/* Definitions and types for pins */
typedef enum _EAnalogChannel
{
  No_ADC_Channel=-1,
  ADC_Channel0=0,
  ADC_Channel1=1,
  ADC_Channel2=2,
  ADC_Channel3=3,
  ADC_Channel4=4,
  ADC_Channel5=5,
  ADC_Channel6=6,
  ADC_Channel7=7,
  ADC_Channel10=10, // 15x15 changed from here
  ADC_Channel11=11,
  ADC_Channel16=16,
  ADC_Channel17=17,
  ADC_Channel18=18,
  ADC_Channel19=19,
  DAC_Channel0,
} EAnalogChannel ;

4 wiring_analog.c 

This file contains analog functions and is located here:
C:\Users\ your-name \AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\cores\arduino

 

/* SAM15x15
  if (pin < A0) {
    pin += A0;
  }*/

5 samd21_host.c

 

This file contains USB functions and is located here:
C:\Users\ your-name \AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\cores\arduino\USB

#ifdef PIN_USB_HOST_ENABLE // 15x15 the SAM 15x15 doesn't use this pin
	// Put VBUS on USB port
	pinMode( PIN_USB_HOST_ENABLE, OUTPUT ); 
	digitalWrite( PIN_USB_HOST_ENABLE, HIGH );
#endif

6 boards.txt

Change arduino_zero_native to SAM15x15:

# SAM 15x15 (only native USB port)
# ---------------------------------------
SAM15x15.name=SAM 15x15
SAM15x15.vid.0=0x2341
SAM15x15.pid.0=0x804d
SAM15x15.vid.1=0x2341
SAM15x15.pid.1=0x004d

SAM15x15.vid.2=0x2341
SAM15x15.pid.2=0x824d
# If the board is a 2341:824d use 2341:824d for build and set other parameters as well
SAM15x15.vid.2.build.vid=0x2341
SAM15x15.vid.2.build.pid=0x824d
SAM15x15.vid.2.build.usb_product="Genuino Zero"
SAM15x15.vid.2.bootloader.file=zero/samd21_sam_ba_genuino.bin

SAM15x15.vid.3=0x2341
SAM15x15.pid.3=0x024d
# If the board is a 2341:024d use 2341:824d for build and set other parameters as well
SAM15x15.vid.3.build.vid=0x2341
SAM15x15.vid.3.build.pid=0x824d
SAM15x15.vid.3.build.usb_product="Genuino Zero"
SAM15x15.vid.3.bootloader.file=zero/samd21_sam_ba_genuino.bin

SAM15x15.upload.tool=bossac
SAM15x15.upload.protocol=sam-ba
SAM15x15.upload.maximum_size=262144
SAM15x15.upload.use_1200bps_touch=true
SAM15x15.upload.wait_for_upload_port=true
SAM15x15.upload.native_usb=true
SAM15x15.build.mcu=cortex-m0plus
SAM15x15.build.f_cpu=48000000L
SAM15x15.build.usb_product="Arduino Zero"
SAM15x15.build.usb_manufacturer="Arduino LLC"
SAM15x15.build.board=SAMD_ZERO
SAM15x15.build.core=arduino
SAM15x15.build.extra_flags=-D__SAMD21G18A__ {build.usb_flags}
SAM15x15.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
SAM15x15.build.openocdscript=openocd_scripts/arduino_zero.cfg
SAM15x15.build.variant=arduino_zero
SAM15x15.build.variant_system_lib=
SAM15x15.build.vid=0x2341
SAM15x15.build.pid=0x804d
SAM15x15.bootloader.tool=openocd
SAM15x15.bootloader.file=zero/samd21_sam_ba.bin

Using the SWD pins SWDIO and SWCLK for general in / out 

The SWD pins SWDIO and SWCLK are used for programming at the Arduino Zero or SAM 15x15. Also the program port communication to the SAMD21 of the Arduino Zero goes trough these pins. Atmel is not very clear about what happens when these 2 pins are also used for I/O, therefore clarification will be given here.

The SWD port explained

See the Atmel story of the Serial Wire Debug (SWD) port HERE.

SWDIO

The SWDIO pin can be used safely for I/O without disturbing the SWD:

// the SWDIO pin can be used safely for I/O 
  const int SWDIO = 33;
  pinMode(SWDIO, OUTPUT); 
  digitalWrite(SWDIO, 0);

SWCLK

If the SWCLK pin is used for I/O, the SWD functionality will be disabled. You can recover this by reset the board by the button.

Using the SWCLK as digital output has a peculiarity too, it requires a patch.

// don't use the SWCLK pin for I/O, this disables the program port
  const int SWCLK = 32;
  pinMode(SWCLK, INPUT); // patch to use the SWCLK pin as output 
  pinMode(SWCLK, OUTPUT); 
  digitalWrite(SWCLK, 0);
  // The program port is disabled now...

How to connect LED's and other loads to a microcontroller 

For the SAMD21, the outputs can supply just 7mA, in contrast to 14mA at the ATmega328. 

The GND pins together can carry more current than the 3.3V VDD pin: 130mA respectively 92mA. Therefore, it is not arbitrary whether loads are connected to the power supply (see A) or the ground (see B). In order to let flow the load current through the processor ground pins, it is advisable to connect loads between the processor outputs and the supply voltage (see A):

How to connect LED's and other loads to a microcontroller
How to connect LED's and other loads to a microcontroller

Notes

  • AREF has become another number (d4) and is not number compatible with the Arduino Zero anymore.

To do

Improvements

If you have improvements then please let me know.

NEW: Mini SAMD21 development board 15x15mm (Arduino compatible)

The smallest Arduino compatible SAMD21 board: 15x15 mm, 34 I/O pins
The smallest Arduino compatible SAMD21 board: 15x15 mm, 34 I/O pins

The SAM 15x15 is an Arduino development board of just 15 x 15mm, with the same powerful controller as the Arduino Zero: the SAMD21G18. Despite the small size, it has more I/O pins than the Arduino Zero: 34 instead of 20. See the article and how to buy here.

Do you have any comments? Please let me know.
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.