USART_ReadBlocking()

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

USART_ReadBlocking()

2,448件の閲覧回数
Nadia
Contributor III

Hi all, I am having a problem with the USART_ReadBlocking() instruction. In this function, the last parameter is the amount of data to be read, in my case it is 3. The instruction is inside an interrupt, and every time it is enabled it enters and reads what is in the port. The problem is that sometimes these data arrive incomplete, and instead of 3 I get 2 or 1, and this instruction is blocked.

Does anyone know what I can do so that this does not happen?

 

0 件の賞賛
返信
5 返答(返信)

2,443件の閲覧回数
frank_m
Senior Contributor III

> Does anyone know what I can do so that this does not happen?

Relatively simple - organize your code in a different way, and do not use blocking functions for asynchronous transmissions.

UART communications is inherently unsafe, i.e. characters can get lost or corrupted. Relying on a fixed sequence and stable timing will throw off you application quickly, and it will never recover until a reset.

A better method is to use single character reception (or more than one character in case of a FIFO).

And, use a protocol with at least a designated end character (like e.g. '\n'), or designated start and end characters. An example would be the NMEA-183 output of GPS receivers, where sentences always starts with '$', and always ends with '\r\n'.

The interrupt handler receives individual characters and stores them, and passes them on to the main loop once an end character is received.

Additionally, your handler would need to check for receive buffer overflows, and "stray" start characters. And you would need to make a copy of the bufferfor the main loop, else follow-up transmissions overwrite your data.

0 件の賞賛
返信

2,439件の閲覧回数
Nadia
Contributor III

I have tried to read byte by by byte, and I get stuck in the usart driver module. In the following line:

while ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) == 0U)

0 件の賞賛
返信

2,435件の閲覧回数
frank_m
Senior Contributor III

> while ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) == 0U)

Looping on the RXNOTEMPTY flag is exactly the problem. This is a blocking read.

You cannot solve tasks relating to asynchronous events (like serial communication) with strictly sequential methods. Multitasking / multiprocessing would be another example of such concurrency. Like e.g. this POSIX thread tutorial: https://randu.org/tutorials/threads/

In your case, the serial interrupt behaves like a separate thread, controlled by the external device via UART.

0 件の賞賛
返信

2,438件の閲覧回数
Nadia
Contributor III

@frank_m 

I have tried to read byte by by byte, and I get stuck in the usart driver module. In the following line:

while ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) == 0U)

0 件の賞賛
返信

2,421件の閲覧回数
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Nadia,

As Frank said it was correct behavior of MCU which stuck in the while() line in polling mode.

As you know there are three methods to transfer data: polling mode, interrupt mode and DMA mode, the while ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) == 0U) belongs to polling mode, it continues to poll if the USART_FIFOSTAT_RXNOTEMPTY_MASK bit in base->FIFOSTAT is set, it does nothing else, that is why is it is calling USART_ReadBlocking.

I suggest you use interrupt mode, when the USART receives a character, the USART_FIFOSTAT_RXNOTEMPTY_MASK bit in base->FIFOSTAT register is set immediately, the event can trigger an interrupt, then the MCU will stop the current task and enter the ISR of the USART and execute the ISR. In the ISR, you can read the character from receiver. You can call the

hal_uart_status_t HAL_UartTransferReceiveNonBlocking(hal_uart_handle_t handle, hal_uart_transfer_t *transfer)
{
hal_uart_state_t *uartHandle;
status_t status;
assert(handle);
assert(transfer);
assert(HAL_UART_TRANSFER_MODE);

uartHandle = (hal_uart_state_t *)handle;

status = USART_TransferReceiveNonBlocking(s_UsartAdapterBase[uartHandle->instance], &uartHandle->hardwareHandle,
(usart_transfer_t *)transfer, NULL);

return HAL_UartGetStatus(status);
}

Hope it can help you

BR

XiangJun Rong

0 件の賞賛
返信