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 rootImport("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
- Add changes that allow use of a portable variants file by Timvrakas · Pull Request #74 · platformio/platform-atmelsam · GitHub
- GitHub - stanford-ssi/olympus-quail: Code that runs on the Ground support board associate with filling and ignition for Olympus
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);