How to access pins on SAMD21 E18A with Arduino Framework on custom board?

Hi,

I am having the same problem for the SAMD21G18. From what I understand there is no other way then creating your own variant.

But I just found out that there is another way creating a variant without having to create you own framework and platform.

  1. Add script.py to the project root

    Import("env")
    env.Append(OVERRIDE_VARIANT=True)
    
  2. Add your custom variant in a “variants” folder in the project root. E.g. variants/samd21g18/

  3. platformio.ini

    [env:samd21g18]
    framework = arduino
    platform = atmelsam
    board_build.variant = samd21g18
    board_build.variants_dir = variants
    board = samd21g18a
    debug_tool = jlink
    upload_protocol = jlink
    

Source

It’s not perfect solution, because this way you have to manually update your variants file in all the projects where you use it. But for me it’s still a bit cleaner and easier than maintaining a fork of the platform and framework.

I started with a generic version for the SAMD21G18, where I have now definitions for all pins with the original names and all the SERCOMs are undefined and can now be configured the way I need them in project. This is still work in progress and the variant.cpp will for sure still contain bugs :slight_smile:

Generic SAMD21G18 Example - WIP !!!

variant.h

#pragma once

// The definitions here needs a SAMD core >=1.6.10
#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610

#include <WVariant.h>

// General definitions
// -------------------

// Frequency of the board main oscillator
#define VARIANT_MAINOSC (32768ul)

// Master clock frequency
#define VARIANT_MCK     (48000000ul)

// Pins
// ----

// Number of pins defined in PinDescription array
#ifdef __cplusplus
extern "C" unsigned int PINCOUNT_fn();
#endif
#define PINS_COUNT           (PINCOUNT_fn())
#define NUM_DIGITAL_PINS     (15u)
#define NUM_ANALOG_INPUTS    (7u)
#define NUM_ANALOG_OUTPUTS   (1u)

// Low-level pin register query macros
// -----------------------------------
#define digitalPinToPort(P)      (&(PORT->Group[g_APinDescription[P].ulPort]))
#define digitalPinToBitMask(P)   (1 << g_APinDescription[P].ulPin)
//#define analogInPinToBit(P)    ()
#define portOutputRegister(port) (&(port->OUT.reg))
#define portInputRegister(port)  (&(port->IN.reg))
#define portModeRegister(port)   (&(port->DIR.reg))
#define digitalPinHasPWM(P)      (g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER)

#define NATIVE_PIN_PA00 1
#define NATIVE_PIN_PA01 2
#define NATIVE_PIN_PA02 3
#define NATIVE_PIN_PA03 4
#define NATIVE_PIN_PB08 7
#define NATIVE_PIN_PB09 8
#define NATIVE_PIN_PA04 9
#define NATIVE_PIN_PA05 10
#define NATIVE_PIN_PA06 11
#define NATIVE_PIN_PA07 12
#define NATIVE_PIN_PA08 13
#define NATIVE_PIN_PA09 14
#define NATIVE_PIN_PA10 15
#define NATIVE_PIN_PA11 16
#define NATIVE_PIN_PB10 19
#define NATIVE_PIN_PB11 20
#define NATIVE_PIN_PA12 21
#define NATIVE_PIN_PA13 22
#define NATIVE_PIN_PA14 23
#define NATIVE_PIN_PA15 24
#define NATIVE_PIN_PA16 25
#define NATIVE_PIN_PA17 26
#define NATIVE_PIN_PA18 27
#define NATIVE_PIN_PA19 28
#define NATIVE_PIN_PA20 29
#define NATIVE_PIN_PA21 30
#define NATIVE_PIN_PA22 31
#define NATIVE_PIN_PA23 32
#define NATIVE_PIN_PA24 33
#define NATIVE_PIN_PA25 34
#define NATIVE_PIN_PB22 37
#define NATIVE_PIN_PB23 38
#define NATIVE_PIN_PA27 39
#define NATIVE_PIN_PA28 41
#define NATIVE_PIN_PB02 47
#define NATIVE_PIN_PB03 48


// Analog pins
// -----------
#ifndef A0
#define A0 NATIVE_PIN_PA10
#endif

