I would like to add an additional serial port for my application on a Sodaq One. The processor has an available SCOM (SCOM4). Is it possible to configure the serial port and have it treated the same way with the serial class as the existing serial ports?
Yes it would be possible to map SERCOM4 as an additional UART.
Using the pin data pp.33-34 of the datasheet (note: the SodaqOne uses the SAMD21G variant): http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
SERCOM4 is available on these pins (Alt mapping):
PB08: PAD0
PB09: PAD1
PB10: PAD2
PB11: PAD3
PA12: PAD0
PA13: PAD1
PA14: PAD2
PA15: PAD3
If you have a look at the SodaqOne schematic: http://support.sodaq.com/wp-content/uploads/2016/07/sodaq_one_v2-1.png
You can see that the only available pins are PB8 (PAD0), and PB9 (PAD1). These can be setup as a UART and they are available on the external pins J1-11 & J1-12.
In order to achieve this you will need to modify the board variant files.
In variant.h the existing ‘Serial’ objects are defined with:
/*
* Serial interfaces
*/
// Serial
#define PIN_SERIAL_RX (39u)
#define PIN_SERIAL_TX (40u)
#define PAD_SERIAL_TX (UART_TX_PAD_0)
#define PAD_SERIAL_RX (SERCOM_RX_PAD_1)
// Serial1
#define PIN_SERIAL1_RX (41u)
#define PIN_SERIAL1_TX (42u)
#define PAD_SERIAL1_TX (UART_TX_PAD_0)
#define PAD_SERIAL1_RX (SERCOM_RX_PAD_1)
//
//...
//
extern Uart Serial;
extern Uart Serial1;
//
//...
//
// Serial has no physical pins broken out, so it's not listed as HARDWARE port
#define SERIAL_PORT_HARDWARE Serial
#define SERIAL_PORT_HARDWARE_OPEN Serial
#define SERIAL_PORT_HARDWARE1 Serial1
#define SERIAL_PORT_HARDWARE_OPEN1 Serial1
and in variant.cpp where the values in variant.h are the array indicies.
// 39..40 Serial
{ PORTB, 3, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // SERIAL_RX
{ PORTB, 2, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // SERIAL_TX
// 41..42 Serial1
{ PORTA, 13, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13 }, // SERIAL1_RX
{ PORTA, 12, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // SERIAL1_TX
You will need to add the appropriate rows to main pin description array in variant.cpp, you should do so at the end of the array otherwise you will affect references to other entries (note: the SERCOM_ALT mappings). You will also add the required definitions to variant.h , the naming scheme would suggest you use Serial2.
Finally, at the end of variant.cpp you need to instantiate the new Serial object and hook up the IRQ handler, e.g.
Uart Serial(&sercom5, PIN_SERIAL_RX, PIN_SERIAL_TX, PAD_SERIAL_RX, PAD_SERIAL_TX ) ;
Uart Serial1(&sercom2, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX);
void SERCOM2_Handler()
{
Serial1.IrqHandler();
}
void SERCOM5_Handler()
{
Serial.IrqHandler();
}
Awesome. I will get right on it.