cancel
Showing results for 
Search instead for 
Did you mean: 

UART TX inconsistent/delayed timing NUCLEO-F413ZH

alsierraromero
Associate III

Hi,

I'm working on a piece of code using UART, where I need to send a byte of information right after the negative edge of that line is detected. Basically, my dev kit is connected to a 1-wire device through a simple 2 N-FET transistor for the TX side and directly to RX. Additionally, I have another GPIO connected to the 1-wire interface to detect, via interrupt, when the 1-wire device pulls the line down (start bit). The 1-wire device releases the bus right after the start bit.
The problem that I'm facing is that the timing at which the byte is sent by the MCU is very inconsistent, with a delay that is not tolerable by the application. I've tried several things with no improvements:

        - Send UART command using non-blocking mechanisms (interrupt and DMA)
        - Making the GPIO interrupt the one with the highest priority
        - Disable interrupts before sending UART command and enabling afterwards i.e.: __disable_irq() and              __enable_irq() 
         - Send commands in the GPIO edge callback
         - Send commands in main after checking a flag set in the edge callback
 
For the sake of simplicity, I tried all the above with a different setup. Instead of using a UART to 1-wire interface, I made a completely separate project, with the dev kit by itself, not connected to anything, where I'd send the UART command after detecting the edge of the user button in the dev kit. The results were the same. 
Just for reference, find below the simple piece of code of this last scenario I mentioned:
 
while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      if(ready)
      {
          ready = 0;
          __disable_irq();
          HAL_GPIO_TogglePin(GPIOB, LD1_Pin);
          HAL_UART_Transmit_IT(&huart3, smsg, sizeof(smsg));
          __enable_irq();
      }

  }
  /* USER CODE END 3 */
}
 
where ready is set in the user button GPIO callback.
The piece of code above uses UART3, but the result is the same using UART5 for example.
Find attached the clock setup and logic analyzer captures that show the inconsistency of the timing.
I'd appreciate your help on this matter. Thanks!
 
26 REPLIES 26
alsierraromero
Associate III

The screenshots of the logic analyzer show the capture of UART TX on top and UART RX, which is the 1-wire interface, on the bottom. In my code, I don't use any RX API calls since my application does not care about receiving.

TDK
Super User

What is inconsistent about the timing? What are you expecting to see?

Ahh, you want the character to start immediately, and a 0-1 bit delay is not acceptable. I don't think the UART hardware peripheral is set up to do that, unfortunately. 1-bit delays are generally not a big deal in UART communication.

If you feel a post has answered your question, please click "Accept as Solution".

Hi TDK,

Thanks for your swift reply.
As you can see, in the captures, one time the delta time is 15 us and in the other one is 97 us. The first is acceptable for my application since it's a fraction of the bit time (baud rate 9600) and as you can see, the logic analyzer reads the same value that it was sent (0xE7). In the other capture since it takes almost a bit time, the frames are not aligned and the value of the byte sent in the 1-wire interface is shifted 1 bit. My goal is to get that byte out consistently with very little delay, like the example with 15 us. 
So, according to what you are saying, I won't be able to do that? Is that true across all the STMicro MCUs?

Pavel A.
Super User

So transmit the byte right in the user button interrupt handler. To just send one byte you don't need the HAL ...IT overhead, it can be cut off, saving more time.

 

 

I have also tried sending the byte in the button ISR and the result is the same. Sometimes I'd get an acceptable ~10 us delay and other times I'd get 100+ us. Granted that this was using HAL_UART_Transmit_IT().

The other thing you are proposing is to not use HAL_UART_Transmit_IT(). Can you please tell me what do you recommend using/doing?

and other times I'd get 100+ us

This is very strange. Is there some other interrupt with priority same or higher than the EXTI pin interrupt?

The other thing you are proposing is to not use HAL_UART_Transmit_IT(). Can you please tell me what do you recommend using/doing?

Sending one byte takes just one write to the U(S)ART data register. Look at the "LL" library (stm32xxx_ll_usart.h, LL_USART_TransmitData8).

Waiting for the completion may be not necessary if the time between the GPIO pulses is long enough.

 

Even writing directly into the data register in the button callback

UART5->DR = 0xE7;

the result is the same.

I've decreased the priority of all interrupts (increased number) and kept the EXTI at zero: same result. Additionally, I've done the following:

__disable_irq();
UART5->DR = 0xE7;
__enable_irq();

Same result. 

> Additionally, I've done the following:

This won't help. You need to ensure minimal latency of the EXTI handler, and it can be delayed by other handler of priority 0. Maybe the systick still is at priority 0? Try to place the EXTI handler in the RAM. Some STM32F4 have CCM RAM.