Multiple USART interrupt problem - STM32F4

zmay wrote on Monday, February 17, 2014:

FreeRTOS V7.6.0
STM32F4
IAR

I am having two tasks. Task1 is simply showing welcome screen on LCD, Task2 waits for USART interrupt which gives semaphore from ISR. Problem here as appears is that USART interrupt is detected multiple times. Infinite loop ISR --> Task2 --> ISR is created.

USART handler

 1

2
3
4
5
6
7
8
9
10

void USART1_IRQHandler(void) {
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR( xUsartInterrupt, &xHigherPriorityTaskWoken );
<span style="color: #008800; font-weight: bold">if</span>( xHigherPriorityTaskWoken <span style="color: #333333">==</span> pdTRUE ) {
	portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}

}


And the Task2:
 1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

void Task2(void *pvParameters) {
<span style="color: #008800; font-weight: bold">for</span>(;;) {
	xSemaphoreTake(xUsartInterrupt, portMAX_DELAY);
	LCD_Clear(GREEN);
	LCD_SetTextColor(BLACK);
	LCD_SetBackColor(GREEN);
	LCD_CharSize(<span style="color: #0000DD; font-weight: bold">24</span>);
	LCD_StringLine(<span style="color: #0000DD; font-weight: bold">60</span>, <span style="color: #0000DD; font-weight: bold">110</span>, access);
	LCD_StringLine(<span style="color: #0000DD; font-weight: bold">56</span>, <span style="color: #0000DD; font-weight: bold">130</span>, granted);
	<span style="color: #333399; font-weight: bold">long</span> l;
	<span style="color: #008800; font-weight: bold">for</span> (l <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>; l <span style="color: #333333">&lt;</span> <span style="color: #0000DD; font-weight: bold">19999999</span>; l<span style="color: #333333">++</span>)
	  ;
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}

}


If i don’t disable usart interrupts in ISR then Task1 which runns at beginning simply freezes. Here are the priorities:

Task 1 - tskIDLE_PRIORITY + 1UL
Task 2 - tskIDLE_PRIORITY + 2UL
USART1 - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 12

What am i doing wrong?

rtel wrote on Tuesday, February 18, 2014:

[I like the way you have included source code in your post - very easy to read. I **really** wish SourceForge would just format code between <code> tags automatically as well as you have done it in your html].

Some comments:

First, I’m not sure 100% that I understand exactly the problem, but do think from a first read that it is not a FreeRTOS problem as your code looks basically ok. It is much more likely to be a hardware management problem (how and when interrupts are triggered, when and how to enable/disable interrupts etc. are all hardware specific and outside the scope of this forum).

Where is the character actually read form the UART? Your code does not show the character being removed from the UART’s Rx buffer, which probably means that each time you leave the interrupt the interrupt will immediately get asserted again because there is still data waiting to be read.

I would recommend replacing the for() loop null delay with a vTaskDelay() call because that will give it a definitive delay time, rather than a delay that will change depending on how fast the clock is and which other tasks are running in the mean time. Also it will allow other tasks to run during the delay period. One final reason - as soon as you turn optimisation on the whole delay loop will get optimised away because your variable ‘l’ is not declared volatile.

Have you taken note of all the items on this page: http://www.freertos.org/RTOS-Cortex-M3-M4.html regarding interrupt priorities, especially the bits in bold red text that are specific to the STM32? As you are using V7.6.0 ensuring configASSERT() is defined will help trap a lot of the pits that are easy to fall into.

You don’t need to test xHigherPriorityTaskWoken yourself, the test is included inside the portEND_SWITCHING_ISR() macro.

Are you trying to write to the screen on each character that is received? Writing to the screen will take mane thousands of times longer than the time taken to receive each character.

Regards.

dumarjo wrote on Tuesday, February 18, 2014:

Le 2014-02-18 04:53, Real Time Engineers ltd. a écrit :

[I like the way you have included source code in your post - very easy to read. I *really* wish SourceForge would just format code between |tags automatically as well as you have done it in your html]|.

+1

It’s very boring the way code is displayed with sourceforge ml.

Jonathan


Ce courrier électronique ne contient aucun virus ou logiciel malveillant parce que la protection avast! Antivirus est active.

zmay wrote on Tuesday, February 18, 2014:

I used this link for code.

http://hilite.me/

zmay wrote on Wednesday, February 19, 2014:

It is much more likely to be a hardware management problem (how and when interrupts are triggered, when and how to enable/disable interrupts etc. are all hardware specific and outside the scope of this forum).

You already said it’s outside the scope, but i guess i really don’t get it. I have read all about interrupts on CM4 on FreeRTOS page.

Only FreeRTOS API functions that end in “FromISR” can be called from an interrupt service routine - and then only if the priority of the interrupt is less than or equal to that set by the configMAX_SYSCALL_INTERRUPT_PRIORITY configuration constant.

This is in my RTOS.config:

#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
#define configPRIO_BITS 4 /* 15 priority levels */

configMAX_SYSCALL_INTERRUPT_PRIORITY = 5 << (8 - 4) = 80??

So what value should i use in my NVIC structure?

