portRESTORE_CONTEXT – broken under SAM7/GCC?

Hey all, I’m trying to migrate from IAR to Rowley tools, which use GCC. It is important to note that everything below should be read knowing that the exact same code (save for GCC/IAR extension differences) has been working fine under IAR. I’m compiling the project under THUMB release with no optimizations. portISR.c is compiled under ARM, and of course Interworking is enabled. As no Rowley SAM7S port is available, I’ve decided to do something based on the GCC SAM7 port (found under SourceportableGCCARM7_AT91SAM7S). My program lives (peripherals initializing well, etc), but when it gets to starting the scheduler, bad things happen. It goes to xPortStartScheduler() (from the generic scheduler init code), after tasks have been created successfully. From there, it goes to vPortISRStartFirstTask(), which is located under portISR.c. GCC Interworking does it’s magic, the processor is under ARM mode. Now what happens in vPortISRStartFirstTask() is that the Scheduler attempts to restore the idle task context and start running from there, using the portRESTORE_CONTEXT() macro (defined in portmacro.h). While in this macro, the system hangs (jumps to data abort vector). From what I understand, the culpruit lies in these three lines: ======================== /* Restore all system mode registers for the task. */ asm volatile ( "LDMFD LR, {R0-R14}^" );    asm volatile ( "NOP" ); /* Restore the return address. */

asm volatile ( "LDR LR, [LR, #+60]" );

What happens is that LR is loaded with the default TCB stack initialization data (from port.c/pxPortInitialiseStack()), in this case that equals to 0xaaaaaaaa. Needless to mention, LDR LR, [LR, #+60] yields an alignment error (and the resulting data abort exception). In the IAR port case (SAM7_IAR), with different synatx yet nearly identical assembly (in ISR_Support.h>, the above lines seem to load everything BUT R13 and R14, despite being 100% identical! What did I miss?

portRESTORE_CONTEXT – broken under SAM7/GCC?

Ok, just solved the mystery, or so it seems. For some reason, the processor is under different modes in each of the ports – under Supervisor mode in the IAR case and under System mode in GCC case. That’s at least what it looks like. That causes the LDMFD instruction to actually load the data into different R13, R14 regs (the processor got few sets of those, one for each mode). Well, gotta go now, I’ll be back to report my findings tomorrow, after some sleep…

portRESTORE_CONTEXT – broken under SAM7/GCC?

> As no Rowley SAM7S port is available, I’ve decided to do something based on > the GCC SAM7 port (found under SourceportableGCCARM7_AT91SAM7S). There is a Rowley port for the SAM7X – basically the same but with an Ethernet MAC. See FreeRTOS/Demo/lwIP_Demo_Rowley_ARM7. > > From what I understand, the culpruit lies in these three lines: > > ======================== > /* Restore all system mode registers for the task. */ > asm volatile ( "LDMFD LR, {R0-R14}^" );    > asm volatile ( "NOP" ); > > /* Restore the return address. */ > asm volatile ( "LDR LR, [LR, #+60]" ); > ======================== > > What did I miss? 1) Using the existing port. 2) Placing the processor into Supervisor mode before starting the first task. :-) Rowley makes life easy by providing the definition SUPERVISOR_START (or something similar), which does what you want.  You therefore don’t have to change the startup code just the preprocessor settings – but will want to check the stacks are setup as required for the Supervisor and IRQ modes as a minimum.  Setup other stacks also if your application requires it. Best bet is to use the existing port project file as a basis for creating your application.  This way you get the compiler settings (such as SUPERVISOR_START) and startup code that will work "out of the box".  Once you have the example working you can then start removing the demo files and replacing them with your application code. Regards, Richard.

portRESTORE_CONTEXT – broken under SAM7/GCC?

