cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UART_Receive_IT() returns BUSY and no longer receiving any interrupts

JJoy.1
Associate III

I am continuously calling HAL_UART_Receive_IT(), until i get some specified value in receiver buffer. But after some time HAL_UART_Receive_IT() return BUSY and after that it is not receiving any further interrupts and seems like the code is dead.

How can i get out of from BUSY state and receive further interrupts.

Please help me..

Thanks,

Jestina

11 REPLIES 11
TDK
Guru

HAL_BUSY indicates it's already busy doing something, in this case most likely waiting for bytes.

You can abort the transfer and try again if you want, but that should not be needed.

There are examples to follow in the relevant Cube repository for your chip.

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

void handleData(void)

{

int j;

if(resp == 0)

 {

 for(j =0; j <80; j++)

 {

   Serial_PutByte(status[j]);

   if((status[j]== 'P' ) && (status[j+1]== 'L' ) && (status[j+2]== 'L' ) && (status[j+3]== 'R' ) && (status[j+4]== '1' ))

   {

   resp = 1;

   }

  }

 }

}

void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart)

{

Serial_PutString("ABORT COMPLETED");

}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

 handleData();

 if(resp == 0)

 {

 if(HAL_UART_Receive_IT(&huart2, (uint8_t*)status, 80)==HAL_BUSY){

 Serial_PutString("BUSY");

HAL_UART_AbortReceive_IT(&huart2);

}

 __HAL_UART_ENABLE_IT(&huart2,UART_IT_RXNE );

 HAL_UART_Receive_IT(&huart2, (uint8_t*)status, 80);

 }

}

I am expecting "PLLR1" in my received data and if its not in the received value, I will continue reading data by pressing RESET key of my modem. I will continue pressing RESET, until i get "PLLR1".

At some point of time, i got a huge data ( that is more than 80 char..which i am reading), i am getting into

 if(HAL_UART_Receive_IT(&huart2, (uint8_t*)status, 80)==HAL_BUSY) state. After that i am not able to receive any more data. I think overrun occurs here.

So i called HAL_UART_AbortReceive_IT() and i am getting the print from HAL_UART_AbortCpltCallback(); that is "ABORT COMPLETED".

After that i am enabling interrupt again and calling HAL_UART_Receive_IT(). But i am not able to receive any byte further.

Can you please tell how to get out from this scenario...That is... if some huge data comes which i am not reading ..after that also i am able to receive interrupts..

That is to overcome overrun scenario..

Please help me by giving a solution...Thanks in advance...

Thanks,

Jestina

Karl Yamashita
Lead II

You have set HAL_UART_Receive_IT(&huart2, (uint8_t*)status, 80); to interrupt when you receive exactly 80 bytes. So until you receive 80 bytes, HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) callback won't get called.

If you're only going to receive "PLLR1" and no other text, then write it to interrupt for 5 bytes. HAL_UART_Receive_IT(&huart2, (uint8_t*)status, 5);

If you're expecting other length of text then ideally the device that is sending text should send a Carriage Return so you know it is the end of the string.

  • Set HAL_UART_Receive_IT(&huart2, (uint8_t*)status, 1); to receive one byte at a time. Make a character buffer to hold twice as many characters as you're expecting to receive. So if your longest string is lets say 16 characters, then make the buffer at least 32 bytes, 40 to be safe in case you can't parse your character ring buffer in time. Each time you receive a character, save it to the character ring buffer and increment the pointer.
  • Then some where in a polling routine parse the character buffer looking for the '\r' character so you know that is the end of that text and save the characters to a ring buffer for Messages.
  • Then you poll and parse the Messages and actually do a strcmp() like strcmp(&message, "PLLR1"); instead of doing a for loop and indexing the array.

I actually have a library for a character ring buffer but I modified it to make it a universal uart character ring buffer so that it works for STM32, TI's TM4C and Microblaze. I just verified it works for all 3 types. I'll have to make a video tutorial setting up a uart ring buffer after I finish another tutorial.

Edit: actually using strncmp() is better strncmp(&message, "PLLR1", 5);

JJoy.1
Associate III

Thanks for the response.

I am getting 2 types of responses from my device.. log1 and log.

I am expecting log1.txt which contains "PLLR1", which i will get if i receive 80 characters. If log1 is coming everything is working fine.

But sometimes i will get log.txt which is very big and i am receiving only 80 characters . Device is sending huge data and i am reading only 80 chars. I think at that time overrun scenario occurs and HAL_UART_Receive_IT(&huart2, (uint8_t*)status, 80)==HAL_BUSY.

After this STM32 will not respond to any interrupts and not able to receive a single data. Inorder to get out from this scenario, I called HAL_UART_AbortReceive_IT(&huart2); I think Abort is working and it is calling HAL_UART_AbortCpltCallback().

Still after this also i am not able to receive any interrupt...That is my scenario.

My requirement is: if i get into overrun scenario, how can i clear that receive further interrupts.

Thanks,

Jestina

JJoy.1
Associate III
 
Karl Yamashita
Lead II

One of the things i've noticed, but i'm not 100% sure, is that you're handling the data within the interrupt even when calling handleData(). You should save the data to a buffer and then handle the data from a polling routine outside of the interrupt HAL_UART_RxCpltCallback().

You should use the DMA so that the DMA controller will handle the saving of the uart data to your status array so the uC can process the previous data you saved in a ring buffer.

Now that i see it is a text file, each line can be saved as a message in a ring buffer by looking for a "\r\n" characters. So as the DMA is working on filling the 80 characters in the status array, you can be polling and parsing the message buffer. I think using strstr() library to look for "PLLR1" in the buffer would work. If it returns Null then it didn't find "PLLR1". The uC can process the messages faster than the DMA can fill the status array and interrupt.

I'll take your text files and work with it with my library. Other than looking for "PLLR1" and setting resp = 1, are you doing anything with the rest of the text?

I am doing nothing with the rest of the text

I have taken one of my past projects and added some code to look for "PLLR1". I had a little issue at first of it not interrupting after awhile but I was able to make some changes. It seems to work just fine now. I haven't had it not interrupt after sending log.txt with the large amount of text. For Log1.txt, I can parse and indicate the text "PLLR1" has been found. I've uploaded the project to github. You'll of course need to port the code over to your project.

https://github.com/karlyamashita/STM32ParseTextFile

Let me know how it works out or if there are any issues.

JJoy.1
Associate III

Hi Karl,

Thanks for your great support.

Your assumption was correct. My issue was related to the handling the data within the interrupt. Now i am handling the data from a polling routine outside of the  HAL_UART_RxCpltCallback(). I am able to find out "PLLR1" easily. The BUSY status for HAL_UART_Receive_IT() has also gone. Now my code is working fine for my requirement.

These changes i have made as per your explanation. Once again thank you very much for your support.

Thanks,

Jestina