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.

CC3220SF: UART Callback in UARTCC32XX ISR safe

Part Number: CC3220SF

Hello,

is the data accessed through the rxcallback ISR safe. In my understanding the callback can either be called from the isr or from mainline if function UARTCC32XX_readCancel() is used. So if i am using uart readcancel do i have to secure the access to data provided by the callback from new ISR-call ? Or if i am save because next isr call is unlocked by UARTCC32XX_read() ?

I am using the following params for uart:

uartParams.readMode = UART_MODE_CALLBACK;
uartParams.readCallback = &readCallback;
uartParams.readDataMode = UART_DATA_BINARY;
uartParams.readReturnMode = UART_RETURN_FULL;
uartParams.readEcho = UART_ECHO_OFF;
uartParams.writeDataMode = UART_DATA_BINARY;
uartParams.writeMode = UART_MODE_CALLBACK;
uartParams.writeCallback = writeCallback;
uartParams.baudRate = UART_BAUDRATE;

Best regards,

  • Hi Arnaud,

    I'm not sure what you mean by ISR safe. If you cancel during a transfer then you will still get the number of bytes sent or received in the callback function. The buffer you pass read will get overwritten next time you call it unless you decide to use a different one.

    Jesu

  • Hi,

    my thought was if the data in the callback could be corrupted by an isr call becuase it is updating the data while i am reading it. But ok my understanding of the handling is for every receive the UART ISR has to be enabled through UART_read()-Call and if i am cancelling the read with UART_readCancel() the isr will be enabled till next time i call UART_read. But what is happening if full size of data has been received number of bytes expected 8. And no UARt_readCancel() is going on . Is then the callback executed from ISR because buffer is full and we got what we expected ?

    My setup is the following: From my task i call periodically ( every 2 ms) these two functions:

    UART_readCancel(uart);/* Cancel pendig requests */
    UART_read(uart, rxBuffer, 8);

    And in the readCallback i do the following things:

    /**
    *****************************************************************************
    * @brief readCallback for UART.
    *****************************************************************************
    */
    static void readCallback( UART_Handle handle, void *rxBuf, size_t size )
    {
    char *cChar;
    size_t i;
    cChar = (char*)rxBuf;
    if( size <= BYTES_TO_READ )
    {
    for( i = 0; i < size; i++ )
    {
    UART_generateRxEvent( *cChar );
    cChar++;
    }
    }
    }

    So my question is will the callback be exceuted only from taskcontext or also from isr. If it is only from taskcontext i have to be sure that isr is disabled while processing data.

    My thought is if i can check the callsource and secure my handling checking:

    static void readCallback( UART_Handle handle, void *rxBuf, size_t size )

    {

    UARTCC32XX_Object         *object = handle->object;

    if(object->state.drainByISR)

    {

    }

    }

    So the processing isn't interruptable anymore or is my thought false ?

  • Hi Arnaud,

    my thought was if the data in the callback could be corrupted by an isr call becuase it is updating the data while i am reading it

    The UART drivers load the data to your buffer from the internal FIFO buffer and once your buffer is full the user callback is invoked from ISR context. 

    But what is happening if full size of data has been received number of bytes expected 8. And no UARt_readCancel() is going on .

    If you cancel, the callback will be invoked to send the user data that has already been received. I believe the callback is always invoked from UART even if you call ISR. This is a quick test from checking ROV in CCS if you want to verify. 

    If you are concerned about checking call source you can maybe set a flag in your application when you call cancel. There is no way to check from callback if it was invoked from cancel or if receive is complete. Maybe if you received everything you expect in the callback you can assume receive is complete whereas if you receive less than expected bytes you can assume it was a cancel call.

    Jesu

  • Thank you very much Jesu.

    The UART drivers load the data to your buffer from the internal FIFO buffer and once your buffer is full the user callback is invoked from ISR context.

    Ok so i have to ensure that the source of the callback is isr or task. So i have to disable isr because i am working on the buffer.

    UARTCC32XX.c

    *
    * ======== readIsrBinaryCallback ========
    */
    static bool readIsrBinaryCallback(UART_Handle handle)
    {
    UARTCC32XX_Object *object = handle->object;
    UARTCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
    int readIn;
    bool ret = true;

    while (MAP_UARTCharsAvail(hwAttrs->baseAddr)) {
    if (RingBuf_isFull(&object->ringBuffer)) {
    ret = false;
    break;
    }

    readIn = MAP_UARTCharGetNonBlocking(hwAttrs->baseAddr);
    if (readIn > 0xFF) {
    if (hwAttrs->errorFxn) {
    hwAttrs->errorFxn(handle, (uint32_t)((readIn >> 8) & 0xF));
    }
    MAP_UARTRxErrorClear(hwAttrs->baseAddr);
    ret = false;
    break;
    }

    RingBuf_put(&object->ringBuffer, (unsigned char)readIn);
    }

    /*
    * Check and see if a UART_read in callback mode told use to continue
    * servicing the user buffer...
    */
    if (object->state.drainByISR) {
    readTaskCallback(handle);
    }

    return (ret);
    }
    So i am thinking i will be call from isr with object->state.drainByISR == TRUE

    So in my application i check this flag in callback and disable isr if FALSE == object->state.drainByISR so that my buffer won't be corrupted.

    static void readCallback( UART_Handle handle, void *rxBuf, size_t size )
    {
    bool b_EnableIsr = FALSE;
    char *cChar;
    size_t i;
    cChar = (char*)rxBuf;
    uintptr_t uip_Key;
    UARTCC32XX_Object *object = handle->object;
    if( FALSE == object->state.drainByISR )
    {
    b_EnableIsr = TRUE;
    uip_Key = HwiP_disable();
    u32_ThreadCalls++;
    }
    else
    {
    u32_ISRCalls++;
    }
    if( size <= BYTES_TO_READ )
    {
    for( i = 0; i < size; i++ )
    {
    UART_generateRxEvent( *cChar );
    cChar++;
    }
    }

    if( TRUE == b_EnableIsr )
    {
    HwiP_restore( uip_Key );
    }
    }

    Is this interpretation correct ?

  • Hi Arnaud,

    Based on your current UART configuration, readIsrBinaryCallback and readTaskCallback is being used. Your user callback is always going to be invoked from readTaskCallback. However you are correct, if drainByISR == TRUE then it should be okay to assume readIsrBinaryCallback called but I cannot say for certain as I'm not 100% sure. If you're goal is to disable the ISR changing this flag will not work anyway because readIsrBinaryCallback is called from a HW interrupt context. You would have to disable HW interrupts entirely which is not recommended. 

    Why are you concerned that the buffer will be corrupted? Are you making modifications to the drivers? I can't tell if you are making modifications to the UART drivers but if you are I do not suggest it. If you help me understand what you are trying to accomplish maybe I can provide better guidance.

    Jesu

  • My worry was that through a callback thrown by task context and another callback thrown  by isr the buffer will be corrupted. Assume task callback will be happen and is starting to copy data from buffer. Now isr callback will happen and interrupt task callback. They are both using the same buffer which is given to them by Uart_read(). So maybe there could buffer data be corrupted. But i dived a little bit deeper in the implementation and saw that isr is using an ringbuffer for buffering symbols received by uart. I also saw that there are many flags to prevent interrupt of data handling. I assume this mechanism will ensure data processing once started won't be corrupted rather symbols will get lost if ringbuffer from isr is full.

    And no we aren't modifiying the driver.

    So i think my worry would not happen or what are do you thinking ?

  • Hi Arnaud,

    What you are saying make sense. Especially the comment about the ring buffer. What I can tell you is that the team that developed this UART peripheral has been maintaining it for many years and continues to do so. Anytime a UART issue is reported to us, we try our best to reproduce it and if so, we report it to the relevant owners and work with them to solve the issue. Part of the reason why we are on a quarterly release schedule is to release the latest bug fixes that we have learned through E2E or any other support channels. With that said, I'm not 100% familiar with the intricacies of our UART driver to tell you for certain you do not have to worry. What I can tell you is that we guarantee the performance and reliability of its function and any problems that you may discover in the future we will work with our customers to ensure they are solved as soon as possible. 

    I hope this provides you with some level of confidence and eases you worries. 

    Jesu