void init_NVIC_USART1() {

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ??;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}




NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ) is called in prvSetupHardware function. Is there any other config regarding interrupts i should be aware of?

davedoors wrote on Wednesday, February 19, 2014:

This seems to be the same as the other thread started today
https://sourceforge.net/p/freertos/discussion/382005/thread/93ec609b/

Take FreeRTOS out of the equation, does the interrupt work as expected then? I doubt it because it does not look like you are clearing the interrupt so it will just execute again and again.

If you can verify it works as you want without using any FreeRTOS functions and without the FreeRTOS scheduler running then you can try the exact same code with the FreeRTOS scheduler working, and once you have verified that is working you can add back in the FreeRTOS API function and task.

guoguiwu wrote on Thursday, February 20, 2014:

Maybe this answer will help you https://sourceforge.net/p/freertos/discussion/382005/thread/93ec609b/#9899

zmay wrote on Thursday, February 20, 2014:

Looks like the problem was because i was calling vTaskDelay() at the end of the task which starts to execute after it gets semaphore from ISR. Without vTaskDelay() works OK. Now i have to solve why RFID tag number isn’t read correctly.

zmay wrote on Tuesday, February 25, 2014:

I dont manage to read RFID tag correctly. Any ideas why?
Same code without FreeRTOS works. Problem when running with FreeRTOS is that 0x02, which is 1 byte start flag is never read.

zmay wrote on Monday, March 03, 2014:

I am getting just some weird characters: ‘.’, ‘@’, ‘\0’… which are repeating.

FE, NE and ORE flags are always set in USART status register after reading. What could be wrong, what causes the noise in transmission. Even if i don’t use API problem persists, exact same code works only without FreeRTOS.

NVIC_IRQChannelPreemptionPriority = 12; 

#define configKERNEL_INTERRUPT_PRIORITY 255
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 159

zmay wrote on Saturday, April 19, 2014:

I am stucked and i think this is somehow connected to FreeRTOS. In my ISR i now read only 1 character per interrupt request and save it to buffer.

 1

2
3
4
5
6
7
8
9
10
11
12
13
14
15

//having only RX IRQs enabled
void USART1_IRQHandler(void) {
sign = USART_ReceiveData(USART1);
<span style="color: #008800; font-weight: bold">if</span> (sign <span style="color: #333333">==</span> <span style="color: #005588; font-weight: bold">0x03</span>)
	ETX <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">1</span>;

<span style="color: #008800; font-weight: bold">if</span> (<span style="color: #333333">!</span>ETX)
	temp[k<span style="color: #333333">++</span>] <span style="color: #333333">=</span> sign;
	
<span style="color: #008800; font-weight: bold">if</span> (sign <span style="color: #333333">==</span> <span style="color: #005588; font-weight: bold">0x02</span>) {
	ETX <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>;
	k <span style="color: #333333">=</span> <span style="color: #0000DD; font-weight: bold">0</span>;
}

}


But stil.. this characters are different (not right) of those i read without FreeRTOS. Does anyone have any idea what else could be the problem here? Priorities are set correctly, interrupt is triggered, everything is OK, only char read is wrong? Initialization code of USART is not changed, it is just taken from the program which works without FreeRTOS.

davedoors wrote on Sunday, April 20, 2014:

What is the difference between the FreeRTOS case and the non FreeRTOS case? Is it because characters are missing, or that characters are completely different?

If it is because characters are missing then try raising the priority of the interrupt. It is not using any FreeRTOS API functions so you can set its priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.

If it is because characters are wrong then is the clock the same in the two cases. Maybe you need to change the baud rate setting? This is probably a statement of something that is obvious to you but I will say it anyway, sometimes things are too obvious to get seen.

Is USART_ReceiveData() safe to call from an interrupt? In particular a FreeRTOS interrupt? Does it mess with interrupt settings itself, like enabling and disabling global interrupts?

zmay wrote on Sunday, April 20, 2014:

Characters are wrong. Now i made a single task which is reading UART all the time, result is same, so it has to be something with the clock. Difference between working program without FreeRTOS and this one is in system_stm32f4xx.c. But even if i change values which are different it doesen’t work. Values which were changed are:
SYSCLK and HCLK from 150 to 168MHz, HSE freq. from 25 to 8MHz, PLL_M from 25 to 8 and PLL_N from 300 to 336. Also tried to change baudrate, then i get different chars but still not the right ones. I must say that i am rookie in this things so any other suggestions are welcomed.

davedoors wrote on Sunday, April 20, 2014:

So the addition of FreeRTOS was not the only change, but the hardware setup changed also :o)

ST have a spread sheet in their library to assist in setting up clocks and baud rates. I think this has also been included in a more helpful way into their STM Cube software now. That should help you figure out how to generate the baud rate I think.

zmay wrote on Tuesday, April 22, 2014:

For STM32F4-Discovery you have to edit stm32f4xx.h and go to line 92 and change
#define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz /
to
#define HSE_VALUE ((uint32_t)8000000) /
!< Value of the External oscillator in Hz */
25MHz oscillator is for STM32-EVAL board

This was the problem, thanks for help.