We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello experts,
I would like to ask the reason why the exception frame forms on PSP in the Cortex-M architecture.My understanding is that MSP (Main Stack Pointer) is the interrupt stack pointer and PSP (Porcess Stack Pointer) is the normal (user) stack pointer.From my little experiences, the exception frame was formed on the interrupt stack.However, the ARM forms it on the user stack.
Best regards,Yasuhiko Kouoto.
If one wants to have a number of user processes and swap between them then having the resume information on the user stack makes life much easier - in essence the main work is just loading the new process stack pointer. In fact one needs to set a pending interrupt for when just returning to the process stack to handle some messing with registers properly so it isn't totally straightforward - the callee save registers of the old process need to be saved and those of the new process loaded before resuming it.. Interrupts are normally just nested though and one doesn't swap between them so a single stack is fine for them. Anything similar to a thread is driven by having a series of interrupts for the different stages rather than waiting in interrupt code.
Hello,
thank you for your reply but I cannot fully understand your opinion due to my poor English ability.From the security view point, the interrupt stack should be used to separate the influences by the user stack problem such as the overflow. If the exception information was stored on the user stack, it could not handle the user stack overflow.
Now, I think I found the reason.In Cortex-M Architecture, the bank registers were abandoned.Instead of the bank registers, I guess some registers would be saved on the user stack in advance to go to the exception handler.
Are there any comments for my comments?I would like to wait for the other advantages for it.
Best regards,Yasuhiko Koumoto.
There's a whole section on errors like stack overflow in the manual but it won't stop an interrupt being handled Basically there is a derived interrupt and the information for that goes on the interrupt stack.
Whether the registers are saved on the interrupt stack or the process stack makes very little difference except when switching processes. I believe the real reason is as I said to cut down overheads on switching between different processes.
Hello daith,
I am sorry but I cannot understand what you say.
What is the overhead?
I would like you to explain by pictures as even a monkey can understand.
If you think of the concrete OS, please tell me what it is.
Best regards,
Yasuhiko Koumoto.
The saving is in not copying 16 words on every process switch or possibly more if using floating point.
I had alook on the web and here's a description of what's done
Context Switching on the Cortex-M3
Suppose we are time-slicing between processes.
When the timer interrupts the current process a stack frame is stored on the process stack instead of the interrupt stack. The stack frame will include any registers which are not callee save. That is r0-r3,r12,lr,pc and PSR
The interrupt routine decides which process should get then next timeslice. It sets the PendSV interrupt to do the actual switch when the process stack is about to resume execution. This isn't very relevant but it is a mechanism to ensure the routine doing the switch has very low priority and will return to the process stack and that all the callee save registers are okay. The timer interrupt might be written in C but the PendSV interrupt would be written in assembler to have complete control over what happens with the registers.
The processor will chain to the PendSV interrupt when just about to return to the process.
In this routine what it has to do is store all the callee save registers of the old process and load up all the callee save registers of the new process. These are all the registers except r0..r3 etc. above. These can be saved on the process stacks or into a structure associated with the process. It saves the old process stack pointer into the structure associated with the old process. and loads the new process stack pointer from a structure associated with the new process.
It then returns from the interrupt. This will automatically load all the registers which are callee save and continue execution in the new process.
If the interrupt frame for the initial timer interrupt was stored on the interrupt stack then as well as what is done above that stack frame would have to be moved from the interrupt stack either to a structure associated with the old process or to the old process stack. It would then have to move the interrupt frame for the new process to overwrite where the interrupt frame of the old process was. Thus having the frame on the interrupt stack rather than the process stack means that two interrupt frames worth of data have to be moved for every process switch. Therefore another 16 words at least have to be moved. If the process uses floating point registers a lot more have to be moved.
thank you for your effort.
It is very helpful.
However, it looks to me like a problem chicken and egg.
I think the OS is so designed to utilize fully Cortex-M features.
According to your explanations, the Cortex-A case has a big overhead in the multi-processing or multi-tasking.
Is it correct?
The Cortex-A series don't handle things like interrupt chaining or preemption quite so nicely and efficiently. The big difference is that Cortex-M is designed to be simple to program using C and yet to handle interrupts as quickly as possible when used in the way it is designed for, whereas the Cortex-A series is designed more for flexibility, the programmers are in full charge of every aspect and can put all sorts of operating systems on top. Cortex-A cores are faster and yet are not normally expected to be handling enormous numbers of real time low level interrupts like Cortex-M cores do but to be more concerned with higher level decisions and user programs. There isn't quite the same drive to extract the very last cycle out of interrupt handling. A very simple Cortex-M system though might not even have anything that looks like an operating system on it, just interrupt routines to handle some hardware.
I'm sorry for late reply.
I want not to get a semantic or structural reason, but I'd like to simply know that ARM Cortex-M takes such a scheme.
Regarding the overhead, I cannot still understand without any pictures to explain it.
At the context switch, I think the registers would not get from the stack frame.
Also, I cannot understand your explanation why Cortex-A does not take such a scheme.
The overhead is pretty straightforward. This isn't exactly what happens but it illustrates the main point.
Context switch if interrupt data is stored on MSP
Timer interrupt. Interrupt data stored on MSP
Copy some registers to old process specific area
Copy interrupt data from MSP to old process specifc area
Set PSP for new process
Copy interrupt data for new process to MSP
Copy some registers from new process specific area
exit to continue new process, restore state from MSP
Context switch if interrupt data is stored on PSP
Timer interrupt Interrupt data stored on old process PSP
exit to continue new process, restore state from new process PSP
The way Cortex-M does it is just not what a person used to Linux or some other such operating system would expect. It could be simulated on Cortex-A series but it requires hardware support to work well.
thank you again for the detailed explanations.
I have a question.
When a context switching, all registers should be saved to some memory area, but the context on PSP is r0-r3, r12, r14, r15 and xPSR. From where do the other registers bring?
I'm sorry if you had already explained it.
The other register are what I referred to as 'some registers' above.
One could have the timer routine do the copying in the top level of the interrupt routine as I showed above - but it is easier to do it by setting the PendSV flag when it is decided a switch should be done. Then instead of returning to the old process when the timer routine exits it enters the PendSV interrupt routine.
The PendSV routine will be entered with the interrupt state saved on PSP and all the other registers ready to be saved away. It does all the saving and restoring and setting the new PSP pointer and finally returning to continue execution in the new process.
thank you for your patient explanations.
I have now almost understood what you had said.
However, I wonder one thing.
In a case of a context switch, why are the registers on the stack (e.g. MSP or PSP) referred? I think to use STM or LDM is more convenient.
How do you think?
I'm not sure I've understood you properly - sorry. Yes I very much suppose they various registers would be saved or loaded using LDM and STM instructions. It is a place where one can't get away with just C code unfortunately.
my concerning point is that I guess the context switch routine will be written by assembler.In the case, the software can directly save the current registers to the appropriate area other than LR, PC and xPSR.If this is correct, it will be convenient if those registers (i.e. LR, PC and xPSR) are on MSP rather than PSP.If they are on PSP, the software should check where they exist on MSP or PSP.Therefore, I feel it is really advantage which some contexts are saved on PSP.Although I basically understand what you say, I cannot believe it will be for the context switch that some contexts are saved on PSP.
I have just found out another reason.
It would be why a function could not be distinguished whether it was an ISR or a normal function.
Therefore a Compiler would compile it in the same manner.
However, in an ISR, all registers should kept their values which had been before entering it.
So the caller saved registers such as r0-r3, r12, lr and pc should be saved onto the user stack.
Probably it would be a correct answer.
Also I would close this issue because there has been no further posts while 3 months.