# Task priority, interrupt, semaphore problem

**URL:** <https://forums.freertos.org/t/task-priority-interrupt-semaphore-problem/2435>\
**Category:** Kernel\
**Created:** [August 8, 2012, 12:36pm UTC](https://forums.freertos.org/t/task-priority-interrupt-semaphore-problem/2435 "2012-08-08T12:36:35Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [August 8, 2012, 12:36pm UTC](https://forums.freertos.org/t/task-priority-interrupt-semaphore-problem/2435/1 "2012-08-08T12:36:35Z")

</div>

**[eriksage](https://sourceforge.net/u/eriksage/)** wrote on [Wednesday, August 08, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/6725c1f4/#50ff):

Dear support forum,  
I have a problem regarding tha task priority, interrupt priority and the use of semaphores.

At initialization, a startupThread is created and the scheduler is started.  
If the task priority of the startupThread is lower than 9, the code is working. If it is higher than 9, the code only works if I put a breakpoint in the xPortPendSVHandler and steps through the code.

The problem occurs when the startupThread is waiting for a semaphore that is released in an I2C interrupt. When the semaphore is released, the StartupThread does not continue to run. Neither because of a semaphore timeout or because of the release. I can see that the semaphore is released and that portEND\_SWITCHING\_ISR ( xHigherPriorityTaskWoken ) is called with xHigherPriorityTaskWoken == 1. However the startupThread is never continued. Since the semaphore also have a timeout I find this very strange.

I suspect that there might be an issue regarding the setup of the interrupt priorities or task priorities. Any ideas? Can the increased size of the taskList cause more delay and trigger a problem with a race-condition?  
Is there a limit for the task priority other than configMAX\_PRIORITIES?

Info:  
FreeRTOS V7.0.1  
MCU: Freescale Kinetis K10.  
Compiler: IAR 6.21

#define configMAX\_PRIORITIES ( ( unsigned portBASE\_TYPE ) 12 )  
#define configLIBRARY\_LOWEST\_INTERRUPT\_PRIORITY 0xf  
#define configLIBRARY\_MAX\_SYSCALL\_INTERRUPT\_PRIORITY 5

Best regards,  
Erik Agerup

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [August 8, 2012, 3:00pm UTC](https://forums.freertos.org/t/task-priority-interrupt-semaphore-problem/2435/2 "2012-08-08T15:00:10Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Wednesday, August 08, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/6725c1f4/#72aa):

Have you followed all the instructions on this page?  
[http://www.freertos.org/RTOS-Cortex-M3-M4.html](http://www.freertos.org/RTOS-Cortex-M3-M4.html)

Regards.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [August 9, 2012, 8:32am UTC](https://forums.freertos.org/t/task-priority-interrupt-semaphore-problem/2435/3 "2012-08-09T08:32:12Z")

</div>

**[eriksage](https://sourceforge.net/u/eriksage/)** wrote on [Thursday, August 09, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/6725c1f4/#0f97):

Yes, I have followed the instructions, and I can see that the BASEPRI register is set to 0x50 during the first xTaskCreate().  
However, after calling vTaskStartScheduler() and starting the first task, the BASEPRI register is reset to 0. This is also the case in the FreeRTOS blinky demo. Is this correct?

Regards

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [August 9, 2012, 12:05pm UTC](https://forums.freertos.org/t/task-priority-interrupt-semaphore-problem/2435/4 "2012-08-09T12:05:08Z")

</div>

**[eriksage](https://sourceforge.net/u/eriksage/)** wrote on [Thursday, August 09, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/6725c1f4/#3c5b):

Forget my previous post, I now understand the BASEPRI register, and I also found the error:)

In xPortPendSVHandler the interupts are disabled, vTaskSwitchContext is run and the interrupts are enabled again.

stmdb sp!, {r3, r14}  
mov r0, #configMAX\_SYSCALL\_INTERRUPT\_PRIORITY  
msr basepri, r0  
bl vTaskSwitchContext  
mov r0, #0  
msr basepri, r0  
ldmia sp!, {r3, r14}

But in vTaskSwitchContext, the function portGET\_RUN\_TIME\_COUNTER\_VALUE is run when configGENERATE\_RUN\_TIME\_STATS is enabled, and that function calls xTaskGetTickCountFromISR();

xTaskGetTickCountFromISR() disables interrupts, and enables them again.  
The remaining code of vTaskSwitchContext is now run with interrupts enabled.

portTickType xTaskGetTickCountFromISR( void )  
{  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; portTickType xReturn;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned portBASE\_TYPE uxSavedInterruptStatus;  
uxSavedInterruptStatus = portSET\_INTERRUPT\_MASK\_FROM\_ISR();  
xReturn = xTickCount;  
portCLEAR\_INTERRUPT\_MASK\_FROM\_ISR( uxSavedInterruptStatus );  
return xReturn;  
}  
I am sure the intension is to store the previous state of the interrupt in uxSavedInterruptStatus, but that does not work, it is always 0.

I think these defines need to be changed in portmacro.h:  
#define portSET\_INTERRUPT\_MASK\_FROM\_ISR() 0;vPortSetInterruptMask()  
#define portCLEAR\_INTERRUPT\_MASK\_FROM\_ISR(x) vPortClearInterruptMask();(void)x

If 0 always is returned from portSET\_INTERRUPT\_MASK\_FROM\_ISR(), interrupts will be enabled when they are not supposed to.

How can I update these macros such that the BASEPRI register is read instead of 0?

Regards

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [August 9, 2012, 12:50pm UTC](https://forums.freertos.org/t/task-priority-interrupt-semaphore-problem/2435/5 "2012-08-09T12:50:59Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Thursday, August 09, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/6725c1f4/#a980):

> In xPortPendSVHandler the interupts are disabled, vTaskSwitchContext is run and the interrupts are enabled again.

No they are not.&nbsp; The intelligent Cortex-M NVIC (nested interrupt controller) will not accept an interrupt at a priority above the currently running interrupt.&nbsp; As BASE\_PRI is set to 0 the code effectively sets the interrupt mask to the priority of the existing interrupt.&nbsp;

> I think these defines need to be changed in portmacro.h:  
> #define portSET\_INTERRUPT\_MASK\_FROM\_ISR() 0;vPortSetInterruptMask()  
> #define portCLEAR\_INTERRUPT\_MASK\_FROM\_ISR(x) vPortClearInterruptMask();(void)x

It is set to zero because saving the old interrupt state and then restoring the old interrupt state would cause the compiler to generate more assembly code with no difference being made to the effective state of the compiler or the execution of your code.&nbsp; As it is, turning the optimiser on in the compiler settings will just remove the code all together as it does nothing.

Regards.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [August 9, 2012, 1:17pm UTC](https://forums.freertos.org/t/task-priority-interrupt-semaphore-problem/2435/6 "2012-08-09T13:17:45Z")

</div>

**[eriksage](https://sourceforge.net/u/eriksage/)** wrote on [Thursday, August 09, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/6725c1f4/#6ea2):

Ok, I understand, and thank you for your reply.  
That was strange, because changing the code solved my problem.

The strange thing is that if I either disable configGENERATE\_RUN\_TIME\_STATS or uncomment as shown below, the code is working.  
If I don’t do this, it depends on the value of the highest task priority if it works or not. I suspect that a higher task priority value will make it take a longer time to go through the task list in vTaskSwitchContext and therefore it is more likely that the I2C interrupt is occurring here. I can see that the I2C interrupt is run while vTaskSwitchContext is running.

//uxSavedInterruptStatus = portSET\_INTERRUPT\_MASK\_FROM\_ISR();  
xReturn = xTickCount;  
//portCLEAR\_INTERRUPT\_MASK\_FROM\_ISR( uxSavedInterruptStatus );

So, it is OK that the BASEPRI is changed from 0x50 to 0x00 during vTaskSwitchContext if and only if configGENERATE\_RUN\_TIME\_STATS is enabled?

Can you think of something else causing my problem, when changing this makes my problem disappear.

Regards.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [August 10, 2012, 3:31pm UTC](https://forums.freertos.org/t/task-priority-interrupt-semaphore-problem/2435/7 "2012-08-10T15:31:04Z")

</div>

**[edwards3](https://sourceforge.net/u/edwards3/)** wrote on [Friday, August 10, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/6725c1f4/#d6a7):

When configGENERATE\_RUN\_TIME\_STATS&nbsp; is set to 1, the kernel will try an call user defined functions to first initialize the run time stats gathering, and then obtain the run time stats pointers. How are your run time stats functions implemented?

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [August 16, 2012, 1:22pm UTC](https://forums.freertos.org/t/task-priority-interrupt-semaphore-problem/2435/8 "2012-08-16T13:22:10Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Thursday, August 16, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/6725c1f4/#5476):

Update -

This is probably the cause of the issue.&nbsp; The run time stats function is called from within a critical section, and exiting the critical section from the run time stats implementation would be a problem on a Cortex-M.&nbsp; I have just looked at the run time stats implementation in the FreeRTOS/Demo projects, and see that it specifically accounts for this potential issue be re-entering the critical section in the code.&nbsp; See the call to portSET\_INTERRUPT\_MASK\_FROM\_ISR() in the snipped below, which is taken from the official Kinetis K60 demo.

```
	/* The SysTick is a down counter. How many clocks have passed since it was
	last reloaded? */
	ulSysTickCounts = ulSysTickReloadValue - *pulCurrentSysTickCount;
	
	/* How many times has it overflowed? */
	ulTickCount = xTaskGetTickCountFromISR();
	/* This is called from the context switch, so will be called from a
	critical section. xTaskGetTickCountFromISR() contains its own critical
	section, and the ISR safe critical sections are not designed to nest,
	so reset the critical section. */
	portSET_INTERRUPT_MASK_FROM_ISR();
	
	/* Is there a SysTick interrupt pending? */
	if( ( *pulInterruptCTRLState & ulSysTickPendingBit ) != 0UL )
	{
		/* There is a SysTick interrupt pending, so the SysTick has overflowed
		but the tick count not yet incremented. */
		ulTickCount++;
		
		/* Read the SysTick again, as the overflow might have occurred since
		it was read last. */
		ulSysTickCounts = ulSysTickReloadValue - *pulCurrentSysTickCount;
	}	
	
	/* Convert the tick count into tenths of a millisecond. THIS ASSUMES
	configTICK_RATE_HZ is 1000! */
	ulReturn = ( ulTickCount * 10UL ) ;
		
	/* Add on the number of tenths of a millisecond that have passed since the
	tick count last got updated. */
	ulReturn += ( ulSysTickCounts / ulClocksPer10thOfAMilliSecond );
	
	return ulReturn;	

```

I might put something into the core code to guard against this, as I can see it is an area that could cause users an issue.

Regards.
