Interesting non-instant failure: Superspeed!

anders8 wrote on Friday, November 20, 2009:

Hi everyone, first post here. My name is Anders, embedded systems are no stranger to me, and I’m not looking for basic C help or a way to run this RTOS at 50,000 ticks a second. *grin*
I ported FreeRTOS 6.0.0 to the Atmel AVR 1281. For those not familiar, it’s a fairly orthogonal architecture, and this model has 8k ram and uses 16 bit timers. I’ve set the tick (both the OS macros and actual hardware timers) to 1kHz. The interrupt rate was verified via some pin toggling within the OS isr and a pleasantly accurate waveform verified both the correct speed and that the RTOS was actually running. I created two test tasks, at two and five tick intervals, to toggle pins, and those motored right along, again verified with the scope.
Naturally, the actual program is larger (about 32kB of flash out of 128kB, and maybe 4kB of ram) and now I’m getting funky activity. The OS interrupt continues to run at it’s 1kHz rate. However, a task that I’ve set to delay (not delay-until) for 50ms (so, 50 ticks in this configuration) runs correctly for the first couple seconds. It then changes and **runs continuously**.

It’s the only task running. (Apart from the idle task that I’m assuming the OS has handled properly. I haven’t put any hooks in there to test it.) So we’re talking about this task switching to running  every at 200Hz to running at **19.8kHz!!** Yes, **faster than the OS tick!**

The first followup question you should ask will be “Well, what is the task doing?” by which you actually mean “What foolish business is this guy up to that’s eating up the stack and obviously overwriting some variables?” Unfortunately, no, I’m not doing recursive fractal calculations or anything like that. I’ve turned off all activity that would use stack (beyond the natural getting to the function) and really just toggling a pin.

So, for clarity, neither the OS or the overall software *crashes*, things keep running, but the scheduler gets all wacky-do. :slight_smile:
My thought is that it is not being removed from a ready list, or that the tick counter itself is having issues. (With counting/overflow, not the actual running, the scope tells me it’s still running.) What variables or lists might cause this sort of behavior, this instantly returning to being called? Any ideas?

edwards3 wrote on Friday, November 20, 2009:

You have already mentioned stack, which is what I would normally suggest first.

Have you changed the port in any way? Is the 1281 the same as the Mega32, or does it have an extended architecture?

Do you have a debugger you can step through the code in once the error happens?

Sounds like the tick count or the calculation of the wake time from the tick count could be getting corrupted. Are you using 16bit ticks or 32bit ticks?

anders8 wrote on Friday, November 20, 2009:

The port does not have a different architecture, the only work was getting the timer set up, as since there are some additional timers in the 1281 vs the Mega32, those register definitions were not entirely the same.

Lamentably, even though I built a JTAG header into the board, my particular JTAG programmer doesn’t support the 1281, and so I’m stuck with “download/run/serial output”.

16 bit ticks, as mentioned. I agree with your assessment, and I’m wondering in particular which variables are involved with the wake time calculations.



edwards3 wrote on Friday, November 20, 2009:

xTickCount in tasks.c holds the tick count value, which is either a 16 bit variable or a 32 bit variable depending on the configUSE_16_BIT_TICKS value in FreeRTOSConfig.h.

The kernel takes care (or at least it should do) of any tick count overflows, but just in case something is going wrong with that part of the code can you say how long after reboot the problem occurs. Is it always the same, and could it be as the 16 bit tick count reached 65536?

The calculated wake time is a local variable within the vTaskDelay() function.

anders8 wrote on Friday, November 20, 2009:

configUSE16BIT_TICKS is properly set to 1.

I thought about an overflow in the tick count as well. However, the action occurs at around 3-5 seconds of run time. We would expect a 65.536 second run if it was strictly that issue (or half that if an off kilter compiler definition had me using *signed* 16bit ).

I’ll take some stopwatch measurements, as well as get something to spit out the tick count via serial.

Once the wake time is calculated, does it store it in an array or structure, one for each task?

edwards3 wrote on Friday, November 20, 2009:

The wake time is placed in TCBofTask->xGenericListItem->xItemValue, I think.

rtel wrote on Monday, November 23, 2009:

I just updated the SVN copy of tasks.c with the else if clause in xTaskCheckForTimeout() changed to:

else if( ( ( portTickType ) ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait )

Ugly, I know, but it seems some compilers require an extra cast that covers the result of the subtraction.  This prevents the < being converted to 32 bits, which is not what is wanted.

Can you please try that and see if it fixes your problem.  Thanks.


anders8 wrote on Monday, November 23, 2009:

We usually only worry about “ugly” for a few minutes… then bask later in the glow of “functionality”. *grin*

I’ll put that in later today. I assume that “the SVN copy” is “the development copy” or something similar.

Thanks Richard. :slight_smile:


rtel wrote on Monday, November 23, 2009:

If you don’t have SVN installed on your host then you can find the latest tasks.c (the development copy) here:


anders8 wrote on Tuesday, November 24, 2009:

Richard, along the same line of not getting into 32 bits when that’s not native for the chip, you may want to change this section within **xTaskGenericCreate()**. It would seem that that this would require yet another flag in the config file, which would be something along the line of “16 bit pointers” or “32 bit pointers”.

> #if( portSTACK_GROWTH < 0 )
pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
            //current FreeRTOS v6.0.1 code:
//pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned long ) pxTopOfStack ) & ( ( unsigned long ) ~portBYTE_ALIGNMENT_MASK  ) );
            //compilers without warning for a 2 byte wide stack pointer
pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned short ) pxTopOfStack ) & ( ( unsigned short ) ~portBYTE_ALIGNMENT_MASK  ) );

These are the errors I get with the current 6.0.1 code:

    tasks.c:423: warning: cast from pointer to integer of different size
    tasks.c:423: warning: cast to pointer from integer of different size

I got the new tasks.c and merged it in. I’ll give it a shot.

Thanks! :smiley:

anders8 wrote on Wednesday, November 25, 2009:

Well, it appears that the supplied fix has solved the problem. The system is stable and tasks continue to run on their proper schedule. :slight_smile:

Thanks for the fix. :slight_smile: