1
0

0001-add-the-config-of-RTTHREAD.patch 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. From 317ee995e9d530587bfb14439b3b1ee38d1afe77 Mon Sep 17 00:00:00 2001
  2. From: supperthomas <78900636@qq.com>
  3. Date: Fri, 6 May 2022 23:06:28 +0800
  4. Subject: [PATCH] add the config of RTTHREAD
  5. add the init link file
  6. ---
  7. Kconfig | 4 +
  8. .../esp_system/ld/esp32c3/sections.ld.in | 26 +++
  9. components/freertos/port/port_common.c | 5 +
  10. components/freertos/port/port_systick.c | 3 +
  11. components/riscv/vectors.S | 220 ++++++++++++++++--
  12. 5 files changed, 239 insertions(+), 19 deletions(-)
  13. diff --git a/Kconfig b/Kconfig
  14. index 928d274106..d368adaa37 100644
  15. --- a/Kconfig
  16. +++ b/Kconfig
  17. @@ -61,6 +61,10 @@ mainmenu "Espressif IoT Development Framework Configuration"
  18. bool
  19. default "y" if IDF_TARGET="linux"
  20. + config IDF_RTOS_RTTHREAD
  21. + bool "RT-THREAD SELECT"
  22. + default "n"
  23. +
  24. config IDF_FIRMWARE_CHIP_ID
  25. hex
  26. default 0x0000 if IDF_TARGET_ESP32
  27. diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in
  28. index 0ebeda06c1..8215237fff 100644
  29. --- a/components/esp_system/ld/esp32c3/sections.ld.in
  30. +++ b/components/esp_system/ld/esp32c3/sections.ld.in
  31. @@ -183,6 +183,32 @@ SECTIONS
  32. _noinit_end = ABSOLUTE(.);
  33. } > dram0_0_seg
  34. + .stack_dummy (COPY):
  35. + {
  36. + . = ALIGN(8);
  37. + __STACKSIZE__ = 40960;
  38. + __stack_start__ = .;
  39. + *(.stack*)
  40. + . += __STACKSIZE__;
  41. + __stack_cpu0 = .;
  42. + __stack_end__ = .;
  43. + } > dram0_0_seg
  44. +
  45. + .stack_dummy (COPY):
  46. + {
  47. + . = ALIGN(8);
  48. + __HEAPSIZE__ = 40960;
  49. + __heap_start__ = .;
  50. + . += __STACKSIZE__;
  51. + __heap_end__ = .;
  52. + /* section information for initial. */
  53. + . = ALIGN(4);
  54. + __rt_init_start = .;
  55. + KEEP(*(SORT(.rti_fn*)))
  56. + __rt_init_end = .;
  57. +
  58. + . = ALIGN(4);
  59. + } > dram0_0_seg
  60. /* Shared RAM */
  61. .dram0.bss (NOLOAD) :
  62. {
  63. diff --git a/components/freertos/port/port_common.c b/components/freertos/port/port_common.c
  64. index ffca3d5429..9d8159f588 100644
  65. --- a/components/freertos/port/port_common.c
  66. +++ b/components/freertos/port/port_common.c
  67. @@ -74,11 +74,16 @@ void esp_startup_start_app_common(void)
  68. esp_gdbstub_init();
  69. #endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
  70. +#ifdef CONFIG_IDF_RTOS_RTTHREAD
  71. + app_main();
  72. +#else
  73. portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
  74. ESP_TASK_MAIN_STACK, NULL,
  75. ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE);
  76. assert(res == pdTRUE);
  77. (void)res;
  78. +#endif
  79. +
  80. }
  81. static void main_task(void* args)
  82. diff --git a/components/freertos/port/port_systick.c b/components/freertos/port/port_systick.c
  83. index 0c14a155a1..0fa203574b 100644
  84. --- a/components/freertos/port/port_systick.c
  85. +++ b/components/freertos/port/port_systick.c
  86. @@ -116,6 +116,8 @@ void vPortSetupTimer(void)
  87. */
  88. IRAM_ATTR void SysTickIsrHandler(void *arg)
  89. {
  90. +#ifdef CONFIG_IDF_RTOS_RTTHREAD
  91. +#else
  92. uint32_t cpuid = xPortGetCoreID();
  93. systimer_hal_context_t *systimer_hal = (systimer_hal_context_t *)arg;
  94. #ifdef CONFIG_PM_TRACE
  95. @@ -144,6 +146,7 @@ IRAM_ATTR void SysTickIsrHandler(void *arg)
  96. #ifdef CONFIG_PM_TRACE
  97. ESP_PM_TRACE_EXIT(TICK, cpuid);
  98. #endif
  99. +#endif
  100. }
  101. #endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
  102. diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S
  103. index 1006d5bea5..963494fcb3 100644
  104. --- a/components/riscv/vectors.S
  105. +++ b/components/riscv/vectors.S
  106. @@ -17,6 +17,9 @@
  107. #include "soc/soc_caps.h"
  108. #include "sdkconfig.h"
  109. +#define STORE sw
  110. +#define LOAD lw
  111. +#define REGBYTES 4
  112. .equ SAVE_REGS, 32
  113. .equ CONTEXT_SIZE, (SAVE_REGS * 4)
  114. @@ -218,25 +221,27 @@ _call_panic_handler:
  115. */
  116. .global _interrupt_handler
  117. .type _interrupt_handler, @function
  118. +#ifndef CONFIG_IDF_RTOS_RTTHREAD
  119. +
  120. _interrupt_handler:
  121. /* entry */
  122. - save_regs
  123. - save_mepc
  124. + save_regs /* 保存寄存器 */
  125. + save_mepc /* 保存MEPC */
  126. /* Before doing anythig preserve the stack pointer */
  127. /* It will be saved in current TCB, if needed */
  128. - mv a0, sp
  129. + mv a0, sp /* 保存SP a0 = sp */
  130. call rtos_int_enter
  131. /* Before dispatch c handler, restore interrupt to enable nested intr */
  132. - csrr s1, mcause
  133. - csrr s2, mstatus
  134. + csrr s1, mcause /* 保存mcause s1 = mcause */
  135. + csrr s2, mstatus /* 保存mstatus s2 = mstatus */
  136. - /* Save the interrupt threshold level */
  137. - la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
  138. - lw s3, 0(t0)
  139. + /* Save the interrupt threshold level 保存中断嵌套层数? */
  140. + la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG /* 保存mstatus t0 = &INTERRUPT_CORE0_CPU_INT_THRESH_REG */
  141. + lw s3, 0(t0) /* s3 = mstatus */
  142. - /* Increase interrupt threshold level */
  143. + /* Increase interrupt threshold level 增加中断嵌套层数*/
  144. li t2, 0x7fffffff
  145. and t1, s1, t2 /* t1 = mcause & mask */
  146. slli t1, t1, 2 /* t1 = mcause * 4 */
  147. @@ -247,8 +252,8 @@ _interrupt_handler:
  148. sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */
  149. fence
  150. - li t0, 0x8
  151. - csrrs t0, mstatus, t0
  152. + li t0, 0x8 /* t0 = 8 */
  153. + csrrs t0, mstatus, t0 /*设置状态MIE寄存器,开总中断*/
  154. #ifdef CONFIG_PM_TRACE
  155. li a0, 0 /* = ESP_PM_TRACE_IDLE */
  156. @@ -269,34 +274,211 @@ _interrupt_handler:
  157. /* call the C dispatcher */
  158. mv a0, sp /* argument 1, stack pointer */
  159. mv a1, s1 /* argument 2, interrupt number (mcause) */
  160. - /* mask off the interrupt flag of mcause */
  161. + /* mask off the interrupt flag of mcause 屏幕异常中断*/
  162. li t0, 0x7fffffff
  163. and a1, a1, t0
  164. jal _global_interrupt_handler
  165. - /* After dispatch c handler, disable interrupt to make freertos make context switch */
  166. + /* After dispatch c handler, disable interrupt to make freertos make context switch
  167. + 在调用c函数之后,disable 中断让freertos能够做内容切换
  168. + */
  169. li t0, 0x8
  170. - csrrc t0, mstatus, t0
  171. + csrrc t0, mstatus, t0 /*清状态MIE寄存器 关总中断*/
  172. - /* restore the interrupt threshold level */
  173. +
  174. + /* restore the interrupt threshold level 中断嵌套 */
  175. la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
  176. sw s3, 0(t0)
  177. fence
  178. /* Yield to the next task is needed: */
  179. - mv a0, sp
  180. + mv a0, sp /* a0 = sp*/
  181. call rtos_int_exit
  182. /* The next (or current) stack pointer is returned in a0 */
  183. - mv sp, a0
  184. + mv sp, a0 /* sp = a0*/
  185. /* restore the rest of the registers */
  186. - csrw mcause, s1
  187. - csrw mstatus, s2
  188. + csrw mcause, s1 /* mcause = s1 */
  189. + csrw mstatus, s2 /* mstatus = s2 */
  190. restore_mepc
  191. restore_regs
  192. /* exit, this will also re-enable the interrupts */
  193. mret
  194. .size _interrupt_handler, .-_interrupt_handler
  195. +#else
  196. +_interrupt_handler:
  197. + /* 此时CPU的sp = from_thread->sp */
  198. + /* 注意: 在这里,并没有将mepc的值赋值为from_thread栈中的epc,但后面会赋值 */
  199. + addi sp, sp, -32 * REGBYTES /* sp = sp - 32 * 4 栈指针向下偏移32个寄存器长度,用来将CPU的寄存器保存到from_thread的栈中*/
  200. + STORE x1, 1 * REGBYTES(sp) /* 将CPU的x1寄存器,即ra寄存器,保存到from_thread->栈中 */
  201. +
  202. + li t0, 0x80 /* t0 = 0x80 */
  203. + STORE t0, 2 * REGBYTES(sp) /* mstatus = t0, 即关闭全局中断 */
  204. +
  205. + /* 将 CPU 的其他寄存器的值,保存到from_thread的任务栈中 */
  206. + STORE x4, 4 * REGBYTES(sp)
  207. + STORE x5, 5 * REGBYTES(sp)
  208. + STORE x6, 6 * REGBYTES(sp)
  209. + STORE x7, 7 * REGBYTES(sp)
  210. + STORE x8, 8 * REGBYTES(sp)
  211. + STORE x9, 9 * REGBYTES(sp)
  212. + STORE x10, 10 * REGBYTES(sp)
  213. + STORE x11, 11 * REGBYTES(sp)
  214. + STORE x12, 12 * REGBYTES(sp)
  215. + STORE x13, 13 * REGBYTES(sp)
  216. + STORE x14, 14 * REGBYTES(sp)
  217. + STORE x15, 15 * REGBYTES(sp)
  218. + STORE x16, 16 * REGBYTES(sp)
  219. + STORE x17, 17 * REGBYTES(sp)
  220. + STORE x18, 18 * REGBYTES(sp)
  221. + STORE x19, 19 * REGBYTES(sp)
  222. + STORE x20, 20 * REGBYTES(sp)
  223. + STORE x21, 21 * REGBYTES(sp)
  224. + STORE x22, 22 * REGBYTES(sp)
  225. + STORE x23, 23 * REGBYTES(sp)
  226. + STORE x24, 24 * REGBYTES(sp)
  227. + STORE x25, 25 * REGBYTES(sp)
  228. + STORE x26, 26 * REGBYTES(sp)
  229. + STORE x27, 27 * REGBYTES(sp)
  230. + STORE x28, 28 * REGBYTES(sp)
  231. + STORE x29, 29 * REGBYTES(sp)
  232. + STORE x30, 30 * REGBYTES(sp)
  233. + STORE x31, 31 * REGBYTES(sp)
  234. +
  235. + /* 备份 CPU 的 sp (这时,CPU的sp其实就是from thread的sp指针) 寄存器的值到 s0 寄存器中,下面会使用s0,恢复 CPU 的寄存器 */
  236. + move s0, sp /* s0 = sp */
  237. +
  238. + /* 在中断函数中,中断函数中调用的C函数,需要使用 sp, 这里,在中断函数中,使用的 sp 为,系统的栈资源 */
  239. + /* switch to interrupt stack */
  240. + la sp, __stack_end__ /* sp = _sp */
  241. +
  242. + /* interrupt handle */
  243. + /* 注意: 在调用C函数之前,比如sp的值为0x30001000, 在执行完C函数后,sp的值还是会变成 0x30001000 */
  244. + call rt_interrupt_enter /* 执行所有的中断函数前,调用该函数 */
  245. +
  246. + csrr s1, mcause
  247. + csrr s2, mstatus
  248. +
  249. + /* Save the interrupt threshold level */
  250. + la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
  251. + lw s3, 0(t0)
  252. +
  253. + li t2, 0x7fffffff
  254. + and t1, s1, t2 /* t1 = mcause & mask */
  255. + slli t1, t1, 2 /* t1 = mcause * 4 */
  256. + la t2, INTC_INT_PRIO_REG(0)
  257. + add t1, t2, t1 /* t1 = INTC_INT_PRIO_REG + 4 * mcause */
  258. + lw t2, 0(t1) /* t2 = INTC_INT_PRIO_REG[mcause] */
  259. + addi t2, t2, 1 /* t2 = t2 +1 */
  260. + sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */
  261. + fence
  262. +
  263. + li t0, 0x8
  264. + csrrs t0, mstatus, t0
  265. +
  266. + /* call the C dispatcher */
  267. + mv a0, sp /* argument 1, stack pointer */
  268. + mv a1, s1 /* argument 2, interrupt number (mcause) */
  269. + /* mask off the interrupt flag of mcause */
  270. + li t0, 0x7fffffff
  271. + and a1, a1, t0
  272. + jal _global_interrupt_handler
  273. +
  274. + li t0, 0x8
  275. + csrrc t0, mstatus, t0
  276. +
  277. + /* restore the interrupt threshold level */
  278. + la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
  279. + sw s3, 0(t0)
  280. + fence
  281. +
  282. + call rt_interrupt_leave /* 执行所有的中断函数后,调用该函数 */
  283. +
  284. + /* 上面,将保存执行中断服务函数之前的CPU的sp寄存器到了s0所指向的位置处,当执行完中断服务函数,需要将之前的CPU寄存器,恢复一下,此时sp又变成了from thread的sp了 */
  285. + move sp, s0 /* sp = s0 */
  286. +
  287. + /* 下面两句话,相当于将 rt_thread_switch_interrupt_flag 值,赋值给了s2 */
  288. + /* 将 rt_thread_switch_interrupt_flag 的地址值,赋值给 s0 寄存器*/
  289. + la s0, rt_thread_switch_interrupt_flag /* s0 = &rt_thread_switch_interrupt_flag */
  290. + /* 将 s0 所指向的地址处的内容,取出来,赋值给 s2 寄存器,其实就是将 rt_thread_switch_interrupt_flag 的值,赋值给了 s2 寄存器*/
  291. + lw s2, 0(s0) /* s2 = *s0 = rt_thread_switch_interrupt_flag */
  292. +
  293. + /* 如果 s2的值,即 rt_thread_switch_interrupt_flag 值,如果不为0,则需要继续执行下一条指令,如果为0,则需要跳转到 spurious_interrupt 标号处 执行 */
  294. + /* 如果 s2的值等于0,rt_thread_switch_interrupt_flag等于0, 则不需要在中断处理函数中,进行上下文切换,反之则需要 */
  295. + /* 如果不需要上下文切换, */
  296. +
  297. + /* 在这里,跳转到 spurious_interrupt的话,是不会进行上下文切换的,因为,此时CPU的sp指针还是from线程的*/
  298. + beqz s2, spurious_interrupt /* if (s2 == 0) goto spurious_interrupt; else 执行下一条语句*/
  299. +
  300. + /* 需要上下文切换: 主要目的是将CPU的sp指针,赋值为to_thread的sp */
  301. +
  302. + /* 将 s0 所执向的地址的内容设置为0, 也就是,将变量 rt_thread_switch_interrupt_flag 赋值为了 0 */
  303. + /* s0存放的值是 rt_thread_switch_interrupt_flag 变量的地址*/
  304. + sw zero, 0(s0) /* *s0 = 0; 也就是 rt_thread_switch_interrupt_flag = 0 */
  305. + /* 将 mepc 的值,赋值给 a0 寄存器,mepc 的值是,跳转到中断函数执行之前的 PC 指针 */
  306. + /* 这时的mpec其实,还是from线程,在跳转到中断执行前的一个PC地址 */
  307. + csrr a0, mepc /* a0 = mepc */
  308. +
  309. + /* 将 mpec 的值写回到freom thread任务栈中的 epc 中,待后续,恢复from线程时,使用 */
  310. + STORE a0, 0 * REGBYTES(sp) /* from_thread->sp->epc = a0 ,中断入口处*/
  311. +
  312. + /* 将from_thread的sp指针,赋值为CPU的sp指针 */
  313. + la s0, rt_interrupt_from_thread /* s0 = &rt_interrupt_from_thread 注意: rt_interrupt_from_thread = &(from_thread->sp) */
  314. + LOAD s1, 0(s0) /* s1 = rt_interrupt_from_thread,也就是s1 = &(from_thread->sp) */
  315. + STORE sp, 0(s1) /* from_thread->sp = sp*/
  316. +
  317. + /* 接下来,需要开始恢复CPU的sp为to_thread的sp了 */
  318. + la s0, rt_interrupt_to_thread /* s0 = &rt_interrupt_to_thread 注意: rt_interrupt_to_thread = &(to_thred->sp)*/
  319. + LOAD s1, 0(s0) /* s1 = rt_interrupt_to_thread, 也就是s1 = &(to_thred->sp) */
  320. + LOAD sp, 0(s1) /* sp = (to_thred->sp)*/
  321. +
  322. + /* 将CPU的 mepc设置为to_thred的mepc,待中断退出,执行mret指令后,将从该地址开始执行 */
  323. + LOAD a0, 0 * REGBYTES(sp) /* a0 = to_thread的mepc的值*/
  324. + csrw mepc, a0 /* mepc = a0 */
  325. +
  326. +
  327. +spurious_interrupt:
  328. + LOAD x1, 1 * REGBYTES(sp)
  329. +
  330. + /* Remain in M-mode after mret */
  331. + li t0, 0x00001800
  332. + csrs mstatus, t0
  333. + LOAD t0, 2 * REGBYTES(sp)
  334. + csrs mstatus, t0
  335. +
  336. + LOAD x4, 4 * REGBYTES(sp)
  337. + LOAD x5, 5 * REGBYTES(sp)
  338. + LOAD x6, 6 * REGBYTES(sp)
  339. + LOAD x7, 7 * REGBYTES(sp)
  340. + LOAD x8, 8 * REGBYTES(sp)
  341. + LOAD x9, 9 * REGBYTES(sp)
  342. + LOAD x10, 10 * REGBYTES(sp)
  343. + LOAD x11, 11 * REGBYTES(sp)
  344. + LOAD x12, 12 * REGBYTES(sp)
  345. + LOAD x13, 13 * REGBYTES(sp)
  346. + LOAD x14, 14 * REGBYTES(sp)
  347. + LOAD x15, 15 * REGBYTES(sp)
  348. + LOAD x16, 16 * REGBYTES(sp)
  349. + LOAD x17, 17 * REGBYTES(sp)
  350. + LOAD x18, 18 * REGBYTES(sp)
  351. + LOAD x19, 19 * REGBYTES(sp)
  352. + LOAD x20, 20 * REGBYTES(sp)
  353. + LOAD x21, 21 * REGBYTES(sp)
  354. + LOAD x22, 22 * REGBYTES(sp)
  355. + LOAD x23, 23 * REGBYTES(sp)
  356. + LOAD x24, 24 * REGBYTES(sp)
  357. + LOAD x25, 25 * REGBYTES(sp)
  358. + LOAD x26, 26 * REGBYTES(sp)
  359. + LOAD x27, 27 * REGBYTES(sp)
  360. + LOAD x28, 28 * REGBYTES(sp)
  361. + LOAD x29, 29 * REGBYTES(sp)
  362. + LOAD x30, 30 * REGBYTES(sp)
  363. + LOAD x31, 31 * REGBYTES(sp)
  364. +
  365. + addi sp, sp, 32 * REGBYTES
  366. + mret
  367. + .size _interrupt_handler, .-_interrupt_handler
  368. +#endif
  369. --
  370. 2.35.1.windows.2