Extra UART on SARA AFF N211

For our project we would like to change J3:1,2 (D14/D15 on GROVE connector) to an additional UART. We added some code to our test file (ino) but are not sure if this is the right way to overwrite SARA config in variant.cpp

Are there community members more familiar with changing board configuration who can give us some pointers on how to proceed with this?

Thanks


Uart mySerial(&sercom2, 15, 14, SERCOM_RX_PAD_3, UART_TX_PAD_2);

void SERCOM2_Handler()
{
  mySerial.IrqHandler();
}

#include "wiring_private.h"

void setup() {
  // change D14 and D15 to Serial
  pinPeripheral(14, PIO_SERCOM);
  pinPeripheral(15, PIO_SERCOM);
  
  // initialize both serial ports:
  Serial.begin(19200);
  mySerial.begin(19200);
  SerialUSB.begin(19200);
}

void loop() {
  // read from additional UART port 'mySerial', send to port USB:
  if (mySerial.available()) {
    int inByte = mySerial.read();
    SerialUSB.write(inByte);
  }

  // read from standard UART port 'Serial', send to port USB:
  if (Serial.available()) {
    int inByte = Serial.read();
    SerialUSB.write(inByte);
  }
}

You have most of it there. However, I’m not sure if the Uart constructer will work correctly before the calls to pinPeripheral().

I would recommend having a look at the Autonomo variant files as we have added the option (via compiler directives set by the sub-variants) which adds up to 2 extra UARTs.

A few things that have to be done:

  1. Add the pin descriptions to the array in Variant.cpp (beware of SERCOM vs SERCOM_ALT)
  2. Specify the pad layout in Variant.h (You have this in the constructor call.)
  3. Initialise the UART instance in Variant.h (You have this at the top.)
  4. Add the IRQ handler in Variant.cpp (You have this a the top.)

Ok, thank you for your help. We are getting an error ‘Serial 2 was not declared in this scope’ on the line " if Serial2.available()) ", did we miss some changes to variant.h or variant.cpp?

#define ENABLE_SERIAL2 
#include "wiring_private.h"

void setup() {
  // change D14/D15 ; A6/A7 on GROVE to Serial2
  pinPeripheral(14, PIO_SERCOM);
  pinPeripheral(15, PIO_SERCOM);
  
  // initialize both serial ports:
  Serial.begin(19200);
  Serial2.begin(19200);
  SerialUSB.begin(19200);
}

void loop() {
  // read from port 'Serial2', send to port USB:
  if (Serial2.available()) {
    int inByte = Serial2.read();
    SerialUSB.write(inByte);
  }

  // read from port 'Serial', send to port USB:
  if (Serial.available()) {
    int inByte = Serial.read();
    SerialUSB.write(inByte);
  }
}

We changed the variant.h serial interfaces:

/*
 * Serial interfaces
 */
// Serial
#define PIN_SERIAL_RX       (0ul)
#define PIN_SERIAL_TX       (1ul)
#define PAD_SERIAL_TX       (UART_TX_PAD_0)
#define PAD_SERIAL_RX       (SERCOM_RX_PAD_1)

// Serial1
#define PIN_SERIAL1_RX       (42ul)
#define PIN_SERIAL1_TX       (41ul)
#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)

 // Serial2
#define PIN_SERIAL2_RX       (37ul)
#define PIN_SERIAL2_TX       (38ul)
#define PAD_SERIAL2_TX       (UART_TX_PAD_2)
#define PAD_SERIAL2_RX       (SERCOM_RX_PAD_3)

and variant.h SERCOM reference:

extern SERCOM sercom0;
extern SERCOM sercom1;
extern SERCOM sercom2;
extern SERCOM sercom3;
extern SERCOM sercom4;
extern SERCOM sercom5;

extern Uart Serial;
extern Uart Serial1;
#ifdef ENABLE_SERIAL2
extern Uart Serial2;
#endif

variant.h hardware reference:


// 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

#define SERIAL_PORT_HARDWARE2       Serial2
#define SERIAL_PORT_HARDWARE_OPEN2  Serial2

