I have setup a simple UART test on my SAML21 and believe I must be misusing the library due to the behavior I'm seeing
uint8_t testData[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}
void broadcast_test_data(void)
{
usart_write_buffer_wait(&usart_instance, testData, sizeof(testData))
}
void serial_data_handler(void)
{
unit16_t rxInt;
if (usart_read_wait(&usart_instance, &rxInt) == STATUS_OK) {
printf("RX %d", rxInt);
}
}
int main(void)
{
struct usart_config config_usart;
usart_get_config_defaults(&config_usart);
config_usart.baudrate = 1000;
config_usart.mux_setting = USART_RX_3_TX_2_XCK_3;
config_usart.pinmux_pad0 = PINMUX_UNUSED;
config_usart.pinmux_pad1 = PINMUX_UNUSED;
config_usart.pinmux_pad2 = PINMUX_PA24C_SERCOM3_PAD2;
config_usart.pinmux_pad3 = PINMUX_PA24C_SERCOM3_PAD3;
usart_enable(&usart_instance);
while (1) {
// run-loop
SYSTEM_RunTasks();
serial_data_handler();
}
}
I verified that the TX data is transmitting the entire testData array via Putty.
The issue is that when I tie the RX and TX together to test receiving, I am only ever getting bytes (0x01, 0x02, and 0x06). Is polling for RX data via the while loop not the way I should be doing this? Do I need to somehow mark data as read before UART moves onto the next received byte? Should I be asking for more than 1 byte at a time?
Thanks for any info you can provide
Best Answer
The issue here is that both
usart_write_buffer_wait()
andusart_read_wait()
are blocking. The USART hardware seems to have a 2 byte FIFO buffer on RX.Now what happens is the RX FIFO is filled during writing, and
usart_write_buffer_wait
returns during the transmission of the last character.As soon as
usart_read_wait
is called - which can only happen afterusart_write_buffer_wait
due to it being a blocking function, it reads the first 2 bytes from the fifo. The following bytes are missing due to fifo overflow - check hardware status registers, they should tell you that. The last byte is received and read once the usart finished the transmission's stop bit.Workaround: Use interrupts or DMA for RX, TX or both.