diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/Day2main.c" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/Day2main.c" new file mode 100644 index 0000000000000000000000000000000000000000..94fc0a78205c740d5cb2dcf1ee0c9228996f1e25 --- /dev/null +++ "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/Day2main.c" @@ -0,0 +1,58 @@ +// 这里是第2天作业的代码 + +#include +#include +#include + +/** + * 定义三个函数用于创建线程 + * usr_thread_high_priority:高优先级线程用于实验抢占式调度 + * + * usr_thread_low_priority_1 + * usr_thread_low_priority_2:低优先级线程且优先级相同,用于实验时间片轮转的调度 + * + */ +void usr_thread_high_priority(void){ + while(1){ + for(int i = 0;i<10;i++){ + rt_kprintf("run in usr high priority\r\n"); + } + rt_thread_delay(100); // 主动释放CPU给时间让另外两个线程执行 + } +} + +void usr_thread_low_priority_1(void){ + while(1){ + rt_kprintf("run in usr low priority 1\r\n"); + } +} + +void usr_thread_low_priority_2(void){ + while(1){ + rt_kprintf("run in usr low priority 2\r\n"); + } +} + +rt_thread_t tid1 = RT_NULL; +rt_thread_t tid2 = RT_NULL; +rt_thread_t tid3 = RT_NULL; + +int main(void) { + // 创建并启动三个线程 + tid1 = rt_thread_create("usr1", usr_thread_high_priority, RT_NULL, 1024, RT_MAIN_THREAD_PRIORITY + 1, 5); + if(tid1 != RT_NULL){ + rt_thread_startup(tid1); + } + + tid2 = rt_thread_create("usr2", usr_thread_low_priority_1, RT_NULL, 1024, RT_MAIN_THREAD_PRIORITY + 3, 5); + if(tid2 != RT_NULL){ + rt_thread_startup(tid2); + } + + tid3 = rt_thread_create("usr3", usr_thread_low_priority_2, RT_NULL, 1024, RT_MAIN_THREAD_PRIORITY + 3, 10); + if(tid2 != RT_NULL){ + rt_thread_startup(tid3); + } + + return RT_EOK; +} diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/figures/day2/polling.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/figures/day2/polling.png" new file mode 100644 index 0000000000000000000000000000000000000000..591df48a63a051d3aa645e0f39ac20a73d28568a Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/figures/day2/polling.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/figures/day2/preemptive.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/figures/day2/preemptive.png" new file mode 100644 index 0000000000000000000000000000000000000000..2c8f03639e21af81dc8b7f3f4b05e91aad6dc676 Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/figures/day2/preemptive.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/\347\254\2541\345\244\251\344\275\234\344\270\232.md" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/\347\254\2541\345\244\251\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..3b220eb0a241a33aaa831a4217b79291ad9989c9 --- /dev/null +++ "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/\347\254\2541\345\244\251\344\275\234\344\270\232.md" @@ -0,0 +1,5 @@ +## 针对qemu平台的项目编译 +已经写在[第1天笔记](../笔记/第1天笔记.md#尝试针对qemu平台编译)中了,此处不再赘述。 + +## 整理并提交笔记 +详见夏令营仓库的[PR列表](https://gitee.com/rtthread/rsoc-rtt/pulls)及[夏令营作业收集表](https://docs.qq.com/sheet/DSkFwaW9GZVpYY0VI?tab=BB08J2) \ No newline at end of file diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/\347\254\2542\345\244\251\344\275\234\344\270\232.md" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/\347\254\2542\345\244\251\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..546bba897fa0828f599930b6ded5be816529a995 --- /dev/null +++ "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\344\275\234\344\270\232/\347\254\2542\345\244\251\344\275\234\344\270\232.md" @@ -0,0 +1,38 @@ +## 线程设计 +一个高优先级线程用于实验抢占式调度 + +```c +void usr_thread_high_priority(void){ + while(1){ + for(int i = 0;i<10;i++){ + rt_kprintf("run in usr high priority\r\n"); + } + rt_thread_delay(100); // 主动释放CPU给时间让另外两个线程执行 + } +} +``` + +两个低优先级的线程用于实验时间片轮转调度 + +```c +void usr_thread_low_priority_1(void){ + while(1){ + rt_kprintf("run in usr low priority 1\r\n"); + } +} + +void usr_thread_low_priority_2(void){ + while(1){ + rt_kprintf("run in usr low priority 2\r\n"); + } +} +``` + +详细实现见[Day2main.c](Day2main.c) + +## 实验结果 +抢占式 +![preemptive](figures/day2/preemptive.png) + +时间片轮询 +![polling](figures/day2/polling.png) \ No newline at end of file diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/compile_1.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/compile_1.png" new file mode 100644 index 0000000000000000000000000000000000000000..a80eee2dc6278b6d7f5e60ab4fe55a3cd8f48268 Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/compile_1.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/compile_2.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/compile_2.png" new file mode 100644 index 0000000000000000000000000000000000000000..18554ad97a39f7771f2f140d0b525935f6af8186 Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/compile_2.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/boot.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/boot.png" new file mode 100644 index 0000000000000000000000000000000000000000..cab5f198c08ccff8891d00fcf331a13cce911898 Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/boot.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/entry.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/entry.png" new file mode 100644 index 0000000000000000000000000000000000000000..df40cd0f0fab96b173c4186289f7936b7705eecc Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/entry.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/install_packages.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/install_packages.png" new file mode 100644 index 0000000000000000000000000000000000000000..5c7043943fbb7ec36db61590308a139b5e542b44 Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/install_packages.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project0.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project0.png" new file mode 100644 index 0000000000000000000000000000000000000000..629449d465125f44afcbc89f47a4afa656fc8c32 Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project0.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project1_code.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project1_code.png" new file mode 100644 index 0000000000000000000000000000000000000000..4544cc66baac5481d69cd29049b27e511827bead Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project1_code.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project1_config.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project1_config.png" new file mode 100644 index 0000000000000000000000000000000000000000..790a956a9cf6f49addf8e441338dbcc9663c1201 Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project1_config.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project1_run.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project1_run.png" new file mode 100644 index 0000000000000000000000000000000000000000..d68e0176e5add0b6fe9d987656cf3edb203c67c9 Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/project1_run.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/rtt_startup.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/rtt_startup.png" new file mode 100644 index 0000000000000000000000000000000000000000..04dbb79fed05b7463c5ceea179f5dd75c6553724 Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/rtt_startup.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/runtime_status.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/runtime_status.png" new file mode 100644 index 0000000000000000000000000000000000000000..58564d0e8c0e5b9a911b83bd7fb8b3e4578a58d4 Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/runtime_status.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/schedule.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/schedule.png" new file mode 100644 index 0000000000000000000000000000000000000000..5f547a334772280faa91dac3bbfe7b4f15747b3c Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/schedule.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/stack_frame.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/stack_frame.png" new file mode 100644 index 0000000000000000000000000000000000000000..7d544624d4230d294145f8121a4761ba9f951dcd Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/stack_frame.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/startup.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/startup.png" new file mode 100644 index 0000000000000000000000000000000000000000..b464afed48f85bbdc1b6d86cfb3f3cdc5a360803 Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/startup.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/studio_ui.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/studio_ui.png" new file mode 100644 index 0000000000000000000000000000000000000000..83dacdd58b97b3c023b69928a5858687503ff39b Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/day2/studio_ui.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/gui.png" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/gui.png" new file mode 100644 index 0000000000000000000000000000000000000000..575ba006d67c2109067fca506b9215c04e4586ac Binary files /dev/null and "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/figures/gui.png" differ diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/\347\254\2541\345\244\251\347\254\224\350\256\260.md" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/\347\254\2541\345\244\251\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..9b979a22e90989a2a961fd8d3158580b511469d6 --- /dev/null +++ "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/\347\254\2541\345\244\251\347\254\224\350\256\260.md" @@ -0,0 +1,124 @@ +## 环境搭建与测试 + +### Git +安装版本管理软件[Git](https://git-scm.com/downloads)用于项目源代码仓库的管理和版本控制。 + +### 拉取RT-Thread项目源码 +从[github(国外)](https://github.com/RT-Thread/rt-thread)或[gitee(国内)](https://gitee.com/rtthread/rt-thread)代码仓库获取源码,使用命令 + +```sh +git clone https://gitee.com/rtthread/rt-thread.git +``` + +### 安装env工具 +从[github仓库](https://github.com/RT-Thread/env-windows)、[gitee仓库](https://gitee.com/mirrors_RT-Thread/env-windows)拉取或[官网](https://www.rt-thread.org/download.html)下载,官网的为离线版本,且版本号更新一点。其中使用了sub module,使用以下命令拉取 + +```sh +git clone --recursive --depth 1 https://github.com/RT-Thread/env-windows.git + +git clone --recursive --depth 1 https://gitee.com/mirrors_RT-Thread/env-windows.git +``` + +打开目录下的 `env.bat` 文件等待环境配置完成。 + +在命令窗口的右上角 `settings -> Integration -> Register` 将 `env` 注册到Windows右键菜单中。方便之后在对应目录打开 `env` + +先进行一次 `menuconfig` 生成配置文件,直接保存退出。 + +使用以下命令更新 +```sh +pkgs --update #更新包 + +pkgs --upgrade #更新env +``` + +可以使用 `help` 命令查看所有命令 + +### RT-Thread目录结构 +|名称 |描述 | +|-------------|---------------------------------------------------| +|bsp |Board Support Package(板级支持包)基于各种开发板的移植| +|components |RT-Thread 的各个组件代码,例如 finsh,gui 等。 | +|documentation|相关文档,如编码规范等 | +|examples |相关示例代码 | +|include |RT-Thread 内核的头文件。 | +|libcpu |各类芯片的移植代码。 | +|src |RT-Thread 内核的源文件。 | +|tools |RT-Thread 命令构建工具的脚本文件。 | + +### 尝试针对qemu平台编译 +在 `rt-thread\bsp\qemu-vexpress-a9` 目录下打开 `env` 工具,并使用menuconfig生成配置文件,直接保存退出即可。 + +使用以下命令编译,其中的数字表示编译使用的线程数。最终编译生成elf文件。 +```sh +scons -j4 #编译 +scons -c #清除编译文件 +``` + +![编译](figures/compile_1.png) + +使用以下命令启动,进入shell界面 +```sh +qemu-nographic.bat +``` + +在shell界面可以使用以下命令 +```sh +list device #查看当前所有的设备 +list thread #查看当前启动的线程 +list timer #当前使用到的定时器 +Ctrl+A松开后再按X #退出终端 +``` +尝试修改 `applications` 目录下的 `main.c` 文件后重新编译运行。 +![修改main后重新编译](figures/compile_2.png) + +### 编译过程概述 +项目的编译依赖于python脚本包括项目根目录的 `SConstruct` 、 `SConscript` 文件 以及各个目录下的`SConscript` 文件,通过递归查找目录下的 `.c` 和 `.cpp` 文件并返回,最终形成编译命令。 + +### 重新配置项目实现图像显示 +在 `rt-thread\bsp\qemu-vexpress-a9` 目录下打开 `env` 工具,并使用menuconfig生成配置文件,打开 `Hardware Drivers Config -> Onboard Peripheral Drivers -> Enable LVGL for LCD` 返回保存,更新 `Kconfig` 文件,同时会同步到 `.config` 文件中并生成 `rtconfig.h` 文件。 + +LVGL是一个软件包使用 `pkgs --update` 。实际上在保存退出后就会默认进行下载。下载的文件在根目录packages文件夹下。 + +再次编译生成elf文件并使用以下命令启动带有图形界面的终端。 +```sh +qemu.bat +``` +![图形界面](figures/gui.png) + + +### 安装VSCode +在[官网](https://code.visualstudio.com/)安装VSCode用于编辑代码及后续调试等 + +## Git使用及提交PR +Git主要用于项目的版本管理及多人协作。 + +### .git文件夹 +项目根目录下有.git文件夹,其中存储了和git 相关的文件,包括历史记录及一些配置主要的配置可以在 `config` 文件中查看。 + +### 常用命令 +```sh +git init #初始化文件夹成为一个git仓库 +git status #查看当前状态 +git add #暂存文件,将文件放到暂存区 +git log #查看历史 +git switch #切换分支 +git checkout #回退,迁出分支 +git reset --soft/--hard HEAD~ #重置,soft保留操作到暂存区hard直接删除 +git branch/checkout -b #创建新的分支 +git commit -m "本次提交说明" #提交代码 +git merge #合并分支 +``` + +### 使用ssh拉取仓库 +在第一次使用时需要创建一对密钥完成ssh配置(gitee平台) +```sh +ssh-keygen -t rsa #创建密钥对 +``` +windows环境下使用OpenSSH密钥对默认的存储位置为 `C:/Users/UserName/.ssh/` 默认文件名称为 `id_rsa(私钥)` 和 `id_rsa.pub(公钥)` 生成密钥时最好不要修改名称,修改名称会涉及到配置该目录下的 `config` 文件。使用以下命令测试配置正确性。 +```sh +ssh -T git@gitee.com +``` + +### 提交PR +首先对目标仓库进行 `fork` 操作将其拷贝到自己的仓库。本地完成编辑之后推送到自己的仓库。最后在目标仓库的PR列表提交PR请求。 \ No newline at end of file diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/\347\254\2542\345\244\251\347\254\224\350\256\260.md" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/\347\254\2542\345\244\251\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..71fbcd99954a90d22c7995db43a234338e237f10 --- /dev/null +++ "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\346\235\234\346\265\251\347\204\266/\347\254\224\350\256\260/\347\254\2542\345\244\251\347\254\224\350\256\260.md" @@ -0,0 +1,129 @@ +## RT-Thread内核基础与线程 + +### 裸机与RTOS +功能单一的情况下,系统整体功能没有细分多个线程的必要,采用裸机较为合适。例如电动牙刷 + +系统功能丰富情况下,使用裸机编程需要编写复杂的逻辑协调多个事件,同时代码的耦合度较高,采用RTOS较为合适。例如机器人。 + +裸机优点与缺点: +- 单一功能的嵌入式系统使用裸机可以提高运行效率 +- 可以使用较少的存储实现单一功能的嵌入式系统 +- 代码耦合度较高,复用性差 +- 不适合复杂的嵌入式系统 +- 代码不合理时容易造成系统阻塞 + +RTOS优点与缺点: +- 代码耦合度低,复用性好 +- 可以使用任务划分的方式降低实现复杂嵌入式操作系统的代码逻辑 +- 延时操作不会一直占用CPU,延时期间处理其他任务 +- 使用RTOS提供的线程同步与信息传递会提高系统的实时性 +- 不适合小容量嵌入式系统,RTOS本身会占据部分存储 +- 不适合单一嵌入式系统,系统调度会引入额外的开销 + +> RTOS编程的思想为模块化“分而治之”的拆分思想,降低每个任务的复杂性。 + +下图为两种程序的运行情况 +![运行情况](figures/day2/runtime_status.png) + +### 临界区 +临界区的资源在同一时间只能被一个线程使用,一但临界资源被占用,其他线程只能等待。 + +一个线程先占用了临界区的资源,其他线程想使用临界资源就必须等待,这种阻塞其他线程继续执行的情况就是线程阻塞(Blocking) + +### 系统启动 +如下图为RT-Thread的系统启动过程 +![启动过程](figures/day2/rtt_startup.png) + +其中启动文件 `startup_xx.S` 对flash、ram等硬件介质进行初始化。之后根据不同的编译环境(MDK、IAR、GCC)进入不同的函数。如图为STM32F407的板级开发包,其中的启动文件中调用了entry函数。 +![启动文件](figures/day2/startup.png) + +而在 `component.c` 文件中又根据不同的编译环境分别写了预编译命令。如图中框出的为gcc环境下的entry函数,其中调用了又调用了 `rtthread_startup` 函数。 +![entry](figures/day2/entry.png) + +在 `rtthread_startup` 中首先进行了关中断的操作 `rt_hw_interrupt_disable`,避免外部的中断打断操作系统的初始化。 + +`rt_hw_board_init` 进行一些板级外设硬件的初始化。初始化外设之后就可以通过 `rt_show_version` 从串口打印信息。 + +对于 `rt_system_timer_init` 和 `rt_system_timer_thread_init` 他们用于初始化系统中的定时器。前者是系统中使用硬件中断计时的,后者是软件定时器对线程进行计时,前者的精度更高。 + +`rt_system_scheduler_init` 用于初始化调度器的队列 + +`rt_system_signal_init` 软件中断的初始化 + +`rt_application_init` 和 `rt_thread_idle_init` 后者创建了一个空闲线程,若系统中没有要运行的线程,则调度空闲线程,它是优先级最低的一个线程它永远处于就绪状态不会被挂起。其中适合使用一些钩子函数进行功耗管理看门狗喂狗等操作。前者创建main函数的线程。 + +`rt_system_scheduler_start` 启动系统开始进行线程调度。在main函数执行之前还有一部分软件初始化,如协议栈、驱动、软件包等的初始化。 + +### 线程调度 +若某线程运行完毕,系统将自动删除线程:自动执行 `rt_thread_exit` 函数,先将该线程从系统就绪队列中删除,再将该线程的状态更改为关闭,不再参与系统调度,然后挂入 `rt_thread_defunct` 僵尸队列(资源未回收、处于关闭状态的线程队列),最后空闲线程会回收被删除线程的资源。 + +### 线程创建 +一个线程要成为可执行的对象,就必须由操作系统的内核来为它创建一个线程,可以通过一下接口创建一个动态线程。 +```c +rt_thread_t rt_thread_create(const char*name, + void (*entry)(void* parameter), + void* parameter, + rt_uint32_t stack_size, + rt_uint8_t priority, + rt_uint32_t tick); +``` +其中参数 `name` 用于找到线程的控制块,最终获得句柄,通过句柄获得线程的状态等信息。 `priority` 是优先级,数字越小优先级越高。 `tick` 是时间片大小。 + +调用此函数时,系统从动态堆内存中分配一个线程句柄以及按照参数中指定的栈大小相应的空间。分配出来的栈空间按照 `rtconfig.h` 中配置的 `RT_ALIGN_SIZE` 方式对齐。 + +创建线程还可以使用函数 `rt_thread_init` 创建线程,两者区别在于此函数是静态创建线程,而create函数是动态创建线程。静态创建在编译阶段就分配了空间,只为此线程使用更安全,无论后续线程处于什么状态都不会给其他线程使用。系统的几乎所有线程都是静态分配的。动态创建使用动态分配的方式分配空间,后续可以回收。使用init创建的线程使用函数 `rt_thread_detach` 进行分离(从就绪队列移除),使用create创建的函数则用函数 `rt_thread_delete` 释放空间。 + +### 其他线程相关函数 +`rt_thead_self` 获取当前运行的线程 +`rt_thead_find` 通过名称寻找线程控制块 +`rt_thead_startup` 启动线程进入就绪状态(创建后状态处于初始状态还未加入调度) +`rt_thead_yield` 立刻放弃当前线程的时间片 +`rt_thead_delay` 延时,主动释放CPU +`rt_thead_control` 修改线程的优先级等控制信息 +`rt_thead_suspend` 挂起线程,只能对自己线程操作 +`rt_thead_resume` 恢复线程 + +### 线程创建的一些原理 +两种创建都调用了函数 `_thread_init` 该函数除了进行回调函数的初始化之外还调用了一个重要的函数 `rt_hw_stack_init` 其中对栈帧进行了初始化。由于该线程还未被调用初始化栈帧实际相当于手动设置了现场。 + +栈帧结构体 `stack_frame` 其中又包含了一个结构体 `exception_stack_frame`。他们的区别涉及到调用约定。如下图,其中红色的为被调用者保存寄存器,需要被调用函数保存/恢复。绿色中的r0-r3是调用者保存寄存器,函数调用时进行临时传参。此规定与具体芯片有关。此外由于Cortex-M3/M4支持硬件压栈、恢复, `exception_stack_frame` 中的寄存器可以由硬件自动保存,而 `stack_frame` 中的其他寄存器就需要操作系统手动保存。 +![stack_frame](figures/day2/stack_frame.png) + +此外创建线程中还初始化了定时器,用于线程中的delay操作。 + +### 线程状态的转化 +![线程状态转化](figures/day2/schedule.png) + +无循环的线程执行完毕后系统自动回收资源,循环的线程会通过系统延时主动让出CPU或等待IPC。 + +### 调度器的工作 +- 优先级抢占:保证一个最高优先级的任务运行,从就绪链表中查找最高优先级的任务。 +- 时间片轮转:相同优先级状态下根据时间片轮转运行。 + +## RT-Thread Studio简单示例 +首先安装[RT-Thread Studio](https://www.rt-thread.org/studio.html) + +其中主要需要的功能如下图所示 +![studio_ui](figures/day2/studio_ui.png) + +此示例主要针对stm32F407板级开发包。 + +### stm32F407板级开发包安装 +首先在SDK管理中勾选 `Board_Support_Packages/STMicroelectronics/STM32F407-ATK-EXPLORE` 的最新版以及 `Debuger_Support_Packages/QEMU` 的最新版,并安装资源包。 +![安装资源包](figures/day2/install_packages.png) + +之后新建RT-Thread项目,选择基于开发版,选中刚下载的开发板及调试器和对应的模拟器。创建工程后选中项目处于激活状态并编译项目。编译成功后点击下载按钮选择对应的模拟器运行代码,进入msh。 +![项目0](figures/day2/project0.png) + +### 安装线程软件包 +在工程目录下的 `RT-Thread Settings` 中打开 `软件包 -> 杂项软件包 -> 软件包内核示例/thread` 再按Ctrl+S保存完成软件包的拉取与配置。 +![项目1配置](figures/day2/project1_config.png) + +编译运行后在shell运行 `thread_sample` 查看示例 +![项目1运行](figures/day2/project1_run.png) + +可以看到代码中分别通过动态和静态的方式创建了共2个线程。 +![项目1代码](figures/day2/project1_code.png) + +### 编写代码体现抢占与时间片轮转 +详见[第2天作业](../作业/第2天作业.md) \ No newline at end of file