1/* 2 * FreeRTOS Kernel V11.1.0 3 * Copyright (C) 2020 Synopsys, 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 * \file 31 * \ingroup OS_FREERTOS 32 * \brief freertos support for arc processor 33 * like task dispatcher, interrupt handler 34 */ 35/** @cond OS_FREERTOS_ASM_ARC_SUPPORT */ 36 37/* 38 * core-dependent part in assemble language (for arc) 39 */ 40#define __ASSEMBLY__ 41#include "arc/arc.h" 42#include "arc/arc_asm_common.h" 43 44/* 45 * task dispatcher 46 * 47 */ 48 .text 49 .align 4 50 .global dispatch 51dispatch: 52/* 53 * the pre-conditions of this routine are task context, CPU is 54 * locked, dispatch is enabled. 55 */ 56 SAVE_NONSCRATCH_REGS /* save callee save registers */ 57 mov r1, dispatch_r 58 PUSH r1 /* save return address */ 59 ld r0, [pxCurrentTCB] 60 bl dispatcher 61 62/* return routine when task dispatch happened in task context */ 63dispatch_r: 64 RESTORE_NONSCRATCH_REGS /* recover registers */ 65 j [blink] 66 67/* 68 * start dispatch 69 */ 70 .global start_dispatch 71 .align 4 72start_dispatch: 73/* 74 * this routine is called in the non-task context during the startup of the kernel 75 * , and all the interrupts are locked. 76 * 77 * when the dispatcher is called, the cpu is locked, no nest exception (CPU exception/interrupt). 78 * In target_initialize, all interrupt priority mask should be cleared, cpu should be 79 * locked, the interrupts outside the kernel such as fiq can be 80 * enabled. 81 */ 82 clri 83 mov r0, 0 84 st r0, [exc_nest_count] 85 b dispatcher_0 86/* 87 * dispatcher 88 */ 89dispatcher: 90 ld r1, [ulCriticalNesting] 91 PUSH r1 /* save critical nesting */ 92 st sp, [r0] /* save stack pointer of current task, r0->pxCurrentTCB */ 93 jl vTaskSwitchContext /* change the value of pxCurrentTCB */ 94/* 95 * before dispatcher is called, task context | cpu locked | dispatch enabled 96 * should be satisfied. In this routine, the processor will jump 97 * into the entry of next to run task 98 * 99 * i.e. kernel mode, IRQ disabled, dispatch enabled 100 */ 101dispatcher_0: 102 ld r1, [pxCurrentTCB] 103 ld sp, [r1] /* recover task stack */ 104#if ARC_FEATURE_STACK_CHECK 105 lr r0, [AUX_STATUS32] 106 bclr r0, r0, AUX_STATUS_BIT_SC 107 flag r0 108 jl vPortSetStackCheck 109 lr r0, [AUX_STATUS32] 110 bset r0, r0, AUX_STATUS_BIT_SC 111 flag r0 112#endif 113 POP r0 /* get critical nesting */ 114 st r0, [ulCriticalNesting] 115 POP r0 /* get return address */ 116 j [r0] 117 118/* 119 * task startup routine 120 * 121 */ 122 .text 123 .global start_r 124 .align 4 125start_r: 126 seti /* unlock cpu */ 127 mov blink, vPortEndTask /* set return address */ 128 POP r1 /* get task function body */ 129 POP r0 /* get task parameters */ 130 j [r1] 131 132/****** exceptions and interrupts handing ******/ 133/****** entry for exception handling ******/ 134 .global exc_entry_cpu 135 .align 4 136exc_entry_cpu: 137 138 EXCEPTION_PROLOGUE 139 140 141 mov blink, sp 142 mov r3, sp /* as exception handler's para(p_excinfo) */ 143 144 ld r1, [exc_nest_count] 145 add r1, r1, 1 146 st r1, [exc_nest_count] 147 brne r1, 0, exc_handler_1 148/* change to exception stack if interrupt happened in task context */ 149 mov sp, _e_stack 150exc_handler_1: 151 PUSH blink 152 153/* find the exception cause */ 154#if ARC_FEATURE_CORE_700 155 lr r0, [AUX_ECR] 156 lsr r0, r0, 16 157 bmsk r0, r0, 7 158#endif 159 mov r1, exc_int_handler_table 160 ld.as r2, [r1, r0] 161 162 mov r0, r3 163 jl [r2] /* !!!!jump to exception handler where interrupts are not allowed! */ 164 165/* interrupts are not allowed */ 166ret_exc: 167 POP sp 168 mov r1, exc_nest_count 169 ld r0, [r1] 170 sub r0, r0, 1 171 st r0, [r1] 172 brne r0, 0, ret_exc_1 /* nested exception case */ 173 lr r1, [AUX_IRQ_LV12] 174 brne r1, 0, ret_exc_1 /* nested or pending interrupt case */ 175 176 ld r0, [context_switch_reqflg] 177 brne r0, 0, ret_exc_2 178ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */ 179 180 EXCEPTION_EPILOGUE 181#if ARC_FEATURE_CORE_600 182 rtie ilink2 183#else 184 rtie 185#endif 186 187/* there is a dispatch request */ 188ret_exc_2: 189 /* clear dispatch request */ 190 mov r0, 0 191 st r0, [context_switch_reqflg] 192 193 ld r0, [pxCurrentTCB] 194 breq r0, 0, ret_exc_1 195 196 SAVE_CALLEE_REGS /* save callee save registers */ 197 198 lr r0, [AUX_STATUS32] 199 bclr r0, r0, AUX_STATUS_BIT_AE /* clear exception bit */ 200 flag r0 201 202 mov r1, ret_exc_r /* save return address */ 203 PUSH r1 204 205 bl dispatcher /* r0->pxCurrentTCB */ 206 207ret_exc_r: 208 /* recover exception status */ 209 lr r0, [AUX_STATUS32] 210 bset r0, r0, AUX_STATUS_BIT_AE 211 flag r0 212 213 RESTORE_CALLEE_REGS /* recover registers */ 214 EXCEPTION_EPILOGUE 215#if ARC_FEATURE_CORE_600 216 rtie ilink2 217#else 218 rtie 219#endif 220 221/****** entry for normal interrupt exception handling ******/ 222 .global exc_entry_int /* entry for interrupt handling */ 223 .align 4 224exc_entry_int: 225 226 INTERRUPT_PROLOGUE 227 228 mov blink, sp 229 230 /* disable interrupt */ 231 push r0 232 lr r0, [AUX_STATUS32] 233 push r0 234 bclr r0, r0, AUX_STATUS_BIT_E1 235 bclr r0, r0, AUX_STATUS_BIT_E2 236 flag r0 237 ld r3, [exc_nest_count] 238 add r2, r3, 1 239 st r2, [exc_nest_count] 240 /* enable interrupt */ 241 pop r0 242 flag r0 243 pop r0 244 245 brne r3, 0, irq_handler_1 246/* change to exception stack if interrupt happened in task context */ 247 mov sp, _e_stack 248#if ARC_FEATURE_STACK_CHECK 249 lr r0, [AUX_STATUS32] 250 bclr r0, r0, AUX_STATUS_BIT_SC 251 flag r0 252#endif 253irq_handler_1: 254 PUSH blink 255 256/* critical area */ 257#if ARC_FEATURE_CORE_700 258 lr r0, [AUX_IRQ_CAUSE1] 259#endif 260 mov r1, exc_int_handler_table 261 ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */ 262/* handle software triggered interrupt */ 263 lr r3, [AUX_IRQ_HINT] 264 cmp r3, r0 265 bne.d irq_hint_handled 266 xor r3, r3, r3 267 sr r3, [AUX_IRQ_HINT] 268irq_hint_handled: 269 270 jl [r2] /* jump to interrupt handler */ 271/* no interrupts are allowed from here */ 272ret_int: 273 clri /* disable interrupt */ 274 275 POP sp 276 mov r1, exc_nest_count 277 ld r0, [r1] 278 sub r0, r0, 1 279 st r0, [r1] 280/* if there are multi-bits set in IRQ_LV12, it's still in nest interrupt */ 281 lr r1, [AUX_IRQ_LV12] 282 283 ld r0, [context_switch_reqflg] 284 brne r0, 0, ret_int_2 285ret_int_1: /* return from non-task context */ 286 INTERRUPT_EPILOGUE 287#if ARC_FEATURE_CORE_600 288/* TODO: series 600 IRQ6 and IRQ7 uses ilink2 */ 289 rtie ilink1 290#else 291 rtie 292#endif 293/* there is a dispatch request */ 294ret_int_2: 295 /* clear dispatch request */ 296 mov r0, 0 297 st r0, [context_switch_reqflg] 298 299 ld r0, [pxCurrentTCB] 300 breq r0, 0, ret_int_1 301 302/* r1 has old AUX_IRQ_LV12 */ 303 PUSH r1 304/* clear related bits in IRQ_ACT manually to simulate a irq return */ 305 306 SAVE_CALLEE_REGS /* save callee save registers */ 307 mov r1, ret_int_r /* save return address */ 308 PUSH r1 309 310 bl dispatcher /* r0->pxCurrentTCB */ 311 312ret_int_r: 313 RESTORE_CALLEE_REGS /* recover registers */ 314 POPAX AUX_IRQ_LV12 315 INTERRUPT_EPILOGUE 316#if ARC_FEATURE_CORE_600 317 rtie ilink1 318#else 319 rtie 320#endif 321 322/** @endcond */ 323