I have a project built with freertos integrated on the MIMXRT1015 platform. I'm using LPUART3 to read serial messages that are of unpredictable length (SLIP format, so there are END characters to define messages).
The only Read function in the RTOS LPUART driver is LPUART_RTOS_Receive(). Because I do not know my message length in advance, I can't call it for more than one byte at a time. I have a thread set up to do nothing but call this function and put anything it gets into a buffer so that I can scan that buffer for messages.
Calling function:
size_t tempReadCount = 0;
std::uint8_t tempByte = 0;
if (raw_rx_count < MAX_BUFFER_SIZE)
{
int readStatus = LPUART_RTOS_Receive(&LPUART3_rtos_handle, &tempByte, 1 , &tempReadCount);
if ((readStatus == kStatus_Success) && (tempReadCount == 1))
{
raw_rx_buffer[raw_rx_count++] = tempByte;
}
}
Unfortunately, it does not work correctly. If I call LPUART_RTOS_Receive() and request 50 bytes, then send in enough messages to fill that request I get all of the messages returned correctly as soon as all 50 bytes are read. If I call it and request 1 byte repeatedly, quite a few bytes are skipped, apparently always in the same pattern.
It looks like the unblocking read used at lower level in the driver may be only enabling the interrupt when the read function is called. So, maybe the transition from enabled to disabled each time may be trashing some bytes. That or there is a buffer issue with small requests.
Anyone else seen this issue with the LPUART driver? Any work around besides making my own driver?
This project is proprietary, I would need to remove a lot to be able to share it. The general design though is the above function called in an infinite loop inside a RTOSthread.
From what I can tell, the LPUART fifo is set to 4 and there is no watermark set up in our MIMXRT1015_features.h for LPUART. As a result, when I am not waiting for a LPUART_RTOS_Receive() to complete the fifo fills up as a message is sent in, then overflows since there is no interrupt triggered to read from the fifo to the ring buffer until LPUART_RTOS_Receive() gets called. I am trying to work out if there is hardware support for the watermark, since if that would keep filling the ring buffer in between my 1 byte calls to LPUART_RTOS_Receive then I think I would eventually get the whole message.
That or I need to rewrite the driver to keep the interrupt enabled constantly, and just fill a buffer as soon as a new byte is available.
Is there a different approach I could use on the fsl_lpuart.h driver layer? If so I could write my own RTOS layer replacement.
Hi Andre Jo,
Thank you for your interest in NXP Semiconductor products and
for the opportunity to serve you.
Before answering your question, I was wondering if you can share the demo project and testing procedure, as I'd like to replicate the issue on my site and it can help me to work it out.
Looking forward to your reply.
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
I just noticed this in the driver file fsl_lpuart.c:
/*!
* brief Gets the default configuration structure.
*
* This function initializes the LPUART configuration structure to a default value. The default
* values are:
* lpuartConfig->baudRate_Bps = 115200U;
* lpuartConfig->parityMode = kLPUART_ParityDisabled;
* lpuartConfig->dataBitsCount = kLPUART_EightDataBits;
* lpuartConfig->isMsb = false;
* lpuartConfig->stopBitCount = kLPUART_OneStopBit;
* lpuartConfig->txFifoWatermark = 0;
* lpuartConfig->rxFifoWatermark = 1;
* lpuartConfig->rxIdleType = kLPUART_IdleTypeStartBit;
* lpuartConfig->rxIdleConfig = kLPUART_IdleCharacter1;
* lpuartConfig->enableTx = false;
* lpuartConfig->enableRx = false;
*
* param config Pointer to a configuration structure.
*/
void LPUART_GetDefaultConfig(lpuart_config_t *config)
{
assert(NULL != config);
/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));
config->baudRate_Bps = 115200U;
config->parityMode = kLPUART_ParityDisabled;
config->dataBitsCount = kLPUART_EightDataBits;
config->isMsb = false;
#if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
config->stopBitCount = kLPUART_OneStopBit;
#endif
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
config->txFifoWatermark = 0;
config->rxFifoWatermark = 0;
#endif
#if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
config->enableRxRTS = false;
config->enableTxCTS = false;
config->txCtsConfig = kLPUART_CtsSampleAtStart;
config->txCtsSource = kLPUART_CtsSourcePin;
#endif
config->rxIdleType = kLPUART_IdleTypeStartBit;
config->rxIdleConfig = kLPUART_IdleCharacter1;
config->enableTx = false;
config->enableRx = false;
}
Is there a reason for this or is it a bug?
Hi Andre Jo,
Thanks for your reply.
1) Is there a reason for this or is it a bug?
-- Firstly, I don't think there's any bug in the above code, secondly, I adapted the evkbimxrt1050_freertos_lpuart demo as below shows.
And the LPUART_RTOS_Receive can receive one byte when requesting one byte.
const char *to_send = "FreeRTOS LPUART driver example!\r\n";
const char *send_ring_overrun = "\r\nRing buffer overrun!\r\n";
const char *send_hardware_overrun = "\r\nHardware buffer overrun!\r\n";
uint8_t background_buffer[32];
//uint8_t recv_buffer[4];
uint8_t recv_buffer_new[1];
/* Receive user input and send it back to terminal. */
do
{
error = LPUART_RTOS_Receive(&handle, recv_buffer_new, sizeof(recv_buffer_new), &n);
if (error == kStatus_LPUART_RxHardwareOverrun)
{
/* Notify about hardware buffer overrun */
if (kStatus_Success !=
LPUART_RTOS_Send(&handle, (uint8_t *)send_hardware_overrun, strlen(send_hardware_overrun)))
{
vTaskSuspend(NULL);
}
}
if (error == kStatus_LPUART_RxRingBufferOverrun)
{
/* Notify about ring buffer overrun */
if (kStatus_Success != LPUART_RTOS_Send(&handle, (uint8_t *)send_ring_overrun, strlen(send_ring_overrun)))
{
vTaskSuspend(NULL);
}
}
if (n > 0)
{
/* send back the received data */
if (kStatus_Success != LPUART_RTOS_Send(&handle, (uint8_t *)recv_buffer_new, n))
{
vTaskSuspend(NULL);
}
}
} while (kStatus_Success == error);
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------