portmacro.h 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. /*
  2. * FreeRTOS Kernel <DEVELOPMENT BRANCH>
  3. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * SPDX-License-Identifier: MIT AND BSD-3-Clause
  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. /*This file has been prepared for Doxygen automatic documentation generation.*/
  29. /*! \file *********************************************************************
  30. *
  31. * \brief FreeRTOS port source for AVR32 UC3.
  32. *
  33. * - Compiler: GNU GCC for AVR32
  34. * - Supported devices: All AVR32 devices can be used.
  35. * - AppNote:
  36. *
  37. * \author Atmel Corporation (Now Microchip):
  38. * https://www.microchip.com \n
  39. * Support and FAQ: https://www.microchip.com/support/
  40. *
  41. *****************************************************************************/
  42. /*
  43. * Copyright (c) 2007, Atmel Corporation All rights reserved.
  44. *
  45. * Redistribution and use in source and binary forms, with or without
  46. * modification, are permitted provided that the following conditions are met:
  47. *
  48. * 1. Redistributions of source code must retain the above copyright notice,
  49. * this list of conditions and the following disclaimer.
  50. *
  51. * 2. Redistributions in binary form must reproduce the above copyright notice,
  52. * this list of conditions and the following disclaimer in the documentation
  53. * and/or other materials provided with the distribution.
  54. *
  55. * 3. The name of ATMEL may not be used to endorse or promote products derived
  56. * from this software without specific prior written permission.
  57. *
  58. * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
  59. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  60. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
  61. * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
  62. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  63. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  64. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  65. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  66. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  67. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  68. */
  69. #ifndef PORTMACRO_H
  70. #define PORTMACRO_H
  71. /*-----------------------------------------------------------
  72. * Port specific definitions.
  73. *
  74. * The settings in this file configure FreeRTOS correctly for the
  75. * given hardware and compiler.
  76. *
  77. * These settings should not be altered.
  78. *-----------------------------------------------------------
  79. */
  80. #include <avr32/io.h>
  81. #include "intc.h"
  82. #include "compiler.h"
  83. /* *INDENT-OFF* */
  84. #ifdef __cplusplus
  85. extern "C" {
  86. #endif
  87. /* *INDENT-ON* */
  88. /* Type definitions. */
  89. #define portCHAR char
  90. #define portFLOAT float
  91. #define portDOUBLE double
  92. #define portLONG long
  93. #define portSHORT short
  94. #define portSTACK_TYPE uint32_t
  95. #define portBASE_TYPE long
  96. typedef portSTACK_TYPE StackType_t;
  97. typedef long BaseType_t;
  98. typedef unsigned long UBaseType_t;
  99. #define TASK_DELAY_MS( x ) ( ( x ) / portTICK_PERIOD_MS )
  100. #define TASK_DELAY_S( x ) ( ( x ) * 1000 / portTICK_PERIOD_MS )
  101. #define TASK_DELAY_MIN( x ) ( ( x ) * 60 * 1000 / portTICK_PERIOD_MS )
  102. #define configTICK_TC_IRQ ATPASTE2( AVR32_TC_IRQ, configTICK_TC_CHANNEL )
  103. #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
  104. typedef uint16_t TickType_t;
  105. #define portMAX_DELAY ( TickType_t ) 0xffff
  106. #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
  107. typedef uint32_t TickType_t;
  108. #define portMAX_DELAY ( TickType_t ) ( 0xFFFFFFFFUL )
  109. #else
  110. #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
  111. #endif
  112. /*-----------------------------------------------------------*/
  113. /* Architecture specifics. */
  114. #define portSTACK_GROWTH ( -1 )
  115. #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
  116. #define portBYTE_ALIGNMENT 4
  117. #define portNOP() { __asm__ __volatile__ ( "nop" ); }
  118. /*-----------------------------------------------------------*/
  119. /*-----------------------------------------------------------*/
  120. /* INTC-specific. */
  121. #define DISABLE_ALL_EXCEPTIONS() Disable_global_exception()
  122. #define ENABLE_ALL_EXCEPTIONS() Enable_global_exception()
  123. #define DISABLE_ALL_INTERRUPTS() Disable_global_interrupt()
  124. #define ENABLE_ALL_INTERRUPTS() Enable_global_interrupt()
  125. #define DISABLE_INT_LEVEL( int_lev ) Disable_interrupt_level( int_lev )
  126. #define ENABLE_INT_LEVEL( int_lev ) Enable_interrupt_level( int_lev )
  127. /*
  128. * Debug trace.
  129. * Activated if and only if configDBG is nonzero.
  130. * Prints a formatted string to stdout.
  131. * The current source file name and line number are output with a colon before
  132. * the formatted string.
  133. * A carriage return and a linefeed are appended to the output.
  134. * stdout is redirected to the USART configured by configDBG_USART.
  135. * The parameters are the same as for the standard printf function.
  136. * There is no return value.
  137. * SHALL NOT BE CALLED FROM WITHIN AN INTERRUPT as fputs and printf use malloc,
  138. * which is interrupt-unsafe with the current __malloc_lock and __malloc_unlock.
  139. */
  140. #if configDBG
  141. #define portDBG_TRACE( ... ) \
  142. { \
  143. fputs( __FILE__ ":" ASTRINGZ( __LINE__ ) ": ", stdout ); \
  144. printf( __VA_ARGS__ ); \
  145. fputs( "\r\n", stdout ); \
  146. }
  147. #else
  148. #define portDBG_TRACE( ... )
  149. #endif
  150. /* Critical section management. */
  151. #define portDISABLE_INTERRUPTS() DISABLE_ALL_INTERRUPTS()
  152. #define portENABLE_INTERRUPTS() ENABLE_ALL_INTERRUPTS()
  153. extern void vPortEnterCritical( void );
  154. extern void vPortExitCritical( void );
  155. #define portENTER_CRITICAL() vPortEnterCritical();
  156. #define portEXIT_CRITICAL() vPortExitCritical();
  157. /* Added as there is no such function in FreeRTOS. */
  158. extern void * pvPortRealloc( void * pv,
  159. size_t xSize );
  160. /*-----------------------------------------------------------*/
  161. /*=============================================================================================*/
  162. /*
  163. * Restore Context for cases other than INTi.
  164. */
  165. #define portRESTORE_CONTEXT() \
  166. { \
  167. extern volatile uint32_t ulCriticalNesting; \
  168. extern volatile void * volatile pxCurrentTCB; \
  169. \
  170. __asm__ __volatile__ ( \
  171. /* Set SP to point to new stack */ \
  172. "mov r8, LO(%[pxCurrentTCB]) \n\t" \
  173. "orh r8, HI(%[pxCurrentTCB]) \n\t" \
  174. "ld.w r0, r8[0] \n\t" \
  175. "ld.w sp, r0[0] \n\t" \
  176. \
  177. /* Restore ulCriticalNesting variable */ \
  178. "ld.w r0, sp++ \n\t" \
  179. "mov r8, LO(%[ulCriticalNesting]) \n\t" \
  180. "orh r8, HI(%[ulCriticalNesting]) \n\t" \
  181. "st.w r8[0], r0 \n\t" \
  182. \
  183. /* Restore R0..R7 */ \
  184. "ldm sp++, r0-r7 \n\t" \
  185. /* R0-R7 should not be used below this line */ \
  186. /* Skip PC and SR (will do it at the end) */ \
  187. "sub sp, -2*4 \n\t" \
  188. /* Restore R8..R12 and LR */ \
  189. "ldm sp++, r8-r12, lr \n\t" \
  190. /* Restore SR */ \
  191. "ld.w r0, sp[-8*4]\n\t" /* R0 is modified, is restored later. */ \
  192. "mtsr %[SR], r0 \n\t" \
  193. /* Restore r0 */ \
  194. "ld.w r0, sp[-9*4] \n\t" \
  195. /* Restore PC */ \
  196. "ld.w pc, sp[-7*4]" /* Get PC from stack - PC is the 7th register saved */ \
  197. : \
  198. :[ ulCriticalNesting ] "i" ( &ulCriticalNesting ), \
  199. [ pxCurrentTCB ] "i" ( &pxCurrentTCB ), \
  200. [ SR ] "i" ( AVR32_SR ) \
  201. ); \
  202. }
  203. /*
  204. * portSAVE_CONTEXT_INT() and portRESTORE_CONTEXT_INT(): for INT0..3 exceptions.
  205. * portSAVE_CONTEXT_SCALL() and portRESTORE_CONTEXT_SCALL(): for the scall exception.
  206. *
  207. * Had to make different versions because registers saved on the system stack
  208. * are not the same between INT0..3 exceptions and the scall exception.
  209. */
  210. /* Task context stack layout: */
  211. /* R8 (*) */
  212. /* R9 (*) */
  213. /* R10 (*) */
  214. /* R11 (*) */
  215. /* R12 (*) */
  216. /* R14/LR (*) */
  217. /* R15/PC (*) */
  218. /* SR (*) */
  219. /* R0 */
  220. /* R1 */
  221. /* R2 */
  222. /* R3 */
  223. /* R4 */
  224. /* R5 */
  225. /* R6 */
  226. /* R7 */
  227. /* ulCriticalNesting */
  228. /* (*) automatically done for INT0..INT3, but not for SCALL */
  229. /*
  230. * The ISR used for the scheduler tick depends on whether the cooperative or
  231. * the preemptive scheduler is being used.
  232. */
  233. #if configUSE_PREEMPTION == 0
  234. /*
  235. * portSAVE_CONTEXT_OS_INT() for OS Tick exception.
  236. */
  237. #define portSAVE_CONTEXT_OS_INT() \
  238. { \
  239. /* Save R0..R7 */ \
  240. __asm__ __volatile__ ( "stm --sp, r0-r7" ); \
  241. \
  242. /* With the cooperative scheduler, as there is no context switch by interrupt, */ \
  243. /* there is also no context save. */ \
  244. }
  245. /*
  246. * portRESTORE_CONTEXT_OS_INT() for Tick exception.
  247. */
  248. #define portRESTORE_CONTEXT_OS_INT() \
  249. { \
  250. __asm__ __volatile__ ( \
  251. /* Restore R0..R7 */ \
  252. "ldm sp++, r0-r7\n\t" \
  253. \
  254. /* With the cooperative scheduler, as there is no context switch by interrupt, */ \
  255. /* there is also no context restore. */ \
  256. "rete" \
  257. ); \
  258. }
  259. #else /* if configUSE_PREEMPTION == 0 */
  260. /*
  261. * portSAVE_CONTEXT_OS_INT() for OS Tick exception.
  262. */
  263. #define portSAVE_CONTEXT_OS_INT() \
  264. { \
  265. extern volatile uint32_t ulCriticalNesting; \
  266. extern volatile void * volatile pxCurrentTCB; \
  267. \
  268. /* When we come here */ \
  269. /* Registers R8..R12, LR, PC and SR had already been pushed to system stack */ \
  270. \
  271. __asm__ __volatile__ ( \
  272. /* Save R0..R7 */ \
  273. "stm --sp, r0-r7 \n\t" \
  274. \
  275. /* Save ulCriticalNesting variable - R0 is overwritten */ \
  276. "mov r8, LO(%[ulCriticalNesting])\n\t" \
  277. "orh r8, HI(%[ulCriticalNesting])\n\t" \
  278. "ld.w r0, r8[0] \n\t" \
  279. "st.w --sp, r0 \n\t" \
  280. \
  281. /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
  282. /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
  283. /* level and allow other lower interrupt level to occur). */ \
  284. /* In this case we don't want to do a task switch because we don't know what the stack */ \
  285. /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \
  286. /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \
  287. /* will just be restoring the interrupt handler, no way!!! */ \
  288. /* So, since we won't do a vTaskSwitchContext(), it's of no use to save SP. */ \
  289. "ld.w r0, sp[9*4]\n\t" /* Read SR in stack */ \
  290. "bfextu r0, r0, 22, 3\n\t" /* Extract the mode bits to R0. */ \
  291. "cp.w r0, 1\n\t" /* Compare the mode bits with supervisor mode(b'001) */ \
  292. "brhi LABEL_INT_SKIP_SAVE_CONTEXT_%[LINE] \n\t" \
  293. \
  294. /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \
  295. /* NOTE: we don't enter a critical section here because all interrupt handlers */ \
  296. /* MUST perform a SAVE_CONTEXT/RESTORE_CONTEXT in the same way as */ \
  297. /* portSAVE_CONTEXT_OS_INT/port_RESTORE_CONTEXT_OS_INT if they call OS functions. */ \
  298. /* => all interrupt handlers must use portENTER_SWITCHING_ISR/portEXIT_SWITCHING_ISR. */ \
  299. "mov r8, LO(%[pxCurrentTCB])\n\t" \
  300. "orh r8, HI(%[pxCurrentTCB])\n\t" \
  301. "ld.w r0, r8[0]\n\t" \
  302. "st.w r0[0], sp\n" \
  303. \
  304. "LABEL_INT_SKIP_SAVE_CONTEXT_%[LINE]:" \
  305. : \
  306. :[ ulCriticalNesting ] "i" ( &ulCriticalNesting ), \
  307. [ pxCurrentTCB ] "i" ( &pxCurrentTCB ), \
  308. [ LINE ] "i" ( __LINE__ ) \
  309. ); \
  310. }
  311. /*
  312. * portRESTORE_CONTEXT_OS_INT() for Tick exception.
  313. */
  314. #define portRESTORE_CONTEXT_OS_INT() \
  315. { \
  316. extern volatile uint32_t ulCriticalNesting; \
  317. extern volatile void * volatile pxCurrentTCB; \
  318. \
  319. /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
  320. /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
  321. /* level and allow other lower interrupt level to occur). */ \
  322. /* In this case we don't want to do a task switch because we don't know what the stack */ \
  323. /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \
  324. /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \
  325. /* will just be restoring the interrupt handler, no way!!! */ \
  326. __asm__ __volatile__ ( \
  327. "ld.w r0, sp[9*4]\n\t" /* Read SR in stack */ \
  328. "bfextu r0, r0, 22, 3\n\t" /* Extract the mode bits to R0. */ \
  329. "cp.w r0, 1\n\t" /* Compare the mode bits with supervisor mode(b'001) */ \
  330. "brhi LABEL_INT_SKIP_RESTORE_CONTEXT_%[LINE]" \
  331. : \
  332. :[ LINE ] "i" ( __LINE__ ) \
  333. ); \
  334. \
  335. /* Else */ \
  336. /* because it is here safe, always call vTaskSwitchContext() since an OS tick occurred. */ \
  337. /* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */ \
  338. portENTER_CRITICAL(); \
  339. vTaskSwitchContext(); \
  340. portEXIT_CRITICAL(); \
  341. \
  342. /* Restore all registers */ \
  343. \
  344. __asm__ __volatile__ ( \
  345. /* Set SP to point to new stack */ \
  346. "mov r8, LO(%[pxCurrentTCB]) \n\t" \
  347. "orh r8, HI(%[pxCurrentTCB]) \n\t" \
  348. "ld.w r0, r8[0] \n\t" \
  349. "ld.w sp, r0[0] \n" \
  350. \
  351. "LABEL_INT_SKIP_RESTORE_CONTEXT_%[LINE]: \n\t" \
  352. \
  353. /* Restore ulCriticalNesting variable */ \
  354. "ld.w r0, sp++ \n\t" \
  355. "mov r8, LO(%[ulCriticalNesting]) \n\t" \
  356. "orh r8, HI(%[ulCriticalNesting]) \n\t" \
  357. "st.w r8[0], r0 \n\t" \
  358. \
  359. /* Restore R0..R7 */ \
  360. "ldm sp++, r0-r7 \n\t" \
  361. \
  362. /* Now, the stack should be R8..R12, LR, PC and SR */ \
  363. "rete" \
  364. : \
  365. :[ ulCriticalNesting ] "i" ( &ulCriticalNesting ), \
  366. [ pxCurrentTCB ] "i" ( &pxCurrentTCB ), \
  367. [ LINE ] "i" ( __LINE__ ) \
  368. ); \
  369. }
  370. #endif /* if configUSE_PREEMPTION == 0 */
  371. /*
  372. * portSAVE_CONTEXT_SCALL() for SupervisorCALL exception.
  373. *
  374. * NOTE: taskYIELD()(== SCALL) MUST NOT be called in a mode > supervisor mode.
  375. *
  376. */
  377. #define portSAVE_CONTEXT_SCALL() \
  378. { \
  379. extern volatile uint32_t ulCriticalNesting; \
  380. extern volatile void * volatile pxCurrentTCB; \
  381. \
  382. /* Warning: the stack layout after SCALL doesn't match the one after an interrupt. */ \
  383. /* If SR[M2:M0] == 001 */ \
  384. /* PC and SR are on the stack. */ \
  385. /* Else (other modes) */ \
  386. /* Nothing on the stack. */ \
  387. \
  388. /* WARNING NOTE: the else case cannot happen as it is strictly forbidden to call */ \
  389. /* vTaskDelay() and vTaskDelayUntil() OS functions (that result in a taskYield()) */ \
  390. /* in an interrupt|exception handler. */ \
  391. \
  392. __asm__ __volatile__ ( \
  393. /* in order to save R0-R7 */ \
  394. "sub sp, 6*4 \n\t" \
  395. /* Save R0..R7 */ \
  396. "stm --sp, r0-r7 \n\t" \
  397. \
  398. /* in order to save R8-R12 and LR */ \
  399. /* do not use SP if interrupts occurs, SP must be left at bottom of stack */ \
  400. "sub r7, sp,-16*4 \n\t" \
  401. /* Copy PC and SR in other places in the stack. */ \
  402. "ld.w r0, r7[-2*4] \n\t" /* Read SR */ \
  403. "st.w r7[-8*4], r0 \n\t" /* Copy SR */ \
  404. "ld.w r0, r7[-1*4] \n\t" /* Read PC */ \
  405. "st.w r7[-7*4], r0 \n\t" /* Copy PC */ \
  406. \
  407. /* Save R8..R12 and LR on the stack. */ \
  408. "stm --r7, r8-r12, lr \n\t" \
  409. \
  410. /* Arriving here we have the following stack organizations: */ \
  411. /* R8..R12, LR, PC, SR, R0..R7. */ \
  412. \
  413. /* Now we can finalize the save. */ \
  414. \
  415. /* Save ulCriticalNesting variable - R0 is overwritten */ \
  416. "mov r8, LO(%[ulCriticalNesting]) \n\t" \
  417. "orh r8, HI(%[ulCriticalNesting]) \n\t" \
  418. "ld.w r0, r8[0] \n\t" \
  419. "st.w --sp, r0" \
  420. : \
  421. :[ ulCriticalNesting ] "i" ( &ulCriticalNesting ) \
  422. ); \
  423. \
  424. /* Disable the its which may cause a context switch (i.e. cause a change of */ \
  425. /* pxCurrentTCB). */ \
  426. /* Basically, all accesses to the pxCurrentTCB structure should be put in a */ \
  427. /* critical section because it is a global structure. */ \
  428. portENTER_CRITICAL(); \
  429. \
  430. /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \
  431. __asm__ __volatile__ ( \
  432. "mov r8, LO(%[pxCurrentTCB]) \n\t" \
  433. "orh r8, HI(%[pxCurrentTCB]) \n\t" \
  434. "ld.w r0, r8[0] \n\t" \
  435. "st.w r0[0], sp" \
  436. : \
  437. :[ pxCurrentTCB ] "i" ( &pxCurrentTCB ) \
  438. ); \
  439. }
  440. /*
  441. * portRESTORE_CONTEXT() for SupervisorCALL exception.
  442. */
  443. #define portRESTORE_CONTEXT_SCALL() \
  444. { \
  445. extern volatile uint32_t ulCriticalNesting; \
  446. extern volatile void * volatile pxCurrentTCB; \
  447. \
  448. /* Restore all registers */ \
  449. \
  450. /* Set SP to point to new stack */ \
  451. __asm__ __volatile__ ( \
  452. "mov r8, LO(%[pxCurrentTCB]) \n\t" \
  453. "orh r8, HI(%[pxCurrentTCB]) \n\t" \
  454. "ld.w r0, r8[0] \n\t" \
  455. "ld.w sp, r0[0]" \
  456. : \
  457. :[ pxCurrentTCB ] "i" ( &pxCurrentTCB ) \
  458. ); \
  459. \
  460. /* Leave pxCurrentTCB variable access critical section */ \
  461. portEXIT_CRITICAL(); \
  462. \
  463. __asm__ __volatile__ ( \
  464. /* Restore ulCriticalNesting variable */ \
  465. "ld.w r0, sp++ \n\t" \
  466. "mov r8, LO(%[ulCriticalNesting]) \n\t" \
  467. "orh r8, HI(%[ulCriticalNesting]) \n\t" \
  468. "st.w r8[0], r0 \n\t" \
  469. \
  470. /* skip PC and SR */ \
  471. /* do not use SP if interrupts occurs, SP must be left at bottom of stack */ \
  472. "sub r7, sp, -10*4 \n\t" \
  473. /* Restore r8-r12 and LR */ \
  474. "ldm r7++, r8-r12, lr \n\t" \
  475. \
  476. /* RETS will take care of the extra PC and SR restore. */ \
  477. /* So, we have to prepare the stack for this. */ \
  478. "ld.w r0, r7[-8*4] \n\t" /* Read SR */ \
  479. "st.w r7[-2*4], r0 \n\t" /* Copy SR */ \
  480. "ld.w r0, r7[-7*4] \n\t" /* Read PC */ \
  481. "st.w r7[-1*4], r0 \n\t" /* Copy PC */ \
  482. \
  483. /* Restore R0..R7 */ \
  484. "ldm sp++, r0-r7 \n\t" \
  485. \
  486. "sub sp, -6*4 \n\t" \
  487. \
  488. "rets" \
  489. : \
  490. :[ ulCriticalNesting ] "i" ( &ulCriticalNesting ) \
  491. ); \
  492. }
  493. /*
  494. * The ISR used depends on whether the cooperative or
  495. * the preemptive scheduler is being used.
  496. */
  497. #if configUSE_PREEMPTION == 0
  498. /*
  499. * ISR entry and exit macros. These are only required if a task switch
  500. * is required from the ISR.
  501. */
  502. #define portENTER_SWITCHING_ISR() \
  503. { \
  504. /* Save R0..R7 */ \
  505. __asm__ __volatile__ ( "stm --sp, r0-r7" ); \
  506. \
  507. /* With the cooperative scheduler, as there is no context switch by interrupt, */ \
  508. /* there is also no context save. */ \
  509. }
  510. /*
  511. * Input parameter: in R12, boolean. Perform a vTaskSwitchContext() if 1
  512. */
  513. #define portEXIT_SWITCHING_ISR() \
  514. { \
  515. __asm__ __volatile__ ( \
  516. /* Restore R0..R7 */ \
  517. "ldm sp++, r0-r7 \n\t" \
  518. \
  519. /* With the cooperative scheduler, as there is no context switch by interrupt, */ \
  520. /* there is also no context restore. */ \
  521. "rete" \
  522. ); \
  523. }
  524. #else /* if configUSE_PREEMPTION == 0 */
  525. /*
  526. * ISR entry and exit macros. These are only required if a task switch
  527. * is required from the ISR.
  528. */
  529. #define portENTER_SWITCHING_ISR() \
  530. { \
  531. extern volatile uint32_t ulCriticalNesting; \
  532. extern volatile void * volatile pxCurrentTCB; \
  533. \
  534. /* When we come here */ \
  535. /* Registers R8..R12, LR, PC and SR had already been pushed to system stack */ \
  536. \
  537. __asm__ __volatile__ ( \
  538. /* Save R0..R7 */ \
  539. "stm --sp, r0-r7 \n\t" \
  540. \
  541. /* Save ulCriticalNesting variable - R0 is overwritten */ \
  542. "mov r8, LO(%[ulCriticalNesting]) \n\t" \
  543. "orh r8, HI(%[ulCriticalNesting]) \n\t" \
  544. "ld.w r0, r8[0] \n\t" \
  545. "st.w --sp, r0 \n\t" \
  546. \
  547. /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
  548. /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
  549. /* level and allow other lower interrupt level to occur). */ \
  550. /* In this case we don't want to do a task switch because we don't know what the stack */ \
  551. /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \
  552. /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \
  553. /* will just be restoring the interrupt handler, no way!!! */ \
  554. /* So, since we won't do a vTaskSwitchContext(), it's of no use to save SP. */ \
  555. "ld.w r0, sp[9*4] \n\t" /* Read SR in stack */ \
  556. "bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */ \
  557. "cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */ \
  558. "brhi LABEL_ISR_SKIP_SAVE_CONTEXT_%[LINE] \n\t" \
  559. \
  560. /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \
  561. "mov r8, LO(%[pxCurrentTCB]) \n\t" \
  562. "orh r8, HI(%[pxCurrentTCB]) \n\t" \
  563. "ld.w r0, r8[0] \n\t" \
  564. "st.w r0[0], sp \n" \
  565. \
  566. "LABEL_ISR_SKIP_SAVE_CONTEXT_%[LINE]:" \
  567. : \
  568. :[ ulCriticalNesting ] "i" ( &ulCriticalNesting ), \
  569. [ pxCurrentTCB ] "i" ( &pxCurrentTCB ), \
  570. [ LINE ] "i" ( __LINE__ ) \
  571. ); \
  572. }
  573. /*
  574. * Input parameter: in R12, boolean. Perform a vTaskSwitchContext() if 1
  575. */
  576. #define portEXIT_SWITCHING_ISR() \
  577. { \
  578. extern volatile uint32_t ulCriticalNesting; \
  579. extern volatile void * volatile pxCurrentTCB; \
  580. \
  581. __asm__ __volatile__ ( \
  582. /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
  583. /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
  584. /* level and allow other lower interrupt level to occur). */ \
  585. /* In this case it's of no use to switch context and restore a new SP because we purposely */ \
  586. /* did not previously save SP in its TCB. */ \
  587. "ld.w r0, sp[9*4] \n\t" /* Read SR in stack */ \
  588. "bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */ \
  589. "cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */ \
  590. "brhi LABEL_ISR_SKIP_RESTORE_CONTEXT_%[LINE] \n\t" \
  591. \
  592. /* If a switch is required then we just need to call */ \
  593. /* vTaskSwitchContext() as the context has already been */ \
  594. /* saved. */ \
  595. "cp.w r12, 1 \n\t" /* Check if Switch context is required. */ \
  596. "brne LABEL_ISR_RESTORE_CONTEXT_%[LINE]" \
  597. : \
  598. :[ LINE ] "i" ( __LINE__ ) \
  599. ); \
  600. \
  601. /* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */ \
  602. portENTER_CRITICAL(); \
  603. vTaskSwitchContext(); \
  604. portEXIT_CRITICAL(); \
  605. \
  606. __asm__ __volatile__ ( \
  607. "LABEL_ISR_RESTORE_CONTEXT_%[LINE]: \n\t" \
  608. /* Restore the context of which ever task is now the highest */ \
  609. /* priority that is ready to run. */ \
  610. \
  611. /* Restore all registers */ \
  612. \
  613. /* Set SP to point to new stack */ \
  614. "mov r8, LO(%[pxCurrentTCB]) \n\t" \
  615. "orh r8, HI(%[pxCurrentTCB]) \n\t" \
  616. "ld.w r0, r8[0] \n\t" \
  617. "ld.w sp, r0[0] \n" \
  618. \
  619. "LABEL_ISR_SKIP_RESTORE_CONTEXT_%[LINE]: \n\t" \
  620. \
  621. /* Restore ulCriticalNesting variable */ \
  622. "ld.w r0, sp++ \n\t" \
  623. "mov r8, LO(%[ulCriticalNesting]) \n\t" \
  624. "orh r8, HI(%[ulCriticalNesting]) \n\t" \
  625. "st.w r8[0], r0 \n\t" \
  626. \
  627. /* Restore R0..R7 */ \
  628. "ldm sp++, r0-r7 \n\t" \
  629. \
  630. /* Now, the stack should be R8..R12, LR, PC and SR */ \
  631. "rete" \
  632. : \
  633. :[ ulCriticalNesting ] "i" ( &ulCriticalNesting ), \
  634. [ pxCurrentTCB ] "i" ( &pxCurrentTCB ), \
  635. [ LINE ] "i" ( __LINE__ ) \
  636. ); \
  637. }
  638. #endif /* if configUSE_PREEMPTION == 0 */
  639. #define portYIELD() { __asm__ __volatile__ ( "scall" ); }
  640. /* Task function macros as described on the FreeRTOS.org WEB site. */
  641. #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
  642. #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
  643. /* *INDENT-OFF* */
  644. #ifdef __cplusplus
  645. }
  646. #endif
  647. /* *INDENT-ON* */
  648. #endif /* PORTMACRO_H */