From 317ee995e9d530587bfb14439b3b1ee38d1afe77 Mon Sep 17 00:00:00 2001 From: supperthomas <78900636@qq.com> Date: Fri, 6 May 2022 23:06:28 +0800 Subject: [PATCH] add the config of RTTHREAD add the init link file --- Kconfig | 4 + .../esp_system/ld/esp32c3/sections.ld.in | 26 +++ components/freertos/port/port_common.c | 5 + components/freertos/port/port_systick.c | 3 + components/riscv/vectors.S | 220 ++++++++++++++++-- 5 files changed, 239 insertions(+), 19 deletions(-) diff --git a/Kconfig b/Kconfig index 928d274106..d368adaa37 100644 --- a/Kconfig +++ b/Kconfig @@ -61,6 +61,10 @@ mainmenu "Espressif IoT Development Framework Configuration" bool default "y" if IDF_TARGET="linux" + config IDF_RTOS_RTTHREAD + bool "RT-THREAD SELECT" + default "n" + config IDF_FIRMWARE_CHIP_ID hex default 0x0000 if IDF_TARGET_ESP32 diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in index 0ebeda06c1..8215237fff 100644 --- a/components/esp_system/ld/esp32c3/sections.ld.in +++ b/components/esp_system/ld/esp32c3/sections.ld.in @@ -183,6 +183,32 @@ SECTIONS _noinit_end = ABSOLUTE(.); } > dram0_0_seg + .stack_dummy (COPY): + { + . = ALIGN(8); + __STACKSIZE__ = 40960; + __stack_start__ = .; + *(.stack*) + . += __STACKSIZE__; + __stack_cpu0 = .; + __stack_end__ = .; + } > dram0_0_seg + + .stack_dummy (COPY): + { + . = ALIGN(8); + __HEAPSIZE__ = 40960; + __heap_start__ = .; + . += __STACKSIZE__; + __heap_end__ = .; + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + + . = ALIGN(4); + } > dram0_0_seg /* Shared RAM */ .dram0.bss (NOLOAD) : { diff --git a/components/freertos/port/port_common.c b/components/freertos/port/port_common.c index ffca3d5429..9d8159f588 100644 --- a/components/freertos/port/port_common.c +++ b/components/freertos/port/port_common.c @@ -74,11 +74,16 @@ void esp_startup_start_app_common(void) esp_gdbstub_init(); #endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME +#ifdef CONFIG_IDF_RTOS_RTTHREAD + app_main(); +#else portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main", ESP_TASK_MAIN_STACK, NULL, ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE); assert(res == pdTRUE); (void)res; +#endif + } static void main_task(void* args) diff --git a/components/freertos/port/port_systick.c b/components/freertos/port/port_systick.c index 0c14a155a1..0fa203574b 100644 --- a/components/freertos/port/port_systick.c +++ b/components/freertos/port/port_systick.c @@ -116,6 +116,8 @@ void vPortSetupTimer(void) */ IRAM_ATTR void SysTickIsrHandler(void *arg) { +#ifdef CONFIG_IDF_RTOS_RTTHREAD +#else uint32_t cpuid = xPortGetCoreID(); systimer_hal_context_t *systimer_hal = (systimer_hal_context_t *)arg; #ifdef CONFIG_PM_TRACE @@ -144,6 +146,7 @@ IRAM_ATTR void SysTickIsrHandler(void *arg) #ifdef CONFIG_PM_TRACE ESP_PM_TRACE_EXIT(TICK, cpuid); #endif +#endif } #endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S index 1006d5bea5..963494fcb3 100644 --- a/components/riscv/vectors.S +++ b/components/riscv/vectors.S @@ -17,6 +17,9 @@ #include "soc/soc_caps.h" #include "sdkconfig.h" +#define STORE sw +#define LOAD lw +#define REGBYTES 4 .equ SAVE_REGS, 32 .equ CONTEXT_SIZE, (SAVE_REGS * 4) @@ -218,25 +221,27 @@ _call_panic_handler: */ .global _interrupt_handler .type _interrupt_handler, @function +#ifndef CONFIG_IDF_RTOS_RTTHREAD + _interrupt_handler: /* entry */ - save_regs - save_mepc + save_regs /* 保存寄存器 */ + save_mepc /* 保存MEPC */ /* Before doing anythig preserve the stack pointer */ /* It will be saved in current TCB, if needed */ - mv a0, sp + mv a0, sp /* 保存SP a0 = sp */ call rtos_int_enter /* Before dispatch c handler, restore interrupt to enable nested intr */ - csrr s1, mcause - csrr s2, mstatus + csrr s1, mcause /* 保存mcause s1 = mcause */ + csrr s2, mstatus /* 保存mstatus s2 = mstatus */ - /* Save the interrupt threshold level */ - la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG - lw s3, 0(t0) + /* Save the interrupt threshold level 保存中断嵌套层数? */ + la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG /* 保存mstatus t0 = &INTERRUPT_CORE0_CPU_INT_THRESH_REG */ + lw s3, 0(t0) /* s3 = mstatus */ - /* Increase interrupt threshold level */ + /* Increase interrupt threshold level 增加中断嵌套层数*/ li t2, 0x7fffffff and t1, s1, t2 /* t1 = mcause & mask */ slli t1, t1, 2 /* t1 = mcause * 4 */ @@ -247,8 +252,8 @@ _interrupt_handler: sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */ fence - li t0, 0x8 - csrrs t0, mstatus, t0 + li t0, 0x8 /* t0 = 8 */ + csrrs t0, mstatus, t0 /*设置状态MIE寄存器,开总中断*/ #ifdef CONFIG_PM_TRACE li a0, 0 /* = ESP_PM_TRACE_IDLE */ @@ -269,34 +274,211 @@ _interrupt_handler: /* call the C dispatcher */ mv a0, sp /* argument 1, stack pointer */ mv a1, s1 /* argument 2, interrupt number (mcause) */ - /* mask off the interrupt flag of mcause */ + /* mask off the interrupt flag of mcause 屏幕异常中断*/ li t0, 0x7fffffff and a1, a1, t0 jal _global_interrupt_handler - /* After dispatch c handler, disable interrupt to make freertos make context switch */ + /* After dispatch c handler, disable interrupt to make freertos make context switch + 在调用c函数之后,disable 中断让freertos能够做内容切换 + */ li t0, 0x8 - csrrc t0, mstatus, t0 + csrrc t0, mstatus, t0 /*清状态MIE寄存器 关总中断*/ - /* restore the interrupt threshold level */ + + /* restore the interrupt threshold level 中断嵌套 */ la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG sw s3, 0(t0) fence /* Yield to the next task is needed: */ - mv a0, sp + mv a0, sp /* a0 = sp*/ call rtos_int_exit /* The next (or current) stack pointer is returned in a0 */ - mv sp, a0 + mv sp, a0 /* sp = a0*/ /* restore the rest of the registers */ - csrw mcause, s1 - csrw mstatus, s2 + csrw mcause, s1 /* mcause = s1 */ + csrw mstatus, s2 /* mstatus = s2 */ restore_mepc restore_regs /* exit, this will also re-enable the interrupts */ mret .size _interrupt_handler, .-_interrupt_handler +#else +_interrupt_handler: + /* 此时CPU的sp = from_thread->sp */ + /* 注意: 在这里,并没有将mepc的值赋值为from_thread栈中的epc,但后面会赋值 */ + addi sp, sp, -32 * REGBYTES /* sp = sp - 32 * 4 栈指针向下偏移32个寄存器长度,用来将CPU的寄存器保存到from_thread的栈中*/ + STORE x1, 1 * REGBYTES(sp) /* 将CPU的x1寄存器,即ra寄存器,保存到from_thread->栈中 */ + + li t0, 0x80 /* t0 = 0x80 */ + STORE t0, 2 * REGBYTES(sp) /* mstatus = t0, 即关闭全局中断 */ + + /* 将 CPU 的其他寄存器的值,保存到from_thread的任务栈中 */ + STORE x4, 4 * REGBYTES(sp) + STORE x5, 5 * REGBYTES(sp) + STORE x6, 6 * REGBYTES(sp) + STORE x7, 7 * REGBYTES(sp) + STORE x8, 8 * REGBYTES(sp) + STORE x9, 9 * REGBYTES(sp) + STORE x10, 10 * REGBYTES(sp) + STORE x11, 11 * REGBYTES(sp) + STORE x12, 12 * REGBYTES(sp) + STORE x13, 13 * REGBYTES(sp) + STORE x14, 14 * REGBYTES(sp) + STORE x15, 15 * REGBYTES(sp) + STORE x16, 16 * REGBYTES(sp) + STORE x17, 17 * REGBYTES(sp) + STORE x18, 18 * REGBYTES(sp) + STORE x19, 19 * REGBYTES(sp) + STORE x20, 20 * REGBYTES(sp) + STORE x21, 21 * REGBYTES(sp) + STORE x22, 22 * REGBYTES(sp) + STORE x23, 23 * REGBYTES(sp) + STORE x24, 24 * REGBYTES(sp) + STORE x25, 25 * REGBYTES(sp) + STORE x26, 26 * REGBYTES(sp) + STORE x27, 27 * REGBYTES(sp) + STORE x28, 28 * REGBYTES(sp) + STORE x29, 29 * REGBYTES(sp) + STORE x30, 30 * REGBYTES(sp) + STORE x31, 31 * REGBYTES(sp) + + /* 备份 CPU 的 sp (这时,CPU的sp其实就是from thread的sp指针) 寄存器的值到 s0 寄存器中,下面会使用s0,恢复 CPU 的寄存器 */ + move s0, sp /* s0 = sp */ + + /* 在中断函数中,中断函数中调用的C函数,需要使用 sp, 这里,在中断函数中,使用的 sp 为,系统的栈资源 */ + /* switch to interrupt stack */ + la sp, __stack_end__ /* sp = _sp */ + + /* interrupt handle */ + /* 注意: 在调用C函数之前,比如sp的值为0x30001000, 在执行完C函数后,sp的值还是会变成 0x30001000 */ + call rt_interrupt_enter /* 执行所有的中断函数前,调用该函数 */ + + csrr s1, mcause + csrr s2, mstatus + + /* Save the interrupt threshold level */ + la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG + lw s3, 0(t0) + + li t2, 0x7fffffff + and t1, s1, t2 /* t1 = mcause & mask */ + slli t1, t1, 2 /* t1 = mcause * 4 */ + la t2, INTC_INT_PRIO_REG(0) + add t1, t2, t1 /* t1 = INTC_INT_PRIO_REG + 4 * mcause */ + lw t2, 0(t1) /* t2 = INTC_INT_PRIO_REG[mcause] */ + addi t2, t2, 1 /* t2 = t2 +1 */ + sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */ + fence + + li t0, 0x8 + csrrs t0, mstatus, t0 + + /* call the C dispatcher */ + mv a0, sp /* argument 1, stack pointer */ + mv a1, s1 /* argument 2, interrupt number (mcause) */ + /* mask off the interrupt flag of mcause */ + li t0, 0x7fffffff + and a1, a1, t0 + jal _global_interrupt_handler + + li t0, 0x8 + csrrc t0, mstatus, t0 + + /* restore the interrupt threshold level */ + la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG + sw s3, 0(t0) + fence + + call rt_interrupt_leave /* 执行所有的中断函数后,调用该函数 */ + + /* 上面,将保存执行中断服务函数之前的CPU的sp寄存器到了s0所指向的位置处,当执行完中断服务函数,需要将之前的CPU寄存器,恢复一下,此时sp又变成了from thread的sp了 */ + move sp, s0 /* sp = s0 */ + + /* 下面两句话,相当于将 rt_thread_switch_interrupt_flag 值,赋值给了s2 */ + /* 将 rt_thread_switch_interrupt_flag 的地址值,赋值给 s0 寄存器*/ + la s0, rt_thread_switch_interrupt_flag /* s0 = &rt_thread_switch_interrupt_flag */ + /* 将 s0 所指向的地址处的内容,取出来,赋值给 s2 寄存器,其实就是将 rt_thread_switch_interrupt_flag 的值,赋值给了 s2 寄存器*/ + lw s2, 0(s0) /* s2 = *s0 = rt_thread_switch_interrupt_flag */ + + /* 如果 s2的值,即 rt_thread_switch_interrupt_flag 值,如果不为0,则需要继续执行下一条指令,如果为0,则需要跳转到 spurious_interrupt 标号处 执行 */ + /* 如果 s2的值等于0,rt_thread_switch_interrupt_flag等于0, 则不需要在中断处理函数中,进行上下文切换,反之则需要 */ + /* 如果不需要上下文切换, */ + + /* 在这里,跳转到 spurious_interrupt的话,是不会进行上下文切换的,因为,此时CPU的sp指针还是from线程的*/ + beqz s2, spurious_interrupt /* if (s2 == 0) goto spurious_interrupt; else 执行下一条语句*/ + + /* 需要上下文切换: 主要目的是将CPU的sp指针,赋值为to_thread的sp */ + + /* 将 s0 所执向的地址的内容设置为0, 也就是,将变量 rt_thread_switch_interrupt_flag 赋值为了 0 */ + /* s0存放的值是 rt_thread_switch_interrupt_flag 变量的地址*/ + sw zero, 0(s0) /* *s0 = 0; 也就是 rt_thread_switch_interrupt_flag = 0 */ + /* 将 mepc 的值,赋值给 a0 寄存器,mepc 的值是,跳转到中断函数执行之前的 PC 指针 */ + /* 这时的mpec其实,还是from线程,在跳转到中断执行前的一个PC地址 */ + csrr a0, mepc /* a0 = mepc */ + + /* 将 mpec 的值写回到freom thread任务栈中的 epc 中,待后续,恢复from线程时,使用 */ + STORE a0, 0 * REGBYTES(sp) /* from_thread->sp->epc = a0 ,中断入口处*/ + + /* 将from_thread的sp指针,赋值为CPU的sp指针 */ + la s0, rt_interrupt_from_thread /* s0 = &rt_interrupt_from_thread 注意: rt_interrupt_from_thread = &(from_thread->sp) */ + LOAD s1, 0(s0) /* s1 = rt_interrupt_from_thread,也就是s1 = &(from_thread->sp) */ + STORE sp, 0(s1) /* from_thread->sp = sp*/ + + /* 接下来,需要开始恢复CPU的sp为to_thread的sp了 */ + la s0, rt_interrupt_to_thread /* s0 = &rt_interrupt_to_thread 注意: rt_interrupt_to_thread = &(to_thred->sp)*/ + LOAD s1, 0(s0) /* s1 = rt_interrupt_to_thread, 也就是s1 = &(to_thred->sp) */ + LOAD sp, 0(s1) /* sp = (to_thred->sp)*/ + + /* 将CPU的 mepc设置为to_thred的mepc,待中断退出,执行mret指令后,将从该地址开始执行 */ + LOAD a0, 0 * REGBYTES(sp) /* a0 = to_thread的mepc的值*/ + csrw mepc, a0 /* mepc = a0 */ + + +spurious_interrupt: + LOAD x1, 1 * REGBYTES(sp) + + /* Remain in M-mode after mret */ + li t0, 0x00001800 + csrs mstatus, t0 + LOAD t0, 2 * REGBYTES(sp) + csrs mstatus, t0 + + LOAD x4, 4 * REGBYTES(sp) + LOAD x5, 5 * REGBYTES(sp) + LOAD x6, 6 * REGBYTES(sp) + LOAD x7, 7 * REGBYTES(sp) + LOAD x8, 8 * REGBYTES(sp) + LOAD x9, 9 * REGBYTES(sp) + LOAD x10, 10 * REGBYTES(sp) + LOAD x11, 11 * REGBYTES(sp) + LOAD x12, 12 * REGBYTES(sp) + LOAD x13, 13 * REGBYTES(sp) + LOAD x14, 14 * REGBYTES(sp) + LOAD x15, 15 * REGBYTES(sp) + LOAD x16, 16 * REGBYTES(sp) + LOAD x17, 17 * REGBYTES(sp) + LOAD x18, 18 * REGBYTES(sp) + LOAD x19, 19 * REGBYTES(sp) + LOAD x20, 20 * REGBYTES(sp) + LOAD x21, 21 * REGBYTES(sp) + LOAD x22, 22 * REGBYTES(sp) + LOAD x23, 23 * REGBYTES(sp) + LOAD x24, 24 * REGBYTES(sp) + LOAD x25, 25 * REGBYTES(sp) + LOAD x26, 26 * REGBYTES(sp) + LOAD x27, 27 * REGBYTES(sp) + LOAD x28, 28 * REGBYTES(sp) + LOAD x29, 29 * REGBYTES(sp) + LOAD x30, 30 * REGBYTES(sp) + LOAD x31, 31 * REGBYTES(sp) + + addi sp, sp, 32 * REGBYTES + mret + .size _interrupt_handler, .-_interrupt_handler +#endif -- 2.35.1.windows.2