Hi,
I am using an imx RT1020 evk board, and just found out that it takes rather long to get an idle line interrupt.
I am using LPUART3 with DMA (in 9bits mode).
In the RM I read
So the peripheral waits for 1 full byte to be all 1s, including start and stop bit. But that would be a bit over 1ms. Right?
So why is the idle line interrupt only set after 2.3ms?
Is there a way to decrease this time?
Thx!
Solved! Go to Solution.
Hi @bp1979
Please accept my apologies for the very late reply, I did had some difficulties getting all the required hardware to catch you on the test.
That IDLE Line detection of 2.3ms , actually is okay, since represents the length of two UART characters.
Let me explain:
The UART is running at 9600 bauds, and works at 9 bits
A character is made by : 9 bits + stop bit(1) + stop bit(1) + parity bit(0) or 11 bits.
Thus, calculating the 1 full character time : (1/9600)*11 = 0.0011458333333333
So, if we have two UART characters we get = 0.0022916666666667. This is arround the 2.3 ms that you where reporting.
As you mention this is replicable using the SDK examples and it is not related to code overhead , as I initially thought as a possibility.
Regarding my tests : I made minor modifications on the evkmimxrt1020_lpuart_9bit_interrupt_transfer i.MX RT1021 SDK example .Below the most important ones.
void LPUART_TransferHandleIRQ(LPUART_Type *base, void *irqHandle)
{
...
if((uint32_t)kLPUART_IdleLineFlag & status)
{
/// detect idle line flag
GPIO1->DR_TOGGLE = (1UL << 30);
}
...
}
config.rxIdleType = kLPUART_IdleTypeStopBit;
config.rxIdleConfig = kLPUART_IdleCharacter1;
Then I proceeded to change rxIdleConfig to kLPUART_IdleCharacter1, kLPUART_IdleCharacter2 to set the idle line flag after one, two, and four characters.
See screenshot when we wait one full character length.
Now when wait for two full characters length, we get idle line detection about in around 2.3ms , since each character is arround 1.16 ms.
This wait time of a full character length can also be observed as well , if we change the baud rate to 115200 or different.
Please note that my hand-made measurements are not precise but they get close to the numbers we expect.
Many thanks for your patience.
Diego.
Hi @bp1979
Please accept my apologies for the very late reply, I did had some difficulties getting all the required hardware to catch you on the test.
That IDLE Line detection of 2.3ms , actually is okay, since represents the length of two UART characters.
Let me explain:
The UART is running at 9600 bauds, and works at 9 bits
A character is made by : 9 bits + stop bit(1) + stop bit(1) + parity bit(0) or 11 bits.
Thus, calculating the 1 full character time : (1/9600)*11 = 0.0011458333333333
So, if we have two UART characters we get = 0.0022916666666667. This is arround the 2.3 ms that you where reporting.
As you mention this is replicable using the SDK examples and it is not related to code overhead , as I initially thought as a possibility.
Regarding my tests : I made minor modifications on the evkmimxrt1020_lpuart_9bit_interrupt_transfer i.MX RT1021 SDK example .Below the most important ones.
void LPUART_TransferHandleIRQ(LPUART_Type *base, void *irqHandle)
{
...
if((uint32_t)kLPUART_IdleLineFlag & status)
{
/// detect idle line flag
GPIO1->DR_TOGGLE = (1UL << 30);
}
...
}
config.rxIdleType = kLPUART_IdleTypeStopBit;
config.rxIdleConfig = kLPUART_IdleCharacter1;
Then I proceeded to change rxIdleConfig to kLPUART_IdleCharacter1, kLPUART_IdleCharacter2 to set the idle line flag after one, two, and four characters.
See screenshot when we wait one full character length.
Now when wait for two full characters length, we get idle line detection about in around 2.3ms , since each character is arround 1.16 ms.
This wait time of a full character length can also be observed as well , if we change the baud rate to 115200 or different.
Please note that my hand-made measurements are not precise but they get close to the numbers we expect.
Many thanks for your patience.
Diego.
Dear @diego_charles
Wauw, this was:
- unexpected
- painfully easy to fix
- very refreshing!
Thanks a lot for your detailed explanation. I changed the number of idle line characters and it works like a charm of course.
Many many thanks!!
best regards, bas
Hi @bp1979
I hope that you are doing well!
The first things that come into my mind are consider : code overhead ; the speed of current clock provided to the UART peripheral ; and the desired baud rate . Are you taking as starting point any of our SDK demo examples? I want to get more context on the settings that you are performing .
All the best
Diego.
Code overhead is not the case. I am simply toggling a pin in the interrupt handler so that I can plot the entry of the interrupt handler in my logic analyzer.
void LPUART3_IRQHandler(void)
{
uint32_t status = LPUART_GetStatusFlags(LPUART3);
uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(LPUART3);
if ((0U != ((uint32_t)kLPUART_IdleLineFlag & status)) &&
(0U != ((uint32_t)kLPUART_IdleLineInterruptEnable & enabledInterrupts)))
{
GPIO1->DR ^= (1UL << 23);
GPIO1->DR ^= (1UL << 23);
uartMdb.IdleLineCallback();
GPIO1->DR ^= (1UL << 23);
GPIO1->DR ^= (1UL << 23);
}
}
In the image I posted in my first message you can see that after the last character is received on rx (yellow), it takes up to 2.3ms to toggle the pin (blue).
Uart initialization:
lpuart_config_t config;
LPUART_GetDefaultConfig(&config);
config.rxIdleType = kLPUART_IdleTypeStopBit;
config.rxIdleConfig = kLPUART_IdleCharacter2;
config.baudRate_Bps = _baudRate; // 9600 for LPUART3
config.enableRx = _canRead; // true for LPUART3
config.enableTx = true;
// Initialize the uart with default config and both rx and tx enabled
LPUART_Init(
_instance, // LPUART3
&config,
BOARD_DebugConsoleSrcFreq()); // freq = 80000000
I am seeing the behavior in my real application. I have no doubt it will behave identical in SDK examples.
The idle line flag seem to wait until 2 (9bit) bytes are read as "all ones". I would expect it would only wait for 1 byte.
Any ideas why it behaves this way?
Any idea how to influence that behavior?
Many thanks in advance!