SAMD51 multiple serials, how to spare RX pins

I'm using a SAMD51 with custom variant files, and I added another serial UART,
so now my configuration is like this (and is working fine):

Uart Serial1( &sercom4, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;

void SERCOM4_0_Handler()
{
  Serial1.IrqHandler();
}
void SERCOM4_1_Handler()
{
  Serial1.IrqHandler();
}
void SERCOM4_2_Handler()
{
  Serial1.IrqHandler();
}
void SERCOM4_3_Handler()
{
  Serial1.IrqHandler();
}



Uart Serial2( &sercom3, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX ) ;

void SERCOM3_0_Handler()
{
  Serial2.IrqHandler();
}
void SERCOM3_1_Handler()
{
  Serial2.IrqHandler();
}
void SERCOM3_2_Handler()
{
  Serial2.IrqHandler();
}
void SERCOM3_3_Handler()
{
  Serial2.IrqHandler();
}

#define PIN_SERIAL1_RX       (24ul)
#define PIN_SERIAL1_TX       (25ul)
#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
#define PAD_SERIAL1_TX       (UART_TX_PAD_0)

#define PIN_SERIAL2_RX       (26ul)
#define PIN_SERIAL2_TX       (27ul)
#define PAD_SERIAL2_RX       (SERCOM_RX_PAD_1)
#define PAD_SERIAL2_TX       (UART_TX_PAD_0)

#ifdef __cplusplus
extern SERCOM sercom0;
extern SERCOM sercom1;
extern SERCOM sercom2;
extern SERCOM sercom3;
extern SERCOM sercom4;
extern SERCOM sercom5;
extern Uart Serial1;
extern Uart Serial2;
#endif

I'm now wondering if I can spare both RX pins so that I can use them for other tasks, since I'm only using TX functionality for both serials, and if possible, how should I modify the variant files.
Thank you

Hi @Dimitree

It's possible to disable the receiver in the SERCOM's CTRLB register, however this is enable protected, therefore it's necessary to disable the SERCOM before making the change and re-enabling it once more:

SERCOM3->USART.CTRLA.bit.ENABLE = 0;          // Disable the USART
while (SERCOM3->USART.SYNCBUSY.bit.ENABLE);   // Wait for synchronization
SERCOM3->USART.CTRLB.bit.RXEN = 0;            // Disable the receiver
while (SERCOM1->USART.SYNCBUSY.bit.CTRLB);    // Wait for synchronization
SERCOM3->USART.CTRLA.bit.ENABLE = 1;          // Re-enable the USART
while (SERCOM3->USART.SYNCBUSY.bit.ENABLE);   // Wait for synchronization

Unfortunately, it's not possible to make this change by simply modifying the variant files, since by default the Serialx.begin() function will enable both Tx and Rx functionality.

Another option is to create your own begin function specific to that SERCOM, but only enable the Tx. The code for the begin function is in the Uart.cpp and SERCOM.cpp Arduino (Adafruit) SAMD core files.

thank you @MartinL

but should I also modify the variant file at the corresponding pin entry?

{ PORTA, 12, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_12 },

for example, assuming RX was on PORTA-12, PIO_SERCOM_ALT should become PIO_DIGITAL?

and I believe this definition is only used during the Serial initialization, and then ignored, right?

#define PIN_SERIAL1_RX       (24ul)

also, do you know what those two directive are needed for?

#define SERIAL_PORT_HARDWARE        Serial1
#define SERIAL_PORT_HARDWARE_OPEN   Serial1

I don't have a similar set of directives for Serial2, but it is working without them

Hi @Dimitree

Yes, I think your suggestion will work, since Serial's begin() function (in file Uart.cpp) calls on pinPeripheral(), which will immediately set the receiver pin to a GPIO:

void Uart::begin(unsigned long baudrate, uint16_t config)
{
  pinPeripheral(uc_pinRX, g_APinDescription[uc_pinRX].ulPinType);
  pinPeripheral(uc_pinTX, g_APinDescription[uc_pinTX].ulPinType);

The rest of the begin() function will subsequently set-up the pin to be a receiver, but as it's already set as a GPIO, it's never connected.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.