port.c 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197
  1. /*
  2. * FreeRTOS Kernel V10.4.6
  3. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * SPDX-License-Identifier: MIT
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  8. * this software and associated documentation files (the "Software"), to deal in
  9. * the Software without restriction, including without limitation the rights to
  10. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  11. * the Software, and to permit persons to whom the Software is furnished to do so,
  12. * subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in all
  15. * copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  19. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  20. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  21. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. *
  24. * https://www.FreeRTOS.org
  25. * https://github.com/FreeRTOS
  26. *
  27. */
  28. /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
  29. * all the API functions to use the MPU wrappers. That should only be done when
  30. * task.h is included from an application file. */
  31. #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
  32. /* Scheduler includes. */
  33. #include "FreeRTOS.h"
  34. #include "task.h"
  35. /* MPU wrappers includes. */
  36. #include "mpu_wrappers.h"
  37. /* Portasm includes. */
  38. #include "portasm.h"
  39. #if ( configENABLE_TRUSTZONE == 1 )
  40. /* Secure components includes. */
  41. #include "secure_context.h"
  42. #include "secure_init.h"
  43. #endif /* configENABLE_TRUSTZONE */
  44. #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
  45. /**
  46. * The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only
  47. * i.e. the processor boots as secure and never jumps to the non-secure side.
  48. * The Trust Zone support in the port must be disabled in order to run FreeRTOS
  49. * on the secure side. The following are the valid configuration seetings:
  50. *
  51. * 1. Run FreeRTOS on the Secure Side:
  52. * configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
  53. *
  54. * 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support:
  55. * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
  56. *
  57. * 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support:
  58. * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
  59. */
  60. #if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
  61. #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
  62. #endif
  63. /*-----------------------------------------------------------*/
  64. /**
  65. * @brief Constants required to manipulate the NVIC.
  66. */
  67. #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
  68. #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
  69. #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
  70. #define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
  71. #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
  72. #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
  73. #define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
  74. #define portMIN_INTERRUPT_PRIORITY ( 255UL )
  75. #define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
  76. #define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
  77. #ifndef configSYSTICK_CLOCK_HZ
  78. #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
  79. /* Ensure the SysTick is clocked at the same frequency as the core. */
  80. #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
  81. #else
  82. /* The way the SysTick is clocked is not modified in case it is not the
  83. * same a the core. */
  84. #define portNVIC_SYSTICK_CLK_BIT ( 0 )
  85. #endif
  86. /*-----------------------------------------------------------*/
  87. /**
  88. * @brief Constants required to manipulate the SCB.
  89. */
  90. #define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 )
  91. #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
  92. /*-----------------------------------------------------------*/
  93. /**
  94. * @brief Constants required to manipulate the FPU.
  95. */
  96. #define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
  97. #define portCPACR_CP10_VALUE ( 3UL )
  98. #define portCPACR_CP11_VALUE portCPACR_CP10_VALUE
  99. #define portCPACR_CP10_POS ( 20UL )
  100. #define portCPACR_CP11_POS ( 22UL )
  101. #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
  102. #define portFPCCR_ASPEN_POS ( 31UL )
  103. #define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS )
  104. #define portFPCCR_LSPEN_POS ( 30UL )
  105. #define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS )
  106. /*-----------------------------------------------------------*/
  107. /**
  108. * @brief Constants required to manipulate the MPU.
  109. */
  110. #define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
  111. #define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
  112. #define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) )
  113. #define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) )
  114. #define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) )
  115. #define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) )
  116. #define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) )
  117. #define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) )
  118. #define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) )
  119. #define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) )
  120. #define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) )
  121. #define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
  122. #define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
  123. #define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
  124. #define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
  125. #define portMPU_MAIR_ATTR0_POS ( 0UL )
  126. #define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )
  127. #define portMPU_MAIR_ATTR1_POS ( 8UL )
  128. #define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 )
  129. #define portMPU_MAIR_ATTR2_POS ( 16UL )
  130. #define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 )
  131. #define portMPU_MAIR_ATTR3_POS ( 24UL )
  132. #define portMPU_MAIR_ATTR3_MASK ( 0xff000000 )
  133. #define portMPU_MAIR_ATTR4_POS ( 0UL )
  134. #define portMPU_MAIR_ATTR4_MASK ( 0x000000ff )
  135. #define portMPU_MAIR_ATTR5_POS ( 8UL )
  136. #define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 )
  137. #define portMPU_MAIR_ATTR6_POS ( 16UL )
  138. #define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 )
  139. #define portMPU_MAIR_ATTR7_POS ( 24UL )
  140. #define portMPU_MAIR_ATTR7_MASK ( 0xff000000 )
  141. #define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL )
  142. #define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL )
  143. #define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL )
  144. #define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL )
  145. #define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL )
  146. #define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL )
  147. #define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL )
  148. #define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL )
  149. #define portMPU_RLAR_REGION_ENABLE ( 1UL )
  150. /* Enable privileged access to unmapped region. */
  151. #define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
  152. /* Enable MPU. */
  153. #define portMPU_ENABLE_BIT ( 1UL << 0UL )
  154. /* Expected value of the portMPU_TYPE register. */
  155. #define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
  156. /*-----------------------------------------------------------*/
  157. /**
  158. * @brief The maximum 24-bit number.
  159. *
  160. * It is needed because the systick is a 24-bit counter.
  161. */
  162. #define portMAX_24_BIT_NUMBER ( 0xffffffUL )
  163. /**
  164. * @brief A fiddle factor to estimate the number of SysTick counts that would
  165. * have occurred while the SysTick counter is stopped during tickless idle
  166. * calculations.
  167. */
  168. #define portMISSED_COUNTS_FACTOR ( 45UL )
  169. /*-----------------------------------------------------------*/
  170. /**
  171. * @brief Constants required to set up the initial stack.
  172. */
  173. #define portINITIAL_XPSR ( 0x01000000 )
  174. #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
  175. /**
  176. * @brief Initial EXC_RETURN value.
  177. *
  178. * FF FF FF FD
  179. * 1111 1111 1111 1111 1111 1111 1111 1101
  180. *
  181. * Bit[6] - 1 --> The exception was taken from the Secure state.
  182. * Bit[5] - 1 --> Do not skip stacking of additional state context.
  183. * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
  184. * Bit[3] - 1 --> Return to the Thread mode.
  185. * Bit[2] - 1 --> Restore registers from the process stack.
  186. * Bit[1] - 0 --> Reserved, 0.
  187. * Bit[0] - 1 --> The exception was taken to the Secure state.
  188. */
  189. #define portINITIAL_EXC_RETURN ( 0xfffffffd )
  190. #else
  191. /**
  192. * @brief Initial EXC_RETURN value.
  193. *
  194. * FF FF FF BC
  195. * 1111 1111 1111 1111 1111 1111 1011 1100
  196. *
  197. * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
  198. * Bit[5] - 1 --> Do not skip stacking of additional state context.
  199. * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
  200. * Bit[3] - 1 --> Return to the Thread mode.
  201. * Bit[2] - 1 --> Restore registers from the process stack.
  202. * Bit[1] - 0 --> Reserved, 0.
  203. * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
  204. */
  205. #define portINITIAL_EXC_RETURN ( 0xffffffbc )
  206. #endif /* configRUN_FREERTOS_SECURE_ONLY */
  207. /**
  208. * @brief CONTROL register privileged bit mask.
  209. *
  210. * Bit[0] in CONTROL register tells the privilege:
  211. * Bit[0] = 0 ==> The task is privileged.
  212. * Bit[0] = 1 ==> The task is not privileged.
  213. */
  214. #define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL )
  215. /**
  216. * @brief Initial CONTROL register values.
  217. */
  218. #define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 )
  219. #define portINITIAL_CONTROL_PRIVILEGED ( 0x2 )
  220. /**
  221. * @brief Let the user override the pre-loading of the initial LR with the
  222. * address of prvTaskExitError() in case it messes up unwinding of the stack
  223. * in the debugger.
  224. */
  225. #ifdef configTASK_RETURN_ADDRESS
  226. #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
  227. #else
  228. #define portTASK_RETURN_ADDRESS prvTaskExitError
  229. #endif
  230. /**
  231. * @brief If portPRELOAD_REGISTERS then registers will be given an initial value
  232. * when a task is created. This helps in debugging at the cost of code size.
  233. */
  234. #define portPRELOAD_REGISTERS 1
  235. /**
  236. * @brief A task is created without a secure context, and must call
  237. * portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes
  238. * any secure calls.
  239. */
  240. #define portNO_SECURE_CONTEXT 0
  241. /*-----------------------------------------------------------*/
  242. /**
  243. * @brief Used to catch tasks that attempt to return from their implementing
  244. * function.
  245. */
  246. static void prvTaskExitError( void );
  247. #if ( configENABLE_MPU == 1 )
  248. /**
  249. * @brief Setup the Memory Protection Unit (MPU).
  250. */
  251. static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
  252. #endif /* configENABLE_MPU */
  253. #if ( configENABLE_FPU == 1 )
  254. /**
  255. * @brief Setup the Floating Point Unit (FPU).
  256. */
  257. static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
  258. #endif /* configENABLE_FPU */
  259. /**
  260. * @brief Setup the timer to generate the tick interrupts.
  261. *
  262. * The implementation in this file is weak to allow application writers to
  263. * change the timer used to generate the tick interrupt.
  264. */
  265. void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
  266. /**
  267. * @brief Checks whether the current execution context is interrupt.
  268. *
  269. * @return pdTRUE if the current execution context is interrupt, pdFALSE
  270. * otherwise.
  271. */
  272. BaseType_t xPortIsInsideInterrupt( void );
  273. /**
  274. * @brief Yield the processor.
  275. */
  276. void vPortYield( void ) PRIVILEGED_FUNCTION;
  277. /**
  278. * @brief Enter critical section.
  279. */
  280. void vPortEnterCritical( void ) PRIVILEGED_FUNCTION;
  281. /**
  282. * @brief Exit from critical section.
  283. */
  284. void vPortExitCritical( void ) PRIVILEGED_FUNCTION;
  285. /**
  286. * @brief SysTick handler.
  287. */
  288. void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
  289. /**
  290. * @brief C part of SVC handler.
  291. */
  292. portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION;
  293. /*-----------------------------------------------------------*/
  294. /**
  295. * @brief Each task maintains its own interrupt status in the critical nesting
  296. * variable.
  297. */
  298. PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
  299. #if ( configENABLE_TRUSTZONE == 1 )
  300. /**
  301. * @brief Saved as part of the task context to indicate which context the
  302. * task is using on the secure side.
  303. */
  304. PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
  305. #endif /* configENABLE_TRUSTZONE */
  306. #if ( configUSE_TICKLESS_IDLE == 1 )
  307. /**
  308. * @brief The number of SysTick increments that make up one tick period.
  309. */
  310. PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
  311. /**
  312. * @brief The maximum number of tick periods that can be suppressed is
  313. * limited by the 24 bit resolution of the SysTick timer.
  314. */
  315. PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
  316. /**
  317. * @brief Compensate for the CPU cycles that pass while the SysTick is
  318. * stopped (low power functionality only).
  319. */
  320. PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
  321. #endif /* configUSE_TICKLESS_IDLE */
  322. /*-----------------------------------------------------------*/
  323. #if ( configUSE_TICKLESS_IDLE == 1 )
  324. __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
  325. {
  326. uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
  327. TickType_t xModifiableIdleTime;
  328. /* Make sure the SysTick reload value does not overflow the counter. */
  329. if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
  330. {
  331. xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
  332. }
  333. /* Stop the SysTick momentarily. The time the SysTick is stopped for is
  334. * accounted for as best it can be, but using the tickless mode will
  335. * inevitably result in some tiny drift of the time maintained by the
  336. * kernel with respect to calendar time. */
  337. portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
  338. /* Calculate the reload value required to wait xExpectedIdleTime
  339. * tick periods. -1 is used because this code will execute part way
  340. * through one of the tick periods. */
  341. ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
  342. if( ulReloadValue > ulStoppedTimerCompensation )
  343. {
  344. ulReloadValue -= ulStoppedTimerCompensation;
  345. }
  346. /* Enter a critical section but don't use the taskENTER_CRITICAL()
  347. * method as that will mask interrupts that should exit sleep mode. */
  348. __asm volatile ( "cpsid i" ::: "memory" );
  349. __asm volatile ( "dsb" );
  350. __asm volatile ( "isb" );
  351. /* If a context switch is pending or a task is waiting for the scheduler
  352. * to be un-suspended then abandon the low power entry. */
  353. if( eTaskConfirmSleepModeStatus() == eAbortSleep )
  354. {
  355. /* Restart from whatever is left in the count register to complete
  356. * this tick period. */
  357. portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
  358. /* Restart SysTick. */
  359. portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
  360. /* Reset the reload register to the value required for normal tick
  361. * periods. */
  362. portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
  363. /* Re-enable interrupts - see comments above the cpsid instruction()
  364. * above. */
  365. __asm volatile ( "cpsie i" ::: "memory" );
  366. }
  367. else
  368. {
  369. /* Set the new reload value. */
  370. portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
  371. /* Clear the SysTick count flag and set the count value back to
  372. * zero. */
  373. portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
  374. /* Restart SysTick. */
  375. portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
  376. /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
  377. * set its parameter to 0 to indicate that its implementation
  378. * contains its own wait for interrupt or wait for event
  379. * instruction, and so wfi should not be executed again. However,
  380. * the original expected idle time variable must remain unmodified,
  381. * so a copy is taken. */
  382. xModifiableIdleTime = xExpectedIdleTime;
  383. configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
  384. if( xModifiableIdleTime > 0 )
  385. {
  386. __asm volatile ( "dsb" ::: "memory" );
  387. __asm volatile ( "wfi" );
  388. __asm volatile ( "isb" );
  389. }
  390. configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
  391. /* Re-enable interrupts to allow the interrupt that brought the MCU
  392. * out of sleep mode to execute immediately. See comments above
  393. * the cpsid instruction above. */
  394. __asm volatile ( "cpsie i" ::: "memory" );
  395. __asm volatile ( "dsb" );
  396. __asm volatile ( "isb" );
  397. /* Disable interrupts again because the clock is about to be stopped
  398. * and interrupts that execute while the clock is stopped will
  399. * increase any slippage between the time maintained by the RTOS and
  400. * calendar time. */
  401. __asm volatile ( "cpsid i" ::: "memory" );
  402. __asm volatile ( "dsb" );
  403. __asm volatile ( "isb" );
  404. /* Disable the SysTick clock without reading the
  405. * portNVIC_SYSTICK_CTRL_REG register to ensure the
  406. * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.
  407. * Again, the time the SysTick is stopped for is accounted for as
  408. * best it can be, but using the tickless mode will inevitably
  409. * result in some tiny drift of the time maintained by the kernel
  410. * with respect to calendar time*/
  411. portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
  412. /* Determine if the SysTick clock has already counted to zero and
  413. * been set back to the current reload value (the reload back being
  414. * correct for the entire expected idle time) or if the SysTick is
  415. * yet to count to zero (in which case an interrupt other than the
  416. * SysTick must have brought the system out of sleep mode). */
  417. if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
  418. {
  419. uint32_t ulCalculatedLoadValue;
  420. /* The tick interrupt is already pending, and the SysTick count
  421. * reloaded with ulReloadValue. Reset the
  422. * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
  423. * period. */
  424. ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
  425. /* Don't allow a tiny value, or values that have somehow
  426. * underflowed because the post sleep hook did something
  427. * that took too long. */
  428. if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
  429. {
  430. ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
  431. }
  432. portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
  433. /* As the pending tick will be processed as soon as this
  434. * function exits, the tick value maintained by the tick is
  435. * stepped forward by one less than the time spent waiting. */
  436. ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
  437. }
  438. else
  439. {
  440. /* Something other than the tick interrupt ended the sleep.
  441. * Work out how long the sleep lasted rounded to complete tick
  442. * periods (not the ulReload value which accounted for part
  443. * ticks). */
  444. ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
  445. /* How many complete tick periods passed while the processor
  446. * was waiting? */
  447. ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
  448. /* The reload value is set to whatever fraction of a single tick
  449. * period remains. */
  450. portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
  451. }
  452. /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
  453. * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
  454. * value. */
  455. portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
  456. portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
  457. vTaskStepTick( ulCompleteTickPeriods );
  458. portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
  459. /* Exit with interrupts enabled. */
  460. __asm volatile ( "cpsie i" ::: "memory" );
  461. }
  462. }
  463. #endif /* configUSE_TICKLESS_IDLE */
  464. /*-----------------------------------------------------------*/
  465. __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
  466. {
  467. /* Calculate the constants required to configure the tick interrupt. */
  468. #if ( configUSE_TICKLESS_IDLE == 1 )
  469. {
  470. ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
  471. xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
  472. ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
  473. }
  474. #endif /* configUSE_TICKLESS_IDLE */
  475. /* Stop and reset the SysTick. */
  476. portNVIC_SYSTICK_CTRL_REG = 0UL;
  477. portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
  478. /* Configure SysTick to interrupt at the requested rate. */
  479. portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
  480. portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
  481. }
  482. /*-----------------------------------------------------------*/
  483. static void prvTaskExitError( void )
  484. {
  485. volatile uint32_t ulDummy = 0UL;
  486. /* A function that implements a task must not exit or attempt to return to
  487. * its caller as there is nothing to return to. If a task wants to exit it
  488. * should instead call vTaskDelete( NULL ). Artificially force an assert()
  489. * to be triggered if configASSERT() is defined, then stop here so
  490. * application writers can catch the error. */
  491. configASSERT( ulCriticalNesting == ~0UL );
  492. portDISABLE_INTERRUPTS();
  493. while( ulDummy == 0 )
  494. {
  495. /* This file calls prvTaskExitError() after the scheduler has been
  496. * started to remove a compiler warning about the function being
  497. * defined but never called. ulDummy is used purely to quieten other
  498. * warnings about code appearing after this function is called - making
  499. * ulDummy volatile makes the compiler think the function could return
  500. * and therefore not output an 'unreachable code' warning for code that
  501. * appears after it. */
  502. }
  503. }
  504. /*-----------------------------------------------------------*/
  505. #if ( configENABLE_MPU == 1 )
  506. static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
  507. {
  508. #if defined( __ARMCC_VERSION )
  509. /* Declaration when these variable are defined in code instead of being
  510. * exported from linker scripts. */
  511. extern uint32_t * __privileged_functions_start__;
  512. extern uint32_t * __privileged_functions_end__;
  513. extern uint32_t * __syscalls_flash_start__;
  514. extern uint32_t * __syscalls_flash_end__;
  515. extern uint32_t * __unprivileged_flash_start__;
  516. extern uint32_t * __unprivileged_flash_end__;
  517. extern uint32_t * __privileged_sram_start__;
  518. extern uint32_t * __privileged_sram_end__;
  519. #else /* if defined( __ARMCC_VERSION ) */
  520. /* Declaration when these variable are exported from linker scripts. */
  521. extern uint32_t __privileged_functions_start__[];
  522. extern uint32_t __privileged_functions_end__[];
  523. extern uint32_t __syscalls_flash_start__[];
  524. extern uint32_t __syscalls_flash_end__[];
  525. extern uint32_t __unprivileged_flash_start__[];
  526. extern uint32_t __unprivileged_flash_end__[];
  527. extern uint32_t __privileged_sram_start__[];
  528. extern uint32_t __privileged_sram_end__[];
  529. #endif /* defined( __ARMCC_VERSION ) */
  530. /* Check that the MPU is present. */
  531. if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
  532. {
  533. /* MAIR0 - Index 0. */
  534. portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
  535. /* MAIR0 - Index 1. */
  536. portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
  537. /* Setup privileged flash as Read Only so that privileged tasks can
  538. * read it but not modify. */
  539. portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
  540. portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
  541. ( portMPU_REGION_NON_SHAREABLE ) |
  542. ( portMPU_REGION_PRIVILEGED_READ_ONLY );
  543. portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
  544. ( portMPU_RLAR_ATTR_INDEX0 ) |
  545. ( portMPU_RLAR_REGION_ENABLE );
  546. /* Setup unprivileged flash as Read Only by both privileged and
  547. * unprivileged tasks. All tasks can read it but no-one can modify. */
  548. portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
  549. portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
  550. ( portMPU_REGION_NON_SHAREABLE ) |
  551. ( portMPU_REGION_READ_ONLY );
  552. portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
  553. ( portMPU_RLAR_ATTR_INDEX0 ) |
  554. ( portMPU_RLAR_REGION_ENABLE );
  555. /* Setup unprivileged syscalls flash as Read Only by both privileged
  556. * and unprivileged tasks. All tasks can read it but no-one can modify. */
  557. portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
  558. portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
  559. ( portMPU_REGION_NON_SHAREABLE ) |
  560. ( portMPU_REGION_READ_ONLY );
  561. portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
  562. ( portMPU_RLAR_ATTR_INDEX0 ) |
  563. ( portMPU_RLAR_REGION_ENABLE );
  564. /* Setup RAM containing kernel data for privileged access only. */
  565. portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
  566. portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
  567. ( portMPU_REGION_NON_SHAREABLE ) |
  568. ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
  569. ( portMPU_REGION_EXECUTE_NEVER );
  570. portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
  571. ( portMPU_RLAR_ATTR_INDEX0 ) |
  572. ( portMPU_RLAR_REGION_ENABLE );
  573. /* Enable mem fault. */
  574. portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
  575. /* Enable MPU with privileged background access i.e. unmapped
  576. * regions have privileged access. */
  577. portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
  578. }
  579. }
  580. #endif /* configENABLE_MPU */
  581. /*-----------------------------------------------------------*/
  582. #if ( configENABLE_FPU == 1 )
  583. static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
  584. {
  585. #if ( configENABLE_TRUSTZONE == 1 )
  586. {
  587. /* Enable non-secure access to the FPU. */
  588. SecureInit_EnableNSFPUAccess();
  589. }
  590. #endif /* configENABLE_TRUSTZONE */
  591. /* CP10 = 11 ==> Full access to FPU i.e. both privileged and
  592. * unprivileged code should be able to access FPU. CP11 should be
  593. * programmed to the same value as CP10. */
  594. *( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) |
  595. ( portCPACR_CP11_VALUE << portCPACR_CP11_POS )
  596. );
  597. /* ASPEN = 1 ==> Hardware should automatically preserve floating point
  598. * context on exception entry and restore on exception return.
  599. * LSPEN = 1 ==> Enable lazy context save of FP state. */
  600. *( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK );
  601. }
  602. #endif /* configENABLE_FPU */
  603. /*-----------------------------------------------------------*/
  604. void vPortYield( void ) /* PRIVILEGED_FUNCTION */
  605. {
  606. /* Set a PendSV to request a context switch. */
  607. portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
  608. /* Barriers are normally not required but do ensure the code is
  609. * completely within the specified behaviour for the architecture. */
  610. __asm volatile ( "dsb" ::: "memory" );
  611. __asm volatile ( "isb" );
  612. }
  613. /*-----------------------------------------------------------*/
  614. void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
  615. {
  616. portDISABLE_INTERRUPTS();
  617. ulCriticalNesting++;
  618. /* Barriers are normally not required but do ensure the code is
  619. * completely within the specified behaviour for the architecture. */
  620. __asm volatile ( "dsb" ::: "memory" );
  621. __asm volatile ( "isb" );
  622. }
  623. /*-----------------------------------------------------------*/
  624. void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
  625. {
  626. configASSERT( ulCriticalNesting );
  627. ulCriticalNesting--;
  628. if( ulCriticalNesting == 0 )
  629. {
  630. portENABLE_INTERRUPTS();
  631. }
  632. }
  633. /*-----------------------------------------------------------*/
  634. void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
  635. {
  636. uint32_t ulPreviousMask;
  637. ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
  638. {
  639. /* Increment the RTOS tick. */
  640. if( xTaskIncrementTick() != pdFALSE )
  641. {
  642. /* Pend a context switch. */
  643. portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
  644. }
  645. }
  646. portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
  647. }
  648. /*-----------------------------------------------------------*/
  649. void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
  650. {
  651. #if ( configENABLE_MPU == 1 )
  652. #if defined( __ARMCC_VERSION )
  653. /* Declaration when these variable are defined in code instead of being
  654. * exported from linker scripts. */
  655. extern uint32_t * __syscalls_flash_start__;
  656. extern uint32_t * __syscalls_flash_end__;
  657. #else
  658. /* Declaration when these variable are exported from linker scripts. */
  659. extern uint32_t __syscalls_flash_start__[];
  660. extern uint32_t __syscalls_flash_end__[];
  661. #endif /* defined( __ARMCC_VERSION ) */
  662. #endif /* configENABLE_MPU */
  663. uint32_t ulPC;
  664. #if ( configENABLE_TRUSTZONE == 1 )
  665. uint32_t ulR0, ulR1;
  666. extern TaskHandle_t pxCurrentTCB;
  667. #if ( configENABLE_MPU == 1 )
  668. uint32_t ulControl, ulIsTaskPrivileged;
  669. #endif /* configENABLE_MPU */
  670. #endif /* configENABLE_TRUSTZONE */
  671. uint8_t ucSVCNumber;
  672. /* Register are stored on the stack in the following order - R0, R1, R2, R3,
  673. * R12, LR, PC, xPSR. */
  674. ulPC = pulCallerStackAddress[ 6 ];
  675. ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
  676. switch( ucSVCNumber )
  677. {
  678. #if ( configENABLE_TRUSTZONE == 1 )
  679. case portSVC_ALLOCATE_SECURE_CONTEXT:
  680. /* R0 contains the stack size passed as parameter to the
  681. * vPortAllocateSecureContext function. */
  682. ulR0 = pulCallerStackAddress[ 0 ];
  683. #if ( configENABLE_MPU == 1 )
  684. {
  685. /* Read the CONTROL register value. */
  686. __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
  687. /* The task that raised the SVC is privileged if Bit[0]
  688. * in the CONTROL register is 0. */
  689. ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
  690. /* Allocate and load a context for the secure task. */
  691. xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
  692. }
  693. #else /* if ( configENABLE_MPU == 1 ) */
  694. {
  695. /* Allocate and load a context for the secure task. */
  696. xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
  697. }
  698. #endif /* configENABLE_MPU */
  699. configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
  700. SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
  701. break;
  702. case portSVC_FREE_SECURE_CONTEXT:
  703. /* R0 contains TCB being freed and R1 contains the secure
  704. * context handle to be freed. */
  705. ulR0 = pulCallerStackAddress[ 0 ];
  706. ulR1 = pulCallerStackAddress[ 1 ];
  707. /* Free the secure context. */
  708. SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
  709. break;
  710. #endif /* configENABLE_TRUSTZONE */
  711. case portSVC_START_SCHEDULER:
  712. #if ( configENABLE_TRUSTZONE == 1 )
  713. {
  714. /* De-prioritize the non-secure exceptions so that the
  715. * non-secure pendSV runs at the lowest priority. */
  716. SecureInit_DePrioritizeNSExceptions();
  717. /* Initialize the secure context management system. */
  718. SecureContext_Init();
  719. }
  720. #endif /* configENABLE_TRUSTZONE */
  721. #if ( configENABLE_FPU == 1 )
  722. {
  723. /* Setup the Floating Point Unit (FPU). */
  724. prvSetupFPU();
  725. }
  726. #endif /* configENABLE_FPU */
  727. /* Setup the context of the first task so that the first task starts
  728. * executing. */
  729. vRestoreContextOfFirstTask();
  730. break;
  731. #if ( configENABLE_MPU == 1 )
  732. case portSVC_RAISE_PRIVILEGE:
  733. /* Only raise the privilege, if the svc was raised from any of
  734. * the system calls. */
  735. if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
  736. ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
  737. {
  738. vRaisePrivilege();
  739. }
  740. break;
  741. #endif /* configENABLE_MPU */
  742. default:
  743. /* Incorrect SVC call. */
  744. configASSERT( pdFALSE );
  745. }
  746. }
  747. /*-----------------------------------------------------------*/
  748. /* *INDENT-OFF* */
  749. #if ( configENABLE_MPU == 1 )
  750. StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
  751. StackType_t * pxEndOfStack,
  752. TaskFunction_t pxCode,
  753. void * pvParameters,
  754. BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
  755. #else
  756. StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
  757. StackType_t * pxEndOfStack,
  758. TaskFunction_t pxCode,
  759. void * pvParameters ) /* PRIVILEGED_FUNCTION */
  760. #endif /* configENABLE_MPU */
  761. /* *INDENT-ON* */
  762. {
  763. /* Simulate the stack frame as it would be created by a context switch
  764. * interrupt. */
  765. #if ( portPRELOAD_REGISTERS == 0 )
  766. {
  767. pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
  768. *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
  769. pxTopOfStack--;
  770. *pxTopOfStack = ( StackType_t ) pxCode; /* PC */
  771. pxTopOfStack--;
  772. *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
  773. pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
  774. *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
  775. pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
  776. *pxTopOfStack = portINITIAL_EXC_RETURN;
  777. #if ( configENABLE_MPU == 1 )
  778. {
  779. pxTopOfStack--;
  780. if( xRunPrivileged == pdTRUE )
  781. {
  782. *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
  783. }
  784. else
  785. {
  786. *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
  787. }
  788. }
  789. #endif /* configENABLE_MPU */
  790. pxTopOfStack--;
  791. *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
  792. #if ( configENABLE_TRUSTZONE == 1 )
  793. {
  794. pxTopOfStack--;
  795. *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
  796. }
  797. #endif /* configENABLE_TRUSTZONE */
  798. }
  799. #else /* portPRELOAD_REGISTERS */
  800. {
  801. pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
  802. *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
  803. pxTopOfStack--;
  804. *pxTopOfStack = ( StackType_t ) pxCode; /* PC */
  805. pxTopOfStack--;
  806. *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
  807. pxTopOfStack--;
  808. *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */
  809. pxTopOfStack--;
  810. *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */
  811. pxTopOfStack--;
  812. *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */
  813. pxTopOfStack--;
  814. *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */
  815. pxTopOfStack--;
  816. *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
  817. pxTopOfStack--;
  818. *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */
  819. pxTopOfStack--;
  820. *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */
  821. pxTopOfStack--;
  822. *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */
  823. pxTopOfStack--;
  824. *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */
  825. pxTopOfStack--;
  826. *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */
  827. pxTopOfStack--;
  828. *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */
  829. pxTopOfStack--;
  830. *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */
  831. pxTopOfStack--;
  832. *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */
  833. pxTopOfStack--;
  834. *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */
  835. #if ( configENABLE_MPU == 1 )
  836. {
  837. pxTopOfStack--;
  838. if( xRunPrivileged == pdTRUE )
  839. {
  840. *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
  841. }
  842. else
  843. {
  844. *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
  845. }
  846. }
  847. #endif /* configENABLE_MPU */
  848. pxTopOfStack--;
  849. *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
  850. #if ( configENABLE_TRUSTZONE == 1 )
  851. {
  852. pxTopOfStack--;
  853. *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
  854. }
  855. #endif /* configENABLE_TRUSTZONE */
  856. }
  857. #endif /* portPRELOAD_REGISTERS */
  858. return pxTopOfStack;
  859. }
  860. /*-----------------------------------------------------------*/
  861. BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
  862. {
  863. /* Make PendSV, CallSV and SysTick the same priority as the kernel. */
  864. portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
  865. portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
  866. #if ( configENABLE_MPU == 1 )
  867. {
  868. /* Setup the Memory Protection Unit (MPU). */
  869. prvSetupMPU();
  870. }
  871. #endif /* configENABLE_MPU */
  872. /* Start the timer that generates the tick ISR. Interrupts are disabled
  873. * here already. */
  874. vPortSetupTimerInterrupt();
  875. /* Initialize the critical nesting count ready for the first task. */
  876. ulCriticalNesting = 0;
  877. /* Start the first task. */
  878. vStartFirstTask();
  879. /* Should never get here as the tasks will now be executing. Call the task
  880. * exit error function to prevent compiler warnings about a static function
  881. * not being called in the case that the application writer overrides this
  882. * functionality by defining configTASK_RETURN_ADDRESS. Call
  883. * vTaskSwitchContext() so link time optimization does not remove the
  884. * symbol. */
  885. vTaskSwitchContext();
  886. prvTaskExitError();
  887. /* Should not get here. */
  888. return 0;
  889. }
  890. /*-----------------------------------------------------------*/
  891. void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
  892. {
  893. /* Not implemented in ports where there is nothing to return to.
  894. * Artificially force an assert. */
  895. configASSERT( ulCriticalNesting == 1000UL );
  896. }
  897. /*-----------------------------------------------------------*/
  898. #if ( configENABLE_MPU == 1 )
  899. void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
  900. const struct xMEMORY_REGION * const xRegions,
  901. StackType_t * pxBottomOfStack,
  902. uint32_t ulStackDepth )
  903. {
  904. uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
  905. int32_t lIndex = 0;
  906. #if defined( __ARMCC_VERSION )
  907. /* Declaration when these variable are defined in code instead of being
  908. * exported from linker scripts. */
  909. extern uint32_t * __privileged_sram_start__;
  910. extern uint32_t * __privileged_sram_end__;
  911. #else
  912. /* Declaration when these variable are exported from linker scripts. */
  913. extern uint32_t __privileged_sram_start__[];
  914. extern uint32_t __privileged_sram_end__[];
  915. #endif /* defined( __ARMCC_VERSION ) */
  916. /* Setup MAIR0. */
  917. xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
  918. xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
  919. /* This function is called automatically when the task is created - in
  920. * which case the stack region parameters will be valid. At all other
  921. * times the stack parameters will not be valid and it is assumed that
  922. * the stack region has already been configured. */
  923. if( ulStackDepth > 0 )
  924. {
  925. ulRegionStartAddress = ( uint32_t ) pxBottomOfStack;
  926. ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1;
  927. /* If the stack is within the privileged SRAM, do not protect it
  928. * using a separate MPU region. This is needed because privileged
  929. * SRAM is already protected using an MPU region and ARMv8-M does
  930. * not allow overlapping MPU regions. */
  931. if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) &&
  932. ( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) )
  933. {
  934. xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0;
  935. xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0;
  936. }
  937. else
  938. {
  939. /* Define the region that allows access to the stack. */
  940. ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK;
  941. ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
  942. xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
  943. ( portMPU_REGION_NON_SHAREABLE ) |
  944. ( portMPU_REGION_READ_WRITE ) |
  945. ( portMPU_REGION_EXECUTE_NEVER );
  946. xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) |
  947. ( portMPU_RLAR_ATTR_INDEX0 ) |
  948. ( portMPU_RLAR_REGION_ENABLE );
  949. }
  950. }
  951. /* User supplied configurable regions. */
  952. for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ )
  953. {
  954. /* If xRegions is NULL i.e. the task has not specified any MPU
  955. * region, the else part ensures that all the configurable MPU
  956. * regions are invalidated. */
  957. if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) )
  958. {
  959. /* Translate the generic region definition contained in xRegions
  960. * into the ARMv8 specific MPU settings that are then stored in
  961. * xMPUSettings. */
  962. ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK;
  963. ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1;
  964. ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
  965. /* Start address. */
  966. xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) |
  967. ( portMPU_REGION_NON_SHAREABLE );
  968. /* RO/RW. */
  969. if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 )
  970. {
  971. xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY );
  972. }
  973. else
  974. {
  975. xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE );
  976. }
  977. /* XN. */
  978. if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 )
  979. {
  980. xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER );
  981. }
  982. /* End Address. */
  983. xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) |
  984. ( portMPU_RLAR_REGION_ENABLE );
  985. /* Normal memory/ Device memory. */
  986. if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 )
  987. {
  988. /* Attr1 in MAIR0 is configured as device memory. */
  989. xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1;
  990. }
  991. else
  992. {
  993. /* Attr1 in MAIR0 is configured as normal memory. */
  994. xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0;
  995. }
  996. }
  997. else
  998. {
  999. /* Invalidate the region. */
  1000. xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL;
  1001. xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL;
  1002. }
  1003. lIndex++;
  1004. }
  1005. }
  1006. #endif /* configENABLE_MPU */
  1007. /*-----------------------------------------------------------*/
  1008. BaseType_t xPortIsInsideInterrupt( void )
  1009. {
  1010. uint32_t ulCurrentInterrupt;
  1011. BaseType_t xReturn;
  1012. /* Obtain the number of the currently executing interrupt. Interrupt Program
  1013. * Status Register (IPSR) holds the exception number of the currently-executing
  1014. * exception or zero for Thread mode.*/
  1015. __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
  1016. if( ulCurrentInterrupt == 0 )
  1017. {
  1018. xReturn = pdFALSE;
  1019. }
  1020. else
  1021. {
  1022. xReturn = pdTRUE;
  1023. }
  1024. return xReturn;
  1025. }
  1026. /*-----------------------------------------------------------*/