New Contiki port to STM32W108.
This commit is contained in:
parent
324796cd1a
commit
ec5e3ce0d7
130 changed files with 43157 additions and 0 deletions
158
cpu/stm32w108/hal/micro/cortexm3/context-switch.s79
Normal file
158
cpu/stm32w108/hal/micro/cortexm3/context-switch.s79
Normal file
|
@ -0,0 +1,158 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// @file hal/micro/cortexm3/context-switch.s79
|
||||
// @brief Context save/restore for deep sleep using the PendSV exception.
|
||||
//
|
||||
// This file also contains a simple halInternalIdleSleep() function that
|
||||
// executes just the WFI instruction for idle sleeping.
|
||||
//
|
||||
// When the STM32W108XX enters deep sleep, the hardware will actually remove power
|
||||
// from the Cortex-M3 core (in Deep Sleep 0, power is not removed but the core
|
||||
// is held in reset). Since this will clear the internal state of the core, it
|
||||
// must be properly restored such that execution can resume from the sleep code.
|
||||
// The simplest and most secure mechanism to do this is to perform a context save
|
||||
// and restore. Context save/restore is almost identical to a context switch
|
||||
// used in multi-threaded systems with the main difference being only one stack
|
||||
// pointer is used and the save/restore operations are disjoint.
|
||||
//
|
||||
// When an interrupt is triggered in the STM32W108XX, the core automatically saves 8
|
||||
// of the 16 CPU registers on the stack. The ISR then only needs to save the
|
||||
// other 8 registers and store the resulting stack pointer. Restoring is the
|
||||
// reverse operation where 8 registers are manually copied back with the other 8
|
||||
// being restored on the return from interrupt.
|
||||
//
|
||||
// As its last act, the deep sleep code will trigger the PendSV exception to
|
||||
// perform a context save. When the core is booted upon deep sleep exit, the
|
||||
// RESET_EVENT register informs cstartup if the chip just exited deep sleep.
|
||||
// Cstartup will then trigger halTriggerContextRestore which sets up the stack
|
||||
// pointer and trigger the PendSV exception to perform a restore. When PendSV
|
||||
// returns from interrupt context the system will be back at the same point it
|
||||
// was before deep sleep.
|
||||
//
|
||||
//
|
||||
// <!--(C) COPYRIGHT 2010 STMicroelectronics. All rights reserved. -->
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "compiler/asm.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// boolean halPendSvSaveContext
|
||||
//
|
||||
// A simple boolean flag used to indicate if a context save or a context restore
|
||||
// should be performed. Since context switching is handled with the PendSV
|
||||
// interrupt, parameters cannot be passed into the ISR and as such this boolean
|
||||
// flag is used. If this flag is zero, PendSV should perform a context restore.
|
||||
// If this flag is non-zero, PendSV should perform a context save.
|
||||
// Note: The smallest unit of storage is a single byte.
|
||||
//
|
||||
// NOTE: This flag must be set before PendSV is triggered!
|
||||
//------------------------------------------------------------------------------
|
||||
__BSS__
|
||||
__EXPORT__ halPendSvSaveContext
|
||||
halPendSvSaveContext:
|
||||
__SPACE__ 1
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// int32u savedMSP
|
||||
//
|
||||
// Private storage to hold the saved stack pointer. This variable is only used
|
||||
// in this file and should not be extern'ed. In our current design we
|
||||
// do not use real context switching, but only context saving and restoring.
|
||||
// As such, we only need to keep track of the Main Stack Pointer (MSP). This
|
||||
// variable is used to hold the MSP between a save and a restore.
|
||||
//------------------------------------------------------------------------------
|
||||
__BSS__
|
||||
__EXPORT__ savedMSP
|
||||
savedMSP:
|
||||
__SPACE__ 4
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// void halPendSvIsr(void)
|
||||
//
|
||||
// This ISR is installed by cstartup in the vector table for the PendSV
|
||||
// exception. The purpose of this ISR is to either save the current context
|
||||
// and trigger sleeping through the 'WFI' instruction, or restore a
|
||||
// previous context. The variable halPendSvSaveContext is used to
|
||||
// decide if a save or a restore is performed. Since entering/exiting interrupt
|
||||
// context automatically saves/restores 8 of the 16 CPU registers on the stack
|
||||
// we need to manually save the other 8 onto the stack as well.
|
||||
//
|
||||
// When a context save is complete, the stack will have been expanded by 16
|
||||
// words with the current Stack Pointer stored in savedMSP.
|
||||
//
|
||||
// When a context restore is complete, the stack will have been shrunk by 16
|
||||
// words with the old context restored after the return instruction.
|
||||
//
|
||||
// NOTE: The IAR default handler name for PendSV, PendSV_Handler, is also
|
||||
// instantiated here so it routes to the same code as the St
|
||||
// name halPendSvIsr.
|
||||
//------------------------------------------------------------------------------
|
||||
__CODE__
|
||||
__THUMB__
|
||||
__EXPORT__ PendSV_Handler
|
||||
__EXPORT__ halPendSvIsr
|
||||
PendSV_Handler:
|
||||
halPendSvIsr:
|
||||
LDR R0, =halPendSvSaveContext //load the variable's address
|
||||
LDRB R0, [R0] //get the value in the variable
|
||||
CBZ R0, contextRestore //if variable is zero, branch to contextRestore
|
||||
contextSave:
|
||||
MRS R0, MSP //load the main stack pointer into R0
|
||||
SUB R0, R0, #0x20 //make room on the stack for 8 words (32 bytes)
|
||||
MSR MSP, R0 //load new MSP from adjusted stack pointer
|
||||
STM R0, {R4-R11} //store R4-R11 (8 words) onto the stack
|
||||
LDR R1, =savedMSP //load address of savedMSP into R1
|
||||
STR R0, [R1] //store the MSP into savedMSP
|
||||
WFI //all saved, trigger deep sleep
|
||||
// Even if we fall through the WFI instruction, we will immediately
|
||||
// execute a context restore and end up where we left off with no
|
||||
// ill effects. Normally at this point the core will either be
|
||||
// powered off or reset (depending on the deep sleep level).
|
||||
contextRestore:
|
||||
LDR R0, =savedMSP //load address of savedMSP into R0
|
||||
LDR R0, [R0] //load the MSP from savedMSP
|
||||
LDM R0, {R4-R11} //load R4-R11 (8 words) from the stack
|
||||
ADD R0, R0, #0x20 //eliminate the 8 words (32 bytes) from the stack
|
||||
MSR MSP, R0 //restore the MSP from R0
|
||||
BX LR //return to the old context
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// void halTriggerContextRestore(void)
|
||||
//
|
||||
// Cstartup is responsible for triggering a context restore based upon the
|
||||
// RESET_EVENT register. Since the stack pointer sits at the top of memory
|
||||
// after the core boots, cstartup cannot simply trigger a PendSV to restore
|
||||
// context as this will cause existing stack data to be over written. Cstartup
|
||||
// disables interrupts, pends PendSV, and then calls this function. This
|
||||
// function simply configures the Stack Pointer to be past the previous data
|
||||
// such that when interrupts are enabled and PendSV fires it wont corrupt
|
||||
// previous data.
|
||||
//------------------------------------------------------------------------------
|
||||
__CODE__
|
||||
__THUMB__
|
||||
__EXPORT__ halTriggerContextRestore
|
||||
halTriggerContextRestore:
|
||||
LDR R0, =savedMSP //load address of savedMSP into R0
|
||||
LDR R0, [R0] //load the MSP from savedMSP
|
||||
MSR MSP, R0 //restore the MSP from R0
|
||||
CPSIE i //enable interrupts and let PendSV fire
|
||||
BX LR //this return should never be triggered
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// void halInternalIdleSleep(void)
|
||||
//
|
||||
// A simple internal function call (to be called from halSleep) for executing
|
||||
// the WFI instruction and entering the simple, idle sleep state.
|
||||
//------------------------------------------------------------------------------
|
||||
__CODE__
|
||||
__THUMB__
|
||||
__EXPORT__ halInternalIdleSleep
|
||||
halInternalIdleSleep:
|
||||
WFI //trigger idle sleep
|
||||
BX LR //return
|
||||
|
||||
__END__
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue