diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\345\274\240\347\247\221\345\274\272/\347\254\224\350\256\260/\347\254\254\344\270\200\345\244\251\347\254\224\350\256\260" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\345\274\240\347\247\221\345\274\272/\347\254\224\350\256\260/\347\254\254\344\270\200\345\244\251\347\254\224\350\256\260" new file mode 100644 index 0000000000000000000000000000000000000000..e2b82fe7fe1485b0254e3bb68b68352916b1b871 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\345\274\240\347\247\221\345\274\272/\347\254\224\350\256\260/\347\254\254\344\270\200\345\244\251\347\254\224\350\256\260" @@ -0,0 +1,31 @@ +# 初始化仓库(在项目文件夹内执行) +git init + +# 查看仓库状态 +git status + +# 添加文件到暂存区 +git add <文件名> # 添加单个文件 + +git add . # 添加所有修改 + +# 提交到本地仓库 +git commit -m "提交说明" + +# 查看提交历史 +git log + +# 查看所有分支 +git branch -a + +# 创建并切换到新分支 +git switch -c <分支名> # 推荐新写法 + +# 切换分支 +git switch <分支名> + +# 删除分支 +git branch -d <分支名> + +# 远端推送 +git push origin ljl \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\345\274\240\347\247\221\345\274\272/\347\254\224\350\256\260/\347\254\254\344\272\214\345\244\251\347\254\224\350\256\260" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\345\274\240\347\247\221\345\274\272/\347\254\224\350\256\260/\347\254\254\344\272\214\345\244\251\347\254\224\350\256\260" new file mode 100644 index 0000000000000000000000000000000000000000..c64959a75847c1ae105acfe0d942b04df2f567ab --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\345\274\240\347\247\221\345\274\272/\347\254\224\350\256\260/\347\254\254\344\272\214\345\244\251\347\254\224\350\256\260" @@ -0,0 +1,238 @@ +第1步:关中断(保护初始化原子性) +## +rt_hw_interrupt_disable(); // 关键一步! +## +防止硬件中断打断内核初始化(如调度器/定时器初始化),导致数据不一致。 + +何时恢复中断? +在 rt_system_scheduler_start() 启动调度器时自动恢复! + +第2步:硬件初始化 +(rt_hw_board_init()) + +// 必须在此函数内完成: + + +``` +void rt_hw_board_init() { + + 1. 初始化系统时钟、内存 + + 2. 初始化调试串口(如UART1) + + 3. 注册控制台设备:rt_console_set_device("uart1"); + + +} +``` + + + +重点:串口初始化必须在这里完成! + +第3步:双定时器系统初始化 + +定时器类型 初始化函数 运行位置 精度 用途 + +系统时钟 rt_system_timer_init() 硬件中断 微秒级 线程延时/时间片轮转 + + +软件定时器 rt_system_timer_thread_init() 线程 毫秒级 应用层定时任务 + + +硬件定时器中断示例: + + + +``` +void SysTick_Handler() { + rt_tick_increase(); // 每1ms触发一次(驱动OS心跳) +} + +``` + +第4步:调度器初始化(核心!) + + +``` + +rt_system_scheduler_init(); // 初始化就绪列表 +``` + +调度规则: +永远从就绪列表中选择优先级最高的线程运行! + +优先级数字越小越高(pri=0 最高) + +同优先级才用时间片轮转(需开启 RT_USING_RR) + +第5步:创建系统线程 + + +``` +// 1. 主线程(运行用户main函数) +rt_application_init() --> 创建 main_thread_entry + +// 2. 定时器线程(管理软件定时器) +rt_thread_init(rt_thread_timer_entry) + +// 3. 空闲线程(系统最低优先级) +rt_thread_idle_init() // 优先级31,永不休眠! +``` + +空闲线程特殊作用: + +执行低功耗睡眠(通过钩子函数) + +回收已删除线程的资源 + + + +``` +// 低功耗示例 +void idle_hook() { __WFI(); } // CPU睡眠 +rt_thread_idle_sethook(idle_hook); +``` + + + 第6步:启动调度器(引爆点!) + +``` + +rt_system_scheduler_start(); // 从此进入多线程世界! +``` + +此时: + +中断恢复 + +系统开始按优先级调度线程 + +CPU控制权交给最高优先级就绪线程(通常是 main 线程) +``` +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-11-06 SummerGift first version + * 2018-11-19 flybreak add stm32f407-atk-explorer bsp + */ + +#include +#include +#include + +void usr_thread1(void){ + while(1){ + rt_kprintf("run in usr1 thread\r\n"); + rt_thread_delay(5); + + } +} +void usr_thread2(void){ + while(1){ + rt_kprintf("run in usr2 thread\r\n"); + rt_thread_delay(5); + + } +} +rt_thread_t tid1 = RT_NULL; +rt_thread_t tid2 = RT_NULL; +int main(void) +{ + tid1 = rt_thread_create("usr1", usr_thread1, RT_NULL, 1024, 2, 5); + + if (tid1 != RT_NULL){ + rt_thread_startup(tid1); + } + + tid2 = rt_thread_create("usr2", usr_thread2, RT_NULL, 1024, 2, 5); + + if (tid2 != RT_NULL){ + rt_thread_startup(tid2); + } + rt_kprintf("run in main thread\r\n"); + return RT_EOK; +} + +``` + +## ai解释 + +1. **初始状态** _(Initial State)_ +比喻:你刚入职一家公司,填完入职表,但还没被分配到具体的部门或工作。 + +说明:线程被创建但尚未激活,就像你还没开始正式工作。 + +2. **就绪状态** _(Ready State)_ + +比喻:你被分配到了部门,坐在工位上,随时等待领导给你安排任务。 + +说明:线程已经准备好执行,等待 CPU 调度,就像你在工位上等活儿干。 + +3. **运行状态** _(Running State)_ + +比喻:领导给你安排了任务,你正在执行任务(比如写报告、开会)。 + +说明:线程正在占用 CPU 执行代码,就像你正在干活。 + +4. **挂起状态** _(Suspended State)_ + +比喻: + +你在写报告时,突然被领导叫去开会(被迫暂停)。 + +或者你主动休息一下(比如喝咖啡、回邮件)。 + +说明:线程暂时停止执行,等待被唤醒,就像你暂时停下手中的活。 + +5. **关闭状态** _(Closed State)_ + +比喻:你完成了所有任务,或者被公司解雇,离开了公司。 + +说明:线程执行完毕或被删除,资源被释放,就像你不再为公司工作。 + +状态转换的比喻 + + **初始 → 就绪** : + +你入职后被分配到部门(rt_thread_startup())。 + + **就绪 → 运行** : + +领导给你安排任务(调度器调度)。 + +**运行 → 挂起** : + +你被临时叫走(rt_thread_delay()、rt_sem_take() 等)。 + +你主动休息(rt_thread_suspend())。 + + **挂起 → 就绪** : + +会议结束,你回到工位(rt_thread_resume()、rt_sem_release() 等)。 + + **运行 → 关闭** : + +你完成任务离职(rt_thread_exit())。 + + **挂起 → 关闭** : + +你被解雇(rt_thread_delete() 或 rt_thread_detach())。 + + **就绪 → 挂起** + +比喻:你坐在工位上(就绪状态),突然收到一封紧急邮件需要处理,你放下手头的工作去处理邮件(挂起状态)。 + +说明:线程在就绪状态时,被外部事件(如信号量、消息队列等)触发,主动进入挂起状态,等待事件处理完毕后再恢复。 + + + ** + 运行 → 就绪** + +比喻:你正在写报告(运行状态),突然领导说 “先停一下,等会儿再继续”,你停下手中的工作,回到工位等待下一步指示(就绪状态)。 + +说明:线程在运行状态时,时间片用完或被更高优先级的线程抢占,回到就绪状态等待下一次调度。