]> begriffs open source - cmsis-freertos/blob - Source/portable/CCRH/F1Kx/portasm.s
Correct memory allocation and access in osMemoryPoolNew (#142)
[cmsis-freertos] / Source / portable / CCRH / F1Kx / portasm.s
1 ;/*
2 ; * FreeRTOS Kernel V11.2.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 ;------------------------------------------------------------------------------
30 ; Extern symbols
31 ;------------------------------------------------------------------------------
32 .extern _uxInterruptNesting
33 .extern _uxPortMaxInterruptDepth
34 .extern _xPortScheduleStatus
35 .extern _vTaskSwitchContext
36 .extern _pvPortGetCurrentTCB
37 .extern _vCommonISRHandler
38 .extern _xPortGET_CORE_ID
39
40 .public _vIrq_Handler
41 .public _vPortStartFirstTask
42 .public _vPortYield
43 .public _vTRAP0_Handler
44 ;------------------------------------------------------------------------------
45 ; Macro definitions
46 ;------------------------------------------------------------------------------
47 EIPC  .set 0
48 EIPSW .set 1
49 PSW   .set 5
50 FPSR  .set 6
51 FPEPC .set 7
52 EIIC  .set 13
53 CTPC  .set 16
54 CTPSW .set 17
55 EIIC_MSK .set 0x00000FFF
56 FPU_MSK  .set 0x00010000
57 ;------------------------------------------------------------------------------
58 ; portSAVE_CONTEXT
59 ; Context saving
60 ;------------------------------------------------------------------------------
61 portSAVE_CONTEXT .macro
62     prepare lp, 0
63
64     ; Save general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC into stack.
65     pushsp  r5, r30
66     $nowarning
67     pushsp  r1, r2
68     $warning
69
70     stsr    EIPSW, r15
71     stsr    EIPC, r16
72     stsr    EIIC, r17
73     stsr    CTPSW, r18
74     stsr    CTPC, r19
75     pushsp  r15, r19
76
77     ; Save FPU registers to stack if FPU is enabled
78     mov     FPU_MSK, r19
79     tst     r15, r19
80
81     ; Jump over next 3 instructions: stsr (4 bytes)*2 + pushsp (4 bytes)
82     bz      12
83     stsr    FPSR, r18
84     stsr    FPEPC, r19
85     pushsp  r18, r19
86
87     ; Save EIPSW register to stack
88     ; Due to the syntax of the pushsp instruction, using r14 as dummy value
89     pushsp  r14, r15
90
91     ; Get current TCB, the return value is stored in r10 (CCRH compiler)
92     jarl    _pvPortGetCurrentTCB, lp
93     st.w    sp, 0[r10]
94
95 .endm
96
97 ;------------------------------------------------------------------------------
98 ; portRESTORE_CONTEXT
99 ; Context restoring
100 ;------------------------------------------------------------------------------
101 portRESTORE_CONTEXT .macro
102     ; Current TCB is returned by r10 (CCRH compiler)
103     jarl    _pvPortGetCurrentTCB, lp
104     ld.w    0[r10], sp                  ; Restore the stack pointer from the TCB
105
106     ; Restore FPU registers if FPU is enabled
107     mov     FPU_MSK, r19
108     ; Restore EIPSW register to check FPU
109     ; Due to the syntax of the popsp instruction, using r14 as dummy value
110     popsp       r14, r15
111     tst     r15, r19
112     ; Jump over next 3 instructions: stsr (4 bytes)*2 + popsp (4 bytes)
113     bz      12
114     popsp   r18, r19
115     ldsr    r19, FPEPC
116     ldsr    r18, FPSR
117
118     ;Restore general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC
119     popsp   r15, r19
120     ldsr    r19, CTPC
121     ldsr    r18, CTPSW
122     ldsr    r17, EIIC
123     ldsr    r16, EIPC
124     ldsr    r15, EIPSW
125
126     $nowarning
127     popsp   r1, r2
128     $warning
129     popsp   r5, r30
130
131     dispose 0, lp
132 .endm
133
134 ;------------------------------------------------------------------------------
135 ; Save used registers
136 ;------------------------------------------------------------------------------
137 SAVE_REGISTER .macro
138     ; Save general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC into stack.
139     ; Callee-Save registers (r20 to r30) are not used in interrupt handler and
140     ; guaranteed no change after function call. So, don't need to save register
141     ; to optimize the used stack memory.
142     pushsp  r5, r19
143     $nowarning
144     pushsp  r1, r2
145     $warning
146
147     stsr    EIPSW, r19
148     stsr    EIPC, r18
149     stsr    EIIC, r17
150     mov     lp, r16
151     mov     ep, r15
152     stsr    CTPSW, r14
153     stsr    CTPC, r13
154     pushsp  r13, r18
155
156     mov     FPU_MSK, r16
157     tst     r16, r19
158     bz      8
159     stsr    FPSR, r17
160     stsr    FPEPC, r18
161
162     pushsp  r17, r19
163
164 .endm
165 ;------------------------------------------------------------------------------
166 ; Restore used registers
167 ;------------------------------------------------------------------------------
168 RESTORE_REGISTER .macro
169
170         mov     FPU_MSK, r15
171         popsp   r17, r19
172     tst     r19, r15
173     bz      8
174     ldsr    r18, FPEPC
175     ldsr    r17, FPSR
176
177     popsp   r13, r18
178     ldsr    r13, CTPC
179     ldsr    r14, CTPSW
180     mov     r15, ep
181     mov     r16, lp
182     ldsr    r17, EIIC
183     ldsr    r18, EIPC
184     ldsr    r19, EIPSW
185
186     $nowarning
187     popsp   r1, r2
188     $warning
189     popsp   r5, r19
190 .endm
191
192 ;------------------------------------------------------------------------------
193 ; Start the first task.
194 ;------------------------------------------------------------------------------
195 _vPortStartFirstTask:
196     portRESTORE_CONTEXT
197     eiret
198
199 ;------------------------------------------------------------------------------
200 ; _vPortYield
201 ;------------------------------------------------------------------------------
202 _vPortYield:
203     trap    0
204     jmp     [lp]                        ; Return to caller function
205
206 ;------------------------------------------------------------------------------
207 ; PortYield handler. This is installed as the TRAP exception handler.
208 ;------------------------------------------------------------------------------
209 _vTRAP0_Handler:
210     ;Save the context of the current task.
211     portSAVE_CONTEXT
212
213     ; The use case that portYield() is called from interrupt context as nested interrupt.
214     ; Context switch should be executed at the most outer of interrupt tree.
215     ; In that case, set xPortScheduleStatus to flag context switch in interrupt handler.
216     jarl    _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
217     mov     r10, r11
218     shl     2, r11
219     mov     #_uxInterruptNesting, r19
220     add     r11, r19
221     ld.w    0[r19], r18
222     cmp     r0, r18
223     be      _vTRAP0_Handler_ContextSwitch
224
225     mov     #_xPortScheduleStatus, r19
226     add     r11, r19
227
228     ; Set xPortScheduleStatus[coreID]=PORT_SCHEDULER_TASKSWITCH
229     mov     1, r17
230     st.w    r17, 0[r19]
231     br      _vTRAP0_Handler_Exit
232
233 _vTRAP0_Handler_ContextSwitch:
234     ; Pass coreID (r10) as parameter by r6 (CCRH compiler) in SMP support.
235     mov     r10, r6
236     ; Call the scheduler to select the next task.
237     ; vPortYeild may be called to current core again at the end of vTaskSwitchContext.
238     ; This may case nested interrupt, however, it is not necessary to set
239     ; uxInterruptNesting (currently 0) for nested trap0 exception. The user interrupt
240     ; (EI level interrupt) is not accepted inside of trap0 exception.
241     jarl    _vTaskSwitchContext, lp
242
243 _vTRAP0_Handler_Exit:
244     ; Restore the context of the next task to run.
245     portRESTORE_CONTEXT
246     eiret
247
248 ;------------------------------------------------------------------------------
249 ; _Irq_Handler
250 ; Handler interrupt service routine (ISR).
251 ;------------------------------------------------------------------------------
252 _vIrq_Handler:
253     ; Save used registers.
254     SAVE_REGISTER
255
256     ; Get core ID by HTCFG0, thread configuration register.
257     ; Then, increase nesting count for current core.
258     jarl    _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
259     shl     2, r10
260     mov     r10, r17
261
262     mov     #_uxInterruptNesting, r19
263     add     r17, r19
264     ld.w    0[r19], r18
265     addi    0x1, r18, r16
266     st.w    r16, 0[r19]
267
268     pushsp  r17, r19
269
270     ;Call the interrupt handler.
271     stsr    EIIC, r6
272     andi    EIIC_MSK, r6, r6
273
274     ; Do not enable interrupt for nesting. Stackover flow may occurs if the
275     ; depth of nesting interrupt is exceeded.
276     mov     #_uxPortMaxInterruptDepth, r19
277     ld.w    0[r19], r15
278     cmp     r15, r16
279         bge     4                            ; Jump over ei instruction
280     ei
281     jarl    _vCommonISRHandler, lp
282     di
283     synce
284
285     popsp   r17, r19
286     st.w    r18, 0[r19]                  ; Restore the old nesting count.
287
288     ; A context switch if no nesting interrupt.
289     cmp     0x0, r18
290     bne     _vIrq_Handler_NotSwitchContext
291
292     ; Check if context switch is requested.
293     mov     #_xPortScheduleStatus, r19
294     add     r17, r19
295     ld.w    0[r19], r18
296     cmp     r0, r18
297     bne     _vIrq_Handler_SwitchContext
298
299 _vIrq_Handler_NotSwitchContext:
300     ; No context switch.  Restore used registers
301     RESTORE_REGISTER
302     eiret
303
304 ;This sequence is executed for primary core only to switch context
305 _vIrq_Handler_SwitchContext:
306     ; Clear the context switch pending flag.
307     st.w r0, 0[r19]
308
309     add     -1, r18
310     bnz     _vIrq_Handler_StartFirstTask
311     ; Restore used registers before saving the context to the task stack.
312     RESTORE_REGISTER
313     portSAVE_CONTEXT
314
315     ; Get Core ID and pass to vTaskSwitchContext as parameter (CCRH compiler)
316     ; The parameter is  unused in single core, no problem with this redudant setting
317     jarl    _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
318     mov     r10, r6
319
320     ; vPortYeild may be called to current core again at the end of vTaskSwitchContext.
321     ; This may case nested interrupt, however, it is not necessary to set
322     ; uxInterruptNesting (currently 0) for  trap0 exception. The user interrupt
323     ; (EI level interrupt) is not accepted inside of trap0 exception.
324     jarl    _vTaskSwitchContext, lp    ;
325     portRESTORE_CONTEXT
326     eiret
327
328 _vIrq_Handler_StartFirstTask:
329     RESTORE_REGISTER
330     jr _vPortStartFirstTask
331