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

394 lines
14 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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