So I have spent the last few evenings really trying to learn how the ARM port of ChibiOS works. I am a bit hung up on the use of extctx. Here is my understanding of the two ctx structures:
extctx (External Context?): The are the registers a function is allowed to clobber. After a call to a function or method they may be different so the compiler is in charge of adding the correct prologue and epilogue to save these registers in use (hence it's name.. external). In order for all of these registers to be saved by the prologue all of them would have to be in use so this structure is really a worst-case representation of the stack.
intctx (Internal Context?): These are the registers that are expected to be the same after a function call. ChibiOS saves these internally in the port_switch function (hence the name Internal). These registers are ALWAYS saved during a contect switch, therefore the number of registers and their order is fixed.
Does that sound correct? If so this is the problem I have(the wording is a bit tricky... sorry): SVCallVector and PendSVVector both increment the PSP by the size of an extctx, and seem to use a value (the FPU Condition Code Register) from the structure. How is it known that those values were actually stored at that location on the stack? I am not really sure what the SVC and PendSV vectors are for, but this is seems strange to me. I have included the code that is giving me trouble:
Code: Select all
#if !CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__)
/**
* @brief SVC vector.
* @details The SVC vector is used for exception mode re-entering after a
* context switch.
* @note The PendSV vector is only used in advanced kernel mode.
*/
void SVCallVector(void) {
struct extctx *ctxp;
/* Current PSP value.*/
asm volatile ("mrs %0, PSP" : "=r" (ctxp) : : "memory");
/* Discarding the current exception context and positioning the stack to
point to the real one.*/
ctxp++;
#if CORTEX_USE_FPU
/* Restoring the special register SCB_FPCCR.*/
SCB_FPCCR = (uint32_t)ctxp->fpccr;
SCB_FPCAR = SCB_FPCAR + sizeof (struct extctx);
#endif
asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory");
port_unlock_from_isr();
}
#endif /* !CORTEX_SIMPLIFIED_PRIORITY */
#if CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__)
/**
* @brief PendSV vector.
* @details The PendSV vector is used for exception mode re-entering after a
* context switch.
* @note The PendSV vector is only used in compact kernel mode.
*/
void PendSVVector(void) {
struct extctx *ctxp;
/* Current PSP value.*/
asm volatile ("mrs %0, PSP" : "=r" (ctxp) : : "memory");
/* Discarding the current exception context and positioning the stack to
point to the real one.*/
ctxp++;
#if CORTEX_USE_FPU
/* Restoring the special register SCB_FPCCR.*/
SCB_FPCCR = (uint32_t)ctxp->fpccr;
SCB_FPCAR = SCB_FPCAR + sizeof (struct extctx);
#endif
asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory");
}
#endif /* CORTEX_SIMPLIFIED_PRIORITY */
Thanks for your time!
Sam