]> begriffs open source - freertos/blob - portable/IAR/AVR_Mega0/portmacro.s90
[AUTO][RELEASE]: Bump file header version to "10.5.1"
[freertos] / portable / IAR / AVR_Mega0 / portmacro.s90
1 ;/*
2 ; * FreeRTOS Kernel V10.5.1
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 #include "porthardware.h"
30
31 ; Declare all extern symbols here - including any ISRs that are referenced in
32 ; the vector table.
33
34 ; ISR functions
35 ; -------------
36 EXTERN TICK_INT
37
38 ; Functions used by scheduler
39 ; ---------------------------
40 EXTERN vTaskSwitchContext
41 EXTERN pxCurrentTCB
42 EXTERN xTaskIncrementTick
43 EXTERN uxCriticalNesting
44
45 ; Functions implemented in this file
46 ; ----------------------------------
47 PUBLIC vPortYield
48 PUBLIC vPortYieldFromTick
49 PUBLIC vPortYieldFromISR
50 PUBLIC vPortStart
51
52 ; Interrupt vector table.
53 ; -----------------------
54 ;
55 ; For simplicity the RTOS tick interrupt routine uses the __task keyword.
56 ; As the IAR compiler does not permit a function to be declared using both
57 ; __task and __interrupt, the use of __task necessitates that the interrupt
58 ; vector table be setup manually.
59 ;
60 ; To write an ISR, implement the ISR function using the __interrupt keyword
61 ; but do not install the interrupt using the "#pragma vector=ABC" method.
62 ; Instead manually place the name of the ISR in the vector table using an
63 ; ORG and jmp instruction as demonstrated below.
64 ; You will also have to add an EXTERN statement at the top of the file.
65
66     ASEG
67
68     ORG TICK_INT_vect                   ; Vector address
69         jmp TICK_INT                    ; ISR
70
71     RSEG CODE
72
73 CLR_INT MACRO  FLAG_REG, FLAG_MASK
74     st -y, r16
75     ldi r16, FLAG_MASK
76     sts FLAG_REG, r16
77     ld r16, y+
78         
79     ENDM
80
81 ; Saving and Restoring a Task Context and Task Switching
82 ; ------------------------------------------------------
83 ;
84 ; The IAR compiler does not fully support inline assembler, so saving and
85 ; restoring a task context has to be written in an asm file.
86 ;
87 ; vPortYield() and vPortYieldFromTick() are usually written in C.  Doing
88 ; so in this case would required calls to be made to portSAVE_CONTEXT() and
89 ; portRESTORE_CONTEXT().  This is dis-advantageous as the context switch
90 ; function would require two extra jump and return instructions over the
91 ; WinAVR equivalent.
92 ;
93 ; To avoid this I have opted to implement both vPortYield() and
94 ; vPortYieldFromTick() in this assembly file.  For convenience
95 ; portSAVE_CONTEXT and portRESTORE_CONTEXT are implemented as macros.
96
97 portSAVE_CONTEXT MACRO
98     st  -y, r0          ; First save the r0 register - we need to use this.
99     in  r0, SREG        ; Obtain the SREG value so we can disable interrupts...
100     cli                 ; ... as soon as possible.
101     st  -y, r0          ; Store the SREG as it was before we disabled interrupts.
102
103     in  r0, SPL         ; Next store the hardware stack pointer.  The IAR...
104     st  -y, r0          ; ... compiler uses the hardware stack as a call stack ...
105     in  r0, SPH         ; ...  only.
106     st  -y, r0
107
108     st  -y, r1          ; Now store the rest of the registers.  Dont store the ...
109     st  -y, r2          ; ... the Y register here as it is used as the software
110     st  -y, r3          ; stack pointer and will get saved into the TCB.
111     st  -y, r4
112     st  -y, r5
113     st  -y, r6
114     st  -y, r7
115     st  -y, r8
116     st  -y, r9
117     st  -y, r10
118     st  -y, r11
119     st  -y, r12
120     st  -y, r13
121     st  -y, r14
122     st  -y, r15
123     st  -y, r16
124     st  -y, r17
125     st  -y, r18
126     st  -y, r19
127     st  -y, r20
128     st  -y, r21
129     st  -y, r22
130     st  -y, r23
131     st  -y, r24
132     st  -y, r25
133     st  -y, r26
134     st  -y, r27
135     st  -y, r30
136     st  -y, r31
137         
138     lds r0, uxCriticalNesting
139     st  -y, r0                  ; Store the critical nesting counter.
140
141     lds r26, pxCurrentTCB       ; Finally save the software stack pointer (Y ...
142     lds r27, pxCurrentTCB + 1   ; ... register) into the TCB.
143     st  x+, r28
144     st  x+, r29
145
146     ENDM
147
148
149 portRESTORE_CONTEXT MACRO
150     lds r26, pxCurrentTCB
151     lds r27, pxCurrentTCB + 1       ; Restore the software stack pointer from ...
152     ld  r28, x+                     ; the TCB into the software stack pointer (...
153     ld  r29, x+                     ; ... the Y register).
154
155     ld  r0, y+
156     sts uxCriticalNesting, r0
157
158     ld  r31, y+                     ; Restore the registers down to R0.  The Y
159     ld  r30, y+                     ; register is missing from this list as it
160     ld  r27, y+                     ; has already been restored.
161     ld  r26, y+
162     ld  r25, y+
163     ld  r24, y+
164     ld  r23, y+
165     ld  r22, y+
166     ld  r21, y+
167     ld  r20, y+
168     ld  r19, y+
169     ld  r18, y+
170     ld  r17, y+
171     ld  r16, y+
172     ld  r15, y+
173     ld  r14, y+
174     ld  r13, y+
175     ld  r12, y+
176     ld  r11, y+
177     ld  r10, y+
178     ld  r9, y+
179     ld  r8, y+
180     ld  r7, y+
181     ld  r6, y+
182     ld  r5, y+
183     ld  r4, y+
184     ld  r3, y+
185     ld  r2, y+
186     ld  r1, y+
187
188     ld  r0, y+                      ; The next thing on the stack is the ...
189     out SPH, r0                     ; ... hardware stack pointer.
190     ld  r0, y+
191     out SPL, r0
192
193     ld  r0, y+                      ; Next there is the SREG register.
194     out SREG, r0
195
196     ld  r0, y+                      ; Finally we have finished with r0, so restore r0.
197
198     ENDM
199
200
201
202 ; vPortYield(), vPortYieldFromTick() and vPortYieldFromISR()
203 ; -------------------------------------
204 ;
205 ; Manual and preemptive context switch functions respectively.
206 ; The IAR compiler does not fully support inline assembler,
207 ; so these are implemented here rather than the more usually
208 ; place of within port.c.
209
210 vPortYield:
211     portSAVE_CONTEXT                ; Save the context of the current task.
212     call vTaskSwitchContext         ; Call the scheduler.
213     portRESTORE_CONTEXT             ; Restore the context of whichever task the ...
214     ret                             ; ... scheduler decided should run.
215
216 vPortYieldFromTick:
217     CLR_INT INT_FLAGS, INT_MASK     ; Clear tick interrupt flag
218  
219     portSAVE_CONTEXT                ; Save the context of the current task.
220     call xTaskIncrementTick         ; Call the timer tick function.
221     tst r16
222     breq SkipTaskSwitch
223     call vTaskSwitchContext         ; Call the scheduler.
224
225 SkipTaskSwitch:
226     portRESTORE_CONTEXT             ; Restore the context of whichever task the ...
227     reti                            ; ... scheduler decided should run.
228
229 vPortYieldFromISR:
230     portSAVE_CONTEXT                ; Save the context of the current task.
231     call vTaskSwitchContext         ; Call the scheduler.
232     portRESTORE_CONTEXT             ; Restore the context of whichever task the ...
233     reti                            ; ... scheduler decided should run.
234
235 ; vPortStart()
236 ; ------------
237 ;
238 ; Again due to the lack of inline assembler, this is required
239 ; to get access to the portRESTORE_CONTEXT macro.
240
241 vPortStart:
242         portRESTORE_CONTEXT
243         ret
244
245 ; Just a filler for unused interrupt vectors.
246 vNoISR:
247     reti
248
249 END