]> begriffs open source - freertos/blob - portable/GCC/ARM_CR5/port.c
[AUTO][RELEASE]: Bump file header version to "10.4.3 LTS Patch 3"
[freertos] / portable / GCC / ARM_CR5 / port.c
1 /*\r
2  * FreeRTOS Kernel V10.4.3 LTS Patch 3\r
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * https://www.FreeRTOS.org\r
23  * https://github.com/FreeRTOS\r
24  *\r
25  */\r
26 \r
27 /* Standard includes. */\r
28 #include <stdlib.h>\r
29 \r
30 /* Scheduler includes. */\r
31 #include "FreeRTOS.h"\r
32 #include "task.h"\r
33 \r
34 #ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS\r
35     #error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined.  Refer to Cortex-A equivalent: http: /*www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */\r
36 #endif\r
37 \r
38 #ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET\r
39     #error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined.  Refer to Cortex-A equivalent: http: /*www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */\r
40 #endif\r
41 \r
42 #ifndef configUNIQUE_INTERRUPT_PRIORITIES\r
43     #error configUNIQUE_INTERRUPT_PRIORITIES must be defined.  Refer to Cortex-A equivalent: http: /*www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */\r
44 #endif\r
45 \r
46 #ifndef configSETUP_TICK_INTERRUPT\r
47     #error configSETUP_TICK_INTERRUPT() must be defined.  Refer to Cortex-A equivalent: http: /*www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */\r
48 #endif /* configSETUP_TICK_INTERRUPT */\r
49 \r
50 #ifndef configMAX_API_CALL_INTERRUPT_PRIORITY\r
51     #error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined.  Refer to Cortex-A equivalent: http: /*www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */\r
52 #endif\r
53 \r
54 #if configMAX_API_CALL_INTERRUPT_PRIORITY == 0\r
55     #error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0\r
56 #endif\r
57 \r
58 #if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES\r
59     #error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority\r
60 #endif\r
61 \r
62 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1\r
63     /* Check the configuration. */\r
64     #if ( configMAX_PRIORITIES > 32 )\r
65         #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.\r
66     #endif\r
67 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
68 \r
69 /* In case security extensions are implemented. */\r
70 #if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )\r
71     #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )\r
72 #endif\r
73 \r
74 /* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in\r
75  * portmacro.h. */\r
76 #ifndef configCLEAR_TICK_INTERRUPT\r
77     #define configCLEAR_TICK_INTERRUPT()\r
78 #endif\r
79 \r
80 /* A critical section is exited when the critical section nesting count reaches\r
81  * this value. */\r
82 #define portNO_CRITICAL_NESTING          ( ( uint32_t ) 0 )\r
83 \r
84 /* In all GICs 255 can be written to the priority mask register to unmask all\r
85  * (but the lowest) interrupt priority. */\r
86 #define portUNMASK_VALUE                 ( 0xFFUL )\r
87 \r
88 /* Tasks are not created with a floating point context, but can be given a\r
89  * floating point context after they have been created.  A variable is stored as\r
90  * part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task\r
91  * does not have an FPU context, or any other value if the task does have an FPU\r
92  * context. */\r
93 #define portNO_FLOATING_POINT_CONTEXT    ( ( StackType_t ) 0 )\r
94 \r
95 /* Constants required to setup the initial task context. */\r
96 #define portINITIAL_SPSR                 ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */\r
97 #define portTHUMB_MODE_BIT               ( ( StackType_t ) 0x20 )\r
98 #define portINTERRUPT_ENABLE_BIT         ( 0x80UL )\r
99 #define portTHUMB_MODE_ADDRESS           ( 0x01UL )\r
100 \r
101 /* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary\r
102  * point is zero. */\r
103 #define portBINARY_POINT_BITS            ( ( uint8_t ) 0x03 )\r
104 \r
105 /* Masks all bits in the APSR other than the mode bits. */\r
106 #define portAPSR_MODE_BITS_MASK          ( 0x1F )\r
107 \r
108 /* The value of the mode bits in the APSR when the CPU is executing in user\r
109  * mode. */\r
110 #define portAPSR_USER_MODE               ( 0x10 )\r
111 \r
112 /* The critical section macros only mask interrupts up to an application\r
113  * determined priority level.  Sometimes it is necessary to turn interrupt off in\r
114  * the CPU itself before modifying certain hardware registers. */\r
115 #define portCPU_IRQ_DISABLE()                  \\r
116     __asm volatile ( "CPSID i" ::: "memory" ); \\r
117     __asm volatile ( "DSB" );                  \\r
118     __asm volatile ( "ISB" );\r
119 \r
120 #define portCPU_IRQ_ENABLE()                   \\r
121     __asm volatile ( "CPSIE i" ::: "memory" ); \\r
122     __asm volatile ( "DSB" );                  \\r
123     __asm volatile ( "ISB" );\r
124 \r
125 \r
126 /* Macro to unmask all interrupt priorities. */\r
127 #define portCLEAR_INTERRUPT_MASK()                            \\r
128     {                                                         \\r
129         portCPU_IRQ_DISABLE();                                \\r
130         portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \\r
131         __asm volatile ( "DSB           \n"                       \\r
132                          "ISB           \n");                         \\r
133         portCPU_IRQ_ENABLE();                                 \\r
134     }\r
135 \r
136 #define portINTERRUPT_PRIORITY_REGISTER_OFFSET    0x400UL\r
137 #define portMAX_8_BIT_VALUE                       ( ( uint8_t ) 0xff )\r
138 #define portBIT_0_SET                             ( ( uint8_t ) 0x01 )\r
139 \r
140 /* Let the user override the pre-loading of the initial LR with the address of\r
141  * prvTaskExitError() in case is messes up unwinding of the stack in the\r
142  * debugger. */\r
143 #ifdef configTASK_RETURN_ADDRESS\r
144     #define portTASK_RETURN_ADDRESS    configTASK_RETURN_ADDRESS\r
145 #else\r
146     #define portTASK_RETURN_ADDRESS    prvTaskExitError\r
147 #endif\r
148 \r
149 /*-----------------------------------------------------------*/\r
150 \r
151 /*\r
152  * Starts the first task executing.  This function is necessarily written in\r
153  * assembly code so is implemented in portASM.s.\r
154  */\r
155 extern void vPortRestoreTaskContext( void );\r
156 \r
157 /*\r
158  * Used to catch tasks that attempt to return from their implementing function.\r
159  */\r
160 static void prvTaskExitError( void );\r
161 \r
162 /*-----------------------------------------------------------*/\r
163 \r
164 /* A variable is used to keep track of the critical section nesting.  This\r
165  * variable has to be stored as part of the task context and must be initialised to\r
166  * a non zero value to ensure interrupts don't inadvertently become unmasked before\r
167  * the scheduler starts.  As it is stored as part of the task context it will\r
168  * automatically be set to 0 when the first task is started. */\r
169 volatile uint32_t ulCriticalNesting = 9999UL;\r
170 \r
171 /* Saved as part of the task context.  If ulPortTaskHasFPUContext is non-zero then\r
172  * a floating point context must be saved and restored for the task. */\r
173 uint32_t ulPortTaskHasFPUContext = pdFALSE;\r
174 \r
175 /* Set to 1 to pend a context switch from an ISR. */\r
176 uint32_t ulPortYieldRequired = pdFALSE;\r
177 \r
178 /* Counts the interrupt nesting depth.  A context switch is only performed if\r
179  * if the nesting depth is 0. */\r
180 uint32_t ulPortInterruptNesting = 0UL;\r
181 \r
182 /* Used in asm code. */\r
183 __attribute__( ( used ) ) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;\r
184 __attribute__( ( used ) ) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;\r
185 __attribute__( ( used ) ) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;\r
186 __attribute__( ( used ) ) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
187 \r
188 /*-----------------------------------------------------------*/\r
189 \r
190 /*\r
191  * See header file for description.\r
192  */\r
193 StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,\r
194                                      TaskFunction_t pxCode,\r
195                                      void * pvParameters )\r
196 {\r
197     /* Setup the initial stack of the task.  The stack is set exactly as\r
198      * expected by the portRESTORE_CONTEXT() macro.\r
199      *\r
200      * The fist real value on the stack is the status register, which is set for\r
201      * system mode, with interrupts enabled.  A few NULLs are added first to ensure\r
202      * GDB does not try decoding a non-existent return address. */\r
203     *pxTopOfStack = ( StackType_t ) NULL;\r
204     pxTopOfStack--;\r
205     *pxTopOfStack = ( StackType_t ) NULL;\r
206     pxTopOfStack--;\r
207     *pxTopOfStack = ( StackType_t ) NULL;\r
208     pxTopOfStack--;\r
209     *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;\r
210 \r
211     if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )\r
212     {\r
213         /* The task will start in THUMB mode. */\r
214         *pxTopOfStack |= portTHUMB_MODE_BIT;\r
215     }\r
216 \r
217     pxTopOfStack--;\r
218 \r
219     /* Next the return address, which in this case is the start of the task. */\r
220     *pxTopOfStack = ( StackType_t ) pxCode;\r
221     pxTopOfStack--;\r
222 \r
223     /* Next all the registers other than the stack pointer. */\r
224     *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */\r
225     pxTopOfStack--;\r
226     *pxTopOfStack = ( StackType_t ) 0x12121212;              /* R12 */\r
227     pxTopOfStack--;\r
228     *pxTopOfStack = ( StackType_t ) 0x11111111;              /* R11 */\r
229     pxTopOfStack--;\r
230     *pxTopOfStack = ( StackType_t ) 0x10101010;              /* R10 */\r
231     pxTopOfStack--;\r
232     *pxTopOfStack = ( StackType_t ) 0x09090909;              /* R9 */\r
233     pxTopOfStack--;\r
234     *pxTopOfStack = ( StackType_t ) 0x08080808;              /* R8 */\r
235     pxTopOfStack--;\r
236     *pxTopOfStack = ( StackType_t ) 0x07070707;              /* R7 */\r
237     pxTopOfStack--;\r
238     *pxTopOfStack = ( StackType_t ) 0x06060606;              /* R6 */\r
239     pxTopOfStack--;\r
240     *pxTopOfStack = ( StackType_t ) 0x05050505;              /* R5 */\r
241     pxTopOfStack--;\r
242     *pxTopOfStack = ( StackType_t ) 0x04040404;              /* R4 */\r
243     pxTopOfStack--;\r
244     *pxTopOfStack = ( StackType_t ) 0x03030303;              /* R3 */\r
245     pxTopOfStack--;\r
246     *pxTopOfStack = ( StackType_t ) 0x02020202;              /* R2 */\r
247     pxTopOfStack--;\r
248     *pxTopOfStack = ( StackType_t ) 0x01010101;              /* R1 */\r
249     pxTopOfStack--;\r
250     *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0 */\r
251     pxTopOfStack--;\r
252 \r
253     /* The task will start with a critical nesting count of 0 as interrupts are\r
254      * enabled. */\r
255     *pxTopOfStack = portNO_CRITICAL_NESTING;\r
256     pxTopOfStack--;\r
257 \r
258     /* The task will start without a floating point context.  A task that uses\r
259      * the floating point hardware must call vPortTaskUsesFPU() before executing\r
260      * any floating point instructions. */\r
261     *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;\r
262 \r
263     return pxTopOfStack;\r
264 }\r
265 /*-----------------------------------------------------------*/\r
266 \r
267 static void prvTaskExitError( void )\r
268 {\r
269     /* A function that implements a task must not exit or attempt to return to\r
270      * its caller as there is nothing to return to.  If a task wants to exit it\r
271      * should instead call vTaskDelete( NULL ).\r
272      *\r
273      * Artificially force an assert() to be triggered if configASSERT() is\r
274      * defined, then stop here so application writers can catch the error. */\r
275     configASSERT( ulPortInterruptNesting == ~0UL );\r
276     portDISABLE_INTERRUPTS();\r
277 \r
278     for( ; ; )\r
279     {\r
280     }\r
281 }\r
282 /*-----------------------------------------------------------*/\r
283 \r
284 BaseType_t xPortStartScheduler( void )\r
285 {\r
286     uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */\r
287 \r
288     #if ( configASSERT_DEFINED == 1 )\r
289         {\r
290             volatile uint32_t ulOriginalPriority;\r
291             volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );\r
292             volatile uint8_t ucMaxPriorityValue;\r
293 \r
294             /* Determine how many priority bits are implemented in the GIC.\r
295              *\r
296              * Save the interrupt priority value that is about to be clobbered. */\r
297             ulOriginalPriority = *pucFirstUserPriorityRegister;\r
298 \r
299             /* Determine the number of priority bits available.  First write to\r
300              * all possible bits. */\r
301             *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;\r
302 \r
303             /* Read the value back to see how many bits stuck. */\r
304             ucMaxPriorityValue = *pucFirstUserPriorityRegister;\r
305 \r
306             /* Shift to the least significant bits. */\r
307             while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )\r
308             {\r
309                 ucMaxPriorityValue >>= ( uint8_t ) 0x01;\r
310 \r
311                 /* If ulCycles reaches 0 then ucMaxPriorityValue must have been\r
312                  * read as 0, indicating a misconfiguration. */\r
313                 ulCycles--;\r
314 \r
315                 if( ulCycles == 0 )\r
316                 {\r
317                     break;\r
318                 }\r
319             }\r
320 \r
321             /* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read\r
322              * value. */\r
323             configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );\r
324 \r
325             /* Restore the clobbered interrupt priority register to its original\r
326              * value. */\r
327             *pucFirstUserPriorityRegister = ulOriginalPriority;\r
328         }\r
329     #endif /* conifgASSERT_DEFINED */\r
330 \r
331     /* Only continue if the CPU is not in User mode.  The CPU must be in a\r
332      * Privileged mode for the scheduler to start. */\r
333     __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR )::"memory" );\r
334     ulAPSR &= portAPSR_MODE_BITS_MASK;\r
335     configASSERT( ulAPSR != portAPSR_USER_MODE );\r
336 \r
337     if( ulAPSR != portAPSR_USER_MODE )\r
338     {\r
339         /* Only continue if the binary point value is set to its lowest possible\r
340          * setting.  See the comments in vPortValidateInterruptPriority() below for\r
341          * more information. */\r
342         configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );\r
343 \r
344         if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )\r
345         {\r
346             /* Interrupts are turned off in the CPU itself to ensure tick does\r
347              * not execute      while the scheduler is being started.  Interrupts are\r
348              * automatically turned back on in the CPU when the first task starts\r
349              * executing. */\r
350             portCPU_IRQ_DISABLE();\r
351 \r
352             /* Start the timer that generates the tick ISR. */\r
353             configSETUP_TICK_INTERRUPT();\r
354 \r
355             /* Start the first task executing. */\r
356             vPortRestoreTaskContext();\r
357         }\r
358     }\r
359 \r
360     /* Will only get here if vTaskStartScheduler() was called with the CPU in\r
361      * a non-privileged mode or the binary point register was not set to its lowest\r
362      * possible value.  prvTaskExitError() is referenced to prevent a compiler\r
363      * warning about it being defined but not referenced in the case that the user\r
364      * defines their own exit address. */\r
365     ( void ) prvTaskExitError;\r
366     return 0;\r
367 }\r
368 /*-----------------------------------------------------------*/\r
369 \r
370 void vPortEndScheduler( void )\r
371 {\r
372     /* Not implemented in ports where there is nothing to return to.\r
373      * Artificially force an assert. */\r
374     configASSERT( ulCriticalNesting == 1000UL );\r
375 }\r
376 /*-----------------------------------------------------------*/\r
377 \r
378 void vPortEnterCritical( void )\r
379 {\r
380     /* Mask interrupts up to the max syscall interrupt priority. */\r
381     ulPortSetInterruptMask();\r
382 \r
383     /* Now interrupts are disabled ulCriticalNesting can be accessed\r
384      * directly.  Increment ulCriticalNesting to keep a count of how many times\r
385      * portENTER_CRITICAL() has been called. */\r
386     ulCriticalNesting++;\r
387 \r
388     /* This is not the interrupt safe version of the enter critical function so\r
389      * assert() if it is being called from an interrupt context.  Only API\r
390      * functions that end in "FromISR" can be used in an interrupt.  Only assert if\r
391      * the critical nesting count is 1 to protect against recursive calls if the\r
392      * assert function also uses a critical section. */\r
393     if( ulCriticalNesting == 1 )\r
394     {\r
395         configASSERT( ulPortInterruptNesting == 0 );\r
396     }\r
397 }\r
398 /*-----------------------------------------------------------*/\r
399 \r
400 void vPortExitCritical( void )\r
401 {\r
402     if( ulCriticalNesting > portNO_CRITICAL_NESTING )\r
403     {\r
404         /* Decrement the nesting count as the critical section is being\r
405          * exited. */\r
406         ulCriticalNesting--;\r
407 \r
408         /* If the nesting level has reached zero then all interrupt\r
409          * priorities must be re-enabled. */\r
410         if( ulCriticalNesting == portNO_CRITICAL_NESTING )\r
411         {\r
412             /* Critical nesting has reached zero so all interrupt priorities\r
413              * should be unmasked. */\r
414             portCLEAR_INTERRUPT_MASK();\r
415         }\r
416     }\r
417 }\r
418 /*-----------------------------------------------------------*/\r
419 \r
420 void FreeRTOS_Tick_Handler( void )\r
421 {\r
422     /* Set interrupt mask before altering scheduler structures.   The tick\r
423      * handler runs at the lowest priority, so interrupts cannot already be masked,\r
424      * so there is no need to save and restore the current mask value.  It is\r
425      * necessary to turn off interrupts in the CPU itself while the ICCPMR is being\r
426      * updated. */\r
427     portCPU_IRQ_DISABLE();\r
428     portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
429     __asm volatile ( "dsb               \n"\r
430                      "isb               \n"::: "memory" );\r
431     portCPU_IRQ_ENABLE();\r
432 \r
433     /* Increment the RTOS tick. */\r
434     if( xTaskIncrementTick() != pdFALSE )\r
435     {\r
436         ulPortYieldRequired = pdTRUE;\r
437     }\r
438 \r
439     /* Ensure all interrupt priorities are active again. */\r
440     portCLEAR_INTERRUPT_MASK();\r
441     configCLEAR_TICK_INTERRUPT();\r
442 }\r
443 /*-----------------------------------------------------------*/\r
444 \r
445 void vPortTaskUsesFPU( void )\r
446 {\r
447     uint32_t ulInitialFPSCR = 0;\r
448 \r
449     /* A task is registering the fact that it needs an FPU context.  Set the\r
450      * FPU flag (which is saved as part of the task context). */\r
451     ulPortTaskHasFPUContext = pdTRUE;\r
452 \r
453     /* Initialise the floating point status register. */\r
454     __asm volatile ( "FMXR      FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" );\r
455 }\r
456 /*-----------------------------------------------------------*/\r
457 \r
458 void vPortClearInterruptMask( uint32_t ulNewMaskValue )\r
459 {\r
460     if( ulNewMaskValue == pdFALSE )\r
461     {\r
462         portCLEAR_INTERRUPT_MASK();\r
463     }\r
464 }\r
465 /*-----------------------------------------------------------*/\r
466 \r
467 uint32_t ulPortSetInterruptMask( void )\r
468 {\r
469     uint32_t ulReturn;\r
470 \r
471     /* Interrupt in the CPU must be turned off while the ICCPMR is being\r
472      * updated. */\r
473     portCPU_IRQ_DISABLE();\r
474 \r
475     if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )\r
476     {\r
477         /* Interrupts were already masked. */\r
478         ulReturn = pdTRUE;\r
479     }\r
480     else\r
481     {\r
482         ulReturn = pdFALSE;\r
483         portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
484         __asm volatile ( "dsb           \n"\r
485                          "isb           \n"::: "memory" );\r
486     }\r
487 \r
488     portCPU_IRQ_ENABLE();\r
489 \r
490     return ulReturn;\r
491 }\r
492 /*-----------------------------------------------------------*/\r
493 \r
494 #if ( configASSERT_DEFINED == 1 )\r
495 \r
496     void vPortValidateInterruptPriority( void )\r
497     {\r
498         /* The following assertion will fail if a service routine (ISR) for\r
499          * an interrupt that has been assigned a priority above\r
500          * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API\r
501          * function.  ISR safe FreeRTOS API functions must *only* be called\r
502          * from interrupts that have been assigned a priority at or below\r
503          * configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
504          *\r
505          * Numerically low interrupt priority numbers represent logically high\r
506          * interrupt priorities, therefore the priority of the interrupt must\r
507          * be set to a value equal to or numerically *higher* than\r
508          * configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
509          *\r
510          * FreeRTOS maintains separate thread and ISR API functions to ensure\r
511          * interrupt entry is as fast and simple as possible. */\r
512 \r
513         configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );\r
514 \r
515         /* Priority grouping:  The interrupt controller (GIC) allows the bits\r
516          * that define each interrupt's priority to be split between bits that\r
517          * define the interrupt's pre-emption priority bits and bits that define\r
518          * the interrupt's sub-priority.  For simplicity all bits must be defined\r
519          * to be pre-emption priority bits.  The following assertion will fail if\r
520          * this is not the case (if some bits represent a sub-priority).\r
521          *\r
522          * The priority grouping is configured by the GIC's binary point register\r
523          * (ICCBPR).  Writing 0 to ICCBPR will ensure it is set to its lowest\r
524          * possible value (which may be above 0). */\r
525         configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );\r
526     }\r
527 \r
528 #endif /* configASSERT_DEFINED */\r
529 /*-----------------------------------------------------------*/\r