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


Questions on the ARM ports context switches

Posted by Gordon Parke on October 27, 2008
I'm trying to port FreeRTOS to the Nintendo DS and have been having some problems with starting and switching tasks. The STORE_CONTEXT and RESTORE_CONTEXT procedures that seems to be identical on most of the other ARM7/ARM9 ports don't work for me, and although I'm a novice at all of this I'm not sure how they're meant to work in the first place.

The first thing that I'd like to know is which processor mode the ARM is meant to be in when it starts the first task, as there is a line in it that writes the stacks value for the PSR to the SPSR. When I check it at runtime I seem to be in System mode, but since this has no SPSR I think this instruction causes problems.

I also don't understand the last few lines of the RESTORE:

LDMFDLR, {R0-R14}^
LDRLR, [LR, #+60]

Specifically the second last line, as the value in LR is set in initialiseStack to 0xAAAAAAAA, I don't see how this should provide the PC with the start of the first task.

Hopefully someone can help me understand this as my degree projet is resting on it.

Thanks in advance,
Gordon Parke

RE: Questions on the ARM ports context switches

Posted by Ricky on October 28, 2008
The processor needs to be in Supervisor mode when it starts up. Tasks run in System mode, but FreeRTOS must be in Supervisor mode when it starts so that it has the necessary privileges when controlling tasks. After setting up the interrupt and abort stacks, the last lines of your stack setup code in the startup file should set up the supervisor stack and leave it in supervisor mode.

The first line of the restore, LDMFD LR, {R0-R14}^ restores the user mode registers from the task stack which the link register is pointing to. The ^ specifies user registers rather than the registers of the current mode.

The NOP is required because the processor cannot access banked registers (the supervisor mode registers) in the instruction following the LDMFD instruction. The next instruction (LDR LR, ...) would be accessing the link register which is a banked register. Page A4-33 of the ARM Architecture Reference Manual mentions this (although not in much detail).

The LDMFD instruction restored the user link register since r14 was mentioned in the list. Now LDR LR, [LR, #+60] restores the program counter (return address) from the task stack. The program counter is stored 60 bytes away from where the link register is pointing because r0 to r14 were stored in that area.

The last line, SUBS PC, LR, #4 subtracts 4 from the return address because the instruction pipeline mechanism causes the PC to be advanced by 4 by the time it gets stored on the stack. Using the SUBS version of the subtract instruction instead of SUB causes the SPSR of the current mode to be copied to the CPSR (referenced in page A4-98 of the ARM Architecture Reference Manual).

RE: Questions on the ARM ports context switches

Posted by Gordon Parke on October 28, 2008
OK, lets see. After reading your reply I added a few lines to switch the mode to Supervisor before running the Restore context code, which worked and the first task start. I tried edited the startup file but this didn't work, I'm using a toolchain that I'm not very familiar with so it's very possible that I'm just editing the wrong file. Also, do FreeRTOS tasks have to be run in system mode? My mentor thought that they should be user mode.

I'm having a hard time working out which registers are the user mode ones and which ones are the supervisors. in LDMFD LR, {R0-R14}^ I get that r0-r14 are the user mode registers, but is LR supervisor or user? If you just say r13 does that always refer to user/system mode, or is it the mode you're in. Does LR have a different meaning that R14, implying anything different?

Even when I do get the first task loaded I get a strange bug in that after my timer interrupt goes off, the name of the current task gets corrupted, the first 4 characters get replaced with random symbols (the last two seem to be smiley faces, one inverted..) I suspect that this means the rest of the task is corrupted too... Doubt anyone can help with that at the minute though.

RE: Questions on the ARM ports context switches

Posted by Richard Damon on October 29, 2008
FreeRTOS tasks need to run in system mode as that is needed for its implementation of critical sections (user mode tasks can't disable interrupts, to run tasks with critical sections in user mode, you would need to make critical section use a SWI to create critical sections).

RE: Questions on the ARM ports context switches

Posted by Ricky on October 29, 2008
In LDMFD LR, {R0-R14}^, the LR is a supervisor register. When working in a privileged mode with user registers, everything to the left of the comma is a banked register in the mode you are in, and everything to the right of the comma is a user register (assuming that you have the ^).

Check to make sure you have enough IRQ stack space. When memory gets corrupted after an IRQ fires off, that's the first thing I look for. The smiley faces are caused by bytes with values 0x00 and 0x01. So you're probably looking at 0x0001xxxx as the first four characters which looks like a program return address which is making me think that your IRQ stack is too small.

RE: Questions on the ARM ports context switches

Posted by Gordon Parke on October 29, 2008
I wonder if anyone knows how much stack space is required for the basic context switch?

I've looked at a few example demos and they all allocate 0x400 stack space, but the loader for the NDS only allocates 0x100, with this memory (DTCM) being quite limited. Others have tried relocating the stacks to main memory but this has a substansial performance hit and some nds library functions get messed up.

RE: Questions on the ARM ports context switches

Posted by Dave on October 29, 2008
0x400 is way more than is needed by the context switch. But this is the Supervisor more stack so also has to be big enough for main().

[ 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