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
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 typedef void TCB_t;
30 extern volatile TCB_t * volatile pxCurrentTCB;
31 extern void vTaskSwitchContext( void );
32 
33 /*
34  * Saves the stack pointer for one task into its TCB, calls
35  * vTaskSwitchContext() to update the TCB being used, then restores the stack
36  * from the new TCB read to run the task.
37  */
38 void portSWITCH_CONTEXT( void );
39 
40 /*
41  * Load the stack pointer from the TCB of the task which is going to be first
42  * to execute.  Then force an IRET so the registers and IP are popped off the
43  * stack.
44  */
45 void portFIRST_CONTEXT( void );
46 
47 /* There are slightly different versions depending on whether you are building
48 to include debugger information.  If debugger information is used then there
49 are a couple of extra bytes left of the ISR stack (presumably for use by the
50 debugger).  The true stack pointer is then stored in the bp register.  We add
51 2 to the stack pointer to remove the extra bytes before we restore our context. */
52 
53 #ifdef DEBUG_BUILD
54 
55     #pragma aux portSWITCH_CONTEXT =    "mov    ax, seg pxCurrentTCB"                                                       \
56                                         "mov    ds, ax"                                                                     \
57                                         "les    bx, pxCurrentTCB"           /* Save the stack pointer into the TCB. */      \
58                                         "mov    es:0x2[ bx ], ss"                                                           \
59                                         "mov    es:[ bx ], sp"                                                              \
60                                         "call   vTaskSwitchContext"         /* Perform the switch. */                       \
61                                         "mov    ax, seg pxCurrentTCB"       /* Restore the stack pointer from the TCB. */   \
62                                         "mov    ds, ax"                                                                     \
63                                         "les    bx, dword ptr pxCurrentTCB"                                                 \
64                                         "mov    ss, es:[ bx + 2 ]"                                                          \
65                                         "mov    sp, es:[ bx ]"                                                              \
66                                         "mov    bp, sp"                     /* Prepair the bp register for the restoration of the SP in the compiler generated portion of the ISR */    \
67                                         "add    bp, 0x0002"
68 
69 
70 
71     #pragma aux portFIRST_CONTEXT =     "mov    ax, seg pxCurrentTCB"           \
72                                         "mov    ds, ax"                         \
73                                         "les    bx, dword ptr pxCurrentTCB"     \
74                                         "mov    ss, es:[ bx + 2 ]"              \
75                                         "mov    sp, es:[ bx ]"                  \
76                                         "add    sp, 0x0002"                     /* Remove the extra bytes that exist in debug builds before restoring the context. */ \
77                                         "pop    ax"                             \
78                                         "pop    ax"                             \
79                                         "pop    es"                             \
80                                         "pop    ds"                             \
81                                         "popa"                                  \
82                                         "iret"
83 #else
84 
85     #pragma aux portSWITCH_CONTEXT =    "mov    ax, seg pxCurrentTCB"                                                       \
86                                         "mov    ds, ax"                                                                     \
87                                         "les    bx, pxCurrentTCB"           /* Save the stack pointer into the TCB. */      \
88                                         "mov    es:0x2[ bx ], ss"                                                           \
89                                         "mov    es:[ bx ], sp"                                                              \
90                                         "call   vTaskSwitchContext"         /* Perform the switch. */                       \
91                                         "mov    ax, seg pxCurrentTCB"       /* Restore the stack pointer from the TCB. */   \
92                                         "mov    ds, ax"                                                                     \
93                                         "les    bx, dword ptr pxCurrentTCB"                                                 \
94                                         "mov    ss, es:[ bx + 2 ]"                                                          \
95                                         "mov    sp, es:[ bx ]"
96 
97 
98     #pragma aux portFIRST_CONTEXT =     "mov    ax, seg pxCurrentTCB"           \
99                                         "mov    ds, ax"                         \
100                                         "les    bx, dword ptr pxCurrentTCB"     \
101                                         "mov    ss, es:[ bx + 2 ]"              \
102                                         "mov    sp, es:[ bx ]"                  \
103                                         "pop    ax"                             \
104                                         "pop    ax"                             \
105                                         "pop    es"                             \
106                                         "pop    ds"                             \
107                                         "popa"                                  \
108                                         "iret"
109 #endif
110