turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Setting up modes?

Fri Apr 03, 2015 11:21 pm

I was wondering about setting up SP in different modes, and in
DEN0013D_cortex_a_series_PG I found this:

Code: Select all

Code to initialize the stack pointers
LDR R0, stack_base
@ Enter each mode in turn and set up the stack pointer
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit ;
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit ;
MOV SP, R0
Could someone cast some light on this?
What is CPSR_c? I haven't found the explanation in the documents.
How does that work mode-wise?
I mean, if I change the mode to USER to set the stack, can I get back to SUPERVISOR without SVC
(and the handler)?

I understand
#Mode_FIQ:OR:I_Bit:OR:F_Bit
is 3 bit-fields ORed: Mode_FIQ = 0x11, I_Bit = 1<<7, F_Bit = 1<<6.
(I guess "Mode_FIQ:OR:I_Bit:OR:F_Bit" is ARM tools syntax.)
De-bugging is for sissies - real men do de-monstrations.

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: Setting up modes?

Sat Apr 04, 2015 4:36 am

This stuff is dealt with in a document called the ARM ARM. There's one for each iteration of the ARM. The latest is ARM v7 ARM, I think. Each version gets more complicated and unpleasant to read than the previous :-)

The CPSR is the current program status register, and holds info like processor mode (User mode or the various privileged modes) and whether (fast)interrupts are enabled. This stuff used to be encoded within the PC (ARM v2, as described in that old book...).

Each exception mode (the privileged modes, other than System, ie. SVC, UND, ABT, IRQ, FIQ) which are entered from User mode when an exception occurs, such as an undefined instruction, or a hardware interrupt) has its own R13 (SP) and R14 (LR) registers. (FIQ also has its own R8-R12).

When, for example, an interrupt occurs, the processor switches to IRQ mode and jumps to memory location 0x00000018 which, hopefully, contains a branch to your interrupt handler code.

If that code uses R13 or R14 those will not be the User mode R13 and R14, but IRQ's R13 and R14 registers. So, you need to set IRQ's SP as well as User mode's. The only way to do that is to switch to IRQ mode, and then set SP.

This sort of thing is usually done on Reset, because you're in a privileged mode, from which you can set your SP and then switch to another privileged mode to set that mode's SP and so on.

Finally you switch to the unprivileged User mode, and can only get back into a privileged mode through one of the aforementioned exceptions.

To change the CPSR (to change mode) a special instruction, msr, is used. The _c flag on CPSR means that only the "control" bits of the whole register will be changed. The IRQ and FIQ bits are specified so that interrupts don't occur while you're doing this.

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Setting up modes?

Sat Apr 04, 2015 1:06 pm

colinh wrote:This stuff is dealt with in a document called the ARM ARM. There's one for each iteration of the ARM. The latest is ARM v7 ARM, I think. Each version gets more complicated and unpleasant to read than the previous :-)
I agree. The organization of the text is not "user oriented". If there's a flag, the setting is first explained in all modes. Then 20 pages later the document explains its meaning in all modes. Usually the user has one mode (or mode change) in mind and wants to know about the flag in the context of that mode (or those modes). The reader gets the feeling that the information is spread all over the document.
Finally you switch to the unprivileged User mode, and can only get back into a privileged mode through one of the aforementioned exceptions.
Ok, thanks.
To change the CPSR (to change mode) a special instruction, msr, is used. The _c flag on CPSR means that only the "control" bits of the whole register will be changed. The IRQ and FIQ bits are specified so that interrupts don't occur while you're doing this.
[/quote]
The PG didn't mention anything about the '_c' suffix.

Also, In the ARM-ARM (ARMv7-A and ARMv7-R edition, issue C) it says

Code: Select all

B1.8.5 Processor state on exception entry
...
CPSR.{A, I, F, M} values on exception entry
...
Table B1-10 shows the cases where CPSR.{A, I, F} bits are set to 1 on an exception entry, and how this depends on
the mode and security state to which an exception is taken. If the table entry for a particular mode and security state
does not define a value for a CPSR.{A, I, F} bit then that bit is unchanged by the exception entry. In this table:
...
Exception mode	Security state and implementation
		Non-secure, no Virtualization Extensions 	All others
...
FIQ 		If SCR.AW==1 then CPSR.A is set to 1		CPSR.A is set to 1
		CPSR.I is set to 1				                        CPSR.I is set to 1
		If SCR.FW==1 then CPSR.F is set to 1		CPSR.F is set to 1
IRQ, Abort 	If SCR.AW==1 then CPSR.A is set to 1      CPSR.A is set to 1
		CPSR.I is set to 1				                        CPSR.I is set to 1
...
So if the saved PSR is used, the above is not true? If not, why the maskbits?
And the example was from ARM® Cortex™-A Series Programmer’s Guide, Version: 4.0
De-bugging is for sissies - real men do de-monstrations.

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: Setting up modes?

Sat Apr 04, 2015 3:01 pm

You'll get the hang of it :-)

I actually checked in ARM v6 ARM.

The _c is described in A3.10 Status register access instructions and A.4.1.39 MSR. The syntax is slightly odd, because the _c is actually part of the MSR instruction.

I haven't had to do anything with the SPSR yet.

"Each exception mode also has a Saved Program Status Register (SPSR) which holds the CPSR of the task
immediately before the exception occurred. The CPSR and the SPSRs are accessed with special
instructions."

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Setting up modes?

Sat Apr 04, 2015 3:45 pm

