How to receive a varying amount of data on a UART?

cancel
Showing results for 
Search instead for 
Did you mean: 

How to receive a varying amount of data on a UART?

1,181 Views
razed11
Contributor V

I seem to be stymied at every turn with the SDK 2.4.2. If one has a binary protocol with a fixed header size one can wait for the header, look for a packet length, then setup the UART to read the remaining amount. But I'm receiving a varying amount of ASCII data terminated with a carriage return. The EDMA driver fails to do this. Now I'm trying the ring buffer.

There is this from the header file:

* When the RX ring buffer is used, data received are stored into the ring buffer even when the
* user doesn't call the UART_TransferReceiveNonBlocking() API. If data is already received
* in the ring buffer, the user can get the received data from the ring buffer directly.

From the ring buffer directly? How do I know where in the ring to start pulling data? This can't be right. The implementation details are not exposed (and shouldn't be).

The comments for UART_TransferReceiveNonBlocking() include this:

* If the RX ring buffer is used and not empty, the data in the ring buffer is copied and
* the parameter @p receivedBytes shows how many bytes are copied from the ring buffer.
* After copying, if the data in the ring buffer is not enough to read, the receive
* request is saved by the UART driver. When the new data arrives, the receive request
* is serviced first. When all data is received, the UART driver notifies the upper layer
* through a callback function and passes the status parameter @ref kStatus_UART_RxIdle.
* For example, the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer.
* The 5 bytes are copied to the xfer->data and this function returns with the
* parameter @p receivedBytes set to 5. For the left 5 bytes, newly arrived data is
* saved from the xfer->data[5]. When 5 bytes are received, the UART driver notifies the upper layer.

Again, I'm being forced to know the number of expected bytes and I don't know why anyone would want to use the callback in this fashion. If you already know the number of bytes why not just wait on the callback in the first place?

I don't understand why there isn't an API to access that ring buffer. I don't think the callback is needed at all.

What is a technique to read until a carriage return is detected? I just want to read what is available and look for that character.

It's 2018. Blade Runner and Soylent Green will both happen in the next few years yet we continue to write firmware like it's 1990. We deserve a punch in the face by a replicant. There. I said it. Now I'm off to my tiny house in the woods.

2 Replies

767 Views
razed11
Contributor V

I hacked UART_TransferReceiveNonBlocking() to just use the ring buffer. It doesn't pass the request to the UART driver nor does it call the callback.

// KK: No. Let the ring buffer continue to collect data.
#if 0

/* If ring buffer does not have enough data, still need to read more data. */
if (bytesToReceive)
{
/* No data in ring buffer, save the request to UART handle. */
handle->rxData = xfer->data + bytesCurrentReceived;
handle->rxDataSize = bytesToReceive;
handle->rxDataSizeAll = bytesToReceive;
handle->rxState = kUART_RxBusy;
}
#endif

/* Enable UART RX IRQ if previously enabled. */
UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable);

#if 0
/* Call user callback since all data are received. */
if (0 == bytesToReceive)
{
if (handle->callback)
{
handle->callback(base, handle, kStatus_UART_RxIdle, handle->userData);
}
}
#endif
0 Kudos

767 Views
mjbcswitzerland
Specialist V

Hi Kenny

Compare with the uTasker UART interface (see some links below). It is free on GitHib and includes K64 simulation with (with UART, interrupt and DMA to allow testing complete project operation in real time in VisualStudio). It allows also DMA transmission and reception on all UARTs and LPUARTs (including DMA rx operation when the reception length is not known - i.e. free-running). It can also be used with FreeRTOS and adds that which is missing in the FreeRTOSs and NXP libraries for this Rx DMA compatibility.

Regards

Mark

Kinetis: http://www.utasker.com/kinetis.html
Kinetis K64:
- http://www.utasker.com/kinetis/FRDM-K64F.html
- http://www.utasker.com/kinetis/TWR-K64F120M.html
- http://www.utasker.com/kinetis/TEENSY_3.5.html
- http://www.utasker.com/kinetis/Hexiwear-K64F.html

--UART: http://www.utasker.com/docs/uTasker/uTaskerUART.PDF
--Modbus UART RTU/ASCII: http://www.utasker.com/docs/MODBUS/uTasker_MODBUS.PDF

0 Kudos