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

I understand. The time between when you send data to UARTx->DR and the time the TX line goes low (beginning of the START bit) has a jitter of 1 bit period. At 9600 baud, this is 105 us, which is what you see. There's no way around this.

One time the delay can be 5 us, the next it can be 105 us.

Use SPI. It's possible that USART in master mode will not have this drawback. It's not clear why you're trying to shoehorn UART into this application, but there's certainly a way to achieve what you want. But not with the UART peripheral.

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

I took an STM32F042K (Nucleo), clocked it at 48MHz, ran a simple program that waits for a rising edge on PB3, and as soon as it arrives, it sends 1 byte via UART (baud rate 9600). The delay of 2-3us corresponds to what would be expected with this method.

I assume that the core of your problem is HAL_UART_Transmit_IT. Try sending using the HAL_UART_Transmit() function or, in general, simply without HAL.


 while (1){
  	while(!LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_3)){}
  	while(!LL_USART_IsActiveFlag_TXE(USART2)){}
  	LL_USART_TransmitData8(USART2, 0b01010101);
  	while(LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_3)){}
 }

G01.PNGG02.PNG

@Michal Dudka ,

the UART in 'F0 is different from that in 'F4. I believe it may behave differently in this detail.

Again, this is ST unwilling to properly version the IP modules in the individual STM32 families...

This, btw., may be solution to @alsierraromero 's problem, too - using a newer STM32, including and beyond 'F0/'F3.

JW

Pavel A.
Super User

The interrupt entry itself can cause varying delay (as Jan W. explained here).

For better synchronization, maybe reconnect the trigger signal from the GPIO to the hardware flow control for the UART, with preloaded TX byte in the DR....) so that the CPU won't be in the loop at all.

 

What he describes is not software jitter. It is a feature of the UART on the F4. I decided to test it myself, and it is true—there is a 1-bit jitter (so it depends on the baud rate). The datasheet does not discuss this in detail.

alsierraromero
Associate III

Thank you @TDK @Pavel A. @Michal Dudka and @waclawek.jan for all your help. Since it's clear now that the issue is related to the F4, I'll try a newer STM32 like @waclawek.jan suggested.

Cheers!

alsierraromero
Associate III

Picked a NUCLEO-H533RE, used the user button callback to send a single byte via UART4 and it's working just fine. The byte is being sent consistently 4.4us after the GPIO edge.