rt-thread-official/bsp/ESP32_C3/0001-add-the-config-of-RTTH...

394 lines
14 KiB
Diff
Raw Normal View History

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的值等于0rt_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