STR71x with GCC ?

nobody wrote on Friday, January 20, 2006:


I need FreeRTOS on STR71 with GCC.
I wonder if its better to start from the already
existing IAR port, or some other ARM7 GCC port.
The IAR port includes much stuff GCC doesn’t understand. I can’t find an intrinsic.h…
Did anyone made an attempt on GCC for STR7 yet?

rtel wrote on Friday, January 20, 2006:

You are probably best off starting with a GCC port.

Here is a suggested route:

+ Create a directory as FreeRTOS/Source/Portable/GCC/STR71x.

+ Copy into this new directory the files from the FreeRTOS/Source/Portable/GCC/ARM7_AT91SAM7S directory.

Now working in the new directory, you need to change the SAM7 files to work with the STR71x.  As both are ARM7 only the peripheral information needs changing.

+ Open up the port.c file from the new directory and the port.c file from the existing IAR STR71x port.

+ Find the function prvSetupTimerInterrupt().  This sets the timer used to create the RTOS tick.  Replace the workings of the function in the new port.c with those from the existing STR71x port.c.  You may also need the #defines and #includes from the top of the file (replace the SAM7x defines and includes with those relevant to the STR71x).  I think actually that prvSetupTimerInterrupt() uses library functions on the STR71X and might not be quite correct, but don’t worry about this for now.

+ Next open portISR.c (this is the ARM mode stuff).  The interrupt handlers vNonPreemptiveTick() and/or vPreemptiveTick() have some code that clear the interrupt.  This is specific to the peripheral and the SAM7 version again needs replacing with the way the interrupt is cleared in the STR71x version (note that the IAR version has this code in the port.c file as it mixes ARM and THUMB mode in the same file.  In the IAR version the function is called vPortNonPreemptiveTick(), and you need the WDG->SR = 0x0000;portCLEAR_EIC(); lines).

+Now the timer peripheral is correct for the STR71x and the ISR clears the interrupt correctly - you have to actually setup the interrupt vector.  The IAR port loads the vector table manually in a file called vect.s79 which can be found in the FreeRTOS/Demo/ARM7_STR71x_IAR directory.

I think that might be it as far as the kernel code goes.  I’m sure there will be other minor changes needed when you come to compile it.

You also need a makefile, startup code and linker script for the STR71x.  I suggest taking these from an existing GCC demo project and editing them accordingly.

Note that stacks need to be setup for IRQ and Supervisor mode and that the processor MUST BE IN SUPERVISOR MODE when the scheduler is started.  It is easiest to achieve this by switching to supervisor mode prior to calling main(), and this is what the existing GCC demo’s do.

You can place the makefile, linker script and startup code in the FreeRTOS\Demo\ARM7_STR71x_IAR directory (make sure the makefile uses the correct (new) port files from the directory just created).  The main.c file in that directory setups up the processor as required.


nobody wrote on Tuesday, January 24, 2006:

Hallo Richard,

thanks for your detailed reply.
I started a new project and got so far that
the preemptiveTick and the only task runs once or twice. Then it crashes.
So I need some more advice.
I successfully tested my own interrupt routine earlier.
As the STR7 data book states I used some asm macros to switch from IRQ to SYS mode and back in the isr.
I can’t find this in your isr functions. Is that because you are in supervisor mode?
I haven’t got the right startup files for SVC mode. Your GCC examples aren’t for STR7 and the ones for STR7 are not for GCC. I tried to change my own (from Hitex) but that didn’t work so far.
Do you think its possible to switch to SVC mode in main() with inline assembler before the call to StartScheduler()?

nobody wrote on Tuesday, January 24, 2006:

>As the STR7 data book states I used some asm
>macros to switch from IRQ to SYS mode and back
>in the isr

Definitely do not do this!  The IRQ should run in IRQ mode.  Using the scheduler allows the IRQ to do very little but collect data for processing at task level and can therefore be very short and quick.  If you want to switch context from within an IRQ then you have to save/restore the task context and this code relies on the fact that you are in an exception state, so if you are not it definitely will not work.

The startup code between arm processors is very similar.  You need to add the line:

/* Switch to svc mode. */

before main is called (the defines can be obtained from the LPC boot.s file).  You can probably do this from asm in main() also.  If you do this ensure that the startup code sets up stacks for the IRQ and Supervisor modes.

nobody wrote on Tuesday, January 24, 2006:



if my debugger doesn’t lie, I always stay in user mode 0x10, the upper command doesn’t work.
Is it at some point too late for this command or is there a spezial sequence?
I tried it in the startup assembler files an in main().

nobody wrote on Tuesday, January 24, 2006:

User mode is a mode with limited rights, and therefore you cannot change the processor mode from this state. The state will change when an interrupt occurs (also SWI).

As far as I understand, the user mode is never used in freeRTOS, so simplest is to skip the stack init for user mode. Then you will not have this start-up problem (that is how it is done in the distributed demo’s, at the least the KEIL ARM7).

This also makes sense, right?


rtel wrote on Tuesday, January 24, 2006:

Makes sense :slight_smile:

nobody wrote on Wednesday, January 25, 2006:

Ok, i skipped the user stack init and added a
SVC init instead.
The tick is running now 5000 times or so, then it hangs. The task gets activated but taskdelay seems not to work properly. I suspect some wrong initialisation, stack?
Hmm, I didn’t know that FreeRTOS relies on stdio functions (in task.c, sprintf).
I think they need much of stack?
Maybe I’ll try with the Keil or Demo startup files. Though I fear running into other problems then.
Bye, Joerg

