Task switching does not happen

gary-e-a wrote on Monday, January 28, 2013:

I am a newbie with FreeRTOS and have encountered a problem with tasks not being switched to when the demo application is running.

The target is a Tern 186 B engine board>  I am using Paradigm 7.00 as the developer IDE.

I am using the demo project WizNET_DEMO_TERN_186… I have seen task / priority issues with this demo. Since I did not have all of the hardware used in this project I commented out the serial and http task creates in main.c. I also modified 186.cfg (changed the amount of RAM from 128 to 512, the rdonly map from 0x0800 to 0x7ffff to 0x2c000 to 0x7ffff and the CODE_START from 0x0800 to 0x2c000) and freertosconfig.h (config_USE_IDLE_HOOK from 1 to 0 configCPU_CLOCK_HZ from 80000000 to 40000000). After downloading the application I set breakpoints inside the various forever loops that are in the created tasks. When I executed the code none of the breakpoints were hit. I did this because an earlier debug session with a breakpoint in the prvCheckTask function in main.c showed that no other task was running so I thought I could confirm this by breakpoints in the forever loops.

What could be causing the lack of task execution other than prvCheckTask (I even changed its priority from tskIDLE_PRIORITY + 4 to tskIDLE_PRIORITY + 2)?


edwards3 wrote on Monday, January 28, 2013:

It sounds like the scheduler is not starting. Have you stepped through the vTaskStartScheduler() function in the debugger? At the end it will call the portable layer start scheduler function. You should see the context of the first task being restored in that (after the timer for the tick interrupt has been configured). What happens then?

gary-e-a wrote on Thursday, January 31, 2013:

I stepped through VTaskStartScheduler and found that when portFIRST_CONTEXT() is done is when things go bad.  I stepped through the portFIRST_CONTEXT assembler code and saw this: the registers AX, BX, CX, DX, SI, DI, BP, DS, and ES all got the value 0xA5A5.  SP had 0x3DC.  When the iret is done the CPU display shows A5A5:A5A5, at that and succeeding addresses is the value xFF - so the iRet went to memory that did not contain code.

When I stepped this again I put a breakpoint in pxPortInitialiseStack() and saw this code execute for each of the tasks created (the last task created was prvIdleTask).  Is it possible there is something wrong in the memory map definitions in 186,cfg?

Thanks for your help.

rtel wrote on Thursday, January 31, 2013:

AX should be loaded with 0xaaaa, BX with 0xbbbb etc. so something is not good there.

I have just reviewed the web page for this demo (I have not used it in a *long* time) and see the following text:

“Note for Paradigm C/C++ Version 7 Users: Version 7 uses a slightly different stack frame and therefore requires a few modifications to the RTOS kernel port files. Dave Lyneham has generously provided a project that contains the changes necessary, along with a readme.txt file to explain why they are needed. The files can be obtained from the FreeRTOS Interactive x86 forum. Thanks Dave!”

Have you seen this?


gary-e-a wrote on Thursday, January 31, 2013:

I had seen that note and I do have the files that Dave provided.  In fact my first project was based on his code - but the problem with it was that it was using libraries from FreeRTOS 6.

So what you are telling me is that I have to use Dave’s notes to modify the WIZNET demo project to be compatible with Paradigm 7.  I will start on that tonight.  If I have questions about Dave’s notes can I post them here?


gary-e-a wrote on Saturday, February 02, 2013:

I used the readme.txt notes from Dave’s files to modify the project file as well as the files port.c and portasm.h.  The files that Dave provided were all marked as FreeRTOS V5.2.0.  I used these files to make changes to the version 7.3 files port.c and portasm.h contained in the directory source\protable\Paradigm\Tern_EEe\small.  The project built without errors but when it ran it crashed.  Single-stepping through the code showed that call to t1_init was done by prvSetupTimerInterrupt() caused the system to crash when out dx,ax was done (dx had 0xff5e and ax had 0xe00b).  I believe t1_init() is in the ae.lib file provided by the Paradigm installation.

Any suggestions would be most appreciated.

gary-e-a wrote on Monday, February 04, 2013:

Some additional information on the crash:
The FreeRTOS source line is:
t1_init( portENABLE_TIMER_AND_INTERRUPT, usTimerCompare, usTimerCompare, prvPreemptiveTick ); where portENABLE_TIMER_AND_INTERRUPT is 0xe00b, usTimerCompare is 0x271, and the address of prvPreemptiveTick is 0x1000:031b.  When I stepped through the assembler code I saw that the crash happened in this section of the code:
mov dx, 0xff5e
mov ax, si (si has the value 0xe00b)
out dx, ax (crash happened here - debug showed a message that communications with the Tern SBC was disconnected)
pop si
pop bp

The ae.lib I used is in the directory c:\tern\186\lib\small which was installed by the Paradigm installation.

I also built et_beep.axe in c:\tern\186\samples\et.  When I ran it the call to t1_init worked without any problem.

Paradigm support told me this:
I guess the problem would be related to the differences in interrupt stack frames.  Here is something to consider:

Paradigm C++ does not use the same interrupt stack layout as Borland C++ so you have to make a minor change if you are manipulating the interrupt stack.  We use the same as the Microsoft compiler so we can use the more efficient PUSHA/POPA instructions.

You can determine what the interrupt stack format will be

    #if __PARADIGM__ >= 0x540
    void __interrupt intHandler(
                         uint16 es, uint16 ds,
                         uint16 di, uint16 si,
                         uint16 bp, uint16 sp,
                         uint16 bx, uint16 dx, uint16 cx, uint16 ax,
                         uint16 ip, uint16 cs, uint16 flags
    void __interrupt intHandler(
                         uint16 bp,
                         uint16 di, uint16 si,
                         uint16 ds, uint16 es,
                         uint16 dx, uint16 cx, uint16 bx, uint16 ax,
                         uint16 ip, uint16 cs, uint16 flags

I would check any code accessing the interrupt stack frame and make sure it reads.writes registers at the correct offsets.