port.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. /*
  2. * FreeRTOS Kernel V10.4.3 LTS Patch 2
  3. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  6. * this software and associated documentation files (the "Software"), to deal in
  7. * the Software without restriction, including without limitation the rights to
  8. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  9. * the Software, and to permit persons to whom the Software is furnished to do so,
  10. * subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in all
  13. * copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  17. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  18. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  19. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  20. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. * https://www.FreeRTOS.org
  23. * https://github.com/FreeRTOS
  24. *
  25. */
  26. /*-----------------------------------------------------------
  27. * Implementation of functions defined in portable.h for the ARM CM4 MPU port.
  28. *----------------------------------------------------------*/
  29. /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
  30. * all the API functions to use the MPU wrappers. That should only be done when
  31. * task.h is included from an application file. */
  32. #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
  33. /* Scheduler includes. */
  34. #include "FreeRTOS.h"
  35. #include "task.h"
  36. #ifndef __VFP_FP__
  37. #error This port can only be used when the project options are configured to enable hardware floating point support.
  38. #endif
  39. #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
  40. #ifndef configSYSTICK_CLOCK_HZ
  41. #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
  42. /* Ensure the SysTick is clocked at the same frequency as the core. */
  43. #define portNVIC_SYSTICK_CLK ( 1UL << 2UL )
  44. #else
  45. /* The way the SysTick is clocked is not modified in case it is not the same
  46. * as the core. */
  47. #define portNVIC_SYSTICK_CLK ( 0 )
  48. #endif
  49. /* Constants required to access and manipulate the NVIC. */
  50. #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
  51. #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
  52. #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
  53. #define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
  54. #define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xe000ed1c ) )
  55. #define portNVIC_SYS_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
  56. #define portNVIC_MEM_FAULT_ENABLE ( 1UL << 16UL )
  57. /* Constants required to access and manipulate the MPU. */
  58. #define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
  59. #define portMPU_REGION_BASE_ADDRESS_REG ( *( ( volatile uint32_t * ) 0xe000ed9C ) )
  60. #define portMPU_REGION_ATTRIBUTE_REG ( *( ( volatile uint32_t * ) 0xe000edA0 ) )
  61. #define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
  62. #define portEXPECTED_MPU_TYPE_VALUE ( portTOTAL_NUM_REGIONS << 8UL )
  63. #define portMPU_ENABLE ( 0x01UL )
  64. #define portMPU_BACKGROUND_ENABLE ( 1UL << 2UL )
  65. #define portPRIVILEGED_EXECUTION_START_ADDRESS ( 0UL )
  66. #define portMPU_REGION_VALID ( 0x10UL )
  67. #define portMPU_REGION_ENABLE ( 0x01UL )
  68. #define portPERIPHERALS_START_ADDRESS 0x40000000UL
  69. #define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL
  70. /* Constants required to access and manipulate the SysTick. */
  71. #define portNVIC_SYSTICK_INT ( 0x00000002UL )
  72. #define portNVIC_SYSTICK_ENABLE ( 0x00000001UL )
  73. #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
  74. #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
  75. #define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL )
  76. /* Constants required to manipulate the VFP. */
  77. #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */
  78. #define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
  79. /* Constants required to set up the initial stack. */
  80. #define portINITIAL_XPSR ( 0x01000000UL )
  81. #define portINITIAL_EXC_RETURN ( 0xfffffffdUL )
  82. #define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 )
  83. #define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 )
  84. /* Constants required to check the validity of an interrupt priority. */
  85. #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
  86. #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
  87. #define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) )
  88. #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
  89. #define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
  90. #define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
  91. #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
  92. #define portPRIGROUP_SHIFT ( 8UL )
  93. /* Offsets in the stack to the parameters when inside the SVC handler. */
  94. #define portOFFSET_TO_PC ( 6 )
  95. /* For strict compliance with the Cortex-M spec the task start address should
  96. * have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
  97. #define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
  98. /*
  99. * Configure a number of standard MPU regions that are used by all tasks.
  100. */
  101. static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
  102. /*
  103. * Return the smallest MPU region size that a given number of bytes will fit
  104. * into. The region size is returned as the value that should be programmed
  105. * into the region attribute register for that region.
  106. */
  107. static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVILEGED_FUNCTION;
  108. /*
  109. * Setup the timer to generate the tick interrupts. The implementation in this
  110. * file is weak to allow application writers to change the timer used to
  111. * generate the tick interrupt.
  112. */
  113. void vPortSetupTimerInterrupt( void );
  114. /*
  115. * Standard FreeRTOS exception handlers.
  116. */
  117. void xPortPendSVHandler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
  118. void xPortSysTickHandler( void ) PRIVILEGED_FUNCTION;
  119. void vPortSVCHandler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
  120. /*
  121. * Starts the scheduler by restoring the context of the first task to run.
  122. */
  123. static void prvRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
  124. /*
  125. * C portion of the SVC handler. The SVC handler is split between an asm entry
  126. * and a C wrapper for simplicity of coding and maintenance.
  127. */
  128. static void prvSVCHandler( uint32_t * pulRegisters ) __attribute__( ( noinline ) ) PRIVILEGED_FUNCTION;
  129. /*
  130. * Function to enable the VFP.
  131. */
  132. static void vPortEnableVFP( void ) __attribute__( ( naked ) );
  133. /**
  134. * @brief Checks whether or not the processor is privileged.
  135. *
  136. * @return 1 if the processor is already privileged, 0 otherwise.
  137. */
  138. BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
  139. /**
  140. * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
  141. * register.
  142. *
  143. * Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
  144. * Bit[0] = 0 --> The processor is running privileged
  145. * Bit[0] = 1 --> The processor is running unprivileged.
  146. */
  147. void vResetPrivilege( void ) __attribute__( ( naked ) );
  148. /**
  149. * @brief Enter critical section.
  150. */
  151. void vPortEnterCritical( void ) FREERTOS_SYSTEM_CALL;
  152. /**
  153. * @brief Exit from critical section.
  154. */
  155. void vPortExitCritical( void ) FREERTOS_SYSTEM_CALL;
  156. /*-----------------------------------------------------------*/
  157. /* Each task maintains its own interrupt status in the critical nesting
  158. * variable. Note this is not saved as part of the task context as context
  159. * switches can only occur when uxCriticalNesting is zero. */
  160. static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
  161. /*
  162. * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
  163. * FreeRTOS API functions are not called from interrupts that have been assigned
  164. * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
  165. */
  166. #if ( configASSERT_DEFINED == 1 )
  167. static uint8_t ucMaxSysCallPriority = 0;
  168. static uint32_t ulMaxPRIGROUPValue = 0;
  169. static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
  170. #endif /* configASSERT_DEFINED */
  171. /*-----------------------------------------------------------*/
  172. /*
  173. * See header file for description.
  174. */
  175. StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
  176. TaskFunction_t pxCode,
  177. void * pvParameters,
  178. BaseType_t xRunPrivileged )
  179. {
  180. /* Simulate the stack frame as it would be created by a context switch
  181. * interrupt. */
  182. pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
  183. *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
  184. pxTopOfStack--;
  185. *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
  186. pxTopOfStack--;
  187. *pxTopOfStack = 0; /* LR */
  188. pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
  189. *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
  190. /* A save method is being used that requires each task to maintain its
  191. * own exec return value. */
  192. pxTopOfStack--;
  193. *pxTopOfStack = portINITIAL_EXC_RETURN;
  194. pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
  195. if( xRunPrivileged == pdTRUE )
  196. {
  197. *pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED;
  198. }
  199. else
  200. {
  201. *pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED;
  202. }
  203. return pxTopOfStack;
  204. }
  205. /*-----------------------------------------------------------*/
  206. void vPortSVCHandler( void )
  207. {
  208. /* Assumes psp was in use. */
  209. __asm volatile
  210. (
  211. #ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */
  212. " tst lr, #4 \n"
  213. " ite eq \n"
  214. " mrseq r0, msp \n"
  215. " mrsne r0, psp \n"
  216. #else
  217. " mrs r0, psp \n"
  218. #endif
  219. " b %0 \n"
  220. ::"i" ( prvSVCHandler ) : "r0", "memory"
  221. );
  222. }
  223. /*-----------------------------------------------------------*/
  224. static void prvSVCHandler( uint32_t * pulParam )
  225. {
  226. uint8_t ucSVCNumber;
  227. uint32_t ulPC;
  228. #if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
  229. #if defined( __ARMCC_VERSION )
  230. /* Declaration when these variable are defined in code instead of being
  231. * exported from linker scripts. */
  232. extern uint32_t * __syscalls_flash_start__;
  233. extern uint32_t * __syscalls_flash_end__;
  234. #else
  235. /* Declaration when these variable are exported from linker scripts. */
  236. extern uint32_t __syscalls_flash_start__[];
  237. extern uint32_t __syscalls_flash_end__[];
  238. #endif /* #if defined( __ARMCC_VERSION ) */
  239. #endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
  240. /* The stack contains: r0, r1, r2, r3, r12, LR, PC and xPSR. The first
  241. * argument (r0) is pulParam[ 0 ]. */
  242. ulPC = pulParam[ portOFFSET_TO_PC ];
  243. ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
  244. switch( ucSVCNumber )
  245. {
  246. case portSVC_START_SCHEDULER:
  247. portNVIC_SHPR2_REG |= portNVIC_SVC_PRI;
  248. prvRestoreContextOfFirstTask();
  249. break;
  250. case portSVC_YIELD:
  251. portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
  252. /* Barriers are normally not required
  253. * but do ensure the code is completely
  254. * within the specified behaviour for the
  255. * architecture. */
  256. __asm volatile ( "dsb" ::: "memory" );
  257. __asm volatile ( "isb" );
  258. break;
  259. #if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
  260. case portSVC_RAISE_PRIVILEGE: /* Only raise the privilege, if the
  261. * svc was raised from any of the
  262. * system calls. */
  263. if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
  264. ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
  265. {
  266. __asm volatile
  267. (
  268. " mrs r1, control \n"/* Obtain current control value. */
  269. " bic r1, #1 \n"/* Set privilege bit. */
  270. " msr control, r1 \n"/* Write back new control value. */
  271. ::: "r1", "memory"
  272. );
  273. }
  274. break;
  275. #else /* if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
  276. case portSVC_RAISE_PRIVILEGE:
  277. __asm volatile
  278. (
  279. " mrs r1, control \n"/* Obtain current control value. */
  280. " bic r1, #1 \n"/* Set privilege bit. */
  281. " msr control, r1 \n"/* Write back new control value. */
  282. ::: "r1", "memory"
  283. );
  284. break;
  285. #endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
  286. default: /* Unknown SVC call. */
  287. break;
  288. }
  289. }
  290. /*-----------------------------------------------------------*/
  291. static void prvRestoreContextOfFirstTask( void )
  292. {
  293. __asm volatile
  294. (
  295. " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */
  296. " ldr r0, [r0] \n"
  297. " ldr r0, [r0] \n"
  298. " msr msp, r0 \n"/* Set the msp back to the start of the stack. */
  299. " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */
  300. " ldr r1, [r3] \n"
  301. " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */
  302. " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */
  303. " \n"
  304. " dmb \n"/* Complete outstanding transfers before disabling MPU. */
  305. " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
  306. " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
  307. " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
  308. " str r3, [r2] \n"/* Disable MPU. */
  309. " \n"
  310. " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */
  311. " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
  312. " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
  313. " \n"
  314. #if ( portTOTAL_NUM_REGIONS == 16 )
  315. " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
  316. " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
  317. " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
  318. " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
  319. #endif /* portTOTAL_NUM_REGIONS == 16. */
  320. " \n"
  321. " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
  322. " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
  323. " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
  324. " str r3, [r2] \n"/* Enable MPU. */
  325. " dsb \n"/* Force memory writes before continuing. */
  326. " \n"
  327. " ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */
  328. " msr control, r3 \n"
  329. " msr psp, r0 \n"/* Restore the task stack pointer. */
  330. " mov r0, #0 \n"
  331. " msr basepri, r0 \n"
  332. " bx r14 \n"
  333. " \n"
  334. " .align 4 \n"
  335. "pxCurrentTCBConst2: .word pxCurrentTCB \n"
  336. );
  337. }
  338. /*-----------------------------------------------------------*/
  339. /*
  340. * See header file for description.
  341. */
  342. BaseType_t xPortStartScheduler( void )
  343. {
  344. /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See
  345. * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
  346. configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
  347. #if ( configASSERT_DEFINED == 1 )
  348. {
  349. volatile uint32_t ulOriginalPriority;
  350. volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
  351. volatile uint8_t ucMaxPriorityValue;
  352. /* Determine the maximum priority from which ISR safe FreeRTOS API
  353. * functions can be called. ISR safe functions are those that end in
  354. * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
  355. * ensure interrupt entry is as fast and simple as possible.
  356. *
  357. * Save the interrupt priority value that is about to be clobbered. */
  358. ulOriginalPriority = *pucFirstUserPriorityRegister;
  359. /* Determine the number of priority bits available. First write to all
  360. * possible bits. */
  361. *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
  362. /* Read the value back to see how many bits stuck. */
  363. ucMaxPriorityValue = *pucFirstUserPriorityRegister;
  364. /* Use the same mask on the maximum system call priority. */
  365. ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
  366. /* Calculate the maximum acceptable priority group value for the number
  367. * of bits read back. */
  368. ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
  369. while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
  370. {
  371. ulMaxPRIGROUPValue--;
  372. ucMaxPriorityValue <<= ( uint8_t ) 0x01;
  373. }
  374. #ifdef __NVIC_PRIO_BITS
  375. {
  376. /* Check the CMSIS configuration that defines the number of
  377. * priority bits matches the number of priority bits actually queried
  378. * from the hardware. */
  379. configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
  380. }
  381. #endif
  382. #ifdef configPRIO_BITS
  383. {
  384. /* Check the FreeRTOS configuration that defines the number of
  385. * priority bits matches the number of priority bits actually queried
  386. * from the hardware. */
  387. configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
  388. }
  389. #endif
  390. /* Shift the priority group value back to its position within the AIRCR
  391. * register. */
  392. ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
  393. ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
  394. /* Restore the clobbered interrupt priority register to its original
  395. * value. */
  396. *pucFirstUserPriorityRegister = ulOriginalPriority;
  397. }
  398. #endif /* conifgASSERT_DEFINED */
  399. /* Make PendSV and SysTick the same priority as the kernel, and the SVC
  400. * handler higher priority so it can be used to exit a critical section (where
  401. * lower priorities are masked). */
  402. portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
  403. portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
  404. /* Configure the regions in the MPU that are common to all tasks. */
  405. prvSetupMPU();
  406. /* Start the timer that generates the tick ISR. Interrupts are disabled
  407. * here already. */
  408. vPortSetupTimerInterrupt();
  409. /* Initialise the critical nesting count ready for the first task. */
  410. uxCriticalNesting = 0;
  411. /* Ensure the VFP is enabled - it should be anyway. */
  412. vPortEnableVFP();
  413. /* Lazy save always. */
  414. *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
  415. /* Start the first task. This also clears the bit that indicates the FPU is
  416. * in use in case the FPU was used before the scheduler was started - which
  417. * would otherwise result in the unnecessary leaving of space in the SVC stack
  418. * for lazy saving of FPU registers. */
  419. __asm volatile (
  420. " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */
  421. " ldr r0, [r0] \n"
  422. " ldr r0, [r0] \n"
  423. " msr msp, r0 \n"/* Set the msp back to the start of the stack. */
  424. " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */
  425. " msr control, r0 \n"
  426. " cpsie i \n"/* Globally enable interrupts. */
  427. " cpsie f \n"
  428. " dsb \n"
  429. " isb \n"
  430. " svc %0 \n"/* System call to start first task. */
  431. " nop \n"
  432. " .ltorg \n"
  433. ::"i" ( portSVC_START_SCHEDULER ) : "memory" );
  434. /* Should not get here! */
  435. return 0;
  436. }
  437. /*-----------------------------------------------------------*/
  438. void vPortEndScheduler( void )
  439. {
  440. /* Not implemented in ports where there is nothing to return to.
  441. * Artificially force an assert. */
  442. configASSERT( uxCriticalNesting == 1000UL );
  443. }
  444. /*-----------------------------------------------------------*/
  445. void vPortEnterCritical( void )
  446. {
  447. BaseType_t xRunningPrivileged;
  448. xPortRaisePrivilege( xRunningPrivileged );
  449. portDISABLE_INTERRUPTS();
  450. uxCriticalNesting++;
  451. vPortResetPrivilege( xRunningPrivileged );
  452. }
  453. /*-----------------------------------------------------------*/
  454. void vPortExitCritical( void )
  455. {
  456. BaseType_t xRunningPrivileged;
  457. xPortRaisePrivilege( xRunningPrivileged );
  458. configASSERT( uxCriticalNesting );
  459. uxCriticalNesting--;
  460. if( uxCriticalNesting == 0 )
  461. {
  462. portENABLE_INTERRUPTS();
  463. }
  464. vPortResetPrivilege( xRunningPrivileged );
  465. }
  466. /*-----------------------------------------------------------*/
  467. void xPortPendSVHandler( void )
  468. {
  469. /* This is a naked function. */
  470. __asm volatile
  471. (
  472. " mrs r0, psp \n"
  473. " isb \n"
  474. " \n"
  475. " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */
  476. " ldr r2, [r3] \n"
  477. " \n"
  478. " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */
  479. " it eq \n"
  480. " vstmdbeq r0!, {s16-s31} \n"
  481. " \n"
  482. " mrs r1, control \n"
  483. " stmdb r0!, {r1, r4-r11, r14} \n"/* Save the remaining registers. */
  484. " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */
  485. " \n"
  486. " stmdb sp!, {r0, r3} \n"
  487. " mov r0, %0 \n"
  488. " msr basepri, r0 \n"
  489. " dsb \n"
  490. " isb \n"
  491. " bl vTaskSwitchContext \n"
  492. " mov r0, #0 \n"
  493. " msr basepri, r0 \n"
  494. " ldmia sp!, {r0, r3} \n"
  495. " \n"/* Restore the context. */
  496. " ldr r1, [r3] \n"
  497. " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */
  498. " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */
  499. " \n"
  500. " dmb \n"/* Complete outstanding transfers before disabling MPU. */
  501. " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
  502. " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
  503. " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
  504. " str r3, [r2] \n"/* Disable MPU. */
  505. " \n"
  506. " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */
  507. " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
  508. " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
  509. " \n"
  510. #if ( portTOTAL_NUM_REGIONS == 16 )
  511. " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
  512. " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
  513. " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
  514. " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
  515. #endif /* portTOTAL_NUM_REGIONS == 16. */
  516. " \n"
  517. " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
  518. " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
  519. " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
  520. " str r3, [r2] \n"/* Enable MPU. */
  521. " dsb \n"/* Force memory writes before continuing. */
  522. " \n"
  523. " ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */
  524. " msr control, r3 \n"
  525. " \n"
  526. " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */
  527. " it eq \n"
  528. " vldmiaeq r0!, {s16-s31} \n"
  529. " \n"
  530. " msr psp, r0 \n"
  531. " bx r14 \n"
  532. " \n"
  533. " .align 4 \n"
  534. "pxCurrentTCBConst: .word pxCurrentTCB \n"
  535. ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
  536. );
  537. }
  538. /*-----------------------------------------------------------*/
  539. void xPortSysTickHandler( void )
  540. {
  541. uint32_t ulDummy;
  542. ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
  543. {
  544. /* Increment the RTOS tick. */
  545. if( xTaskIncrementTick() != pdFALSE )
  546. {
  547. /* Pend a context switch. */
  548. portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
  549. }
  550. }
  551. portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
  552. }
  553. /*-----------------------------------------------------------*/
  554. /*
  555. * Setup the systick timer to generate the tick interrupts at the required
  556. * frequency.
  557. */
  558. __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )
  559. {
  560. /* Stop and clear the SysTick. */
  561. portNVIC_SYSTICK_CTRL_REG = 0UL;
  562. portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
  563. /* Configure SysTick to interrupt at the requested rate. */
  564. portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
  565. portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE );
  566. }
  567. /*-----------------------------------------------------------*/
  568. /* This is a naked function. */
  569. static void vPortEnableVFP( void )
  570. {
  571. __asm volatile
  572. (
  573. " ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */
  574. " ldr r1, [r0] \n"
  575. " \n"
  576. " orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */
  577. " str r1, [r0] \n"
  578. " bx r14 \n"
  579. " .ltorg \n"
  580. );
  581. }
  582. /*-----------------------------------------------------------*/
  583. static void prvSetupMPU( void )
  584. {
  585. #if defined( __ARMCC_VERSION )
  586. /* Declaration when these variable are defined in code instead of being
  587. * exported from linker scripts. */
  588. extern uint32_t * __privileged_functions_start__;
  589. extern uint32_t * __privileged_functions_end__;
  590. extern uint32_t * __FLASH_segment_start__;
  591. extern uint32_t * __FLASH_segment_end__;
  592. extern uint32_t * __privileged_data_start__;
  593. extern uint32_t * __privileged_data_end__;
  594. #else
  595. /* Declaration when these variable are exported from linker scripts. */
  596. extern uint32_t __privileged_functions_start__[];
  597. extern uint32_t __privileged_functions_end__[];
  598. extern uint32_t __FLASH_segment_start__[];
  599. extern uint32_t __FLASH_segment_end__[];
  600. extern uint32_t __privileged_data_start__[];
  601. extern uint32_t __privileged_data_end__[];
  602. #endif /* if defined( __ARMCC_VERSION ) */
  603. /* The only permitted number of regions are 8 or 16. */
  604. configASSERT( ( portTOTAL_NUM_REGIONS == 8 ) || ( portTOTAL_NUM_REGIONS == 16 ) );
  605. /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
  606. configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
  607. /* Check the expected MPU is present. */
  608. if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
  609. {
  610. /* First setup the unprivileged flash for unprivileged read only access. */
  611. portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
  612. ( portMPU_REGION_VALID ) |
  613. ( portUNPRIVILEGED_FLASH_REGION );
  614. portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) |
  615. ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
  616. ( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
  617. ( portMPU_REGION_ENABLE );
  618. /* Setup the privileged flash for privileged only access. This is where
  619. * the kernel code is placed. */
  620. portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */
  621. ( portMPU_REGION_VALID ) |
  622. ( portPRIVILEGED_FLASH_REGION );
  623. portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
  624. ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
  625. ( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) |
  626. ( portMPU_REGION_ENABLE );
  627. /* Setup the privileged data RAM region. This is where the kernel data
  628. * is placed. */
  629. portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
  630. ( portMPU_REGION_VALID ) |
  631. ( portPRIVILEGED_RAM_REGION );
  632. portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
  633. ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
  634. prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
  635. ( portMPU_REGION_ENABLE );
  636. /* By default allow everything to access the general peripherals. The
  637. * system peripherals and registers are protected. */
  638. portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
  639. ( portMPU_REGION_VALID ) |
  640. ( portGENERAL_PERIPHERALS_REGION );
  641. portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) |
  642. ( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) |
  643. ( portMPU_REGION_ENABLE );
  644. /* Enable the memory fault exception. */
  645. portNVIC_SYS_CTRL_STATE_REG |= portNVIC_MEM_FAULT_ENABLE;
  646. /* Enable the MPU with the background region configured. */
  647. portMPU_CTRL_REG |= ( portMPU_ENABLE | portMPU_BACKGROUND_ENABLE );
  648. }
  649. }
  650. /*-----------------------------------------------------------*/
  651. static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
  652. {
  653. uint32_t ulRegionSize, ulReturnValue = 4;
  654. /* 32 is the smallest region size, 31 is the largest valid value for
  655. * ulReturnValue. */
  656. for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
  657. {
  658. if( ulActualSizeInBytes <= ulRegionSize )
  659. {
  660. break;
  661. }
  662. else
  663. {
  664. ulReturnValue++;
  665. }
  666. }
  667. /* Shift the code by one before returning so it can be written directly
  668. * into the the correct bit position of the attribute register. */
  669. return( ulReturnValue << 1UL );
  670. }
  671. /*-----------------------------------------------------------*/
  672. BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
  673. {
  674. __asm volatile
  675. (
  676. " mrs r0, control \n"/* r0 = CONTROL. */
  677. " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
  678. " ite ne \n"
  679. " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
  680. " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
  681. " bx lr \n"/* Return. */
  682. " \n"
  683. " .align 4 \n"
  684. ::: "r0", "memory"
  685. );
  686. }
  687. /*-----------------------------------------------------------*/
  688. void vResetPrivilege( void ) /* __attribute__ (( naked )) */
  689. {
  690. __asm volatile
  691. (
  692. " mrs r0, control \n"/* r0 = CONTROL. */
  693. " orr r0, #1 \n"/* r0 = r0 | 1. */
  694. " msr control, r0 \n"/* CONTROL = r0. */
  695. " bx lr \n"/* Return to the caller. */
  696. ::: "r0", "memory"
  697. );
  698. }
  699. /*-----------------------------------------------------------*/
  700. void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
  701. const struct xMEMORY_REGION * const xRegions,
  702. StackType_t * pxBottomOfStack,
  703. uint32_t ulStackDepth )
  704. {
  705. #if defined( __ARMCC_VERSION )
  706. /* Declaration when these variable are defined in code instead of being
  707. * exported from linker scripts. */
  708. extern uint32_t * __SRAM_segment_start__;
  709. extern uint32_t * __SRAM_segment_end__;
  710. extern uint32_t * __privileged_data_start__;
  711. extern uint32_t * __privileged_data_end__;
  712. #else
  713. /* Declaration when these variable are exported from linker scripts. */
  714. extern uint32_t __SRAM_segment_start__[];
  715. extern uint32_t __SRAM_segment_end__[];
  716. extern uint32_t __privileged_data_start__[];
  717. extern uint32_t __privileged_data_end__[];
  718. #endif /* if defined( __ARMCC_VERSION ) */
  719. int32_t lIndex;
  720. uint32_t ul;
  721. if( xRegions == NULL )
  722. {
  723. /* No MPU regions are specified so allow access to all RAM. */
  724. xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
  725. ( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */
  726. ( portMPU_REGION_VALID ) |
  727. ( portSTACK_REGION );
  728. xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
  729. ( portMPU_REGION_READ_WRITE ) |
  730. ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
  731. ( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) |
  732. ( portMPU_REGION_ENABLE );
  733. /* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
  734. * just removed the privileged only parameters. */
  735. xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
  736. ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
  737. ( portMPU_REGION_VALID ) |
  738. ( portSTACK_REGION + 1 );
  739. xMPUSettings->xRegion[ 1 ].ulRegionAttribute =
  740. ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
  741. ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
  742. prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
  743. ( portMPU_REGION_ENABLE );
  744. /* Invalidate all other regions. */
  745. for( ul = 2; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
  746. {
  747. xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID;
  748. xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
  749. }
  750. }
  751. else
  752. {
  753. /* This function is called automatically when the task is created - in
  754. * which case the stack region parameters will be valid. At all other
  755. * times the stack parameters will not be valid and it is assumed that the
  756. * stack region has already been configured. */
  757. if( ulStackDepth > 0 )
  758. {
  759. /* Define the region that allows access to the stack. */
  760. xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
  761. ( ( uint32_t ) pxBottomOfStack ) |
  762. ( portMPU_REGION_VALID ) |
  763. ( portSTACK_REGION ); /* Region number. */
  764. xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
  765. ( portMPU_REGION_READ_WRITE ) | /* Read and write. */
  766. ( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) |
  767. ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
  768. ( portMPU_REGION_ENABLE );
  769. }
  770. lIndex = 0;
  771. for( ul = 1; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
  772. {
  773. if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
  774. {
  775. /* Translate the generic region definition contained in
  776. * xRegions into the CM4 specific MPU settings that are then
  777. * stored in xMPUSettings. */
  778. xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
  779. ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
  780. ( portMPU_REGION_VALID ) |
  781. ( portSTACK_REGION + ul ); /* Region number. */
  782. xMPUSettings->xRegion[ ul ].ulRegionAttribute =
  783. ( prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) ) |
  784. ( xRegions[ lIndex ].ulParameters ) |
  785. ( portMPU_REGION_ENABLE );
  786. }
  787. else
  788. {
  789. /* Invalidate the region. */
  790. xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID;
  791. xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
  792. }
  793. lIndex++;
  794. }
  795. }
  796. }
  797. /*-----------------------------------------------------------*/
  798. #if ( configASSERT_DEFINED == 1 )
  799. void vPortValidateInterruptPriority( void )
  800. {
  801. uint32_t ulCurrentInterrupt;
  802. uint8_t ucCurrentPriority;
  803. /* Obtain the number of the currently executing interrupt. */
  804. __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
  805. /* Is the interrupt number a user defined interrupt? */
  806. if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
  807. {
  808. /* Look up the interrupt's priority. */
  809. ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
  810. /* The following assertion will fail if a service routine (ISR) for
  811. * an interrupt that has been assigned a priority above
  812. * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
  813. * function. ISR safe FreeRTOS API functions must *only* be called
  814. * from interrupts that have been assigned a priority at or below
  815. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
  816. *
  817. * Numerically low interrupt priority numbers represent logically high
  818. * interrupt priorities, therefore the priority of the interrupt must
  819. * be set to a value equal to or numerically *higher* than
  820. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
  821. *
  822. * Interrupts that use the FreeRTOS API must not be left at their
  823. * default priority of zero as that is the highest possible priority,
  824. * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
  825. * and therefore also guaranteed to be invalid.
  826. *
  827. * FreeRTOS maintains separate thread and ISR API functions to ensure
  828. * interrupt entry is as fast and simple as possible.
  829. *
  830. * The following links provide detailed information:
  831. * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
  832. * https://www.FreeRTOS.org/FAQHelp.html */
  833. configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
  834. }
  835. /* Priority grouping: The interrupt controller (NVIC) allows the bits
  836. * that define each interrupt's priority to be split between bits that
  837. * define the interrupt's pre-emption priority bits and bits that define
  838. * the interrupt's sub-priority. For simplicity all bits must be defined
  839. * to be pre-emption priority bits. The following assertion will fail if
  840. * this is not the case (if some bits represent a sub-priority).
  841. *
  842. * If the application only uses CMSIS libraries for interrupt
  843. * configuration then the correct setting can be achieved on all Cortex-M
  844. * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
  845. * scheduler. Note however that some vendor specific peripheral libraries
  846. * assume a non-zero priority group setting, in which cases using a value
  847. * of zero will result in unpredicable behaviour. */
  848. configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
  849. }
  850. #endif /* configASSERT_DEFINED */
  851. /*-----------------------------------------------------------*/