Skip to main content
SSRIN.1
Associate III
December 10, 2021
Question

Help in writing a bare metal code for implementing a UART RX interrupt routine in SMT32F767ZI ?

  • December 10, 2021
  • 11 replies
  • 4646 views

I started writing embedded code 7 months back for a robotics project. Till now , I was able to handle most of the stuff with HAL libraries. I hit a snag when trying to interface with a AHRS(Microstrain CX5-25) unit. There were time when only first few bytes will be received and the device won't receive any more bytes, even thought the IMU status shows streaming. Suspecting something is wrong with the IMU, I tried reading it from PC using Pyserial and it worked. I suspect something is wrong with HAL Receive IT Function call.

Either way,After inputs from previous posts regarding handling of frames with different sizes. I decided to shift to bare metal register based programming at least for interfacing this device.

Currently I have the following hardware setup.

STM324767ZI Nucleo Uart 5 port is connected to pc via USB-TTL device. I will be using pyserial from PC side to send some arbitrary data. This will help me check the Uart receive isr routine written in STM32 micro controller.

Initial peripheral initialisation code is set using cubemx pre-generated code.

In main.c

I call

__HAL_UART_ENABLE_IT(&huart5,UART_IT_RXNE);

__HAL_UART_ENABLE_IT(&huart5,UART_IT_ERR);

to enable interrupts

Then I write a customisr routine which is called from 

void UART5_IRQHandler(void)

custom_isr(UART_HandleTypeDef * huart)

{

uint32_t isrflags = huart->Instance->ISR;

uint32_t crlits = huart->Instance->CR1;

if (((isrflags & USART_ISR_RXNE) != RESET) )//&& ((crlits & USART_CR1_RXNEIE) != RESET))

{unsigned char a = huart->Instance->RDR;

store_ring (a , rbuf);

}

}

I could verify that when ever, I send a byte from pc. The interrupt is triggered, But RDR register is empty.

When I checked the ISR register following bits were set : IDLE,TC complete,Transmit Data,End of Block,Busy flag,character match flag.

Strangely I have enabled interrupt only for error and rx not empty. However after interrupt trigger, when I check the ISR flag, rx not empty flag is not set.

I think, I am making a mistake in the sequence of how its done. Can any one advice on what I am missing ?

Thank you

Yours Sincerely,

S.Shyam

This topic has been closed for replies.

11 replies

MFran.4
Senior
December 10, 2021

If your clock is running fast enough you could still use the api by calling HAL_UART_RECEIVE_IT(huart, &byteBuf, 1U)

You'll get "received callback" for each byte, and at the end of the callback you have to put hal receive it again.

SSRIN.1
SSRIN.1Author
Associate III
December 10, 2021

Actually the callback is not even triggering

MFran.4
Senior
December 10, 2021

Try sending one character, placing a breakpoint in the IRQHandler and following the program flow. It's possible that it could have something to do with Overrun (which if not managed can cause some headaches, so if you don't use overrun error you should disable it).

Anyway, if you want to try from scratch:

Try creating a new project with cube, then (still in CubeMX) enable the desired uart, enable the relative NVIC uart interrupt, and then in your main do as I wrote.

Tesla DeLorean
Guru
December 10, 2021

Would suggest clearing Noise,Framing or Parity errors whenever you encounter them, as these WILL block reception.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
TDK
December 10, 2021

Reading RDR in the debugger will clear the flag. Make sure you're not doing that.

If the ISR is getting triggered, there's a reason. There are not glaring hardware issues. Recheck your assumptions.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Pavel A.
December 11, 2021

> There were time when only first few bytes will be received and the device won't receive any more bytes, even thought the IMU status shows streaming.

As @Community member​ wrote, this likely is the notorious UART overrun bug, still not resolved in the HAL libraries.

The HAL library takes care of other error flags mentioned by Tesla.

Set OVRDIS bit in the USART_CR3 or disable overrun detection in Cube configuration.

If you want continuous receive (you likely do for the IMU) consider DMA.

HAL_UART_RECEIVE_IT(huart, &byteBuf, 1U) is never a good idea, because it will enable and disable RX interrupt for every byte, after every byte there's a window when the interrupt is disabled.

MFran.4
Senior
December 13, 2021

You are right, I omitted that I also set USART IRQ priority to max (0 or 1) and usually I have fast clock frequency so it did not represent a problem even with higher baudrates (e.g. 115200).