Based on FRDM-K64 example I use UART and CANBUS in Transfer mode. In this examples (respectively frdmk64f_uart_interrupt_transfer and frdmk64f_flexcan_loopback_transfer), however, in callback only a few status
are managed, tipically TxIdle and RxIdle, while the actual states are many more. Sometimes the callback return other status, like RxOverrun/TxOverrun or Error and it gets stuck in these states.
How should these states be managed and / or how can I prevent these situations?
Are there more in-depth examples for both the UART and the CANBUS?
Thank you in advance!
I should have solved it!
It seems that error was due to baudrate that is too high (I had set it to 921600
even if in the UARTInit function documentation it set baudrate to 20000000).
Reducing it I stopped having serial locking problems in the busy state most likely due to errors in communication.
Having said that, what is the maximum baudrate that can be set for the serial port? Does it depend on the source clock?
Thank you very much!
The max baud rate varies by device, but can be calculated using the following formula.
UART Max Baud Rate = (UART Module Clock Frequency) / 16
Please take into consideration that UART0 and UART1 modules operate from the core/system clock, which provides higher performance level for these modules. All other UART modules operate from the bus clock.
I noticed now reading the documentation and seeing the examples that function UART_TransferReceiveNonBlocking is used in combination with ring buffer while I have the ring buffer disabled.
This may be the problem, or the function UART_TransferReceiveNonBlocking can we used without ring buffer?
What is the advantage of the ring buffer compared to the internal FIFO?
Can I use them together?
Thank you in advance.
In case of overrun you should use kUART_RxOverrunFlag when using UART_ClearStatusFlags. Please check the below explanaition from fsl_uart.c driver.
- If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize to uart handle, enable interrupt to store received data to xfer->data. When all data received, trigger callback.
- If RX ring buffer is enabled and not empty, get data from ring buffer first.
If there are enough data in ring buffer, copy them to xfer->data and return.
If there are not enough data in ring buffer, copy all of them to xfer->data, save the xfer->data remained empty space to uart handle, receive data to this empty space and trigger callback when finished.
Hope it helps!
I saw the function UART_ClearStatusFlags.
Reading the comments it expects a bit mask with the following values:
kUART_TxDataRegEmptyFlag, kUART_TransmissionCompleteFlag, kUART_RxDataRegFullFlag,
kUART_RxActiveFlag, kUART_NoiseErrorInRxDataRegFlag, kUART_ParityErrorInRxDataRegFlag,
Which flag should i reset? All?
In the example the callback it's the following:
yes, I'm referring to UART/FlexCAN callback.
Specifically regarding UART, in the example on callback, only kStatus_UART_TxIdle and kStatus_UART_RxIdle state are managed, but other states? For example if callback return kStatus_UART_RxHardwareOverrun that typically I find,
what I have to do? You showed me the S1 register but is this not managed internally by fs_uart library?
Are there high-level functions to manage these conditions?
For FlexCAN, for example, that has a similar interface before calling FLEXCAN_TransferSendNonBlocking or FLEXCAN_TransferReceiveNonBlocking,
I call respectively FLEXCAN_TransferAbortSend and FLEXCAN_TransferAbortReceive which should cancel any previous sending / receiving in progress,
but I don't think it's the best solution.
Thank you very much
According to the reference manual when receive a hardware overrun status, software should do the following.
1. Remove data from the receive data buffer. This could be done by reading data from the data buffer and processing it if the data in the FIFO was still valuable when the overrun event occurred, or using CFIFO[RXFLUSH] to clear the buffer.
2. Clear S1[OR]. Note that if data was cleared using CFIFO[RXFLUSH], then clearing S1[OR] will result in SFIFO[RXUF] asserting. This is because the only way to clear S1[OR] requires reading additional information from the FIFO. Care should be taken to disable the SFIFO[RXUF] interrupt prior to clearing the OR flag and then clearing SFIFO[RXUF] after the OR flag has been cleared.
To do this I recommend you to call UART_ClearStatusFlags function that will clear the flags and flush all data in FIFO.
I hope this helps.
Are you referring to the UART callback? An overrun indicates that received data has been lost because there was a lack of room to store it in the data buffer. Therefore, while S1[OR] is set, no further data is stored in the data buffer until S1[OR] is cleared.
I recommend you to check chapter 52.8.4 of the reference manual for more in depth information about this issue.
Also take a look at the open source uTasker project which contains proven parallel operation of I2C, UART and FlexCAN:
as well as simulation of the peripherals for simpler debugging and project development.
The supported developer's version give addition features like integrated CANopen for professional needs.
[uTasker project developer for Kinetis and i.MX RT]