nobody wrote on Wednesday, January 25, 2006:

FreeRTOS does not rely on functions such as sprintf().  These are only used within the trace tool which is clearly marked as only for debug use and not for production systems.  Make sure you have configUSE_TRACE_FACILITY set to 0 in FreeRTOSConfig.h.

The only library function really used by FreeRTOS is memcpy where it was decided it was preferable to rely on the compiler vendors implementation to ensure portability across different access requirements.  This function is normally inlined unless you have debug switches.

Try increasing the stack sizes of your tasks.

nobody wrote on Thursday, January 26, 2006:

I went one step forward and two steps back:
I used other startup files and changed them to SVC mode.
The system crashes when taskCreate calls taskYIELD(). This is defined as an ‘swi’ instruction. I found out I have to make vPortYieldProcessor the SWI-Handler. I tried: LDR pc, Undefined_Addr B _vPortYieldProcessor

I needed to add some assembler to vPortYieldProcessor:
asm volatile ( ".global _vPortYieldProcessor" );
asm volatile ( "_vPortYieldProcessor:" );

Otherwise the linker didn’t found it.
I don’t know why it works in the SAM7 demo.
So the function gets called but then it crashes.
As you can see, I use a ‘B’ command, where the other exeptions use a ‘LDR’. I found it this way in the SAM7 demo. Anyway, something goes wrong with the stack / return address?
Any help is appreciated.

nobody wrote on Thursday, January 26, 2006:

> I needed to add some assembler to vPortYieldProcessor:
> asm volatile ( ".global _vPortYieldProcessor" );
> asm volatile ( "_vPortYieldProcessor:" );

Don’t know why this is.  On the LPC2000 the interrupt is setup with a function call - so I presume you are setting up a static table to need this?

> So the function gets called but then it crashes.

Did you follow the LPC2000 example - declaring the function naked, adding 4 to the lr and saving/restoring correctly?

void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));

void vPortYieldProcessor( void )
/* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not.  Add the offset manually so the same
ISR return code can be used in both cases. */
asm volatile ( "ADD LR, LR, #4" );

/* Perform the context switch.  First save the context of the current task. */

/* Find the highest priority task that is ready to run. */

/* Restore the context of the new task. */

rtel wrote on Thursday, January 26, 2006:

>On the LPC2000 the interrupt is setup with a function call

? Don’t think so.

nobody wrote on Friday, January 27, 2006:

I can start two tasks with no preemption.
After some time the system resets.
The stacks are:
.equ    UND_Stack_Size , 4
.equ    SVC_Stack_Size , 500
.equ    ABT_Stack_Size , 4
.equ    FIQ_Stack_Size , 4
.equ    IRQ_Stack_Size , 100
.equ    SYS_Stack_Size , 500
Don’t know where the heap goes.
Can’t imagine why it runs for a couple of times and then stops. There is nothing growing, is there?
Barry:  Maybe I can send you startup and linker files so you can have a look at?

Regards, Joerg

rtel wrote on Friday, January 27, 2006:

The system mode stack is not required (unless you call main in system mode) as a stack is given to each task individually.

The IRQ stack could potentially need to be larger depending on what is going on.  Try setting it to 400.

The heap (at least the heap used by the scheduler) is allocated statically.

I can take a look if you like but might not be able to run it on actual hardware.  If you want to zip up the files and send them then please also provide build instructions (ie where your makefile is) and make sure that the project is in a buildable state.  Send the zip file to the address given on the WEB site contacts page rather than the sourceforge address as otherwise the zip file will be stripped off.


nobody wrote on Monday, January 30, 2006:

Hi John (Barry :-),

I found that the IRQ stack pointer increases by four on every call of:
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
So it grows in the wrong direction, upwards!
Is there a special compiler option to use (
I tried -mno-apcs-frame and the opposite)?
I tried with gcc 4.0.1 and 3.4.3.


rtel wrote on Monday, January 30, 2006:

That is odd as it should directly enter the interrupt as per any other interrupt you write using GCC.  The preemptive tick is a bit different as it is naked, but the nonpreemptive tick should be straight forward.

Is the interrupt being called directly, or is there some ST code that does some handling before calling the interrupt handler?  Maybe there is a problem there.

Send me the code if you like and I can take a peek.


nobody wrote on Tuesday, January 31, 2006:


I found the bug at:
EIC_SIR30 = ((unsigned int)vNonPreemptiveTick + 4)<<16 | T0_INT_PRIORITY;

The +4 leads to a jump over the first bytes of the ISR. So there was more popping than pushing.
Still don’t know where it comes from.
I sent the port to Richard, maybe he could put it on his site as a beta version.
Still not sure about the interrupts, the st data book tells something about reading the IVR register…
But it works in general with two tasks running, blinkin LEDs on a Hitex starter board.
Thanks for your support so far.

nobody wrote on Friday, February 17, 2006:

which version of gcc are you using?

nobody wrote on Saturday, February 25, 2006:


It would be great to have access to beta version sent to Richard, so that everybody share the same codes.

If we all work on the same sources, release version could come quickly.


rtel wrote on Saturday, February 25, 2006:

Email me using the address on the contacts of the FreeRTOS WEB site (   r _dot_ barry _@@@_ freertos =dot= com ).