Hi, I'm developing a product based on Arduino. Since it's a custom product I have created a new board definition file to use with an existing bootloader. The MCU used is ATSAMD21E18A. The issue is that when I enable SerialUSB and turn off some I/O the MCU crashes. Once it happens it no longer appear as a COM port and I need to reupload the bootloader to recover from this. I have spent days trying to figure out where the issue is. I have tested the hardware using a seperate C code and it works fine. Therefore, it is definitely a software issue.
The varinat.cpp file as below
#include "variant.h"
// Pins descriptions
// ------------------------
const PinDescription g_APinDescription[] =
{
// 0..6 - Digital pins
// ----------------------
{ PORTA, 2, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // D1/DAC
{ PORTA, 6, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // D2/MOSI
{ PORTA, 5, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel5, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 }, // D3/MISO
{ PORTA, 7, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // D4/SCK
{ PORTA, 0, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, TCC2_CH0, EXTERNAL_INT_0 }, // D5
{ PORTA, 1, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, TCC2_CH1, EXTERNAL_INT_1 }, // D6
{ PORTA, 4, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel4,PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 }, // D7/VREFB
// 7/8 - I2C
// ----------------------
{ PORTA, 8, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI }, // SDA/D0
{ PORTA, 9, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // SCL/D2
// 9..10 - SPI
// --------------------
{ PORTA, 3, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // D12
{ PORTA, 10, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel18, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_10}, // D13/LED
// 11/12 - RX/TX
// --------------------
{ PORTA, 23, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM4_CH1, TC4_CH1, EXTERNAL_INT_7 }, // RX/D17
{ PORTA, 22, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM4_CH0, TC4_CH0, EXTERNAL_INT_6 }, // TX/D16
// 13-16 - Flash SPI
// --------------------
{ PORTA, 16, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // Flash MOSI
{ PORTA, 17, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH1, TCC2_CH1, EXTERNAL_INT_1 }, // Flash SCK
{ PORTA, 18, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // Flash MISO
{ PORTA, 19, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_3 }, // Flash SS
// 17/18 - SWD
// --------------------
{ PORTA, 30, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_10 }, // SWCLK/D22
{ PORTA, 31, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_11 }, // SWDIO/D23
// 19..21 - USB
// --------------------
{ PORTA, 28, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // usb hOST Disable
{ PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // usb/dm
{ PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // usb/dp
// 22..25 - Other Pins
// ----------------------
{ PORTA, 11, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel19, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_11 },
{ PORTA, 14, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
{ PORTA, 15, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 },
{ PORTA, 27, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }
};
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 ) ;
Uart Serial( &sercom3, PIN_SERIAL_RX, PIN_SERIAL_TX, PAD_SERIAL_RX, PAD_SERIAL_TX ) ;
void SERCOM3_Handler()
{
Serial.IrqHandler();
}
variant.h file as below
#ifndef _VARIANT_ARDUINO_ZERO_
#define _VARIANT_ARDUINO_ZERO_
// The definitions here needs a SAMD core >=1.6.6
#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10606
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
/** Frequency of the board main oscillator */
#define VARIANT_MAINOSC (32768ul)
/** Master clock frequency */
#define VARIANT_MCK (F_CPU)
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
#include "SERCOM.h"
#include "Uart.h"
#endif // __cplusplus
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
/*----------------------------------------------------------------------------
* 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 (14u)
#define NUM_ANALOG_INPUTS (0u)
#define NUM_ANALOG_OUTPUTS (0u)
#define analogInputToDigitalPin(p) ((p < 6u) ? (p) + 22u : -1)
#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 )
// RX and TX LEDs are not present on the board.
#define PIN_LED_13 (10u)
#define PIN_LED PIN_LED_13
/*
* Serial interfaces
*/
// Serial
#define PIN_SERIAL_TX (11ul)
#define PIN_SERIAL_RX (12ul)
#define PAD_SERIAL_TX (UART_TX_PAD_0)
#define PAD_SERIAL_RX (SERCOM_RX_PAD_1)
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 1
#define PIN_SPI_MOSI (13u)
#define PIN_SPI_MISO (14u)
#define PIN_SPI_SCK (15u)
#define PIN_SPI_SS (16u)
#define PERIPH_SPI sercom1
#define PAD_SPI_TX SPI_PAD_0_SCK_1
#define PAD_SPI_RX SERCOM_RX_PAD_2
static const uint8_t SS = PIN_SPI_SS ;
static const uint8_t MOSI = PIN_SPI_MOSI ;
static const uint8_t MISO = PIN_SPI_MISO ;
static const uint8_t SCK = PIN_SPI_SCK ;
/*
* Wire Interfaces
*/
//I2C/Qwiic Interface
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (7u)
#define PIN_WIRE_SCL (8u)
#define PERIPH_WIRE sercom2
#define WIRE_IT_HANDLER SERCOM2_Handler
static const uint8_t SDA = PIN_WIRE_SDA;
static const uint8_t SCL = PIN_WIRE_SCL;
/*
* USB
*/
//#define PIN_USB_HOST_ENABLE (10ul)
#define PIN_USB_DM (20ul)
#define PIN_USB_DP (21ul)
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
/* =========================
* ===== SERCOM DEFINITION
* =========================
*/
extern SERCOM sercom0;
extern SERCOM sercom1;
extern SERCOM sercom2;
extern SERCOM sercom3;
extern Uart Serial;
#endif
// These serial port names are intended to allow libraries and architecture-neutral
// sketches to automatically default to the correct port name for a particular type
// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
//
// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
//
// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
//
// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
//
// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
//
// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
// pins are NOT connected to anything by default.
#define SERIAL_PORT_USBVIRTUAL SerialUSB
#define SERIAL_PORT_MONITOR SerialUSB
#define SERIAL_PORT_HARDWARE Serial
#define SERIAL_PORT_HARDWARE_OPEN Serial
#endif /* _VARIANT_ARDUINO_ZERO_ */
The Arduino sketch:
const int IV_EN = 15;
const int Modem_PWR_EN = 28;
const int ADC_PWR_EN = 30;
const int Sensor_PWR_EN = 31;
void setup()
{
//Initialise serial monitor
SerialUSB.begin(9600); // Initialize Serial Monitor USB
//Serial.begin(9600); // Initialize hardware serial port, pins 17/16
while (!SerialUSB) ; // Wait for Serial monitor to open
SerialUSB.println("Monitor");
SerialUSB.print("Software Version ");
SerialUSB.print(SW_Version/10);
SerialUSB.print(".");
SerialUSB.println(SW_Version%10);
SerialUSB.println("");
pinMode(IV_EN, OUTPUT);
digitalWrite(IV_EN, LOW);
pinMode(Sensor_PWR_EN, OUTPUT);
digitalWrite(Sensor_PWR_EN, HIGH);
pinMode(ADC_PWR_EN, OUTPUT);
digitalWrite(ADC_PWR_EN, LOW);
//Crashes when I try to set this pin low
pinMode(Modem_PWR_EN, OUTPUT);
digitalWrite(Modem_PWR_EN, LOW);
void loop()
{
}