Hi all
Previously, I used the nRF52832 with the interrupt-driven UART at 1Mbaud. But due to SoftDevice interrupts that blocked the UART-RX-IRQ for more than 6 bytes, I tried to use the UARTE with EasyDMA.
I need to receive an arbitrary amount of bytes and can therefore not wait until the RX buffer is filled. So, I tried the suggestion from this thread, by enabling the shortcut between ENDRX and STARTRX and by triggering the STOPRX task in a certain interval.
Now, I check in a certain interval if the RXDRDY event occurred. If yes, I set the second RX buffer as the active buffer and trigger afterwards the STOPRX task. After the ENDRX event occurred, I copy the amount of received bytes.
My code looks like this:
void UART_init(void) { // Disable UART NRF_UARTE0->ENABLE = (UARTE_ENABLE_ENABLE_Disabled << UARTE_ENABLE_ENABLE_Pos); // Set baudrate NRF_UARTE0->BAUDRATE = UARTE_BAUDRATE_BAUDRATE_Baud1M; // Disable flow control and parity check NRF_UARTE0->CONFIG = (UART_DISABLE_HW_FLOW | UART_EXCLUDE_PARITY); // Set TX and RX pin NRF_UARTE0->PSEL.TXD = HWH_HIF_MISO_TX; NRF_UARTE0->PSEL.RXD = HWH_HIF_MOSI_RX; // Set the TX and RX buffers gRX_buf_1_active = true; NRF_UARTE0->RXD.PTR = (uint32_t)gRX_buf_1; NRF_UARTE0->TXD.PTR = (uint32_t)gTX_buf; NRF_UARTE0->RXD.MAXCNT = 255; NRF_UARTE0->TXD.MAXCNT = 0; // Clear all possible pending events NRF_UARTE0->EVENTS_RXDRDY = 0; NRF_UARTE0->EVENTS_ENDRX = 0; NRF_UARTE0->EVENTS_TXDRDY = 0; NRF_UARTE0->EVENTS_ENDTX = 0; NRF_UARTE0->EVENTS_ERROR = 0; NRF_UARTE0->EVENTS_RXTO = 0; NRF_UARTE0->EVENTS_RXSTARTED = 0; NRF_UARTE0->EVENTS_TXSTARTED = 0; NRF_UARTE0->EVENTS_TXSTOPPED = 0; // Clear Interrupts NRF_UARTE0->INTENCLR = 0xFFFFFFFFUL; // Enable shortcut bwetwen ENDRX and STARTRX NRF_UARTE0->SHORTS = UARTE_SHORTS_ENDRX_STARTRX_Enabled << UARTE_SHORTS_ENDRX_STARTRX_Pos; // Enable UART NRF_UARTE0->ENABLE = (UARTE_ENABLE_ENABLE_Enabled << UARTE_ENABLE_ENABLE_Pos); // Start RX NRF_UARTE0->TASKS_STARTRX = 1; }
void UART_handle(uint8_t * const pData, size_t const data_size) { uint32_t rx_length; uint32_t i; if (NRF_UARTE0->EVENTS_RXDRDY) { // Switch the RX buffer if (gRX_buf_1_active) { NRF_UARTE0->RXD.PTR = (uint32_t)gRX_buf_2; NRF_UARTE0->RXD.MAXCNT = 255; gRX_buf_1_active = false; } else { NRF_UARTE0->RXD.PTR = (uint32_t)gRX_buf_1; NRF_UARTE0->RXD.MAXCNT = 255; gRX_buf_1_active = true; } // Stop the reception // RX is restarted after the ENDRX event due to shortcut NRF_UARTE0->EVENTS_ENDRX = 0; NRF_UARTE0->TASKS_STOPRX = 1; while (NRF_UARTE0->EVENTS_ENDRX == 0) {} NRF_UARTE0->EVENTS_ENDRX = 0; NRF_UARTE0->EVENTS_RXDRDY = 0; // Copy the received bytes from the used RX buffer rx_length = NRF_UARTE0->RXD.AMOUNT; for (i = 0; i < rx_length; i++) { if (i < data_size) { if (gRX_buf_1_active) {pData[i] = gRX_buf_2[i];} else {pData[i] = gRX_buf_1[i];} } } } }
I assumed that due to the enabled shortcut the reception should immediately switch to the second buffer. But it seems that I lose some bytes (or get corrupted bytes) when the STOPRX task is executed during the reception of bytes. E.g. the byte stream "00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF" is sent to the nRF52, but I receive in RX_BUF_1 the bytes "00 11 22 33 44 55 66" and in RX_BUF_2 the bytes "2C DB DD EE FF". Here is a trace from the flow:
Should the STOPRX task not be triggered during the reception of bytes or am I missing something? Do you know this problem?
Many thanks in advance.
Best regards