lpuart idle line detection takes up to 2.3ms

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

lpuart idle line detection takes up to 2.3ms

Jump to solution
3,567 Views
bp1979
Senior Contributor I

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
Reply
1 Solution
3,435 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
3,436 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.

 

Tags (1)
3,424 Views
bp1979
Senior Contributor I

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

3,550 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
Reply
3,544 Views
bp1979
Senior Contributor I

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
Reply