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