2 * FreeRTOS Kernel V202110.00
3 * Copyright (C) 2020 Synopsys, Inc. or its affiliates. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
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.
22 * https://www.FreeRTOS.org
23 * https://github.com/FreeRTOS
30 * \ingroup OS_FREERTOS
31 * \brief freertos support for arc processor
32 * like task dispatcher, interrupt handler
34 /** @cond OS_FREERTOS_ASM_ARC_SUPPORT */
37 * core-dependent part in assemble language (for arc)
41 #include "arc/arc_asm_common.h"
52 * the pre-conditions of this routine are task context, CPU is
53 * locked, dispatch is enabled.
55 SAVE_NONSCRATCH_REGS /* save callee save registers */
57 PUSH r1 /* save return address */
61 /* return routine when task dispatch happened in task context */
63 RESTORE_NONSCRATCH_REGS /* recover registers */
69 .global start_dispatch
73 * this routine is called in the non-task context during the startup of the kernel
74 * , and all the interrupts are locked.
76 * when the dispatcher is called, the cpu is locked, no nest exception (CPU exception/interrupt).
77 * In target_initialize, all interrupt priority mask should be cleared, cpu should be
78 * locked, the interrupts outside the kernel such as fiq can be
83 st r0, [exc_nest_count]
89 ld r1, [ulCriticalNesting]
90 PUSH r1 /* save critical nesting */
91 st sp, [r0] /* save stack pointer of current task, r0->pxCurrentTCB */
92 jl vTaskSwitchContext /* change the value of pxCurrentTCB */
94 * before dispatcher is called, task context | cpu locked | dispatch enabled
95 * should be satisfied. In this routine, the processor will jump
96 * into the entry of next to run task
98 * i.e. kernel mode, IRQ disabled, dispatch enabled
101 ld r1, [pxCurrentTCB]
102 ld sp, [r1] /* recover task stack */
103 #if ARC_FEATURE_STACK_CHECK
104 lr r0, [AUX_STATUS32]
105 bclr r0, r0, AUX_STATUS_BIT_SC
107 jl vPortSetStackCheck
108 lr r0, [AUX_STATUS32]
109 bset r0, r0, AUX_STATUS_BIT_SC
112 POP r0 /* get critical nesting */
113 st r0, [ulCriticalNesting]
114 POP r0 /* get return address */
118 * task startup routine
125 seti /* unlock cpu */
126 mov blink, vPortEndTask /* set return address */
127 POP r1 /* get task function body */
128 POP r0 /* get task parameters */
131 /****** exceptions and interrupts handing ******/
132 /****** entry for exception handling ******/
133 .global exc_entry_cpu
141 mov r3, sp /* as exception handler's para(p_excinfo) */
143 ld r1, [exc_nest_count]
145 st r1, [exc_nest_count]
146 brne r1, 0, exc_handler_1
147 /* change to exception stack if interrupt happened in task context */
152 /* find the exception cause */
153 #if ARC_FEATURE_CORE_700
158 mov r1, exc_int_handler_table
162 jl [r2] /* !!!!jump to exception handler where interrupts are not allowed! */
164 /* interrupts are not allowed */
167 mov r1, exc_nest_count
171 brne r0, 0, ret_exc_1 /* nested exception case */
172 lr r1, [AUX_IRQ_LV12]
173 brne r1, 0, ret_exc_1 /* nested or pending interrupt case */
175 ld r0, [context_switch_reqflg]
176 brne r0, 0, ret_exc_2
177 ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */
180 #if ARC_FEATURE_CORE_600
186 /* there is a dispatch request */
188 /* clear dispatch request */
190 st r0, [context_switch_reqflg]
192 ld r0, [pxCurrentTCB]
193 breq r0, 0, ret_exc_1
195 SAVE_CALLEE_REGS /* save callee save registers */
197 lr r0, [AUX_STATUS32]
198 bclr r0, r0, AUX_STATUS_BIT_AE /* clear exception bit */
201 mov r1, ret_exc_r /* save return address */
204 bl dispatcher /* r0->pxCurrentTCB */
207 /* recover exception status */
208 lr r0, [AUX_STATUS32]
209 bset r0, r0, AUX_STATUS_BIT_AE
212 RESTORE_CALLEE_REGS /* recover registers */
214 #if ARC_FEATURE_CORE_600
220 /****** entry for normal interrupt exception handling ******/
221 .global exc_entry_int /* entry for interrupt handling */
229 /* disable interrupt */
231 lr r0, [AUX_STATUS32]
233 bclr r0, r0, AUX_STATUS_BIT_E1
234 bclr r0, r0, AUX_STATUS_BIT_E2
236 ld r3, [exc_nest_count]
238 st r2, [exc_nest_count]
239 /* enable interrupt */
244 brne r3, 0, irq_handler_1
245 /* change to exception stack if interrupt happened in task context */
247 #if ARC_FEATURE_STACK_CHECK
248 lr r0, [AUX_STATUS32]
249 bclr r0, r0, AUX_STATUS_BIT_SC
256 #if ARC_FEATURE_CORE_700
257 lr r0, [AUX_IRQ_CAUSE1]
259 mov r1, exc_int_handler_table
260 ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */
261 /* handle software triggered interrupt */
262 lr r3, [AUX_IRQ_HINT]
264 bne.d irq_hint_handled
266 sr r3, [AUX_IRQ_HINT]
269 jl [r2] /* jump to interrupt handler */
270 /* no interrupts are allowed from here */
272 clri /* disable interrupt */
275 mov r1, exc_nest_count
279 /* if there are multi-bits set in IRQ_LV12, it's still in nest interrupt */
280 lr r1, [AUX_IRQ_LV12]
282 ld r0, [context_switch_reqflg]
283 brne r0, 0, ret_int_2
284 ret_int_1: /* return from non-task context */
286 #if ARC_FEATURE_CORE_600
287 /* TODO: series 600 IRQ6 and IRQ7 uses ilink2 */
292 /* there is a dispatch request */
294 /* clear dispatch request */
296 st r0, [context_switch_reqflg]
298 ld r0, [pxCurrentTCB]
299 breq r0, 0, ret_int_1
301 /* r1 has old AUX_IRQ_LV12 */
303 /* clear related bits in IRQ_ACT manually to simulate a irq return */
305 SAVE_CALLEE_REGS /* save callee save registers */
306 mov r1, ret_int_r /* save return address */
309 bl dispatcher /* r0->pxCurrentTCB */
312 RESTORE_CALLEE_REGS /* recover registers */
315 #if ARC_FEATURE_CORE_600