// USB
// ---
#ifndef PIN_USB_DM
#define PIN_USB_DM          NATIVE_PIN_PA24
#endif
#ifndef PIN_USB_DP
#define PIN_USB_DP          NATIVE_PIN_PA25
#endif
#ifndef PIN_USB_HOST_ENABLE
#define PIN_USB_HOST_ENABLE NATIVE_PIN_PA18
#endif

// SERCOM ports
// ------------
#ifdef __cplusplus
#include "SERCOM.h"
#include "Uart.h"

// Instances of SERCOM
extern SERCOM sercom0;
extern SERCOM sercom1;
extern SERCOM sercom2;
extern SERCOM sercom3;
extern SERCOM sercom4;
extern SERCOM sercom5;

#endif // __cplusplus

#ifdef __cplusplus
extern "C" {
#endif
unsigned int PINCOUNT_fn();
#ifdef __cplusplus
}
#endif

variant.cpp

#include "variant.h"

const PinDescription g_APinDescription[] = {
  { NOT_A_PORT, 99, PIO_NOT_A_PIN,    (PIN_ATTR_NONE                         ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 00
  { PORTA,  0, PIO_DIGITAL,    (PIN_ATTR_NONE                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 01
  { PORTA,  1, PIO_DIGITAL,    (PIN_ATTR_NONE                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 02
  { PORTA,  2, PIO_DIGITAL,  (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG /*DAC*/       ), ADC_Channel0,   NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2    }, // 03
  { PORTA,  3, PIO_DIGITAL, (PIN_ATTR_DIGITAL                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3    }, // 04 // DAC/VREFP
  { NOT_A_PORT, 99, PIO_NOT_A_PIN,    (PIN_ATTR_NONE                         ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 05
  { NOT_A_PORT, 99, PIO_NOT_A_PIN,    (PIN_ATTR_NONE                         ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 06
  { PORTB,  8, PIO_DIGITAL,    (PIN_ATTR_NONE                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 07
  { PORTB,  9, PIO_ANALOG,     (PIN_ATTR_PWM|PIN_ATTR_TIMER                  ), ADC_Channel3,   PWM4_CH1,   TC4_CH1,      EXTERNAL_INT_9    }, // 08
  { PORTA,  4, PIO_ANALOG,  (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER    ), ADC_Channel4,   PWM0_CH0,   TCC0_CH0,     EXTERNAL_INT_NONE }, // 09
  { PORTA,  5, PIO_ANALOG,  (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER    ), ADC_Channel5,   PWM0_CH1,   TCC0_CH1,     EXTERNAL_INT_NONE }, // 10
  { PORTA,  6, PIO_ANALOG,  (PIN_ATTR_DIGITAL                                ), ADC_Channel6,   NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 11
  { PORTA,  7, PIO_ANALOG,  (PIN_ATTR_DIGITAL                                ), ADC_Channel7,   NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 12
  { PORTA,  8, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL                             ), ADC_Channel16,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NMI  }, // 13 // SDA:  SERCOM2/PAD[0]
  { PORTA,  9, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL                             ), ADC_Channel17,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 14 // SCL:  SERCOM2/PAD[1]
  { PORTA, 10, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER    ), ADC_Channel18,  PWM1_CH0,   TCC1_CH0,     EXTERNAL_INT_NONE }, // 15
  { PORTA, 11, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER    ), ADC_Channel19,  PWM1_CH1,   TCC1_CH1,     EXTERNAL_INT_NONE }, // 16
  { NOT_A_PORT, 99, PIO_NOT_A_PIN,    (PIN_ATTR_NONE                         ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 17
  { NOT_A_PORT, 99, PIO_NOT_A_PIN,    (PIN_ATTR_NONE                         ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 18
  { PORTB, 10, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER ), No_ADC_Channel, PWM5_CH0,   TC5_CH0,      EXTERNAL_INT_10   }, // 19
  { PORTB, 11, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER ), No_ADC_Channel, PWM5_CH1,   TC5_CH1,      EXTERNAL_INT_11   }, // 20
  { PORTA, 12, PIO_SERCOM_ALT, (PIN_ATTR_NONE                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 21 // MOSI: SERCOM4/PAD[0]
  { PORTA, 13, PIO_SERCOM_ALT, (PIN_ATTR_NONE                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 22 // SCK:  SERCOM4/PAD[1]
  { PORTA, 14, PIO_DIGITAL,    (PIN_ATTR_NONE                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 23 // SS:   as GPIO
  { PORTA, 15, PIO_SERCOM_ALT, (PIN_ATTR_NONE                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 24 // MISO: SERCOM4/PAD[3]
  { PORTA, 16, PIO_SERCOM,  (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER    ), No_ADC_Channel, PWM2_CH0,   TCC2_CH0,     EXTERNAL_INT_0    }, // 25 // MOSI: SERCOM1/PAD[0]
  { PORTA, 17, PIO_SERCOM,  (PIN_ATTR_DIGITAL                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1    }, // 26 // SCK:  SERCOM1/PAD[1]
  { PORTA, 18, PIO_DIGITAL, (PIN_ATTR_DIGITAL                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 27 // SS:   SERCOM1/PAD[2]
  { PORTA, 19, PIO_SERCOM,  (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER    ), No_ADC_Channel, PWM3_CH1,   TC3_CH1,      EXTERNAL_INT_NONE }, // 28 // MISO: SERCOM1/PAD[3]
  { PORTA, 20, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6,   TCC0_CH6,     EXTERNAL_INT_4    }, // 29
  { PORTA, 21, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH7,   TCC0_CH7,     EXTERNAL_INT_5    }, // 30
  { PORTA, 22, PIO_SERCOM,  (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER    ), No_ADC_Channel, PWM4_CH0,   TC4_CH0,      EXTERNAL_INT_6    }, // 31
  { PORTA, 23, PIO_SERCOM,  (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER    ), No_ADC_Channel, PWM4_CH1,   TC4_CH1,      EXTERNAL_INT_7    }, // 32
  { PORTA, 24, PIO_COM,     (PIN_ATTR_NONE                                   ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 33 // USB/DM
  { PORTA, 25, PIO_COM,     (PIN_ATTR_NONE                                   ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 34 // USB/DP
  { NOT_A_PORT, 99, PIO_NOT_A_PIN,    (PIN_ATTR_NONE                         ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 35
  { NOT_A_PORT, 99, PIO_NOT_A_PIN,    (PIN_ATTR_NONE                         ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 36
  { PORTB, 22, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL                             ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 37 // TX:   SERCOM5/PAD[2]
  { PORTB, 23, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL                             ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 38 // RX:   SERCOM5/PAD[3]
  { PORTA, 27, PIO_DIGITAL,    (PIN_ATTR_NONE                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 39
  { NOT_A_PORT, 99, PIO_NOT_A_PIN,    (PIN_ATTR_NONE                         ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 40
  { PORTA, 28, PIO_DIGITAL,    (PIN_ATTR_NONE                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 41
  { NOT_A_PORT, 99, PIO_NOT_A_PIN,    (PIN_ATTR_NONE                         ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 42
  { NOT_A_PORT, 99, PIO_NOT_A_PIN,    (PIN_ATTR_NONE                         ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 43
  { NOT_A_PORT, 99, PIO_NOT_A_PIN,    (PIN_ATTR_NONE                         ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 44
  { PORTA, 30, PIO_DIGITAL,    (PIN_ATTR_NONE                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 45
  { PORTA, 31, PIO_DIGITAL,    (PIN_ATTR_NONE                                ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 46
  { PORTB,  2, PIO_ANALOG,  (PIN_ATTR_DIGITAL                                ), ADC_Channel10,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2    }, // 47
  { PORTB,  3, PIO_ANALOG,  (PIN_ATTR_DIGITAL                                ), ADC_Channel11,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3    }, // 48
};

extern "C" {
    unsigned int PINCOUNT_fn() {
        return (sizeof(g_APinDescription) / sizeof(g_APinDescription[0]));
    }
}

const void* g_apTCInstances[TCC_INST_NUM + TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 };

// Multi-serial objects instantiation
SERCOM sercom0(SERCOM0);
SERCOM sercom1(SERCOM1);
SERCOM sercom2(SERCOM2);
SERCOM sercom3(SERCOM3);
SERCOM sercom4(SERCOM4);
SERCOM sercom5(SERCOM5);


3 Likes