mode. */\r
#define portAPSR_USER_MODE ( 0x10 )\r
\r
+/* The critical section macros only mask interrupts up to an application\r
+determined priority level. Sometimes it is necessary to turn interrupt off in\r
+the CPU itself before modifying certain hardware registers. */\r
+#define portCPU_IRQ_DISABLE() \\r
+ __asm volatile ( "CPSID i" ); \\r
+ __asm volatile ( "DSB" ); \\r
+ __asm volatile ( "ISB" );\r
+\r
+#define portCPU_IRQ_ENABLE() \\r
+ __asm volatile ( "CPSIE i" ); \\r
+ __asm volatile ( "DSB" ); \\r
+ __asm volatile ( "ISB" );\r
+\r
+\r
/* Macro to unmask all interrupt priorities. */\r
#define portCLEAR_INTERRUPT_MASK() \\r
{ \\r
- __asm volatile ( "cpsid i" ); \\r
- __asm volatile ( "dsb" ); \\r
- __asm volatile ( "isb" ); \\r
+ portCPU_IRQ_DISABLE(); \\r
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \\r
__asm( "DSB \n" \\r
"ISB \n" ); \\r
- __asm volatile( "cpsie i" ); \\r
- __asm volatile ( "dsb" ); \\r
- __asm volatile ( "isb" ); \\r
+ portCPU_IRQ_ENABLE(); \\r
}\r
\r
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL\r
\r
#if configINSTALL_FREERTOS_VECTOR_TABLE == 1\r
{\r
+ extern void vPortInstallFreeRTOSVectorTable( void );\r
+\r
vPortInstallFreeRTOSVectorTable();\r
}\r
#endif\r
\r
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )\r
{\r
- /* Start the timer that generates the tick ISR. */\r
- __asm volatile( "cpsid i" );\r
+ /* Start the timer that generates the tick ISR. Interrupts are\r
+ turned off in the CPU itself to ensure the tick does not execute\r
+ while the scheduler is being started. Interrupts are automatically\r
+ turned back on in the CPU when the first task starts executing. */\r
+ portCPU_IRQ_DISABLE();\r
configSETUP_TICK_INTERRUPT();\r
-\r
-// __asm volatile( "cpsie i" );\r
vPortRestoreTaskContext();\r
}\r
}\r
\r
void vPortEnterCritical( void )\r
{\r
- /* Disable interrupts as per portDISABLE_INTERRUPTS(); */\r
+ /* Mask interrupts up to the max syscall interrupt priority. */\r
ulPortSetInterruptMask();\r
\r
/* Now interrupts are disabled ulCriticalNesting can be accessed\r
{\r
/* Set interrupt mask before altering scheduler structures. The tick\r
handler runs at the lowest priority, so interrupts cannot already be masked,\r
- so there is no need to save and restore the current mask value. */\r
- __asm volatile( "cpsid i" );\r
- __asm volatile ( "dsb" );\r
- __asm volatile ( "isb" );\r
+ so there is no need to save and restore the current mask value. It is\r
+ necessary to turn off interrupts in the CPU itself while the ICCPMR is being\r
+ updated. */\r
+ portCPU_IRQ_DISABLE();\r
portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
__asm( "dsb \n"\r
- "isb \n"\r
- "cpsie i \n"\r
- "dsb \n"\r
- "isb" );\r
+ "isb \n" );\r
+ portCPU_IRQ_ENABLE();\r
\r
/* Increment the RTOS tick. */\r
if( xTaskIncrementTick() != pdFALSE )\r
{\r
uint32_t ulReturn;\r
\r
- __asm volatile ( "cpsid i" );\r
- __asm volatile ( "dsb" );\r
- __asm volatile ( "isb" );\r
+ /* Interrupt in the CPU must be turned off while the ICCPMR is being\r
+ updated. */\r
+ portCPU_IRQ_DISABLE();\r
if( portICCPMR_PRIORITY_MASK_REGISTER == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )\r
{\r
/* Interrupts were already masked. */\r
__asm( "dsb \n"\r
"isb \n" );\r
}\r
- __asm volatile ( "cpsie i" );\r
- __asm volatile ( "dsb" );\r
- __asm volatile ( "isb" );\r
+ portCPU_IRQ_ENABLE();\r
\r
return ulReturn;\r
}\r