port_cmsis.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*
  2. * FreeRTOS Kernel V10.0.0
  3. * Copyright (C) 2017 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. If you wish to use our Amazon
  14. * FreeRTOS name, please do so in a fair use way that does not cause confusion.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. *
  23. * http://www.FreeRTOS.org
  24. * http://aws.amazon.com/freertos
  25. *
  26. * 1 tab == 4 spaces!
  27. */
  28. /*-----------------------------------------------------------
  29. * Implementation of functions defined in portable.h for the ARM CM0 port.
  30. *----------------------------------------------------------*/
  31. /* Scheduler includes. */
  32. #include "FreeRTOS.h"
  33. #include "task.h"
  34. #ifdef SOFTDEVICE_PRESENT
  35. #include "nrf_soc.h"
  36. #endif
  37. /* Make sure that all elements in isr state fits in uint32_t element*/
  38. #include "portmacro_cmsis.h"
  39. STATIC_ASSERT(sizeof(portISRState_t) == sizeof(uint32_t));
  40. /* Constants used for assertion check of the selected CPU */
  41. #define portCORTEX_M0_r0p0_ID ( 0x410CC200UL )
  42. /* Constants required to check the validity of an interrupt priority. */
  43. #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
  44. #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
  45. #define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
  46. /* Constants required to set up the initial stack. */
  47. #define portINITIAL_XPSR (((xPSR_Type){.b.T = 1}).w)
  48. #define portINITIAL_EXEC_RETURN ( 0xfffffffd )
  49. /* Let the user override the pre-loading of the initial LR with the address of
  50. prvTaskExitError() in case is messes up unwinding of the stack in the
  51. debugger. */
  52. #ifdef configTASK_RETURN_ADDRESS
  53. #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
  54. #else
  55. #define portTASK_RETURN_ADDRESS prvTaskExitError
  56. #endif
  57. /* Each task maintains its own interrupt status in the critical nesting
  58. variable. */
  59. static UBaseType_t uxCriticalNesting = 0;
  60. #ifdef SOFTDEVICE_PRESENT
  61. /* Flag that is set when yielding should be done after critical section exiting */
  62. static UBaseType_t uxYieldFlag = 0;
  63. #endif
  64. /*
  65. * Setup the timer to generate the tick interrupts. The implementation in this
  66. * file is weak to allow application writers to change the timer used to
  67. * generate the tick interrupt.
  68. */
  69. extern void vPortSetupTimerInterrupt( void );
  70. /*
  71. * Exception handlers.
  72. */
  73. void xPortSysTickHandler( void );
  74. /*
  75. * Start first task is a separate function so it can be tested in isolation.
  76. */
  77. extern void vPortStartFirstTask( void );
  78. /*
  79. * Used to catch tasks that attempt to return from their implementing function.
  80. */
  81. static void prvTaskExitError( void );
  82. /*-----------------------------------------------------------*/
  83. /*
  84. * See header file for description.
  85. */
  86. StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
  87. {
  88. /* Simulate the stack frame as it would be created by a context switch
  89. interrupt. */
  90. /* Offset added to account for the way the MCU uses the stack on entry/exit
  91. of interrupts, and to ensure alignment. */
  92. pxTopOfStack--;
  93. *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
  94. pxTopOfStack--;
  95. *pxTopOfStack = ( StackType_t ) pxCode; /* PC */
  96. pxTopOfStack--;
  97. *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
  98. /* Save code space by skipping register initialisation. */
  99. pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
  100. *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
  101. pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
  102. return pxTopOfStack;
  103. }
  104. /*-----------------------------------------------------------*/
  105. static void prvTaskExitError( void )
  106. {
  107. /* A function that implements a task must not exit or attempt to return to
  108. its caller as there is nothing to return to. If a task wants to exit it
  109. should instead call vTaskDelete( NULL ).
  110. Artificially force an assert() to be triggered if configASSERT() is
  111. defined, then stop here so application writers can catch the error. */
  112. configASSERT( uxCriticalNesting == ~0UL );
  113. portDISABLE_INTERRUPTS();
  114. for ( ;; );
  115. }
  116. /*-----------------------------------------------------------*/
  117. /*
  118. * See header file for description.
  119. */
  120. BaseType_t xPortStartScheduler( void )
  121. {
  122. /* This port can be used only on Cortex-M0 processor */
  123. configASSERT( SCB->CPUID == portCORTEX_M0_r0p0_ID );
  124. /* Make PendSV the lowest priority interrupts. */
  125. NVIC_SetPriority(PendSV_IRQn, configKERNEL_INTERRUPT_PRIORITY);
  126. /* Start the timer that generates the tick ISR. Interrupts are disabled
  127. here already. */
  128. vPortSetupTimerInterrupt();
  129. /* Initialise the critical nesting count ready for the first task. */
  130. uxCriticalNesting = 0;
  131. /* Finally this port requires SEVONPEND to be active */
  132. SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
  133. /* Start the first task. */
  134. vPortStartFirstTask();
  135. /* Should never get here as the tasks will now be executing! Call the task
  136. exit error function to prevent compiler warnings about a static function
  137. not being called in the case that the application writer overrides this
  138. functionality by defining configTASK_RETURN_ADDRESS. */
  139. prvTaskExitError();
  140. /* Should not get here! */
  141. return 0;
  142. }
  143. /*-----------------------------------------------------------*/
  144. void vPortEndScheduler( void )
  145. {
  146. /* Not implemented in ports where there is nothing to return to.
  147. Artificially force an assert. */
  148. configASSERT( uxCriticalNesting == 1000UL );
  149. }
  150. /*-----------------------------------------------------------*/
  151. void vPortTaskYield( void )
  152. {
  153. #ifdef SOFTDEVICE_PRESENT
  154. if (uxCriticalNesting > 0)
  155. {
  156. uxYieldFlag = 1;
  157. }
  158. else
  159. {
  160. portPendSVSchedule();
  161. }
  162. #else
  163. portPendSVSchedule();
  164. #endif
  165. }
  166. /*-----------------------------------------------------------*/
  167. void vPortEnterCritical( void )
  168. {
  169. portDISABLE_INTERRUPTS();
  170. uxCriticalNesting++;
  171. /* This is not the interrupt safe version of the enter critical function so
  172. assert() if it is being called from an interrupt context. Only API
  173. functions that end in "FromISR" can be used in an interrupt. Only assert if
  174. the critical nesting count is 1 to protect against recursive calls if the
  175. assert function also uses a critical section. */
  176. if ( uxCriticalNesting == 1 )
  177. {
  178. configASSERT( ( SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk ) == 0 );
  179. }
  180. }
  181. /*-----------------------------------------------------------*/
  182. void vPortExitCritical( void )
  183. {
  184. configASSERT( uxCriticalNesting );
  185. uxCriticalNesting--;
  186. if ( uxCriticalNesting == 0 )
  187. {
  188. portENABLE_INTERRUPTS();
  189. #ifdef SOFTDEVICE_PRESENT
  190. if (uxYieldFlag)
  191. {
  192. uxYieldFlag = 0;
  193. portPendSVSchedule();
  194. }
  195. #endif
  196. }
  197. }
  198. /*-----------------------------------------------------------*/
  199. void vPortSafeTaskSwitchContext( void )
  200. {
  201. uint32_t isrstate = portSET_INTERRUPT_MASK_FROM_ISR();
  202. vTaskSwitchContext();
  203. portCLEAR_INTERRUPT_MASK_FROM_ISR(isrstate);
  204. }