Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

vPortSetInterruptMask causes interrupt issue

Posted by Joe on August 19, 2012
MCU: Kinetis K10 - Arm Cortex M4
IDE: CodeWarrior 10.2

I know I'm not supposed to set any interrupt priorities lower than configMAX_SYSCALL_INTERRUPT_PRIORITY for functions that call into RTOS API. So, I've been careful about that.

However, I'm still seeing a VERY WEIRD issue. When I set UART3's Error interrupt, the call into vPortSetInterruptMask disables my Periodic Interrupt Timer (PIT0)! I'm not using UART3, but I wanted to to set all unused interrupts to level 15 (Lowest priority) just to be safe. It's strange because no other interrupts trigger this error.

Any thoughts on what I'm seeing this odd behavior? MY PIT0 is set to interrupt level 0 (highest priority). Maybe I just have a misunderstanding of how things work with this RTOS. I thought this PIT0 interrupt would NEVER be disabled. I need that to be the cause since it's keeping track of time in my system.

RE: vPortSetInterruptMask causes interrupt issue

Posted by Richard on August 19, 2012
“I know I'm not supposed to set any interrupt priorities lower than configMAX_SYSCALL_INTERRUPT_PRIORITY for functions that call into RTOS API. So, I've been careful about that.”


If you mean assign them a priority that is numerically lower, then that statement is correct, but remember that numerically lower means effectively higher on the Cortex-M.

You are right that if you timer is truly at priority 0 it should never be disabled, especially if your UART interrupt priority is 15, and the timer interrupt is not making any calls into the RTOS API.

