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