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.

RTOS/CC2640R2F: UART_read timeout in callback mode

Part Number: CC2640R2F

Tool/software: TI-RTOS

Hi TI,

I am working with the CC2640R2FRGZR 7x7, I need to send an UART message on an external slave controller and receive an answer from the slave MCU if it is active.

I have the following requirements:

- The read size may vary from 4 to 255 byte and I do not know the size when I call the UART_read() so I need to call it every time with the possible maximum size like this:

UART_read(uartHandle, rxBuf_raw, Maximum_msg_size);

- It may also happen that the slave controller is in sleep mode when I send the message so it will not answer. In this case I need to stop reading on a timeout.

- We use asynchronous UART communication without handshaking or flow control.

- The whole UART communication part is linked as a library in a simple peripheral project, so I need to use UART_MODE_CALLBACK in order not to block the main application.

 

I have represented in the figure below what I would like to have.


The problem is:

“An unfinished asynchronous read operation must always be cancelled using UART_readCancel() before calling UART_close()“.

But I don’t know when I need to call the UART_readCancel() as I don’t know the size of the message that I need to receive.

My UART settings:

UART_init();

/* Create a UART with data processing off. */

UART_Params_init(&uartParams);

uartParams.writeDataMode = UART_DATA_BINARY;

uartParams.readDataMode   = UART_DATA_BINARY;

uartParams.readReturnMode = UART_RETURN_FULL;

uartParams.dataLength     = UART_LEN_8;

uartParams.stopBits       = UART_STOP_ONE;

uartParams.parityType     = UART_PAR_NONE;

uartParams.baudRate       = Baud_rate;

 

/* Configure write callback */

uartParams.writeMode     = UART_MODE_CALLBACK;

uartParams.writeCallback = UART_WriteCB;

 

/* Configure read callback */

uartParams.readMode       = UART_MODE_CALLBACK;

uartParams.readCallback   = UART_ReadCB;

These are the suggestions from TI:

Regarding the UART case it appears that the customer would greatly benefit from enforcing a frame format like this: | Start byte | LEN | PAYLOAD | 

Without a known frame format they would either need to implement an application level solution where they run a clock between the uartRxCBs and call readCancel() if they have received nothing in > 3ms. If they implement a frame format they can do something like Read 2 bytes (START, LEN) and based on LEN read the rest of payload.

We do use such a frame format so the idea of reading the start byte and the LEN is possible but it raises the following questions:

  • I still need a clock for the case when no data is received, to call UART_readCancel() because: "Timeouts are not supported in CALLBACK mode" so I need to make my own timeout somehow. Do I understand it correctly?
  • When the UART_read( first 2 bytes START & LEN ) is ready and I call a new UART_read( Remaining bytes based on the LEN ) how can I assure that no data will be lost between the two UART_read() calls. Does the UART module continue to receive in its buffer and UART_read() is only to read out this buffer, or when the new UART_read() is not called early enough (in the Inter Byte Time) the receive is stopped and these bytes could be lost. See the Non ideal case in the figure below.

  • I do not really understand the use and purpose from UART_readPolling() could it be helpful in my case?

Thank you in advance,

Örs

  • Hi Örs,

    First thing first, I appreciate the detailed explanation of you problem and the clear questions, +1 point!

    Regarding your actual questions:

    I still need a clock for the case when no data is received, to call UART_readCancel() because: "Timeouts are not supported in CALLBACK mode" so I need to make my own timeout somehow. 


    You are correct, you would have to implement the timeout yourself to do this. Easiest way to do this is to use the TI-RTOS Clock module and set up a single-shot timer. You could also use the GPTimer but in this case I think Clock is the better alternative.

    When the UART_read( first 2 bytes START & LEN ) is ready and I call a new UART_read( Remaining bytes based on the LEN ) how can I assure that no data will be lost between the two UART_read() calls. Does the UART module continue to receive in its buffer and UART_read() is only to read out this buffer, or when the new UART_read() is not called early enough (in the Inter Byte Time) the receive is stopped and these bytes could be lost. See the Non ideal case in the figure below.


    After the first UART_read the UART will keep RX enabled in between API calls. There is a internal ring buffer to store the received data that arrives in between calls to UART_read so you should not lose any bytes in the "Non ideal case". The size of the ring buffer is configurable inside the device board file.

  • Thank you for the quick reply and the appreciation. I consider that this resolves my issue, could you also answer my last question please regarding the UART_readPolling()?

    Best regards,
    Örs
  • UART_readPolling() is not supported functionality. Refer to "C:/ti/simplelink_cc2640r2_sdk_1_50_00_58/docs/tidrivers/doxygen/html/_u_a_r_t_c_c26_x_x_8h.html"

    -kel