lpuart idle line detection takes up to 2.3ms

cancel
Showing results for 
Search instead for 
Did you mean: 

lpuart idle line detection takes up to 2.3ms

Jump to solution
301 Views
bp1979
Contributor IV

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).

bp1979_0-1635084891248.png

In the RM I read 

bp1979_1-1635085199124.png

 

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!

0 Kudos
1 Solution
169 Views
diego_charles
NXP TechSupport
NXP TechSupport

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.

  •   Set baud rate to 9600
  •  Set a GPIO as output, that it is toggled every time IDLE line detection is detected in the LPUART handler.

 

 

void LPUART_TransferHandleIRQ(LPUART_Type *base, void *irqHandle)
{
	...
	if((uint32_t)kLPUART_IdleLineFlag & status)
	{
		/// detect idle line flag
		GPIO1->DR_TOGGLE = (1UL << 30);
	}
        ...
}

 

 

  • Added this config to the LPUART 3 config.

 

 

  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.

 

diego_charles_2-1639029946645.png

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.

diego_charles_3-1639030418031.png

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.

 

View solution in original post

Tags (1)
4 Replies
170 Views
diego_charles
NXP TechSupport
NXP TechSupport

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.

  •   Set baud rate to 9600
  •  Set a GPIO as output, that it is toggled every time IDLE line detection is detected in the LPUART handler.

 

 

void LPUART_TransferHandleIRQ(LPUART_Type *base, void *irqHandle)
{
	...
	if((uint32_t)kLPUART_IdleLineFlag & status)
	{
		/// detect idle line flag
		GPIO1->DR_TOGGLE = (1UL << 30);
	}
        ...
}

 

 

  • Added this config to the LPUART 3 config.

 

 

  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.

 

diego_charles_2-1639029946645.png

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.

diego_charles_3-1639030418031.png

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.

 

View solution in original post

Tags (1)
158 Views
bp1979
Contributor IV

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

284 Views
diego_charles
NXP TechSupport
NXP TechSupport

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.

0 Kudos
278 Views
bp1979
Contributor IV

Hi @diego_charles 

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!

 

 

0 Kudos