Can you see why the timer is not running? FreeRTOS only manipulates interrupt masks using the Cortex-M BASEPRI register - and an interrupt of priority 0 cannot be masked using BASEPRI. So either interrupts are globally disabled (which FreeRTOS doesn't do) or the timer has stopped for some reason. Are you using *any* functions that manipulate any of the Cortex-M interrupt masks other than taskENTER_CRITICAL() and taskEXIT_CRITICAL(), could anything be globally disabling interrupts in the Cortex-M core itself? (by calling the "cpsid i" asm instruction)?

Regards.

RE: vPortSetInterruptMask causes interrupt issue

Posted by Joe on August 19, 2012
Well, based on that (I'm just now learning about BASEPRI), this is looking a LOT like a Freescale Bug.

I had this code in place to determine it was the BASEPRI causing my trouble. The first delay_ms() works, but the second falls into the trap I've set.
delay_ms( 5 );
portDISABLE_INTERRUPTS();
delay_ms( 5 );



Here is my Delay_ms() function:
/* ===============================================================================================
== FUNCTION DESCRIPTION:
== Delays to for specified amount of milliseconds.
==For safety, 1ms is added to requested ms delay because timer could technically rollover 1us later.
==
== OUTPUTS:
==N/A
== =============================================================================================*/
void TIMERS__delay_ms
(
timer_t delay_amount
)
{
/* Local Variables. */
u32 last_count;
u32 current_count = 0;
u32 trouble_counter = 0;
u32 max_trouble_count = 10000; //Observed trouble counts of 8,303 up to 9,060 while testing successes at 100MHz.

/* Record the current count from the interrupt counter. */
last_count = SYSTICK__counter__1ms;

/* Loop until the local counter matches the specified delay. */
while( TRUE )
{
/* Check if interrupt counter has been updated. */
if( last_count != SYSTICK__counter__1ms )
{
current_count++;//Increment local counter.
if( current_count >= (delay_amount + 1) ) break;

last_count = SYSTICK__counter__1ms; //Record current count;
trouble_counter = 0;//Reset trouble counter.
}

if( ++trouble_counter >= max_trouble_count )
{
//TODO: Figure out why this sometimes occurs.
DEBUG__print_error_message( "SysTick Interrupt stopped triggering!" );
//DEBUG__assert( __FILE__, __func__, __LINE__ );
break;
}
}
} /* TIMERS__delay_ms() */


Here's a snapshot of my PIT0 interrupt priority.
NVICIP84:


With NVICIP84 set to 0 and BASEPRI set to 0x50, I can clearly see my interrupt has stopped ticking by running through the delay_ms() function. If I use my debugger to move back to the top of the function, set BASEPRI 0x00, then everything runs fine again. Setting BASEPRI to any valid value causes the interrupt to stop triggering again!!!

So, looks like a Freescale issue. I'd assume the ARM core is fine since it's been around much longer. Is there anything I'm missing?

RE: vPortSetInterruptMask causes interrupt issue

Posted by Joe on August 19, 2012
And, just to throw a completely random curve-ball in there...

As stated in the previous email, running my delay_ms() function with these conditions causes PIT0 to stop interrupting.
NVICIP84 = 0
BASEPRI = 0x50

Now if I run delay_ms() function with the EXACT SAME conditions, but update NVICIP68 (UART 3's Error Interrupt) to be 0x00 through 0x04, my PIT0 interrupts starts triggering again!!!

Richard, this is now apparent to me that this is a non-FreeRTOS-related issue. My apologies for posting it on your forum. But, you do seem to have an excellent grasp on the Kinetis (ARM Cortex) MCU's. I would be very grateful for any input you have on this matter.

RE: vPortSetInterruptMask causes interrupt issue

Posted by MEdwards on August 19, 2012
I'm not following some of this but have some comments

“delay_ms( 5 );
portDISABLE_INTERRUPTS();
delay_ms( 5 );”


You are calling portDISABLE_INTERRUTPS() but don't appear to be re-enabling them. In that case no interrupts will execute at all, ever.

In a FreeRTOS application you should only use taskENTER_CRITICAL() and taskEXIT_CRITICAL() to enter and exit critical sections, and not use portDISABLE_INTERRUPTS() or portENABLE_INTERRUPTS() unless you are absolutely sure about the internal workings of the chip and the FreeRTOS port.


“void TIMERS__delay_ms
(
timer_t delay_amount
)
{
/* Local Variables. */
u32 last_count;
u32 current_count = 0;
u32 trouble_counter = 0;
u32 max_trouble_count = 10000; //Observed trouble counts of 8,303 up to 9,060 while testing successes at 100MHz.

/* Record the current count from the interrupt counter. */
last_count = SYSTICK__counter__1ms;

/* Loop until the local counter matches the specified delay. */
while( TRUE )
{
/* Check if interrupt counter has been updated. */
if( last_count != SYSTICK__counter__1ms )”


FreeRTOS uses the SYSTICK itself, and the tick rate is set by configTICK_RATE_HZ in FreeRTOS. Are you trying to use SYSTICK too? If you configured SYSTICK before calling vTaskStartScheduler() then FreeRTOS will have just overwritten your settings. If you configure SYSTICK from a task after calling vTaskStartScheduler() then the scheduler will not start properly.

If you want to delay in FreeRTOS you can use the vTaskDelay() and vTaskDelayUntil() functions, which will stop the calling task from using any processing time until the delay period is up.

RE: vPortSetInterruptMask causes interrupt issue

Posted by Joe on August 19, 2012
edwards, I wasn't using portDISABLE_INTERRUTPS() directly. I made the observation that when my code returned from the very first xQueueGenericCreate() call, my delay_ms() function was broke (Interrupts stopped occurring).
So, I followed the breadcrumbs all the way down to portDISABLE_INTERRUTPS() which was calling vPortSetInterruptMask, which was setting BASEPRI. I hacked in these delay_ms() calls around portDISABLE_INTERRUTPS() just to prove it was the BASEPRI causing my interrupt to stop firing.

The portDISABLE_INTERRUTPS() sets the BASEPRI. So, all interrupts with priority level below BASEPRI will still occur. I had my PIT0 interrupt priority set to 0. So, it should never be disabled unless I purposely disable all interrupts.

I was originally using SYSTICK, but when I observed these symptoms, I moved onto PIT0 for my unit to track time. That change however didn't improve anything regarding this behavior.



had simply followed the breadcrumbs

xQueueGenericCreate

RE: vPortSetInterruptMask causes interrupt issue

Posted by Joe on August 19, 2012
edwards, you asked some good questions which got me thinking more.

Why wasn't BASEPRI reset to 0 when returning from xQueueGenericCreate()? I did some digging and found something concerning. The very first time I entered vPortEnterCritical(), the uxCriticalNesting variable was set to 0xaaaaaaaa. I see that is the value assigned during declaration of the variable, but it should be set to 0 in xPortStartScheduler(). But, xPortStartScheduler() is never getting called.

I'm still learning about the FreeRTOS. Do I have something setup incorrectly here? It would appear so.

RE: vPortSetInterruptMask causes interrupt issue

Posted by Richard Damon on August 19, 2012
Since YOUR main() code is supposed to call vTaskStartScheduler() which will setup a few needed things and then call vPortStartScheduler() to start up the system, then you do seem to have something setup wrong. In fact, normally interrupts are totally disabled until vPortStartScheduler is called.

RE: vPortSetInterruptMask causes interrupt issue

Posted by Richard on August 19, 2012
Just to confirm ignisuti's comments in post 6.


“You are calling portDISABLE_INTERRUTPS() but don't appear to be re-enabling them. In that case no interrupts will execute at all, ever”


On the Cortex-M portDISABLE_INTERRUPTS does not completely disable interrupts. It only masks up to configMAX_SYSCALL_INTERRUPT_PRIORITY. The reason not to use portDISABLE_INTERRUPTS is that it does not count the nesting depth, whereas taskENTER_CRITICAL() does.

“The very first time I entered vPortEnterCritical(), the uxCriticalNesting variable was set to 0xaaaaaaaa.”


This is done to prevent interrupts accidentally getting enabled by a FreeRTOS API function before the user is ready and the scheduler has started. uxCriticalNesting() will get set to 0 and interrupts completely unmasked when the first task starts running.

Do you have tasks running?

Regards.

RE: vPortSetInterruptMask causes interrupt issue

Posted by Joe on August 19, 2012
Richard,
Yes, I create two tasks and then call scheduler_start(). I looks like this wasn't happening before, because I made a rather serious mistake and was calling RTOS API before I had a chance to call scheduler_start().
I believe I've got that sorted out now...

Now.... I seem to be stuck in tel_task() and never switch over to SERVICES__main_loop().

Now might be a good time to update you guys on my level of knowledge with FreeRTOS. Very Little! Just learning the basics as I run into issues like these. The Port was done by another engineer.
So, let's start from the basics. What do I need to do to enable SERVICES__main_loop() beyond what I show below?

    /* Initialize the MCU. */
APP__STARTUP__initialize();

/* Create RTOS Tasks. */
task_create( tel_task, "Telemetry Loop", 2 * 1024 / 4, NULL, 3, NULL );
task_create( SERVICES__main_loop,"Main Loop", 8 * 1024 / 4, NULL, 2, NULL );

/* Start the RTOS Scheduler. */
scheduler_start();

RE: vPortSetInterruptMask causes interrupt issue

Posted by Richard on August 20, 2012
“because I made a rather serious mistake and was calling RTOS API before I had a chance to call scheduler_start().”


It is ok to call some RTOS API functions before the scheduler has started, but not all. In particular, it is important not to try and cause a task switch, or call a blocking API function (this makes sense, because both of these actions are asking the scheduler to do something but the scheduler is not running). You have to be particularly careful that interrupts don't execute that call API functions which in turn attempt to do one of these things. It is best therefore to limit the API usage to creating tasks, queues and semaphores before the scheduler starts, and to not enable interrupts before the scheduler starts.


What you are doing in the code snippet looks to be ok, but you are not calling FreeRTOS API functions directly. I presume your task_create() and scheduler_start() functions somehow map to, or wrap, xTaskCreate() and vTaskStartScheduler() respectively, but it depends on what else your wrapper functions are doing.

Have you looked at the official example projects for your processor, or the more generic basic demos?

Regards.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists