portmacro.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  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. /*
  29. Changes from V3.0.0
  30. Changes from V3.0.1
  31. */
  32. #ifndef PORTMACRO_H
  33. #define PORTMACRO_H
  34. #if !defined(_SERIES) || _SERIES != 18
  35. #error "WizC supports FreeRTOS on the Microchip PIC18-series only"
  36. #endif
  37. #if !defined(QUICKCALL) || QUICKCALL != 1
  38. #error "QuickCall must be enabled (see ProjectOptions/Optimisations)"
  39. #endif
  40. #include <stddef.h>
  41. #include <pic.h>
  42. #define portCHAR char
  43. #define portFLOAT float
  44. #define portDOUBLE portFLOAT
  45. #define portLONG long
  46. #define portSHORT short
  47. #define portSTACK_TYPE uint8_t
  48. #define portBASE_TYPE char
  49. typedef portSTACK_TYPE StackType_t;
  50. typedef signed char BaseType_t;
  51. typedef unsigned char UBaseType_t;
  52. #if( configUSE_16_BIT_TICKS == 1 )
  53. typedef uint16_t TickType_t;
  54. #define portMAX_DELAY ( TickType_t ) ( 0xFFFF )
  55. #else
  56. typedef uint32_t TickType_t;
  57. #define portMAX_DELAY ( TickType_t ) ( 0xFFFFFFFF )
  58. #endif
  59. #define portBYTE_ALIGNMENT 1
  60. /*-----------------------------------------------------------*/
  61. /*
  62. * Constant used for context switch macro when we require the interrupt
  63. * enable state to be forced when the interrupted task is switched back in.
  64. */
  65. #define portINTERRUPTS_FORCED (0x01)
  66. /*
  67. * Constant used for context switch macro when we require the interrupt
  68. * enable state to be unchanged when the interrupted task is switched back in.
  69. */
  70. #define portINTERRUPTS_UNCHANGED (0x00)
  71. /* Initial interrupt enable state for newly created tasks. This value is
  72. * used when a task switches in for the first time.
  73. */
  74. #define portINTERRUPTS_INITIAL_STATE (portINTERRUPTS_FORCED)
  75. /*
  76. * Macros to modify the global interrupt enable bit in INTCON.
  77. */
  78. #define portDISABLE_INTERRUPTS() \
  79. do \
  80. { \
  81. bGIE=0; \
  82. } while(bGIE) // MicroChip recommends this check!
  83. #define portENABLE_INTERRUPTS() \
  84. do \
  85. { \
  86. bGIE=1; \
  87. } while(0)
  88. /*-----------------------------------------------------------*/
  89. /*
  90. * Critical section macros.
  91. */
  92. extern uint8_t ucCriticalNesting;
  93. #define portNO_CRITICAL_SECTION_NESTING ( ( uint8_t ) 0 )
  94. #define portENTER_CRITICAL() \
  95. do \
  96. { \
  97. portDISABLE_INTERRUPTS(); \
  98. \
  99. /* \
  100. * Now interrupts are disabled ucCriticalNesting \
  101. * can be accessed directly. Increment \
  102. * ucCriticalNesting to keep a count of how \
  103. * many times portENTER_CRITICAL() has been called. \
  104. */ \
  105. ucCriticalNesting++; \
  106. } while(0)
  107. #define portEXIT_CRITICAL() \
  108. do \
  109. { \
  110. if(ucCriticalNesting > portNO_CRITICAL_SECTION_NESTING) \
  111. { \
  112. /* \
  113. * Decrement the nesting count as we are leaving a \
  114. * critical section. \
  115. */ \
  116. ucCriticalNesting--; \
  117. } \
  118. \
  119. /* \
  120. * If the nesting level has reached zero then \
  121. * interrupts should be re-enabled. \
  122. */ \
  123. if( ucCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
  124. { \
  125. portENABLE_INTERRUPTS(); \
  126. } \
  127. } while(0)
  128. /*-----------------------------------------------------------*/
  129. /*
  130. * The minimal stacksize is calculated on the first reference of
  131. * portMINIMAL_STACK_SIZE. Some input to this calculation is
  132. * compiletime determined, other input is port-defined (see port.c)
  133. */
  134. extern uint16_t usPortCALCULATE_MINIMAL_STACK_SIZE( void );
  135. extern uint16_t usCalcMinStackSize;
  136. #define portMINIMAL_STACK_SIZE \
  137. ((usCalcMinStackSize == 0) \
  138. ? usPortCALCULATE_MINIMAL_STACK_SIZE() \
  139. : usCalcMinStackSize )
  140. /*
  141. * WizC uses a downgrowing stack
  142. */
  143. #define portSTACK_GROWTH ( -1 )
  144. /*-----------------------------------------------------------*/
  145. /*
  146. * Macro's that pushes all the registers that make up the context of a task onto
  147. * the stack, then saves the new top of stack into the TCB. TOSU and TBLPTRU
  148. * are only saved/restored on devices with more than 64kB (32k Words) ROM.
  149. *
  150. * The stackpointer is helt by WizC in FSR2 and points to the first free byte.
  151. * WizC uses a "downgrowing" stack. There is no framepointer.
  152. *
  153. * We keep track of the interruptstatus using ucCriticalNesting. When this
  154. * value equals zero, interrupts have to be enabled upon exit from the
  155. * portRESTORE_CONTEXT macro.
  156. *
  157. * If this is called from an ISR then the interrupt enable bits must have been
  158. * set for the ISR to ever get called. Therefore we want to save
  159. * ucCriticalNesting with value zero. This means the interrupts will again be
  160. * re-enabled when the interrupted task is switched back in.
  161. *
  162. * If this is called from a manual context switch (i.e. from a call to yield),
  163. * then we want to keep the current value of ucCritialNesting so it is restored
  164. * with its current value. This allows a yield from within a critical section.
  165. *
  166. * The compiler uses some locations at the bottom of RAM for temporary
  167. * storage. The compiler may also have been instructed to optimize
  168. * function-parameters and local variables to global storage. The compiler
  169. * uses an area called LocOpt for this wizC feature.
  170. * The total overheadstorage has to be saved in it's entirety as part of
  171. * a task context. These macro's store/restore from data address 0x0000 to
  172. * (OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE - 1).
  173. * OVERHEADPAGE0, LOCOPTSIZE and MAXLOCOPTSIZE are compiler-generated
  174. * assembler definitions.
  175. */
  176. #define portSAVE_CONTEXT( ucInterruptForced ) \
  177. do \
  178. { \
  179. portDISABLE_INTERRUPTS(); \
  180. \
  181. _Pragma("asm") \
  182. ; \
  183. ; Push the relevant SFR's onto the task's stack \
  184. ; \
  185. movff STATUS,POSTDEC2 \
  186. movff WREG,POSTDEC2 \
  187. movff BSR,POSTDEC2 \
  188. movff PRODH,POSTDEC2 \
  189. movff PRODL,POSTDEC2 \
  190. movff FSR0H,POSTDEC2 \
  191. movff FSR0L,POSTDEC2 \
  192. movff FSR1H,POSTDEC2 \
  193. movff FSR1L,POSTDEC2 \
  194. movff TABLAT,POSTDEC2 \
  195. if __ROMSIZE > 0x8000 \
  196. movff TBLPTRU,POSTDEC2 \
  197. endif \
  198. movff TBLPTRH,POSTDEC2 \
  199. movff TBLPTRL,POSTDEC2 \
  200. if __ROMSIZE > 0x8000 \
  201. movff PCLATU,POSTDEC2 \
  202. endif \
  203. movff PCLATH,POSTDEC2 \
  204. ; \
  205. ; Store the compiler-scratch-area as described above. \
  206. ; \
  207. movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
  208. clrf FSR0L,ACCESS \
  209. clrf FSR0H,ACCESS \
  210. _rtos_S1: \
  211. movff POSTINC0,POSTDEC2 \
  212. decfsz WREG,W,ACCESS \
  213. SMARTJUMP _rtos_S1 \
  214. ; \
  215. ; Save the pic call/return-stack belonging to the \
  216. ; current task by copying it to the task's software- \
  217. ; stack. We save the hardware stack pointer (which \
  218. ; is the number of addresses on the stack) in the \
  219. ; W-register first because we need it later and it \
  220. ; is modified in the save-loop by executing pop's. \
  221. ; After the loop the W-register is stored on the \
  222. ; stack, too. \
  223. ; \
  224. movf STKPTR,W,ACCESS \
  225. bz _rtos_s3 \
  226. _rtos_S2: \
  227. if __ROMSIZE > 0x8000 \
  228. movff TOSU,POSTDEC2 \
  229. endif \
  230. movff TOSH,POSTDEC2 \
  231. movff TOSL,POSTDEC2 \
  232. pop \
  233. tstfsz STKPTR,ACCESS \
  234. SMARTJUMP _rtos_S2 \
  235. _rtos_s3: \
  236. movwf POSTDEC2,ACCESS \
  237. ; \
  238. ; Next the value for ucCriticalNesting used by the \
  239. ; task is stored on the stack. When \
  240. ; (ucInterruptForced == portINTERRUPTS_FORCED), we save \
  241. ; it as 0 (portNO_CRITICAL_SECTION_NESTING). \
  242. ; \
  243. if ucInterruptForced == portINTERRUPTS_FORCED \
  244. clrf POSTDEC2,ACCESS \
  245. else \
  246. movff ucCriticalNesting,POSTDEC2 \
  247. endif \
  248. ; \
  249. ; Save the new top of the software stack in the TCB. \
  250. ; \
  251. movff pxCurrentTCB,FSR0L \
  252. movff pxCurrentTCB+1,FSR0H \
  253. movff FSR2L,POSTINC0 \
  254. movff FSR2H,POSTINC0 \
  255. _Pragma("asmend") \
  256. } while(0)
  257. /************************************************************/
  258. /*
  259. * This is the reverse of portSAVE_CONTEXT.
  260. */
  261. #define portRESTORE_CONTEXT() \
  262. do \
  263. { \
  264. _Pragma("asm") \
  265. ; \
  266. ; Set FSR0 to point to pxCurrentTCB->pxTopOfStack. \
  267. ; \
  268. movff pxCurrentTCB,FSR0L \
  269. movff pxCurrentTCB+1,FSR0H \
  270. ; \
  271. ; De-reference FSR0 to set the address it holds into \
  272. ; FSR2 (i.e. *( pxCurrentTCB->pxTopOfStack ) ). FSR2 \
  273. ; is used by wizC as stackpointer. \
  274. ; \
  275. movff POSTINC0,FSR2L \
  276. movff POSTINC0,FSR2H \
  277. ; \
  278. ; Next, the value for ucCriticalNesting used by the \
  279. ; task is retrieved from the stack. \
  280. ; \
  281. movff PREINC2,ucCriticalNesting \
  282. ; \
  283. ; Rebuild the pic call/return-stack. The number of \
  284. ; return addresses is the next item on the task stack. \
  285. ; Save this number in PRODL. Then fetch the addresses \
  286. ; and store them on the hardwarestack. \
  287. ; The datasheets say we can't use movff here... \
  288. ; \
  289. movff PREINC2,PRODL // Use PRODL as tempregister \
  290. clrf STKPTR,ACCESS \
  291. _rtos_R1: \
  292. push \
  293. movf PREINC2,W,ACCESS \
  294. movwf TOSL,ACCESS \
  295. movf PREINC2,W,ACCESS \
  296. movwf TOSH,ACCESS \
  297. if __ROMSIZE > 0x8000 \
  298. movf PREINC2,W,ACCESS \
  299. movwf TOSU,ACCESS \
  300. else \
  301. clrf TOSU,ACCESS \
  302. endif \
  303. decfsz PRODL,F,ACCESS \
  304. SMARTJUMP _rtos_R1 \
  305. ; \
  306. ; Restore the compiler's working storage area to page 0 \
  307. ; \
  308. movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
  309. movwf FSR0L,ACCESS \
  310. clrf FSR0H,ACCESS \
  311. _rtos_R2: \
  312. decf FSR0L,F,ACCESS \
  313. movff PREINC2,INDF0 \
  314. tstfsz FSR0L,ACCESS \
  315. SMARTJUMP _rtos_R2 \
  316. ; \
  317. ; Restore the sfr's forming the tasks context. \
  318. ; We cannot yet restore bsr, w and status because \
  319. ; we need these registers for a final test. \
  320. ; \
  321. movff PREINC2,PCLATH \
  322. if __ROMSIZE > 0x8000 \
  323. movff PREINC2,PCLATU \
  324. else \
  325. clrf PCLATU,ACCESS \
  326. endif \
  327. movff PREINC2,TBLPTRL \
  328. movff PREINC2,TBLPTRH \
  329. if __ROMSIZE > 0x8000 \
  330. movff PREINC2,TBLPTRU \
  331. else \
  332. clrf TBLPTRU,ACCESS \
  333. endif \
  334. movff PREINC2,TABLAT \
  335. movff PREINC2,FSR1L \
  336. movff PREINC2,FSR1H \
  337. movff PREINC2,FSR0L \
  338. movff PREINC2,FSR0H \
  339. movff PREINC2,PRODL \
  340. movff PREINC2,PRODH \
  341. ; \
  342. ; The return from portRESTORE_CONTEXT() depends on \
  343. ; the value of ucCriticalNesting. When it is zero, \
  344. ; interrupts need to be enabled. This is done via a \
  345. ; retfie instruction because we need the \
  346. ; interrupt-enabling and the return to the restored \
  347. ; task to be uninterruptable. \
  348. ; Because bsr, status and W are affected by the test \
  349. ; they are restored after the test. \
  350. ; \
  351. movlb ucCriticalNesting>>8 \
  352. tstfsz ucCriticalNesting,BANKED \
  353. SMARTJUMP _rtos_R4 \
  354. _rtos_R3: \
  355. movff PREINC2,BSR \
  356. movff PREINC2,WREG \
  357. movff PREINC2,STATUS \
  358. retfie 0 ; Return enabling interrupts \
  359. _rtos_R4: \
  360. movff PREINC2,BSR \
  361. movff PREINC2,WREG \
  362. movff PREINC2,STATUS \
  363. return 0 ; Return without affecting interrupts \
  364. _Pragma("asmend") \
  365. } while(0)
  366. /*-----------------------------------------------------------*/
  367. #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
  368. /*-----------------------------------------------------------*/
  369. extern void vPortYield( void );
  370. #define portYIELD() vPortYield()
  371. #define portNOP() _Pragma("asm") \
  372. nop \
  373. _Pragma("asmend")
  374. /*-----------------------------------------------------------*/
  375. #define portTASK_FUNCTION( xFunction, pvParameters ) \
  376. void pointed xFunction( void *pvParameters ) \
  377. _Pragma(asmfunc xFunction)
  378. #define portTASK_FUNCTION_PROTO portTASK_FUNCTION
  379. /*-----------------------------------------------------------*/
  380. #define volatile
  381. #define register
  382. #endif /* PORTMACRO_H */