2 * FreeRTOS Kernel V10.6.2
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * SPDX-License-Identifier: MIT AND BSD-3-Clause
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:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
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.
24 * https://www.FreeRTOS.org
25 * https://github.com/FreeRTOS
29 /*This file has been prepared for Doxygen automatic documentation generation.*/
30 /*! \file *********************************************************************
32 * \brief FreeRTOS port source for AVR32 UC3.
34 * - Compiler: GNU GCC for AVR32
35 * - Supported devices: All AVR32 devices can be used.
38 * \author Atmel Corporation (Now Microchip):
39 * https://www.microchip.com \n
40 * Support and FAQ: https://www.microchip.com/support/
42 *****************************************************************************/
45 * Copyright (c) 2007, Atmel Corporation All rights reserved.
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions are met:
50 * 1. Redistributions of source code must retain the above copyright notice,
51 * this list of conditions and the following disclaimer.
53 * 2. Redistributions in binary form must reproduce the above copyright notice,
54 * this list of conditions and the following disclaimer in the documentation
55 * and/or other materials provided with the distribution.
57 * 3. The name of ATMEL may not be used to endorse or promote products derived
58 * from this software without specific prior written permission.
60 * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
61 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
62 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
63 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
64 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
65 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
66 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
67 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
68 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
69 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
75 /*-----------------------------------------------------------
76 * Port specific definitions.
78 * The settings in this file configure FreeRTOS correctly for the
79 * given hardware and compiler.
81 * These settings should not be altered.
82 *-----------------------------------------------------------
95 /* Type definitions. */
97 #define portFLOAT float
98 #define portDOUBLE double
100 #define portSHORT short
101 #define portSTACK_TYPE uint32_t
102 #define portBASE_TYPE long
104 typedef portSTACK_TYPE StackType_t;
105 typedef long BaseType_t;
106 typedef unsigned long UBaseType_t;
108 #define TASK_DELAY_MS(x) ( (x) /portTICK_PERIOD_MS )
109 #define TASK_DELAY_S(x) ( (x)*1000 /portTICK_PERIOD_MS )
110 #define TASK_DELAY_MIN(x) ( (x)*60*1000/portTICK_PERIOD_MS )
112 #define configTICK_TC_IRQ ATPASTE2(AVR32_TC_IRQ, configTICK_TC_CHANNEL)
114 #if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
115 typedef uint16_t TickType_t;
116 #define portMAX_DELAY ( TickType_t ) 0xffff
117 #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
118 typedef uint32_t TickType_t;
119 #define portMAX_DELAY ( TickType_t ) ( 0xFFFFFFFFUL )
121 #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
123 /*-----------------------------------------------------------*/
125 /* Architecture specifics. */
126 #define portSTACK_GROWTH ( -1 )
127 #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
128 #define portBYTE_ALIGNMENT 4
129 #define portNOP() {__asm__ __volatile__ ("nop");}
130 /*-----------------------------------------------------------*/
133 /*-----------------------------------------------------------*/
136 #define DISABLE_ALL_EXCEPTIONS() Disable_global_exception()
137 #define ENABLE_ALL_EXCEPTIONS() Enable_global_exception()
139 #define DISABLE_ALL_INTERRUPTS() Disable_global_interrupt()
140 #define ENABLE_ALL_INTERRUPTS() Enable_global_interrupt()
142 #define DISABLE_INT_LEVEL(int_lev) Disable_interrupt_level(int_lev)
143 #define ENABLE_INT_LEVEL(int_lev) Enable_interrupt_level(int_lev)
148 * Activated if and only if configDBG is nonzero.
149 * Prints a formatted string to stdout.
150 * The current source file name and line number are output with a colon before
151 * the formatted string.
152 * A carriage return and a linefeed are appended to the output.
153 * stdout is redirected to the USART configured by configDBG_USART.
154 * The parameters are the same as for the standard printf function.
155 * There is no return value.
156 * SHALL NOT BE CALLED FROM WITHIN AN INTERRUPT as fputs and printf use malloc,
157 * which is interrupt-unsafe with the current __malloc_lock and __malloc_unlock.
160 #define portDBG_TRACE(...) \
162 fputs(__FILE__ ":" ASTRINGZ(__LINE__) ": ", stdout);\
163 printf(__VA_ARGS__);\
164 fputs("\r\n", stdout);\
167 #define portDBG_TRACE(...)
171 /* Critical section management. */
172 #define portDISABLE_INTERRUPTS() DISABLE_ALL_INTERRUPTS()
173 #define portENABLE_INTERRUPTS() ENABLE_ALL_INTERRUPTS()
176 extern void vPortEnterCritical( void );
177 extern void vPortExitCritical( void );
179 #define portENTER_CRITICAL() vPortEnterCritical();
180 #define portEXIT_CRITICAL() vPortExitCritical();
183 /* Added as there is no such function in FreeRTOS. */
184 extern void *pvPortRealloc( void *pv, size_t xSize );
185 /*-----------------------------------------------------------*/
188 /*=============================================================================================*/
191 * Restore Context for cases other than INTi.
193 #define portRESTORE_CONTEXT() \
195 extern volatile uint32_t ulCriticalNesting; \
196 extern volatile void *volatile pxCurrentTCB; \
198 __asm__ __volatile__ ( \
199 /* Set SP to point to new stack */ \
200 "mov r8, LO(%[pxCurrentTCB]) \n\t"\
201 "orh r8, HI(%[pxCurrentTCB]) \n\t"\
202 "ld.w r0, r8[0] \n\t"\
203 "ld.w sp, r0[0] \n\t"\
205 /* Restore ulCriticalNesting variable */ \
206 "ld.w r0, sp++ \n\t"\
207 "mov r8, LO(%[ulCriticalNesting]) \n\t"\
208 "orh r8, HI(%[ulCriticalNesting]) \n\t"\
209 "st.w r8[0], r0 \n\t"\
211 /* Restore R0..R7 */ \
212 "ldm sp++, r0-r7 \n\t"\
213 /* R0-R7 should not be used below this line */ \
214 /* Skip PC and SR (will do it at the end) */ \
216 /* Restore R8..R12 and LR */ \
217 "ldm sp++, r8-r12, lr \n\t"\
219 "ld.w r0, sp[-8*4]\n\t" /* R0 is modified, is restored later. */ \
220 "mtsr %[SR], r0 \n\t"\
222 "ld.w r0, sp[-9*4] \n\t"\
224 "ld.w pc, sp[-7*4]" /* Get PC from stack - PC is the 7th register saved */ \
226 : [ulCriticalNesting] "i" (&ulCriticalNesting), \
227 [pxCurrentTCB] "i" (&pxCurrentTCB), \
228 [SR] "i" (AVR32_SR) \
234 * portSAVE_CONTEXT_INT() and portRESTORE_CONTEXT_INT(): for INT0..3 exceptions.
235 * portSAVE_CONTEXT_SCALL() and portRESTORE_CONTEXT_SCALL(): for the scall exception.
237 * Had to make different versions because registers saved on the system stack
238 * are not the same between INT0..3 exceptions and the scall exception.
241 // Task context stack layout:
259 // (*) automatically done for INT0..INT3, but not for SCALL
262 * The ISR used for the scheduler tick depends on whether the cooperative or
263 * the preemptive scheduler is being used.
265 #if configUSE_PREEMPTION == 0
268 * portSAVE_CONTEXT_OS_INT() for OS Tick exception.
270 #define portSAVE_CONTEXT_OS_INT() \
273 __asm__ __volatile__ ("stm --sp, r0-r7"); \
275 /* With the cooperative scheduler, as there is no context switch by interrupt, */ \
276 /* there is also no context save. */ \
280 * portRESTORE_CONTEXT_OS_INT() for Tick exception.
282 #define portRESTORE_CONTEXT_OS_INT() \
284 __asm__ __volatile__ ( \
285 /* Restore R0..R7 */ \
286 "ldm sp++, r0-r7\n\t" \
288 /* With the cooperative scheduler, as there is no context switch by interrupt, */ \
289 /* there is also no context restore. */ \
297 * portSAVE_CONTEXT_OS_INT() for OS Tick exception.
299 #define portSAVE_CONTEXT_OS_INT() \
301 extern volatile uint32_t ulCriticalNesting; \
302 extern volatile void *volatile pxCurrentTCB; \
304 /* When we come here */ \
305 /* Registers R8..R12, LR, PC and SR had already been pushed to system stack */ \
307 __asm__ __volatile__ ( \
309 "stm --sp, r0-r7 \n\t"\
311 /* Save ulCriticalNesting variable - R0 is overwritten */ \
312 "mov r8, LO(%[ulCriticalNesting])\n\t" \
313 "orh r8, HI(%[ulCriticalNesting])\n\t" \
314 "ld.w r0, r8[0] \n\t"\
315 "st.w --sp, r0 \n\t"\
317 /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
318 /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
319 /* level and allow other lower interrupt level to occur). */ \
320 /* In this case we don't want to do a task switch because we don't know what the stack */ \
321 /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \
322 /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \
323 /* will just be restoring the interrupt handler, no way!!! */ \
324 /* So, since we won't do a vTaskSwitchContext(), it's of no use to save SP. */ \
325 "ld.w r0, sp[9*4]\n\t" /* Read SR in stack */ \
326 "bfextu r0, r0, 22, 3\n\t" /* Extract the mode bits to R0. */ \
327 "cp.w r0, 1\n\t" /* Compare the mode bits with supervisor mode(b'001) */ \
328 "brhi LABEL_INT_SKIP_SAVE_CONTEXT_%[LINE] \n\t"\
330 /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \
331 /* NOTE: we don't enter a critical section here because all interrupt handlers */ \
332 /* MUST perform a SAVE_CONTEXT/RESTORE_CONTEXT in the same way as */ \
333 /* portSAVE_CONTEXT_OS_INT/port_RESTORE_CONTEXT_OS_INT if they call OS functions. */ \
334 /* => all interrupt handlers must use portENTER_SWITCHING_ISR/portEXIT_SWITCHING_ISR. */ \
335 "mov r8, LO(%[pxCurrentTCB])\n\t" \
336 "orh r8, HI(%[pxCurrentTCB])\n\t" \
337 "ld.w r0, r8[0]\n\t" \
340 "LABEL_INT_SKIP_SAVE_CONTEXT_%[LINE]:" \
342 : [ulCriticalNesting] "i" (&ulCriticalNesting), \
343 [pxCurrentTCB] "i" (&pxCurrentTCB), \
344 [LINE] "i" (__LINE__) \
349 * portRESTORE_CONTEXT_OS_INT() for Tick exception.
351 #define portRESTORE_CONTEXT_OS_INT() \
353 extern volatile uint32_t ulCriticalNesting; \
354 extern volatile void *volatile pxCurrentTCB; \
356 /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
357 /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
358 /* level and allow other lower interrupt level to occur). */ \
359 /* In this case we don't want to do a task switch because we don't know what the stack */ \
360 /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \
361 /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \
362 /* will just be restoring the interrupt handler, no way!!! */ \
363 __asm__ __volatile__ ( \
364 "ld.w r0, sp[9*4]\n\t" /* Read SR in stack */ \
365 "bfextu r0, r0, 22, 3\n\t" /* Extract the mode bits to R0. */ \
366 "cp.w r0, 1\n\t" /* Compare the mode bits with supervisor mode(b'001) */ \
367 "brhi LABEL_INT_SKIP_RESTORE_CONTEXT_%[LINE]" \
369 : [LINE] "i" (__LINE__) \
373 /* because it is here safe, always call vTaskSwitchContext() since an OS tick occurred. */ \
374 /* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */\
375 portENTER_CRITICAL(); \
376 vTaskSwitchContext(); \
377 portEXIT_CRITICAL(); \
379 /* Restore all registers */ \
381 __asm__ __volatile__ ( \
382 /* Set SP to point to new stack */ \
383 "mov r8, LO(%[pxCurrentTCB]) \n\t"\
384 "orh r8, HI(%[pxCurrentTCB]) \n\t"\
385 "ld.w r0, r8[0] \n\t"\
388 "LABEL_INT_SKIP_RESTORE_CONTEXT_%[LINE]: \n\t"\
390 /* Restore ulCriticalNesting variable */ \
391 "ld.w r0, sp++ \n\t" \
392 "mov r8, LO(%[ulCriticalNesting]) \n\t"\
393 "orh r8, HI(%[ulCriticalNesting]) \n\t"\
394 "st.w r8[0], r0 \n\t"\
396 /* Restore R0..R7 */ \
397 "ldm sp++, r0-r7 \n\t"\
399 /* Now, the stack should be R8..R12, LR, PC and SR */ \
402 : [ulCriticalNesting] "i" (&ulCriticalNesting), \
403 [pxCurrentTCB] "i" (&pxCurrentTCB), \
404 [LINE] "i" (__LINE__) \
412 * portSAVE_CONTEXT_SCALL() for SupervisorCALL exception.
414 * NOTE: taskYIELD()(== SCALL) MUST NOT be called in a mode > supervisor mode.
417 #define portSAVE_CONTEXT_SCALL() \
419 extern volatile uint32_t ulCriticalNesting; \
420 extern volatile void *volatile pxCurrentTCB; \
422 /* Warning: the stack layout after SCALL doesn't match the one after an interrupt. */ \
423 /* If SR[M2:M0] == 001 */ \
424 /* PC and SR are on the stack. */ \
425 /* Else (other modes) */ \
426 /* Nothing on the stack. */ \
428 /* WARNING NOTE: the else case cannot happen as it is strictly forbidden to call */ \
429 /* vTaskDelay() and vTaskDelayUntil() OS functions (that result in a taskYield()) */ \
430 /* in an interrupt|exception handler. */ \
432 __asm__ __volatile__ ( \
433 /* in order to save R0-R7 */ \
436 "stm --sp, r0-r7 \n\t"\
438 /* in order to save R8-R12 and LR */ \
439 /* do not use SP if interrupts occurs, SP must be left at bottom of stack */ \
440 "sub r7, sp,-16*4 \n\t"\
441 /* Copy PC and SR in other places in the stack. */ \
442 "ld.w r0, r7[-2*4] \n\t" /* Read SR */\
443 "st.w r7[-8*4], r0 \n\t" /* Copy SR */\
444 "ld.w r0, r7[-1*4] \n\t" /* Read PC */\
445 "st.w r7[-7*4], r0 \n\t" /* Copy PC */\
447 /* Save R8..R12 and LR on the stack. */ \
448 "stm --r7, r8-r12, lr \n\t"\
450 /* Arriving here we have the following stack organizations: */ \
451 /* R8..R12, LR, PC, SR, R0..R7. */ \
453 /* Now we can finalize the save. */ \
455 /* Save ulCriticalNesting variable - R0 is overwritten */ \
456 "mov r8, LO(%[ulCriticalNesting]) \n\t"\
457 "orh r8, HI(%[ulCriticalNesting]) \n\t"\
458 "ld.w r0, r8[0] \n\t"\
461 : [ulCriticalNesting] "i" (&ulCriticalNesting) \
464 /* Disable the its which may cause a context switch (i.e. cause a change of */ \
465 /* pxCurrentTCB). */ \
466 /* Basically, all accesses to the pxCurrentTCB structure should be put in a */ \
467 /* critical section because it is a global structure. */ \
468 portENTER_CRITICAL(); \
470 /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \
471 __asm__ __volatile__ ( \
472 "mov r8, LO(%[pxCurrentTCB]) \n\t"\
473 "orh r8, HI(%[pxCurrentTCB]) \n\t"\
474 "ld.w r0, r8[0] \n\t"\
477 : [pxCurrentTCB] "i" (&pxCurrentTCB) \
482 * portRESTORE_CONTEXT() for SupervisorCALL exception.
484 #define portRESTORE_CONTEXT_SCALL() \
486 extern volatile uint32_t ulCriticalNesting; \
487 extern volatile void *volatile pxCurrentTCB; \
489 /* Restore all registers */ \
491 /* Set SP to point to new stack */ \
492 __asm__ __volatile__ ( \
493 "mov r8, LO(%[pxCurrentTCB]) \n\t"\
494 "orh r8, HI(%[pxCurrentTCB]) \n\t"\
495 "ld.w r0, r8[0] \n\t"\
498 : [pxCurrentTCB] "i" (&pxCurrentTCB) \
501 /* Leave pxCurrentTCB variable access critical section */ \
502 portEXIT_CRITICAL(); \
504 __asm__ __volatile__ ( \
505 /* Restore ulCriticalNesting variable */ \
506 "ld.w r0, sp++ \n\t"\
507 "mov r8, LO(%[ulCriticalNesting]) \n\t"\
508 "orh r8, HI(%[ulCriticalNesting]) \n\t"\
509 "st.w r8[0], r0 \n\t"\
511 /* skip PC and SR */ \
512 /* do not use SP if interrupts occurs, SP must be left at bottom of stack */ \
513 "sub r7, sp, -10*4 \n\t"\
514 /* Restore r8-r12 and LR */ \
515 "ldm r7++, r8-r12, lr \n\t"\
517 /* RETS will take care of the extra PC and SR restore. */ \
518 /* So, we have to prepare the stack for this. */ \
519 "ld.w r0, r7[-8*4] \n\t" /* Read SR */\
520 "st.w r7[-2*4], r0 \n\t" /* Copy SR */\
521 "ld.w r0, r7[-7*4] \n\t" /* Read PC */\
522 "st.w r7[-1*4], r0 \n\t" /* Copy PC */\
524 /* Restore R0..R7 */ \
525 "ldm sp++, r0-r7 \n\t"\
531 : [ulCriticalNesting] "i" (&ulCriticalNesting) \
537 * The ISR used depends on whether the cooperative or
538 * the preemptive scheduler is being used.
540 #if configUSE_PREEMPTION == 0
543 * ISR entry and exit macros. These are only required if a task switch
544 * is required from the ISR.
546 #define portENTER_SWITCHING_ISR() \
549 __asm__ __volatile__ ("stm --sp, r0-r7"); \
551 /* With the cooperative scheduler, as there is no context switch by interrupt, */ \
552 /* there is also no context save. */ \
556 * Input parameter: in R12, boolean. Perform a vTaskSwitchContext() if 1
558 #define portEXIT_SWITCHING_ISR() \
560 __asm__ __volatile__ ( \
561 /* Restore R0..R7 */ \
562 "ldm sp++, r0-r7 \n\t"\
564 /* With the cooperative scheduler, as there is no context switch by interrupt, */ \
565 /* there is also no context restore. */ \
573 * ISR entry and exit macros. These are only required if a task switch
574 * is required from the ISR.
576 #define portENTER_SWITCHING_ISR() \
578 extern volatile uint32_t ulCriticalNesting; \
579 extern volatile void *volatile pxCurrentTCB; \
581 /* When we come here */ \
582 /* Registers R8..R12, LR, PC and SR had already been pushed to system stack */ \
584 __asm__ __volatile__ ( \
586 "stm --sp, r0-r7 \n\t"\
588 /* Save ulCriticalNesting variable - R0 is overwritten */ \
589 "mov r8, LO(%[ulCriticalNesting]) \n\t"\
590 "orh r8, HI(%[ulCriticalNesting]) \n\t"\
591 "ld.w r0, r8[0] \n\t"\
592 "st.w --sp, r0 \n\t"\
594 /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
595 /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
596 /* level and allow other lower interrupt level to occur). */ \
597 /* In this case we don't want to do a task switch because we don't know what the stack */ \
598 /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \
599 /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \
600 /* will just be restoring the interrupt handler, no way!!! */ \
601 /* So, since we won't do a vTaskSwitchContext(), it's of no use to save SP. */ \
602 "ld.w r0, sp[9*4] \n\t" /* Read SR in stack */\
603 "bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */\
604 "cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */\
605 "brhi LABEL_ISR_SKIP_SAVE_CONTEXT_%[LINE] \n\t"\
607 /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \
608 "mov r8, LO(%[pxCurrentTCB]) \n\t"\
609 "orh r8, HI(%[pxCurrentTCB]) \n\t"\
610 "ld.w r0, r8[0] \n\t"\
613 "LABEL_ISR_SKIP_SAVE_CONTEXT_%[LINE]:" \
615 : [ulCriticalNesting] "i" (&ulCriticalNesting), \
616 [pxCurrentTCB] "i" (&pxCurrentTCB), \
617 [LINE] "i" (__LINE__) \
622 * Input parameter: in R12, boolean. Perform a vTaskSwitchContext() if 1
624 #define portEXIT_SWITCHING_ISR() \
626 extern volatile uint32_t ulCriticalNesting; \
627 extern volatile void *volatile pxCurrentTCB; \
629 __asm__ __volatile__ ( \
630 /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
631 /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
632 /* level and allow other lower interrupt level to occur). */ \
633 /* In this case it's of no use to switch context and restore a new SP because we purposedly */ \
634 /* did not previously save SP in its TCB. */ \
635 "ld.w r0, sp[9*4] \n\t" /* Read SR in stack */\
636 "bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */\
637 "cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */\
638 "brhi LABEL_ISR_SKIP_RESTORE_CONTEXT_%[LINE] \n\t"\
640 /* If a switch is required then we just need to call */ \
641 /* vTaskSwitchContext() as the context has already been */ \
643 "cp.w r12, 1 \n\t" /* Check if Switch context is required. */\
644 "brne LABEL_ISR_RESTORE_CONTEXT_%[LINE]" \
646 : [LINE] "i" (__LINE__) \
649 /* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */ \
650 portENTER_CRITICAL(); \
651 vTaskSwitchContext(); \
652 portEXIT_CRITICAL(); \
654 __asm__ __volatile__ ( \
655 "LABEL_ISR_RESTORE_CONTEXT_%[LINE]: \n\t"\
656 /* Restore the context of which ever task is now the highest */ \
657 /* priority that is ready to run. */ \
659 /* Restore all registers */ \
661 /* Set SP to point to new stack */ \
662 "mov r8, LO(%[pxCurrentTCB]) \n\t"\
663 "orh r8, HI(%[pxCurrentTCB]) \n\t"\
664 "ld.w r0, r8[0] \n\t"\
667 "LABEL_ISR_SKIP_RESTORE_CONTEXT_%[LINE]: \n\t"\
669 /* Restore ulCriticalNesting variable */ \
670 "ld.w r0, sp++ \n\t"\
671 "mov r8, LO(%[ulCriticalNesting]) \n\t"\
672 "orh r8, HI(%[ulCriticalNesting]) \n\t"\
673 "st.w r8[0], r0 \n\t"\
675 /* Restore R0..R7 */ \
676 "ldm sp++, r0-r7 \n\t"\
678 /* Now, the stack should be R8..R12, LR, PC and SR */ \
681 : [ulCriticalNesting] "i" (&ulCriticalNesting), \
682 [pxCurrentTCB] "i" (&pxCurrentTCB), \
683 [LINE] "i" (__LINE__) \
690 #define portYIELD() {__asm__ __volatile__ ("scall");}
692 /* Task function macros as described on the FreeRTOS.org WEB site. */
693 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
694 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
702 #endif /* PORTMACRO_H */