This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF52 840 UARTE EVENTS_ENDRX not generated after TASKS_STOPRX

Hi there,
I have a custom board with nRF52840 and i am transferring fairly large amounts of data via uarte.
I am also using my own driver. For some reason the attached device decided to go crazy and the result is that RXD.MAXCNT is full to the max.  RXD.AMOUNT == RXD.MAXCNT and ERRORSRC value is 0x05 or 0x0D   All this is not a big problem except that when this situation happens the EVENTS_ENDRX is not generated after TASKS_STOPRX = 1

    NRF_UARTE1->TASKS_STOPRX = 1;
    NRF_LOG_INFO("WAIT ENDRX\n");
    while(!NRF_UARTE1->EVENTS_ENDRX); //stoprx generates endrx always ?!?!
    
i.e. I am waiting forever after -> NRF_LOG_INFO("WAIT ENDRX\n");
I guess that this is related to the ERRORSRC somehow but can't figure out how to proceed.

Parents Reply Children
  • Hi,
    This is my code. The function send_buff is called two times in succession with the same parameters except that the
    NRF_UARTE1->TXD.PTR is different.

    int send_buff(unsigned int size, unsigned int data_address, unsigned int wait_response)
    {
        NRF_LOG_INFO("Data xfer start\n");
        tx_data_rdy = 0;
        NRF_UARTE1->TXD.PTR = data_address;
        NRF_LOG_INFO("TXDP 0x%X\n",NRF_UARTE1->TXD.PTR);
        NRF_UARTE1->RXD.PTR = (unsigned int)&uart_rx;
        NRF_UARTE1->TXD.MAXCNT = size;
        //NRF_UARTE1->RXD.MAXCNT = 12;
        NRF_UARTE1->RXD.MAXCNT = sizeof(uart_rx); //this size is 100 bytes
        NRF_UARTE1->TASKS_STARTTX = 1;
        NRF_UARTE1->TASKS_STARTRX = 1;
        while(0 == tx_data_rdy); //this is updated in an IRQ handler
        tx_data_rdy = 0;
        NRF_LOG_INFO("Data xfered\n");
        
        if(wait_response == 1) //this parameter is always 1
            timer3_timeout_poll_sec(2,SEC_PRE); //wait for 2 seconds
        
        
        //uart TX buffer is transferred. The 2 seconds timeout is expired - let's check what we have on the RX side
        if(NRF_UARTE1->RXD.AMOUNT == NRF_UARTE1->RXD.MAXCNT)
        {
            NRF_LOG_INFO("RX BUFFER FULL\n");
            NRF_LOG_INFO("ENDRX STATUS 0x%X\n",NRF_UARTE1->EVENTS_ENDRX);
        }
        
        unsigned int err = NRF_UARTE1->ERRORSRC;
        NRF_LOG_INFO("ERRSRC 0x%X\n",err);
        NRF_UARTE1->ERRORSRC = err;
        
        
        NRF_UARTE1->TASKS_STOPRX = 1;
        NRF_LOG_INFO("WAIT ENDRX\n");
        while(!NRF_UARTE1->EVENTS_ENDRX); //stoprx generates endrx
        NRF_UARTE1->EVENTS_ENDRX = 0;
        NRF_LOG_INFO("WAIT RXTO\n");
        while(!NRF_UARTE1->EVENTS_RXTO);
        NRF_UARTE1->EVENTS_RXTO = 0;        
        unsigned int rx_am = NRF_UARTE1->RXD.AMOUNT;
        NRF_LOG_INFO("BytesReceived %u\n",rx_am);
        uart_rx[rx_am] = '\0';
        uart_rx[(sizeof(uart_rx))-1] = '\0';
        clear_non_printable(sizeof(uart_rx),uart_rx);
        NRF_LOG_INFO("%s",uart_rx);        
        
        return 1;    
    }

    And this is the output.

    <info> app: Data xfer start

    <info> app: TXDP 0x2001000A

    <info> app: Data xfered

    <info> app: ERRSRC 0x0

    <info> app: WAIT ENDRX

    <info> app: WAIT RXTO

    <info> app: BytesReceived 0

    <info> app:
    //Everything is OK when zero bytes are returned.



    <info> app: Data xfer start

    <info> app: TXDP 0x20018CAA

    <info> app: Data xfered

    <info> app: RX BUFFER FULL

    <info> app: ENDRX STATUS 0x0

    <info> app: ERRSRC 0x5

    <info> app: WAIT ENDRX

    So i am waiting for the ENDRX forever. Also ENDRX is not generated when NRF_UARTE1->RXD.AMOUNT == NRF_UARTE1->RXD.MAXCNT.
    According to the datasheet it should be generated when
    "The size of the RX buffer is specified in the RXD.MAXCNT register and the UARTE will
    generate an ENDRX event when it has filled up the RX buffer"
    Of course i can jump over the ENDRX check and go to the RXTO check directly.
    But why it is not generated when NRF_UARTE1->RXD.AMOUNT == NRF_UARTE1->RXD.MAXCNT?

    I am using the same function quite a lot but the difference is that after the 2 seconds timeout NRF_UARTE1->RXD.AMOUNT is always lower than NRF_UARTE1->RXD.MAXCNT and the ERRORSRC is always 0. The ENDRX after TASKS_STOPRX in this case is generated always.

  • You should only check the RXD.AMOUNT register after the ENDRX event is received:

    The RXD.AMOUNT register can be queried following an ENDRX event to see how many new bytes have been transferred to the RX buffer in RAM since the previous ENDRX event.

    I'm not sure why the ENDRX event is not generated in the second case, could it be related to the errors reported? Have you seen it in cases without any errors reported?

  • Then I would recommend that you check why you are getting overrun and framing errors, and fix these. You can wait for EVENTS_ENDRX or EVENTS_ERROR in your application to catch and handle the errors in runtime.

Related