Thanks for explaining the '_c'.
I got the impression, from the example in the programmer's guide, that when an exception occurs,
the cpsr is stored into the current state spsr, the state change takes place and the spsr of the new state is loaded into the cpsr. That would explain the mask bits in the example. The ARM-ARM only states something else: that the processor sets the mask bits as part of the state change.
De-bugging is for sissies - real men do de-monstrations.

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: Setting up modes?

Sat Apr 04, 2015 7:39 pm

I tend only to use the ARM v6 ARM and arm1176jzfs TRM.

From the former, 2.6 Exceptions,

When an exception occurs, the banked versions of R14 and the SPSR for the exception mode are used to save state as follows:
R14_<exception_mode> = return link
SPSR_<exception_mode> = CPSR
CPSR[4:0] = exception mode number
CPSR[5] = 0 /* Execute in ARM state */
if <exception_mode> == Reset or FIQ then
CPSR[6] = 1 /* Disable fast interrupts */
/* else CPSR[6] is unchanged */
CPSR[7] = 1 /* Disable normal interrupts */
if <exception_mode> != UNDEF or SWI then
CPSR[8] = 1 /* Disable imprescise aborts (v6 only) */
/* else CPSR[8] is unchanged */
CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
PC = exception vector address

To return after handling the exception, the SPSR is moved into the CPSR, and R14 is moved to the PC. This can be done atomically in two ways:
• using a data-processing instruction with the S bit set, and the PC as the destination
• using the Load Multiple with Restore CPSR instruction, as described in LDM (3) on page A4-40.

In addition, in ARMv6, the RFE instruction (see RFE on page A4-113) can be used to load the CPSR and PC from memory, so atomically returning from an exception to a PC and CPSR that was previously saved in memory.

Collectively these mechanisms define all of the mechanisms which perform a return from exception.


When an exception occurs, the processor saves the CPSR in the new mode's SPSR. Then it changes the mode and interrupt masking flags automatically, depending on which exception mode is being entered. When you want to return to the previous mode (ie. after your exception handler has done what it does) the CPSR is restored to what it was before (by copying the SPSR). This is done automatically (as well as atomically) if you return by one of the ways mentioned above.

When you're setting up your various stack pointers at the beginning (on Reset) you don't need to worry about restoring anything, because there's no interesting state to be preserved, because nothing has happened yet. You still need to set the interrupt mask flags, because if you didn't, using msr CPSR_c you'd be clearing them, and you don't want interrupts occurring before you've set things up.

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Setting up modes?

Sat Apr 04, 2015 9:48 pm

Thanks a heap, colinh. Now it all makes sense. The masking and everything.
That
SPSR_<exception_mode> = CPSR
was a surprise.

Ive been reading the ARM v7A/R ARM, because I only have RPi 2B,
(got it about a month ago) and I haven't done anything with ARM-devices before,
except an USB driver on STM3240G-EVAL using STM libraries/examples and C.
Getting into the core-stuff was not needed.
De-bugging is for sissies - real men do de-monstrations.

mrvn
Posts: 58
Joined: Wed Jan 09, 2013 6:50 pm

Re: Setting up modes?

Sun Apr 19, 2015 10:34 am

The previous replies went into all the gritty details about what modes are and where in the ARM ARM to read about it. But lets just explain what is going on with a few simple words. Hope that helps future readers.
turboscrew wrote:I was wondering about setting up SP in different modes, and in
DEN0013D_cortex_a_series_PG I found this:

Code: Select all

Code to initialize the stack pointers
LDR R0, stack_base
@ Enter each mode in turn and set up the stack pointer
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit ;
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit ;
MOV SP, R0
Could someone cast some light on this?
What is CPSR_c? I haven't found the explanation in the documents.
How does that work mode-wise?
As mentioned above the CPSR is the Current Processor Status Register. One part of the CPSR register tells the CPU what mode it is in. What the MSR instruction does is to switch modes. Each mode has it's own SP (except SYS and USR share one). So in pseudocode the code does this:

Code: Select all

switch to FIQ mode (IRQ/FIQ disabled)
set stack
adjust R0 to point to the next stack
switch mode to IRQ mode (IRQ/FIQ disabled)
set stack
turboscrew wrote: I mean, if I change the mode to USER to set the stack, can I get back to SUPERVISOR without SVC
(and the handler)?

I understand
#Mode_FIQ:OR:I_Bit:OR:F_Bit
is 3 bit-fields ORed: Mode_FIQ = 0x11, I_Bit = 1<<7, F_Bit = 1<<6.
(I guess "Mode_FIQ:OR:I_Bit:OR:F_Bit" is ARM tools syntax.)
You can set all the stacks for all the modes this way except for USER. As you say yourself you can not get back out of USR mode without SVC. But SYS and USER mode share the same SP and you can switch to SYS mode and back.

There is also another way. You can access the unbanked registers from any mode using the "^" flag on the register list for ldm or stm. For example:

Code: Select all

# load USER SP and LR registers from current stack
ldmia   sp, {sp, lr}^
Enjoy, Mrvn

david.given
Posts: 15
Joined: Sat Dec 05, 2015 8:10 pm

Re: Setting up modes?

Sat Jan 16, 2016 9:27 pm

A bit belated, but the cps instruction is your friend:

cps #0x10 ; Now we're in user mode!

You can also use it to turn interrupts on or off:

cpsie if ; Enable irq and fiq interrupts
cpsid if ; ...and disable them

And do both:

cpsie if, #0x10 ; Interrupts on, go to user mode

When writing exception handlers, I'd also check out the srs and rfe instructions, which simplify a lot of state saving.

Return to “Bare metal, Assembly language”