//------------------------------------------------------------------------------ // @file hal/micro/cortexm3/spmr.s79 // @brief SPMR (Special Purpose Mask Registers) manipulation routines. // // Since the compiler does not provide low level intrinsic functions for some // required operations, this file maintains the small set of assembly code // needed to manipulate the Special Purpose Mask Registers. // // While it is possible to add this functionality as inline assembly in C files, // IAR highly recommends against this due to not only code being fragile in its // surroundings, but it also negates the possibility of size optimization. // // NOTE: This file looks more complicated than it really is. It was originally // generated by writing a C file and having the compiler generate the // corresponding assembly file. This is where all the CFI (Call Frame // Information) expressions came from. The CFI information enables proper debug // backtrace ability. The pieces to pay attention to are the actual funtions // near the end. // // * //------------------------------------------------------------------------------ #include "compiler/asm.h" // NOTE!! IF THIS VALUE IS CHANGED, NVIC-CONFIG.H MUST ALSO BE UPDATED #define INTERRUPTS_DISABLED_PRIORITY (12 << 3) __EXPORT__ _readBasePri __EXPORT__ _writeBasePri __EXPORT__ _disableBasePri __EXPORT__ _basePriIsDisabled __EXPORT__ _enableBasePri __EXPORT__ _setPriMask __EXPORT__ _clearPriMask __EXPORT__ _executeBarrierInstructions //------------------------------------------------------------------------------ // uint8_t _readBasePri(void) // // Read and return the BASEPRI value. // //------------------------------------------------------------------------------ __CODE__ __THUMB__ __CFI__(Block cfiBlock0 Using cfiCommon0) __CFI__(Function _readBasePri) _readBasePri: MRS R0, BASEPRI // read current BASEPRI BX LR __CFI__(EndBlock cfiBlock0) //------------------------------------------------------------------------------ // void _writeBasePri(uint8_t priority) // // Write BASEPRI with the passed value to obtain the proper preemptive priority // group masking. Note that the value passed must have been left shifted by 3 // to be properly aligned in the BASEPRI register. // (Refer to nvic-config.h for the PRIGROUP table.) // //------------------------------------------------------------------------------ __CODE__ __THUMB__ __CFI__(Block cfiBlock1 Using cfiCommon0) __CFI__(Function _writeBasePri) _writeBasePri: MSR BASEPRI, R0 // load BASEPRI from variable (R0) BX LR __CFI__(EndBlock cfiBlock1) //------------------------------------------------------------------------------ // uint8_t _disableBasePri(void) // // Set BASEPRI to mask out interrupts but allow faults. It returns the value // BASEPRI had when it was called. // //------------------------------------------------------------------------------ __CODE__ __THUMB__ __CFI__(Block cfiBlock2 Using cfiCommon0) __CFI__(Function _disableBasePri) _disableBasePri: MRS R0, BASEPRI // read current BASEPRI LDR R1, =INTERRUPTS_DISABLED_PRIORITY // disable ints, allow faults MSR BASEPRI, R1 BX LR __CFI__(EndBlock cfiBlock2) //------------------------------------------------------------------------------ // boolean _basePriIsDisabled(void) // // Compare BASEPRI to the priority used to disable interrupts (but not faults). // Return TRUE if the priority is higher or equal to that. // //------------------------------------------------------------------------------ __CODE__ __THUMB__ __CFI__(Block cfiBlock3 Using cfiCommon0) __CFI__(Function _basePriIsDisabled) _basePriIsDisabled: MRS R0, BASEPRI // read current BASEPRI CMP R0, #INTERRUPTS_DISABLED_PRIORITY ITE lt LDRLT R0, =0 LDRGE R0, =1 BX LR __CFI__(EndBlock cfiBlock3) //------------------------------------------------------------------------------ // void _enableBasePri(void) // // Set BASEPRI to 0, which disables it from masking any interrupts. // //------------------------------------------------------------------------------ __CODE__ __THUMB__ __CFI__(Block cfiBlock4 Using cfiCommon0) __CFI__(Function _enableBasePri) _enableBasePri: LDR R1, = 0 // zero disables BASEPRI masking MSR BASEPRI, R1 BX LR __CFI__(EndBlock cfiBlock4) //------------------------------------------------------------------------------ // void _setPriMask(void) // // Set the 1-bit PRIMASK register, which sets the base priority to 0. This // locks out all interrupts and configurable faults (usage, memory management // and bus faults). // // Note: generally speaking PRIMASK should not be set because faults should // be enabled even when interrupts are disabled. If they are not enabled, // a fault will immediately escalate to a hard fault. // //------------------------------------------------------------------------------ __CODE__ __THUMB__ __CFI__(Block cfiBlock5 Using cfiCommon0) __CFI__(Function _setPriMask) _setPriMask: CPSID i BX LR __CFI__(EndBlock cfiBlock5) //------------------------------------------------------------------------------ // void _clearPriMask(void) // // Clears the 1-bit PRIMASK register, which allows the BASEPRI value to // mask interrupts (if non-zero). // //------------------------------------------------------------------------------ __CODE__ __THUMB__ __CFI__(Block cfiBlock6 Using cfiCommon0) __CFI__(Function _clearPriMask) _clearPriMask: CPSIE i BX LR __CFI__(EndBlock cfiBlock6) //------------------------------------------------------------------------------ // void _executeBarrierInstructions(void) // //A utility function for inserting barrier instructions. These //instructions should be used whenever the MPU is enabled or disabled so //that all memory/instruction accesses can complete before the MPU changes //state. // //------------------------------------------------------------------------------ __CODE__ __THUMB__ __CFI__(Block cfiBlock7 Using cfiCommon0) __CFI__(Function _executeBarrierInstructions) _executeBarrierInstructions: DMB DSB ISB BX LR __CFI__(EndBlock cfiBlock7) __END__