This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC1312R7: Callback in UART2 Callbackmode not containing all bytes

Part Number: CC1312R7


When modifying the uart2callback example to receive more than one char I don't always get a callback even if there is data received in the UART buffer.

I get a callback when the first data is received, but when I call UART2_read again I don't get any callback for the remaining data.

When is the callback called?

  • Without knowing what exact changes you have done to the example, it is hard to explain what you are seeing.

    I took the example and changed 

    status = UART2_read(uart, &input, 1, NULL);

    to

    status = UART2_read(uart, &input, 3, NULL);

    The behavior of the application did not change, and I still got 1 callback from every byte I typed in my terminal program.

    This is as expected, since by default 

    uartParams.readReturnMode =  UART2_ReadReturnMode_PARTIAL; // callback when no new data comes in

    setting

    uartParams.readReturnMode = UART2_ReadReturnMode_FULL;

    will cause 3 bytes to have to be input before the callback is generated.

    BR

    Siri

  • I run with uartParams.readReturnMode =  UART2_ReadReturnMode_PARTIAL.

    When doing the read of 3 bytes and sending in 4 bytes I would expect a new callback when doing a second UART2_read since there is data already received. Instead I don't get that data until something new is received and generates a new callback.

  • I did the following test and I think I see the issues you describe:

    UART2_Params_init(&uartParams);
    uartParams.readMode       = UART2_Mode_CALLBACK;
    uartParams.readCallback   = callbackFxn;
    uartParams.baudRate       = 115200;
    uartParams.readReturnMode =  UART2_ReadReturnMode_PARTIAL;
    
    UART2_open(CONFIG_UART2_0, &uartParams);
    
    while (1)
    {
        numBytesRead = 0;
    
        UART2_read(uart, &input, 3, NULL);
        sem_wait(&sem);
    
        if (numBytesRead > 0)
        {
            UART2_write(uart, &input, numBytesRead, NULL);
        }
    }
    
    void callbackFxn(UART2_Handle handle, void *buffer, size_t count, void *userArg, int_fast16_t status)
    {
        if (status != UART2_STATUS_SUCCESS)
        {
            /* RX error occured in UART2_read() */
            while (1) {}
        }
    
        numBytesRead = count;
        interrupts++;
        sem_post(&sem);
    }
    

    Assume I run the code and set a breakpoint after waiting for the semaphore.

    If I enter one single Character ‘A’ I will get a callback, since readReturnMode =  UART2_ReadReturnMode_PARTIAL.

    The ‘A’ is stored in input, and then printed back.

    If I then Input a second char ‘B’ BEFORE UART2_read is called the second time, the ‘B’ is stored in input, but no new callback is generated.

    This is not happening before a third char ‘C’ is input. 

    I asked R&D about this and got the following feedback:

    "This is a very peculiar edge-case, and is expected with respect to how the code is currently written. The condition for returning from UART2_read in PARTIAL mode is either

    a) All requested bytes are available, or

    b) Some of the bytes were received, and then a timeout occurred.

    However, the driver only checks for these conditions *after* the call to UART2_read, meaning that the timeout that occurred in the past has no effect.

    The driver reads what it can from the internal ringbuffer (the char ‘B’) and then starts waiting for the return-condition to become true.

    There are several ways to get around this

    • Read 1 byte a time (if a byte has been read into the ringbuffer, the function will return / invoke the callback)
    • Cancel the read-operation (the callback will then be called with the ‘B’ in the input buffer)

     The first approach is how the example is written originally.

    I tested approach two and called UART2_readCancel when a button was pushed.

    If I did this in my test case above, AFTER the B was received in the ringbuffer, i got the callback and the B was printed.

    For this "solution" you need to modify the callback to check for UART2_STATUS_ECANCELLED in addition to UART2_STATUS_SUCCESS

    BR

    Siri

  • This is the issue that I see.

    In the implementation I am doing the UART is used to communicate with a modem and this "edge-case" occures all the time.
    Reading one byte at a time would limit the throughput a lot with the very big overhead with one callback/byte.
    Canceling the read-operation would be more of a polling of the UART and I don't see the gain of using UART2_Mode_CALLBACK instead of UART2_Mode_BLOCKING.

    Do you have any suggestion of how the reading of an unknown amount of data should be done in a non-blocking way?

    BR,

    Håkan

  • Hi Håkan

    I am afraid I do not see any other solutions than what I already posted, if you are using our driver. 

    BR

    Siri