/* * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "sdkconfig.h" #include "portmacro.h" #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD #include "esp_private/hw_stack_guard.h" #endif #if CONFIG_FREERTOS_UNICORE #define pxCurrentTCBs pxCurrentTCB #endif .global uxInterruptNesting .global uxSchedulerRunning .global xIsrStackTop .global pxCurrentTCBs .global vTaskSwitchContext .global xPortSwitchFlag #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD .global xIsrStack .global port_offset_pxStack .global port_offset_pxEndOfStack .global esp_hw_stack_guard_monitor_stop .global esp_hw_stack_guard_monitor_start .global esp_hw_stack_guard_set_bounds #endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */ .section .text /** * This function makes the RTOS aware about a ISR entering, it takes the * current task stack saved, places into the TCB, loads the ISR stack. * TODO: ISR nesting code improvements ? */ .global rtos_int_enter .type rtos_int_enter, @function rtos_int_enter: /* scheduler not enabled, jump directly to ISR handler */ lw t0, uxSchedulerRunning beq t0,zero, rtos_enter_end /* increments the ISR nesting count */ la t3, uxInterruptNesting lw t4, 0x0(t3) addi t5,t4,1 sw t5, 0x0(t3) /* If reached here from another low-prio ISR, skip stack pushing to TCB */ bne t4,zero, rtos_enter_end #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD /* esp_hw_stack_guard_monitor_stop(); pass the scratch registers */ ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE a0 a1 #endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */ /* Save current TCB and load the ISR stack */ lw t0, pxCurrentTCBs sw sp, 0x0(t0) lw sp, xIsrStackTop #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD /* esp_hw_stack_guard_set_bounds(xIsrStack, xIsrStackTop); */ la a0, xIsrStack mv a1, sp ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE a2 /* esp_hw_stack_guard_monitor_start(); */ ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE a0 a1 #endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */ rtos_enter_end: ret /** * @brief Restore the stack pointer of the next task to run. * * @param a0 Former mstatus * * @returns New mstatus */ .global rtos_int_exit .type rtos_int_exit, @function rtos_int_exit: /* To speed up this routine and because this current routine is only meant to be called from the interrupt * handler, let's use callee-saved registers instead of stack space. Registers `s3-s11` are not used by * the caller */ mv s11, a0 /* may skip RTOS aware interrupt since scheduler was not started */ lw t0, uxSchedulerRunning beq t0,zero, rtos_exit_end /* update nesting interrupts counter */ la t2, uxInterruptNesting lw t3, 0x0(t2) /* Already zero, protect against underflow */ beq t3, zero, isr_skip_decrement addi t3,t3, -1 sw t3, 0x0(t2) isr_skip_decrement: /* may still have interrupts pending, skip section below and exit */ bne t3,zero,rtos_exit_end /* Schedule the next task if a yield is pending */ la t0, xPortSwitchFlag lw t2, 0x0(t0) beq t2, zero, no_switch /* preserve return address and schedule next task stack pointer for riscv should always be 16 byte aligned */ addi sp,sp,-16 sw ra, 0(sp) /* vTaskSwitchContext(xCoreID) now expects xCoreID as an argument, so the assembly calls below have been modified. xCoreID is hard-wired to 0 for single-core risc-v. */ li a0, 0 call vTaskSwitchContext lw ra, 0(sp) addi sp, sp, 16 /* Clears the switch pending flag */ la t0, xPortSwitchFlag mv t2, zero sw t2, 0x0(t0) no_switch: #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD /* esp_hw_stack_guard_monitor_stop(); */ ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE a0 a1 #endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */ /* Recover the stack of next task */ lw t0, pxCurrentTCBs lw sp, 0x0(t0) #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD /* esp_hw_stack_guard_set_bounds(pxCurrentTCBs[0]->pxStack, * pxCurrentTCBs[0]->pxEndOfStack); */ lw a0, PORT_OFFSET_PX_STACK(t0) lw a1, PORT_OFFSET_PX_END_OF_STACK(t0) ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE a2 /* esp_hw_stack_guard_monitor_start(); */ ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE a0 a1 #endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */ rtos_exit_end: mv a0, s11 /* a0 = new mstatus */ ret