port.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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. #include "FreeRTOS.h"
  29. #include "task.h"
  30. #include "mb91467d.h"
  31. /*-----------------------------------------------------------*/
  32. /* We require the address of the pxCurrentTCB variable, but don't want to know
  33. any details of its type. */
  34. typedef void TCB_t;
  35. extern volatile TCB_t * volatile pxCurrentTCB;
  36. /*-----------------------------------------------------------*/
  37. #pragma asm
  38. #macro SaveContext
  39. ORCCR #0x20 ;Switch to user stack
  40. ST RP,@-R15 ;Store RP
  41. STM0 (R7,R6,R5,R4,R3,R2,R1,R0) ;Store R7-R0
  42. STM1 (R14,R13,R12,R11,R10,R9,R8) ;Store R14-R8
  43. ST MDH, @-R15 ;Store MDH
  44. ST MDL, @-R15 ;Store MDL
  45. ANDCCR #0xDF ;Switch back to system stack
  46. LD @R15+,R0 ;Store PC to R0
  47. ORCCR #0x20 ;Switch to user stack
  48. ST R0,@-R15 ;Store PC to User stack
  49. ANDCCR #0xDF ;Switch back to system stack
  50. LD @R15+,R0 ;Store PS to R0
  51. ORCCR #0x20 ;Switch to user stack
  52. ST R0,@-R15 ;Store PS to User stack
  53. LDI #_pxCurrentTCB, R0 ;Get pxCurrentTCB address
  54. LD @R0, R0 ;Get the pxCurrentTCB->pxTopOfStack address
  55. ST R15,@R0 ;Store USP to pxCurrentTCB->pxTopOfStack
  56. ANDCCR #0xDF ;Switch back to system stack for the rest of tick ISR
  57. #endm
  58. #macro RestoreContext
  59. LDI #_pxCurrentTCB, R0 ;Get pxCurrentTCB address
  60. LD @R0, R0 ;Get the pxCurrentTCB->pxTopOfStack address
  61. ORCCR #0x20 ;Switch to user stack
  62. LD @R0, R15 ;Restore USP from pxCurrentTCB->pxTopOfStack
  63. LD @R15+,R0 ;Store PS to R0
  64. ANDCCR #0xDF ;Switch to system stack
  65. ST R0,@-R15 ;Store PS to system stack
  66. ORCCR #0x20 ;Switch to user stack
  67. LD @R15+,R0 ;Store PC to R0
  68. ANDCCR #0xDF ;Switch to system stack
  69. ST R0,@-R15 ;Store PC to system stack
  70. ORCCR #0x20 ;Switch back to retrieve the remaining context
  71. LD @R15+, MDL ;Restore MDL
  72. LD @R15+, MDH ;Restore MDH
  73. LDM1 (R14,R13,R12,R11,R10,R9,R8) ;Restore R14-R8
  74. LDM0 (R7,R6,R5,R4,R3,R2,R1,R0) ;Restore R7-R0
  75. LD @R15+, RP ;Restore RP
  76. ANDCCR #0xDF ;Switch back to system stack for the rest of tick ISR
  77. #endm
  78. #pragma endasm
  79. /*-----------------------------------------------------------*/
  80. /*
  81. * Perform hardware setup to enable ticks from timer 1,
  82. */
  83. static void prvSetupTimerInterrupt( void );
  84. /*-----------------------------------------------------------*/
  85. /*
  86. * Initialise the stack of a task to look exactly as if a call to
  87. * portSAVE_CONTEXT had been called.
  88. *
  89. * See the header file portable.h.
  90. */
  91. StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
  92. {
  93. /* Place a few bytes of known values on the bottom of the stack.
  94. This is just useful for debugging. */
  95. *pxTopOfStack = 0x11111111;
  96. pxTopOfStack--;
  97. *pxTopOfStack = 0x22222222;
  98. pxTopOfStack--;
  99. *pxTopOfStack = 0x33333333;
  100. pxTopOfStack--;
  101. /* This is a redundant push to the stack, it may be required if
  102. in some implementations of the compiler the parameter to the task
  103. is passed on to the stack rather than in R4 register. */
  104. *pxTopOfStack = (StackType_t)(pvParameters);
  105. pxTopOfStack--;
  106. *pxTopOfStack = ( StackType_t ) 0x00000000; /* RP */
  107. pxTopOfStack--;
  108. *pxTopOfStack = ( StackType_t ) 0x00007777; /* R7 */
  109. pxTopOfStack--;
  110. *pxTopOfStack = ( StackType_t ) 0x00006666; /* R6 */
  111. pxTopOfStack--;
  112. *pxTopOfStack = ( StackType_t ) 0x00005555; /* R5 */
  113. pxTopOfStack--;
  114. /* In the current implementation of the compiler the first
  115. parameter to the task (or function) is passed via R4 parameter
  116. to the task, hence the pvParameters pointer is copied into the R4
  117. register. See compiler manual section 4.6.2 for more information. */
  118. *pxTopOfStack = ( StackType_t ) (pvParameters); /* R4 */
  119. pxTopOfStack--;
  120. *pxTopOfStack = ( StackType_t ) 0x00003333; /* R3 */
  121. pxTopOfStack--;
  122. *pxTopOfStack = ( StackType_t ) 0x00002222; /* R2 */
  123. pxTopOfStack--;
  124. *pxTopOfStack = ( StackType_t ) 0x00001111; /* R1 */
  125. pxTopOfStack--;
  126. *pxTopOfStack = ( StackType_t ) 0x00000001; /* R0 */
  127. pxTopOfStack--;
  128. *pxTopOfStack = ( StackType_t ) 0x0000EEEE; /* R14 */
  129. pxTopOfStack--;
  130. *pxTopOfStack = ( StackType_t ) 0x0000DDDD; /* R13 */
  131. pxTopOfStack--;
  132. *pxTopOfStack = ( StackType_t ) 0x0000CCCC; /* R12 */
  133. pxTopOfStack--;
  134. *pxTopOfStack = ( StackType_t ) 0x0000BBBB; /* R11 */
  135. pxTopOfStack--;
  136. *pxTopOfStack = ( StackType_t ) 0x0000AAAA; /* R10 */
  137. pxTopOfStack--;
  138. *pxTopOfStack = ( StackType_t ) 0x00009999; /* R9 */
  139. pxTopOfStack--;
  140. *pxTopOfStack = ( StackType_t ) 0x00008888; /* R8 */
  141. pxTopOfStack--;
  142. *pxTopOfStack = ( StackType_t ) 0x11110000; /* MDH */
  143. pxTopOfStack--;
  144. *pxTopOfStack = ( StackType_t ) 0x22220000; /* MDL */
  145. pxTopOfStack--;
  146. /* The start of the task code. */
  147. *pxTopOfStack = ( StackType_t ) pxCode; /* PC */
  148. pxTopOfStack--;
  149. /* PS - User Mode, USP, ILM=31, Interrupts enabled */
  150. *pxTopOfStack = ( StackType_t ) 0x001F0030; /* PS */
  151. return pxTopOfStack;
  152. }
  153. /*-----------------------------------------------------------*/
  154. BaseType_t xPortStartScheduler( void )
  155. {
  156. /* Setup the hardware to generate the tick. */
  157. prvSetupTimerInterrupt();
  158. /* Restore the context of the first task that is going to run. */
  159. #pragma asm
  160. RestoreContext
  161. #pragma endasm
  162. /* Simulate a function call end as generated by the compiler. We will now
  163. jump to the start of the task the context of which we have just restored. */
  164. __asm(" reti ");
  165. /* Should not get here. */
  166. return pdFAIL;
  167. }
  168. /*-----------------------------------------------------------*/
  169. void vPortEndScheduler( void )
  170. {
  171. /* Not implemented - unlikely to ever be required as there is nothing to
  172. return to. */
  173. }
  174. /*-----------------------------------------------------------*/
  175. static void prvSetupTimerInterrupt( void )
  176. {
  177. /* The peripheral clock divided by 32 is used by the timer. */
  178. const uint16_t usReloadValue = ( uint16_t ) ( ( ( configPER_CLOCK_HZ / configTICK_RATE_HZ ) / 32UL ) - 1UL );
  179. /* Setup RLT0 to generate a tick interrupt. */
  180. TMCSR0_CNTE = 0; /* Count Disable */
  181. TMCSR0_CSL = 0x2; /* CLKP/32 */
  182. TMCSR0_MOD = 0; /* Software trigger */
  183. TMCSR0_RELD = 1; /* Reload */
  184. TMCSR0_UF = 0; /* Clear underflow flag */
  185. TMRLR0 = usReloadValue;
  186. TMCSR0_INTE = 1; /* Interrupt Enable */
  187. TMCSR0_CNTE = 1; /* Count Enable */
  188. TMCSR0_TRG = 1; /* Trigger */
  189. PORTEN = 0x3; /* Port Enable */
  190. }
  191. /*-----------------------------------------------------------*/
  192. #if configUSE_PREEMPTION == 1
  193. /*
  194. * Tick ISR for preemptive scheduler. The tick count is incremented
  195. * after the context is saved. Then the context is switched if required,
  196. * and last the context of the task which is to be resumed is restored.
  197. */
  198. #pragma asm
  199. .global _ReloadTimer0_IRQHandler
  200. _ReloadTimer0_IRQHandler:
  201. ANDCCR #0xEF ;Disable Interrupts
  202. SaveContext ;Save context
  203. ORCCR #0x10 ;Re-enable Interrupts
  204. LDI #0xFFFB,R1
  205. LDI #_tmcsr0, R0
  206. AND R1,@R0 ;Clear RLT0 interrupt flag
  207. CALL32 _xTaskIncrementTick,R12 ;Increment Tick
  208. CALL32 _vTaskSwitchContext,R12 ;Switch context if required
  209. ANDCCR #0xEF ;Disable Interrupts
  210. RestoreContext ;Restore context
  211. ORCCR #0x10 ;Re-enable Interrupts
  212. RETI
  213. #pragma endasm
  214. #else
  215. /*
  216. * Tick ISR for the cooperative scheduler. All this does is increment the
  217. * tick count. We don't need to switch context, this can only be done by
  218. * manual calls to taskYIELD();
  219. */
  220. __interrupt void ReloadTimer0_IRQHandler( void )
  221. {
  222. /* Clear RLT0 interrupt flag */
  223. TMCSR0_UF = 0;
  224. xTaskIncrementTick();
  225. }
  226. #endif
  227. /*
  228. * Manual context switch. We can use a __nosavereg attribute as the context
  229. * would be saved by PortSAVE_CONTEXT(). The context is switched and then
  230. * the context of the new task is restored saved.
  231. */
  232. #pragma asm
  233. .global _vPortYieldDelayed
  234. _vPortYieldDelayed:
  235. ANDCCR #0xEF ;Disable Interrupts
  236. SaveContext ;Save context
  237. ORCCR #0x10 ;Re-enable Interrupts
  238. LDI #_dicr, R0
  239. BANDL #0x0E, @R0 ;Clear Delayed interrupt flag
  240. CALL32 _vTaskSwitchContext,R12 ;Switch context if required
  241. ANDCCR #0xEF ;Disable Interrupts
  242. RestoreContext ;Restore context
  243. ORCCR #0x10 ;Re-enable Interrupts
  244. RETI
  245. #pragma endasm
  246. /*-----------------------------------------------------------*/
  247. /*
  248. * Manual context switch. We can use a __nosavereg attribute as the context
  249. * would be saved by PortSAVE_CONTEXT(). The context is switched and then
  250. * the context of the new task is restored saved.
  251. */
  252. #pragma asm
  253. .global _vPortYield
  254. _vPortYield:
  255. SaveContext ;Save context
  256. CALL32 _vTaskSwitchContext,R12 ;Switch context if required
  257. RestoreContext ;Restore context
  258. RETI
  259. #pragma endasm
  260. /*-----------------------------------------------------------*/