mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-03 22:08:28 +00:00 
			
		
		
		
	- vTaskPreemptionDisable()/vTaskPreemptionEnable() are no longer available in single-core builds. - xTaskIncrementTick() calls must now be wrapped by critical section - Minimal Idle Task renamed to Passive Idle Task - Port critical section APIs updated
		
			
				
	
	
		
			154 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
/*
 | 
						|
 * 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
 |