Added at the end of the array in variant.cpp this code:

  // 37..40 Other Analog Inputs
  { PORTA, 10, PIO_ANALOG,     PIN_ATTR_ANALOG,                                        ADC_Channel18,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10  }, // ADC/AIN[18], A6 Grove1
  { PORTA, 11, PIO_ANALOG,     PIN_ATTR_ANALOG,                                        ADC_Channel19,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11  }, // ADC/AIN[19], A7 Grove2
  { PORTB,  5, PIO_ANALOG,     PIN_ATTR_ANALOG,                                        ADC_Channel13,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5   }, // BAT_VOLT, A8
  { PORTB,  9, PIO_ANALOG,     PIN_ATTR_ANALOG,                                        ADC_Channel3,   NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9   }, // A9

  // 41..42 - SERCOM/UART (Serial1)
  { PORTA, 6, PIO_SERCOM_ALT,  PIN_ATTR_DIGITAL,                                       No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5   }, // TX: SERCOM0/PAD[2]
  { PORTA, 5, PIO_SERCOM_ALT,  PIN_ATTR_DIGITAL,                                       No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6   }, // RX: SERCOM0/PAD[1]

  // 43..44 - I2C pins (SDA/SCL)
  { PORTA, 16, PIO_SERCOM,     PIN_ATTR_DIGITAL,                                      No_ADC_Channel,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0   }, // SDA: SERCOM1/PAD[0]
  { PORTA, 17, PIO_SERCOM,     PIN_ATTR_DIGITAL,                                      No_ADC_Channel,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1   }, // SCL: SERCOM1/PAD[1]

  // 45..48 - SPI pins (ICSP: MISO, SS, MOSI, SCK)
  // Notice that SCK is sharing the same PA21 with LED_BUILTIN
  { PORTA, 22, PIO_SERCOM,     PIN_ATTR_DIGITAL,                                      No_ADC_Channel,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6   }, // MISO: SERCOM3/PAD[0]
  { PORTA, 23, PIO_SERCOM,     PIN_ATTR_DIGITAL,                                      No_ADC_Channel,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7   }, // SS: SERCOM3/PAD[1]
  { PORTA, 20, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL,                                      No_ADC_Channel,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4   }, // MOSI: SERCOM3/PAD[2]
  { PORTA, 21, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL,                                      No_ADC_Channel,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5   }, // SCK: SERCOM3/PAD[3]

  // 49..50 - USB
  { 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

  // 51..52 - DAC, SARA_R4XX_TOGGLE 
  { PORTA,  2, PIO_ANALOG,     PIN_ATTR_ANALOG,                                       DAC_Channel0,    NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2   }, // DAC
  { PORTB, 17, PIO_OUTPUT,     PIN_ATTR_DIGITAL,                                      No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE},  // SARA_R4XX_TOGGLE
  
  // 53..54 - I2C1 pins (SDA/SCL)
  { PORTA, 8,  PIO_SERCOM_ALT, PIN_ATTR_DIGITAL,                                      No_ADC_Channel,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NMI }, // SDA: SERCOM2/PAD[0]
  { PORTA, 9,  PIO_SERCOM_ALT, PIN_ATTR_DIGITAL,                                      No_ADC_Channel,  NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9   }, // SCL: SERCOM2/PAD[1]

   // 55..56 - Serial2 (alternative use for D14/D15 ; A6/A7 ; Grove pin 1/2)
  { PORTA, 10, PIO_SERCOM,     PIN_ATTR_DIGITAL,                                      No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // RX, SERCOM4/PAD[1]
  { PORTA, 11, PIO_SERCOM,     PIN_ATTR_DIGITAL,                                      No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // TX, SERCOM4/PAD[2]

and at the end of variant.cpp

Uart Serial( &sercom5, PIN_SERIAL_RX, PIN_SERIAL_TX, PAD_SERIAL_RX, PAD_SERIAL_TX ) ;
void SERCOM5_Handler()
{
  Serial.IrqHandler();
}

Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX );
void SERCOM0_Handler()
{
  Serial1.IrqHandler();
}

#ifdef ENABLE_SERIAL2
Uart Serial2( &sercom2, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX );
void SERCOM2_Handler()
{
  Serial2.IrqHandler();
}
#endif

Declaring this:

#define ENABLE_SERIAL2 

In your sketch won’t have any effect on the compilation of the Variant files.

The error you are seeing on the available() line is probably the last instance of the error, not the first.

If you are editing the Variant files, just go ahead and removed the #ifdef blocks for ENABLE_SERIAL2