> Ok, just solved the mystery, or so it seems. > > For some reason, the processor is under different modes in each of the ports > – under Supervisor mode in the IAR case and under System mode in GCC case. In all ports the kernel runs in Supervisor mode and tasks run in System mode. When creating your new port you have not placed the processor in Supervisor mode before starting the processor.  I normally do this from the startup code, prior to calling main(). As per my reply to your original post – Rowley allows this just by defining SUPERVISOR_START as a macro. Hopefully when you try the existing supported Rowley port you will be able to get up and running quickly.  I think you will just have to replace the SAM7X headers with SAM7S headers.  Although even this might not be necessary as I think the S derivatives might be a subset of the X derivatives and have their common peripherals at the same register locations.  You will obviously have to remove the files that access the MAC – being primarily the lwIP source files, the BasicWEB server example file and the SAM7_EMAC driver files. Regards.

portRESTORE_CONTEXT – broken under SAM7/GCC?

Richard, As always, thanks alot for your great OS and quick support. Better than any commercial stuff I’ve seen ;-)

portRESTORE_CONTEXT – broken under SAM7/GCC?

You may find that you require more stack space to be allocated when using GCC as opposed to IAR.  Just something to watch out for.

portRESTORE_CONTEXT – broken under SAM7/GCC?

I’ve just been doing a similar thing.  I got FreeRTOS to run under Rowley on my Sam7S64 Ek board.  I had the same error as you at the beginning.  At the time, I thought I had fixed it by correcting my inclusion of Sam7X headers, by replacing them with Sam7S headers. Then I got to the next problem… no IRQ’s… then the next, etc. etc… I like the FreeRTOS port because it uses all the standard Atmel headers.  So much easier for possible future migration to a purely Open Source solution. Here are the things I remember I did. 1) you have to reduce the size of the heap FreeRTOSConfig.h Line 56 #define configTOTAL_HEAP_SIZE    ( ( size_t ) 13000 ) You may need to check if there’s enough memory for your app.  If the system runs out of memory at some crucial point, you’ll find the main( ) returns and the processor parks it in some fast loop.   /* Return from main, loop forever. */ exit_loop:   b exit_loop 2) you’ll need to remove all the LWIP and Web stuff, but I’m guessing you did that already. 3) be careful of the IRQ differences between IAR and Rowley.  IAR needs small ASM snippets around its IRQ routines, Rowley (GCC) does not.  Taking the Sam7X code as a base should help here. 4) Rowley’s Interrupt project sample also illustrates a curious thing, there’s a single line of code in the main.c that assigns the IRQ vector.    // Put LDR PC, [PC, #-0xF20] instruction into IRQ vector in order to use   // hardware interrupt vectoring.   *(volatile unsigned int *)0x00000018 = 0xE51FFF20; In the FreeRTOS code, this is done in the AT91SAM7_startup.S file, line 72’ish.   nop   ldr pc, [PC, #-0xF20]    /* irq */ If you don’t have it, your code will not respond to FreeRTOS interrupts. I’m still getting everything smoothed out, and since I’m just starting with this, I’m a struggling little. I can send you my project if you like email me "david" domain is "makingthings.com". David, P.S. Many thanks to Richard for an awesome project.

portRESTORE_CONTEXT – broken under SAM7/GCC?

Thanks alot David, that’s some good help! I’ll email you if I encounter any more problems. Unfortunately, my Segger JTAG doesn’t like to be mated with CrossWorks so I can barely get anything done… Waiting for their JTAG to arrive. Thanks again!

portRESTORE_CONTEXT – broken under SAM7/GCC?

>I’ll email you if I encounter any more problems Please post them here as well!

portRESTORE_CONTEXT – broken under SAM7/GCC?

I have the JLink working with Crossworks pretty well.  I’ll admit to having to disconnect and reconnect sometimes, but it is serviceable.  One key value is the Speed.  (Click on the Segger J-Link Target in the Targets pane, and you’ll see the relevant properties) I never had much success with the "auto" setting (0), I tried a few different numbers.  Somewhat unscientifically, I seem to be using 32000 right now.  Much more or much less and it doesn’t seem to work.