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.
-
Add script.py
to the project root
Import("env")
env.Append(OVERRIDE_VARIANT=True)
-
Add your custom variant in a “variants” folder in the project root. E.g. variants/samd21g18/
-
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
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);