]> git.sur5r.net Git - freertos/blob - Source/portable/IAR/ATMega323/portmacro.s90
Add in the critical nesting save and restore.
[freertos] / Source / portable / IAR / ATMega323 / portmacro.s90
1 ;       FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 Richard Barry.\r
2 ;\r
3 ;       This file is part of the FreeRTOS.org distribution.\r
4 ;\r
5 ;       FreeRTOS.org is free software; you can redistribute it and/or modify\r
6 ;       it under the terms of the GNU General Public License as published by\r
7 ;       the Free Software Foundation; either version 2 of the License, or\r
8 ;       (at your option) any later version.\r
9 ;\r
10 ;       FreeRTOS.org is distributed in the hope that it will be useful,\r
11 ;       but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 ;       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 ;       GNU General Public License for more details.\r
14 ;\r
15 ;       You should have received a copy of the GNU General Public License\r
16 ;       along with FreeRTOS.org; if not, write to the Free Software\r
17 ;       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
18 ;\r
19 ;       A special exception to the GPL can be applied should you wish to distribute\r
20 ;       a combined work that includes FreeRTOS.org, without being obliged to provide\r
21 ;       the source code for any proprietary components.  See the licensing section\r
22 ;       of http://www.FreeRTOS.org for full details of how and when the exception\r
23 ;       can be applied.\r
24 ;\r
25 ;       ***************************************************************************\r
26 ;       See http://www.FreeRTOS.org for documentation, latest information, license\r
27 ;       and contact details.  Please ensure to read the configuration and relevant\r
28 ;       port sections of the online documentation.\r
29 ;       ***************************************************************************\r
30 \r
31 #include <iom323.h>\r
32 \r
33 ; Declare all extern symbols here - including any ISRs that are referenced in\r
34 ; the vector table.\r
35 \r
36 ; ISR functions\r
37 ; -------------\r
38 EXTERN SIG_OUTPUT_COMPARE1A\r
39 EXTERN SIG_UART_RECV\r
40 EXTERN SIG_UART_DATA\r
41 \r
42 \r
43 ; Functions used by scheduler\r
44 ; ---------------------------\r
45 EXTERN vTaskSwitchContext\r
46 EXTERN pxCurrentTCB\r
47 EXTERN vTaskIncrementTick\r
48 EXTERN uxCriticalNesting\r
49 \r
50 ; Functions implemented in this file\r
51 ; ----------------------------------\r
52 PUBLIC vPortYield\r
53 PUBLIC vPortYieldFromTick\r
54 PUBLIC vPortStart\r
55 \r
56 \r
57 ; Interrupt vector table.\r
58 ; -----------------------\r
59 ;\r
60 ; For simplicity the RTOS tick interrupt routine uses the __task keyword.\r
61 ; As the IAR compiler does not permit a function to be declared using both\r
62 ; __task and __interrupt, the use of __task necessitates that the interrupt\r
63 ; vector table be setup manually.\r
64 ;\r
65 ; To write an ISR, implement the ISR function using the __interrupt keyword\r
66 ; but do not install the interrupt using the "#pragma vector=ABC" method.\r
67 ; Instead manually place the name of the ISR in the vector table using an\r
68 ; ORG and jmp instruction as demonstrated below.\r
69 ; You will also have to add an EXTERN statement at the top of the file.\r
70 \r
71         ASEG\r
72 \r
73 \r
74         ORG TIMER1_COMPA_vect                           ; Vector address\r
75                 jmp SIG_OUTPUT_COMPARE1A                ; ISR\r
76 \r
77         ORG USART_RXC_vect                                      ; Vector address\r
78                 jmp SIG_UART_RECV                               ; ISR\r
79 \r
80         ORG USART_UDRE_vect                                     ; Vector address\r
81                 jmp SIG_UART_DATA                               ; ISR\r
82 \r
83         \r
84         RSEG CODE\r
85 \r
86 \r
87 \r
88 ; Saving and Restoring a Task Context and Task Switching\r
89 ; ------------------------------------------------------\r
90 ;\r
91 ; The IAR compiler does not fully support inline assembler, so saving and\r
92 ; restoring a task context has to be written in an asm file.\r
93 ;\r
94 ; vPortYield() and vPortYieldFromTick() are usually written in C.  Doing\r
95 ; so in this case would required calls to be made to portSAVE_CONTEXT() and\r
96 ; portRESTORE_CONTEXT().  This is dis-advantageous as the context switch\r
97 ; function would require two extra jump and return instructions over the\r
98 ; WinAVR equivalent.\r
99 ;\r
100 ; To avoid this I have opted to implement both vPortYield() and\r
101 ; vPortYieldFromTick() in this assembly file.  For convenience\r
102 ; portSAVE_CONTEXT and portRESTORE_CONTEXT are implemented as macros.\r
103 \r
104 portSAVE_CONTEXT MACRO\r
105         st      -y, r0                  ; First save the r0 register - we need to use this.\r
106         in      r0, SREG                ; Obtain the SREG value so we can disable interrupts...\r
107         cli                                     ; ... as soon as possible.\r
108         st      -y, r0                  ; Store the SREG as it was before we disabled interrupts.\r
109 \r
110         in      r0, SPL                 ; Next store the hardware stack pointer.  The IAR...\r
111         st      -y, r0                  ; ... compiler uses the hardware stack as a call stack ...\r
112         in      r0, SPH                 ; ...  only.\r
113         st      -y, r0\r
114 \r
115         st      -y, r1                  ; Now store the rest of the registers.  Dont store the ...\r
116         st      -y, r2                  ; ... the Y register here as it is used as the software\r
117         st      -y, r3                  ; stack pointer and will get saved into the TCB.\r
118         st      -y, r4\r
119         st      -y, r5\r
120         st      -y, r6\r
121         st      -y, r7\r
122         st      -y, r8\r
123         st      -y, r9\r
124         st      -y, r10\r
125         st      -y, r11\r
126         st      -y, r12\r
127         st      -y, r13\r
128         st      -y, r14\r
129         st      -y, r15\r
130         st      -y, r16\r
131         st      -y, r17\r
132         st      -y, r18\r
133         st      -y, r19\r
134         st      -y, r20\r
135         st      -y, r21\r
136         st      -y, r22\r
137         st      -y, r23\r
138         st      -y, r24\r
139         st      -y, r25\r
140         st      -y, r26\r
141         st      -y, r27\r
142         st      -y, r30\r
143         st      -y, r31\r
144         lds r0, uxCriticalNesting\r
145         st      -y, r0                                  ; Store the critical nesting counter.\r
146 \r
147         lds     r26, pxCurrentTCB               ; Finally save the software stack pointer (Y ...\r
148         lds     r27, pxCurrentTCB + 1   ; ... register) into the TCB.\r
149         st      x+, r28\r
150         st      x+, r29\r
151 \r
152         ENDM\r
153 \r
154 \r
155 portRESTORE_CONTEXT MACRO\r
156         lds     r26, pxCurrentTCB\r
157         lds     r27, pxCurrentTCB + 1   ; Restore the software stack pointer from ...\r
158         ld      r28, x+                                 ; the TCB into the software stack pointer (...\r
159         ld      r29, x+                                 ; ... the Y register).\r
160 \r
161         ld      r0, y+\r
162         sts     uxCriticalNesting, r0\r
163         ld      r31, y+                                 ; Restore the registers down to R0.  The Y\r
164         ld      r30, y+                                 ; register is missing from this list as it\r
165         ld      r27, y+                                 ; has already been restored.\r
166         ld      r26, y+\r
167         ld      r25, y+\r
168         ld      r24, y+\r
169         ld      r23, y+\r
170         ld      r22, y+\r
171         ld      r21, y+\r
172         ld      r20, y+\r
173         ld      r19, y+\r
174         ld      r18, y+\r
175         ld      r17, y+\r
176         ld      r16, y+\r
177         ld      r15, y+\r
178         ld      r14, y+\r
179         ld      r13, y+\r
180         ld      r12, y+\r
181         ld      r11, y+\r
182         ld      r10, y+\r
183         ld      r9, y+\r
184         ld      r8, y+\r
185         ld      r7, y+\r
186         ld      r6, y+\r
187         ld      r5, y+\r
188         ld      r4, y+\r
189         ld      r3, y+\r
190         ld      r2, y+\r
191         ld      r1, y+\r
192 \r
193         ld      r0, y+                                  ; The next thing on the stack is the ...\r
194         out     SPH, r0                                 ; ... hardware stack pointer.\r
195         ld      r0, y+\r
196         out     SPL, r0\r
197 \r
198         ld      r0, y+                                  ; Next there is the SREG register.\r
199         out SREG, r0\r
200 \r
201         ld      r0, y+                                  ; Finally we have finished with r0, so restore r0.\r
202         \r
203         ENDM\r
204 \r
205 \r
206 \r
207 ; vPortYield() and vPortYieldFromTick()\r
208 ; -------------------------------------\r
209 ;\r
210 ; Manual and preemptive context switch functions respectively.\r
211 ; The IAR compiler does not fully support inline assembler,\r
212 ; so these are implemented here rather than the more usually\r
213 ; place of within port.c.\r
214 \r
215 vPortYield:\r
216         portSAVE_CONTEXT                        ; Save the context of the current task.\r
217         call vTaskSwitchContext         ; Call the scheduler.\r
218         portRESTORE_CONTEXT                     ; Restore the context of whichever task the ...\r
219         ret                                                     ; ... scheduler decided should run.\r
220 \r
221 vPortYieldFromTick:\r
222         portSAVE_CONTEXT                        ; Save the context of the current task.\r
223         call vTaskIncrementTick         ; Call the timer tick function.\r
224         call vTaskSwitchContext         ; Call the scheduler.\r
225         portRESTORE_CONTEXT                     ; Restore the context of whichever task the ...\r
226         ret                                                     ; ... scheduler decided should run.\r
227 \r
228 ; vPortStart()\r
229 ; ------------\r
230 ;\r
231 ; Again due to the lack of inline assembler, this is required\r
232 ; to get access to the portRESTORE_CONTEXT macro.\r
233 \r
234 vPortStart:\r
235         portRESTORE_CONTEXT\r
236         ret\r
237 \r
238 \r
239 ; Just a filler for unused interrupt vectors.\r
240 vNoISR:\r
241         reti\r
242 \r
243 \r
244         END\r
245 \r