]> begriffs open source - freertos/blob - portable/IAR/AVR_Mega0/portmacro.s90
Add SMP in the License Header (#402)
[freertos] / portable / IAR / AVR_Mega0 / portmacro.s90
1 ;/*
2 ; * FreeRTOS SMP Kernel V202110.00
3 ; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4 ; *
5 ; * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 ; * this software and associated documentation files (the "Software"), to deal in
7 ; * the Software without restriction, including without limitation the rights to
8 ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 ; * the Software, and to permit persons to whom the Software is furnished to do so,
10 ; * subject to the following conditions:
11 ; *
12 ; * The above copyright notice and this permission notice shall be included in all
13 ; * copies or substantial portions of the Software.
14 ; *
15 ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 ; *
22 ; * https://www.FreeRTOS.org
23 ; * https://github.com/FreeRTOS
24 ; *
25 ; * 1 tab == 4 spaces!
26 ; */
27
28 #include "porthardware.h"
29
30 ; Declare all extern symbols here - including any ISRs that are referenced in
31 ; the vector table.
32
33 ; ISR functions
34 ; -------------
35 EXTERN TICK_INT
36
37 ; Functions used by scheduler
38 ; ---------------------------
39 EXTERN vTaskSwitchContext
40 EXTERN pxCurrentTCB
41 EXTERN xTaskIncrementTick
42 EXTERN uxCriticalNesting
43
44 ; Functions implemented in this file
45 ; ----------------------------------
46 PUBLIC vPortYield
47 PUBLIC vPortYieldFromTick
48 PUBLIC vPortYieldFromISR
49 PUBLIC vPortStart
50
51 ; Interrupt vector table.
52 ; -----------------------
53 ;
54 ; For simplicity the RTOS tick interrupt routine uses the __task keyword.
55 ; As the IAR compiler does not permit a function to be declared using both
56 ; __task and __interrupt, the use of __task necessitates that the interrupt
57 ; vector table be setup manually.
58 ;
59 ; To write an ISR, implement the ISR function using the __interrupt keyword
60 ; but do not install the interrupt using the "#pragma vector=ABC" method.
61 ; Instead manually place the name of the ISR in the vector table using an
62 ; ORG and jmp instruction as demonstrated below.
63 ; You will also have to add an EXTERN statement at the top of the file.
64
65     ASEG
66
67     ORG TICK_INT_vect                   ; Vector address
68         jmp TICK_INT                    ; ISR
69
70     RSEG CODE
71
72 CLR_INT MACRO  FLAG_REG, FLAG_MASK
73     st -y, r16
74     ldi r16, FLAG_MASK
75     sts FLAG_REG, r16
76     ld r16, y+
77         
78     ENDM
79
80 ; Saving and Restoring a Task Context and Task Switching
81 ; ------------------------------------------------------
82 ;
83 ; The IAR compiler does not fully support inline assembler, so saving and
84 ; restoring a task context has to be written in an asm file.
85 ;
86 ; vPortYield() and vPortYieldFromTick() are usually written in C.  Doing
87 ; so in this case would required calls to be made to portSAVE_CONTEXT() and
88 ; portRESTORE_CONTEXT().  This is dis-advantageous as the context switch
89 ; function would require two extra jump and return instructions over the
90 ; WinAVR equivalent.
91 ;
92 ; To avoid this I have opted to implement both vPortYield() and
93 ; vPortYieldFromTick() in this assembly file.  For convenience
94 ; portSAVE_CONTEXT and portRESTORE_CONTEXT are implemented as macros.
95
96 portSAVE_CONTEXT MACRO
97     st  -y, r0          ; First save the r0 register - we need to use this.
98     in  r0, SREG        ; Obtain the SREG value so we can disable interrupts...
99     cli                 ; ... as soon as possible.
100     st  -y, r0          ; Store the SREG as it was before we disabled interrupts.
101
102     in  r0, SPL         ; Next store the hardware stack pointer.  The IAR...
103     st  -y, r0          ; ... compiler uses the hardware stack as a call stack ...
104     in  r0, SPH         ; ...  only.
105     st  -y, r0
106
107     st  -y, r1          ; Now store the rest of the registers.  Dont store the ...
108     st  -y, r2          ; ... the Y register here as it is used as the software
109     st  -y, r3          ; stack pointer and will get saved into the TCB.
110     st  -y, r4
111     st  -y, r5
112     st  -y, r6
113     st  -y, r7
114     st  -y, r8
115     st  -y, r9
116     st  -y, r10
117     st  -y, r11
118     st  -y, r12
119     st  -y, r13
120     st  -y, r14
121     st  -y, r15
122     st  -y, r16
123     st  -y, r17
124     st  -y, r18
125     st  -y, r19
126     st  -y, r20
127     st  -y, r21
128     st  -y, r22
129     st  -y, r23
130     st  -y, r24
131     st  -y, r25
132     st  -y, r26
133     st  -y, r27
134     st  -y, r30
135     st  -y, r31
136         
137     lds r0, uxCriticalNesting
138     st  -y, r0                  ; Store the critical nesting counter.
139
140     lds r26, pxCurrentTCB       ; Finally save the software stack pointer (Y ...
141     lds r27, pxCurrentTCB + 1   ; ... register) into the TCB.
142     st  x+, r28
143     st  x+, r29
144
145     ENDM
146
147
148 portRESTORE_CONTEXT MACRO
149     lds r26, pxCurrentTCB
150     lds r27, pxCurrentTCB + 1       ; Restore the software stack pointer from ...
151     ld  r28, x+                     ; the TCB into the software stack pointer (...
152     ld  r29, x+                     ; ... the Y register).
153
154     ld  r0, y+
155     sts uxCriticalNesting, r0
156
157     ld  r31, y+                     ; Restore the registers down to R0.  The Y
158     ld  r30, y+                     ; register is missing from this list as it
159     ld  r27, y+                     ; has already been restored.
160     ld  r26, y+
161     ld  r25, y+
162     ld  r24, y+
163     ld  r23, y+
164     ld  r22, y+
165     ld  r21, y+
166     ld  r20, y+
167     ld  r19, y+
168     ld  r18, y+
169     ld  r17, y+
170     ld  r16, y+
171     ld  r15, y+
172     ld  r14, y+
173     ld  r13, y+
174     ld  r12, y+
175     ld  r11, y+
176     ld  r10, y+
177     ld  r9, y+
178     ld  r8, y+
179     ld  r7, y+
180     ld  r6, y+
181     ld  r5, y+
182     ld  r4, y+
183     ld  r3, y+
184     ld  r2, y+
185     ld  r1, y+
186
187     ld  r0, y+                      ; The next thing on the stack is the ...
188     out SPH, r0                     ; ... hardware stack pointer.
189     ld  r0, y+
190     out SPL, r0
191
192     ld  r0, y+                      ; Next there is the SREG register.
193     out SREG, r0
194
195     ld  r0, y+                      ; Finally we have finished with r0, so restore r0.
196
197     ENDM
198
199
200
201 ; vPortYield(), vPortYieldFromTick() and vPortYieldFromISR()
202 ; -------------------------------------
203 ;
204 ; Manual and preemptive context switch functions respectively.
205 ; The IAR compiler does not fully support inline assembler,
206 ; so these are implemented here rather than the more usually
207 ; place of within port.c.
208
209 vPortYield:
210     portSAVE_CONTEXT                ; Save the context of the current task.
211     call vTaskSwitchContext         ; Call the scheduler.
212     portRESTORE_CONTEXT             ; Restore the context of whichever task the ...
213     ret                             ; ... scheduler decided should run.
214
215 vPortYieldFromTick:
216     CLR_INT INT_FLAGS, INT_MASK     ; Clear tick interrupt flag
217  
218     portSAVE_CONTEXT                ; Save the context of the current task.
219     call xTaskIncrementTick         ; Call the timer tick function.
220     tst r16
221     breq SkipTaskSwitch
222     call vTaskSwitchContext         ; Call the scheduler.
223
224 SkipTaskSwitch:
225     portRESTORE_CONTEXT             ; Restore the context of whichever task the ...
226     reti                            ; ... scheduler decided should run.
227
228 vPortYieldFromISR:
229     portSAVE_CONTEXT                ; Save the context of the current task.
230     call vTaskSwitchContext         ; Call the scheduler.
231     portRESTORE_CONTEXT             ; Restore the context of whichever task the ...
232     reti                            ; ... scheduler decided should run.
233
234 ; vPortStart()
235 ; ------------
236 ;
237 ; Again due to the lack of inline assembler, this is required
238 ; to get access to the portRESTORE_CONTEXT macro.
239
240 vPortStart:
241         portRESTORE_CONTEXT
242         ret
243
244 ; Just a filler for unused interrupt vectors.
245 vNoISR:
246     reti
247
248 END