diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000000000000000000000000000000000000..f245504a5ca15e17e7a277924a3b1743130cd283 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "windows-gcc-x64", + "includePath": [ + "${workspaceFolder}/**" + ], + "compilerPath": "D:/Workstudio/Tools/Mingw/mingw64/bin/gcc.exe", + "cStandard": "${default}", + "cppStandard": "${default}", + "intelliSenseMode": "windows-gcc-x64", + "compilerArgs": [ + "" + ] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000000000000000000000000000000000..34f8c5b2161263428ab65a06e040e33a7d6d14be --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "externalConsole": true, + "cwd": "d:/Workstudio/Project/RTTRTOS/rsoc-rtt/2025/第5组(CanMV-K230)/马锡尧/作业/day2", + "program": "d:/Workstudio/Project/RTTRTOS/rsoc-rtt/2025/第5组(CanMV-K230)/马锡尧/作业/day2/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..bb879da5a0774e5e3a4e5e90dba7a0770370c0f7 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,59 @@ +{ + "C_Cpp_Runner.cCompilerPath": "gcc", + "C_Cpp_Runner.cppCompilerPath": "g++", + "C_Cpp_Runner.debuggerPath": "gdb", + "C_Cpp_Runner.cStandard": "", + "C_Cpp_Runner.cppStandard": "", + "C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat", + "C_Cpp_Runner.useMsvc": false, + "C_Cpp_Runner.warnings": [ + "-Wall", + "-Wextra", + "-Wpedantic", + "-Wshadow", + "-Wformat=2", + "-Wcast-align", + "-Wconversion", + "-Wsign-conversion", + "-Wnull-dereference" + ], + "C_Cpp_Runner.msvcWarnings": [ + "/W4", + "/permissive-", + "/w14242", + "/w14287", + "/w14296", + "/w14311", + "/w14826", + "/w44062", + "/w44242", + "/w14905", + "/w14906", + "/w14263", + "/w44265", + "/w14928" + ], + "C_Cpp_Runner.enableWarnings": true, + "C_Cpp_Runner.warningsAsError": false, + "C_Cpp_Runner.compilerArgs": [], + "C_Cpp_Runner.linkerArgs": [], + "C_Cpp_Runner.includePaths": [], + "C_Cpp_Runner.includeSearch": [ + "*", + "**/*" + ], + "C_Cpp_Runner.excludeSearch": [ + "**/build", + "**/build/**", + "**/.*", + "**/.*/**", + "**/.vscode", + "**/.vscode/**" + ], + "C_Cpp_Runner.useAddressSanitizer": false, + "C_Cpp_Runner.useUndefinedSanitizer": false, + "C_Cpp_Runner.useLeakSanitizer": false, + "C_Cpp_Runner.showCompilationTime": false, + "C_Cpp_Runner.useLinkTimeOptimization": false, + "C_Cpp_Runner.msvcSecureNoWarnings": false +} \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/\347\254\254\344\270\200\345\244\251\344\275\234\344\270\232.md" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day1/readme.md" similarity index 100% rename from "2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/\347\254\254\344\270\200\345\244\251\344\275\234\344\270\232.md" rename to "2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day1/readme.md" diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day2/images/readme/1753184948639.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day2/images/readme/1753184948639.png" new file mode 100644 index 0000000000000000000000000000000000000000..61cb25a9024bc7e71ba80606ff51dff0e070933c Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day2/images/readme/1753184948639.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day2/mian.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day2/mian.c" new file mode 100644 index 0000000000000000000000000000000000000000..8037212150a8b505546f34dfc2f4a427b8b7e49c --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day2/mian.c" @@ -0,0 +1,85 @@ +#include +#include +#include + +// 线程控制块指针声明 +rt_thread_t thread1 = RT_NULL; +rt_thread_t thread2 = RT_NULL; +rt_thread_t thread3 = RT_NULL; + +/** + * 线程1入口函数 + * 功能:循环打印"thread1 run",并在特定计数时延时 + */ +void _thread1(void) +{ + int i = 0; // 计数变量,用于控制延时时机 + + while(1) // 线程主循环,持续运行 + { + rt_kprintf("thread1 run\n"); // 打印线程1运行信息 + + // 当计数达到10、100、1000、10000时执行延时(原代码此处i=10000为笔误,保持原样) + if(i == 10 || i == 100 || i == 1000 || i=10000) + { + rt_thread_mdelay(1000); // 延时1000ms,便于观察输出结果 + } + + i++; // 计数自增 + } +} + +/** + * 线程2入口函数 + * 功能:循环打印"thread2 run" + */ +void _thread2(void) +{ + while(1) // 线程主循环,持续运行 + { + rt_kprintf("thread2 run \n"); // 打印线程2运行信息 + } +} + +/** + * 线程3入口函数 + * 功能:循环打印"thread3 run" + */ +void _thread3(void) +{ + while(1) // 线程主循环,持续运行 + { + rt_kprintf("thread3 run \n"); // 打印线程3运行信息 + } +} + +/** + * 主函数 + * 功能:创建并启动三个线程,打印主函数运行信息 + */ +int main(void) +{ + // 创建线程1:名称"thread1",入口函数_thread1,无参数,栈大小1024,优先级9,时间片5 + thread1 = rt_thread_create("thread1", _thread1, RT_NULL, 1024, 9, 5); + // 创建线程2:名称"thread2",入口函数_thread2,无参数,栈大小1024,优先级11,时间片5 + thread2 = rt_thread_create("thread2", _thread2, RT_NULL, 1024, 11, 5); + // 创建线程3:名称"thread3",入口函数_thread3,无参数,栈大小1024,优先级11,时间片5 + thread3 = rt_thread_create("thread3", _thread3, RT_NULL, 1024, 11, 5); + + // 若线程1创建成功,则启动线程1 + if(thread1 != RT_NULL) + { + rt_thread_startup(thread1); + } + + // 若线程2和线程3均创建成功,则启动这两个线程 + if(thread2 != RT_NULL && thread3 != RT_NULL) + { + rt_thread_startup(thread2); + rt_thread_startup(thread3); + } + + rt_kprintf("main run conut \n"); // 打印主函数运行信息 + + return 0; // 主函数返回(RT-Thread中主函数退出后仍会运行线程) +} diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day2/readme.md" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day2/readme.md" new file mode 100644 index 0000000000000000000000000000000000000000..b63a7b38fd1635e67a48be53ddd2f5a5da0e0e8a --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day2/readme.md" @@ -0,0 +1,79 @@ +# day2 :homework + + +今日作业: +1.在论坛发文章描述对今天内容的总结与收获 +2.编写代码上传至git仓库,创建至少3个线程,能体现抢占与时间片轮转,在今天的工程的mian.c中实现,其他同学拿到该文件可以直接运行。 + +自行研究: +1.ARM函数调用规范 + +代码图解: + +![1753184948639](images/readme/1753184948639.png) + + +``` +#include +#include +#include + + +rt_thread_t thread1 =RT_NULL; +void _thread1(void) +{ + int i =0; + + while(1) { + + rt_kprintf("thread1 run\n"); + + + if(i == 10 || i == 100 || i == 1000||i=10000) { //防止太快根本看不清结果 + rt_thread_mdelay(1000); // 延时1000ms + } + + i++; +} +} + +rt_thread_t thread2 =RT_NULL; +void _thread2(void) +{ + + while(1){ + rt_kprintf("thread2 run \n"); + } +} + +rt_thread_t thread3 =RT_NULL; +void _thread3(void) +{ + + + while(1){ + rt_kprintf("thread3 run \n"); + } +} +int main(void) +{ + + thread1 = rt_thread_create("thread1", _thread1, RT_NULL, 1024, 9, 5); + thread2 = rt_thread_create("thread2", _thread2, RT_NULL, 1024, 11, 5); + thread3 = rt_thread_create("thread3", _thread3, RT_NULL, 1024, 11, 5); + if(thread1 != RT_NULL) + { + rt_thread_startup(thread1); + + } + if(thread2 != RT_NULL||thread3 != RT_NULL) + { + + rt_thread_startup(thread2); + rt_thread_startup(thread3); + } + rt_kprintf("main run conut \n"); +} + + +``` diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC1/event_demo.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC1/event_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..d0aeaa41e394bd800057fb2fcab61becebfb84be --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC1/event_demo.c" @@ -0,0 +1,74 @@ +#include + +#define THREAD_PRIORITY 15 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +/* 定义事件标志 */ +#define EVENT_A (1 << 0) // 事件A +#define EVENT_B (1 << 1) // 事件B + +static struct rt_event event; + +/* 事件等待线程 */ +static void event_wait_thread(void *param) +{ + rt_uint32_t recv_events; + + /* 第一次等待:事件A或事件B(任意一个发生) */ + rt_event_recv(&event, EVENT_A | EVENT_B, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + RT_WAITING_FOREVER, &recv_events); + rt_kprintf("Wait 1: Received events 0x%x\n", recv_events); + + /* 第二次等待:事件A和事件B(同时发生) */ + rt_event_recv(&event, EVENT_A | EVENT_B, + RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, + RT_WAITING_FOREVER, &recv_events); + rt_kprintf("Wait 2: Received events 0x%x\n", recv_events); + + rt_kprintf("Event wait thread exit\n"); +} + +/* 事件发送线程 */ +static void event_send_thread(void *param) +{ + rt_thread_mdelay(500); + rt_kprintf("Send event A\n"); + rt_event_send(&event, EVENT_A); + + rt_thread_mdelay(500); + rt_kprintf("Send event B\n"); + rt_event_send(&event, EVENT_B); + + rt_thread_mdelay(500); + rt_kprintf("Send event A again\n"); + rt_event_send(&event, EVENT_A); + + rt_thread_mdelay(500); + rt_kprintf("Send event B again\n"); + rt_event_send(&event, EVENT_B); // 此时A和B同时存在,触发第二次等待 +} + +int event_demo(void) +{ + /* 初始化事件 */ + rt_event_init(&event, "event_demo", RT_IPC_FLAG_PRIO); + + /* 创建等待线程 */ + rt_thread_t tid1 = rt_thread_create("event_wait", + event_wait_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (tid1) rt_thread_startup(tid1); + + /* 创建发送线程 */ + rt_thread_t tid2 = rt_thread_create("event_send", + event_send_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid2) rt_thread_startup(tid2); + + return 0; +} +MSH_CMD_EXPORT(event_demo, event demo); \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC1/mutex_demo.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC1/mutex_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..c35e99083cf070d49c8912d6c772bf9ce30e7cc5 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC1/mutex_demo.c" @@ -0,0 +1,69 @@ +#include + +#define THREAD_PRIORITY 20 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_mutex_t mutex = RT_NULL; +static rt_int32_t shared_var = 0; // 共享变量 + +/* 线程1:对共享变量加1 */ +static void thread1_entry(void *param) +{ + while (1) + { + rt_mutex_take(mutex, RT_WAITING_FOREVER); + shared_var++; + rt_kprintf("Thread1: shared_var = %d\n", shared_var); + rt_thread_mdelay(100); // 模拟耗时操作 + rt_mutex_release(mutex); + rt_thread_mdelay(100); + } +} + +/* 线程2:对共享变量加1并检查一致性 */ +static void thread2_entry(void *param) +{ + rt_int32_t last_val = 0; + while (1) + { + rt_mutex_take(mutex, RT_WAITING_FOREVER); + shared_var++; + if (shared_var != last_val + 2) // 检查是否连续递增 + { + rt_kprintf("Thread2: Data race detected! shared_var = %d\n", shared_var); + } + last_val = shared_var; + rt_kprintf("Thread2: shared_var = %d\n", shared_var); + rt_mutex_release(mutex); + rt_thread_mdelay(100); + } +} + +int mutex_demo(void) +{ + /* 创建互斥量 */ + mutex = rt_mutex_create("mutex_demo", RT_IPC_FLAG_PRIO); + if (mutex == RT_NULL) + { + rt_kprintf("Create mutex failed!\n"); + return -1; + } + + /* 创建线程1 */ + rt_thread_t tid1 = rt_thread_create("thread1", + thread1_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1) rt_thread_startup(tid1); + + /* 创建线程2 */ + rt_thread_t tid2 = rt_thread_create("thread2", + thread2_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid2) rt_thread_startup(tid2); + + return 0; +} +MSH_CMD_EXPORT(mutex_demo, mutex demo); \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC1/semaphore_demo.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC1/semaphore_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..7a407cd9d52b7bab29992bf47ac0d73232142670 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC1/semaphore_demo.c" @@ -0,0 +1,69 @@ +#include + +#define THREAD_PRIORITY 25 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_sem_t sem = RT_NULL; +static rt_uint32_t product_count = 0; + +/* 生产者线程 */ +static void producer_thread(void *param) +{ + while (1) + { + product_count++; + rt_kprintf("Produced: %d\n", product_count); + + /* 每生产10个产品,释放一次信号量 */ + if (product_count % 10 == 0) + { + rt_kprintf("Producer: release semaphore\n"); + rt_sem_release(sem); + } + rt_thread_mdelay(100); + } +} + +/* 消费者线程 */ +static void consumer_thread(void *param) +{ + rt_uint32_t consumed = 0; + while (1) + { + /* 等待信号量(永久等待) */ + if (rt_sem_take(sem, RT_WAITING_FOREVER) == RT_EOK) + { + consumed += 10; + rt_kprintf("Consumer: consumed %d products\n", consumed); + } + } +} + +int semaphore_demo(void) +{ + /* 创建信号量,初始值为0 */ + sem = rt_sem_create("sem_demo", 0, RT_IPC_FLAG_PRIO); + if (sem == RT_NULL) + { + rt_kprintf("Create semaphore failed!\n"); + return -1; + } + + /* 创建生产者线程 */ + rt_thread_t producer = rt_thread_create("producer", + producer_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (producer) rt_thread_startup(producer); + + /* 创建消费者线程 */ + rt_thread_t consumer = rt_thread_create("consumer", + consumer_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (consumer) rt_thread_startup(consumer); + + return 0; +} +MSH_CMD_EXPORT(semaphore_demo, semaphore demo); \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC2/mailbox_demo.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC2/mailbox_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..edff8502f107ae4ca8dd0205b2614f7ea89d3b64 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC2/mailbox_demo.c" @@ -0,0 +1,76 @@ +#include + +#define THREAD_PRIORITY 10 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +/* 邮箱控制块和内存池 */ +static struct rt_mailbox mb; +static char mb_pool[64]; // 邮箱内存池(存放指针) + +/* 邮件内容 */ +static char msg1[] = "Hello, Mailbox!"; +static char msg2[] = "RT-Thread IPC"; +static char msg3[] = "Exit"; + +/* 接收邮件线程 */ +static void recv_mail_thread(void *param) +{ + char *msg; + while (1) + { + rt_kprintf("Waiting for mail...\n"); + /* 接收邮件(永久等待) */ + if (rt_mb_recv(&mb, (rt_ubase_t *)&msg, RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("Received: %s\n", msg); + if (msg == msg3) // 收到退出消息 + { + rt_kprintf("Exit recv thread\n"); + break; + } + } + } + rt_mb_detach(&mb); // 脱离邮箱 +} + +/* 发送邮件线程 */ +static void send_mail_thread(void *param) +{ + rt_mb_send(&mb, (rt_ubase_t)msg1); + rt_thread_mdelay(1000); + + rt_mb_send(&mb, (rt_ubase_t)msg2); + rt_thread_mdelay(1000); + + rt_mb_send(&mb, (rt_ubase_t)msg3); // 发送退出消息 +} + +int mailbox_demo(void) +{ + /* 初始化邮箱 */ + if (rt_mb_init(&mb, "mb_demo", + mb_pool, sizeof(mb_pool)/sizeof(rt_ubase_t), + RT_IPC_FLAG_PRIO) != RT_EOK) + { + rt_kprintf("Init mailbox failed!\n"); + return -1; + } + + /* 创建接收线程 */ + rt_thread_t tid1 = rt_thread_create("recv_mail", + recv_mail_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1) rt_thread_startup(tid1); + + /* 创建发送线程 */ + rt_thread_t tid2 = rt_thread_create("send_mail", + send_mail_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY + 1, THREAD_TIMESLICE); + if (tid2) rt_thread_startup(tid2); + + return 0; +} +MSH_CMD_EXPORT(mailbox_demo, mailbox demo); \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC2/msgqueue_demo.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC2/msgqueue_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..cc46c986c02d4f35946db0bb53cd1b656779cd64 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC2/msgqueue_demo.c" @@ -0,0 +1,78 @@ +#include + +#define THREAD_PRIORITY 20 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +/* 消息队列控制块和内存池 */ +static struct rt_messagequeue mq; +static char msg_pool[256]; // 消息队列内存池 + +/* 接收消息线程 */ +static void recv_msg_thread(void *param) +{ + char msg_buf; + rt_uint8_t count = 0; + + while (count < 5) + { + /* 接收消息(永久等待) */ + if (rt_mq_recv(&mq, &msg_buf, sizeof(msg_buf), RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("Received message: %c\n", msg_buf); + count++; + } + } + rt_mq_detach(&mq); // 脱离消息队列 +} + +/* 发送消息线程 */ +static void send_msg_thread(void *param) +{ + char msg = 'A'; + rt_thread_mdelay(500); + + /* 发送普通消息 */ + rt_mq_send(&mq, &msg, 1); + rt_kprintf("Sent: %c\n", msg); + msg++; + + /* 发送紧急消息(插入队列头部) */ + rt_mq_urgent(&mq, &msg, 1); + rt_kprintf("Sent urgent: %c\n", msg); + msg++; + + /* 继续发送普通消息 */ + rt_mq_send(&mq, &msg, 1); + rt_kprintf("Sent: %c\n", msg); +} + +int msgqueue_demo(void) +{ + /* 初始化消息队列 */ + if (rt_mq_init(&mq, "mq_demo", + msg_pool, 1, // 每个消息1字节 + sizeof(msg_pool), + RT_IPC_FLAG_PRIO) != RT_EOK) + { + rt_kprintf("Init msgqueue failed!\n"); + return -1; + } + + /* 创建接收线程 */ + rt_thread_t tid1 = rt_thread_create("recv_msg", + recv_msg_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1) rt_thread_startup(tid1); + + /* 创建发送线程 */ + rt_thread_t tid2 = rt_thread_create("send_msg", + send_msg_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY + 1, THREAD_TIMESLICE); + if (tid2) rt_thread_startup(tid2); + + return 0; +} +MSH_CMD_EXPORT(msgqueue_demo, message queue demo); \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC2/signal_demo.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC2/signal_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..ddd003af463832103f8d70db3dc49917a79ac677 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/IPC2/signal_demo.c" @@ -0,0 +1,51 @@ +#include + +#define THREAD_PRIORITY 25 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_thread_t tid = RT_NULL; + +/* 信号处理函数 */ +void signal_handler(int sig) +{ + rt_kprintf("Received signal: %d, handling...\n", sig); + /* 信号处理逻辑:例如清理资源 */ +} + +/* 线程入口:等待信号 */ +static void signal_thread(void *param) +{ + /* 安装信号处理函数 */ + rt_signal_install(SIGUSR1, signal_handler); + rt_signal_unmask(SIGUSR1); // 解除信号屏蔽 + + rt_kprintf("Signal thread running, wait for signal...\n"); + while (1) + { + rt_thread_mdelay(500); // 线程正常运行逻辑 + } +} + +int signal_demo(void) +{ + /* 创建线程 */ + tid = rt_thread_create("signal_thread", + signal_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid) rt_thread_startup(tid); + + /* 延迟1秒后发送信号 */ + rt_thread_mdelay(1000); + rt_kprintf("Sending SIGUSR1 to thread...\n"); + rt_thread_kill(tid, SIGUSR1); // 发送信号 + + /* 再延迟1秒后发送第二次信号 */ + rt_thread_mdelay(1000); + rt_kprintf("Sending SIGUSR1 again...\n"); + rt_thread_kill(tid, SIGUSR1); + + return 0; +} +MSH_CMD_EXPORT(signal_demo, signal demo); \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274092708.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274092708.png" new file mode 100644 index 0000000000000000000000000000000000000000..5f1eb07d1bb291552d8fa57e29ce193a8b5a747a Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274092708.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274220908.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274220908.png" new file mode 100644 index 0000000000000000000000000000000000000000..7ea05bc9a70562b5fc76963ea76bae0caf718bef Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274220908.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274335229.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274335229.png" new file mode 100644 index 0000000000000000000000000000000000000000..8ced3798eea00c1d441a35bf08bea716fec497d4 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274335229.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274466555.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274466555.png" new file mode 100644 index 0000000000000000000000000000000000000000..22efc44819101ab341070eef651911ca267e3267 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274466555.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274796350.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274796350.png" new file mode 100644 index 0000000000000000000000000000000000000000..e84a156f4e761184a142f582e97d3be692a3bcaf Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753274796350.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275087433.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275087433.png" new file mode 100644 index 0000000000000000000000000000000000000000..0126dfd683036e70ac5271fc31f36ad4decce993 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275087433.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275282059.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275282059.png" new file mode 100644 index 0000000000000000000000000000000000000000..e73c3293d48a7ec33df93544108cb7dcb7b02d56 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275282059.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275443413.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275443413.png" new file mode 100644 index 0000000000000000000000000000000000000000..6937c746f2527917cc3092b5773e55b90c959348 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275443413.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275529048.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275529048.png" new file mode 100644 index 0000000000000000000000000000000000000000..511ba803c09863a1d2a5751d642019c26d23369e Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275529048.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275621637.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275621637.png" new file mode 100644 index 0000000000000000000000000000000000000000..acefdddb595856f71ed47c06e9f5511ec32f196f Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/images/readme/1753275621637.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/readme.md" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/readme.md" new file mode 100644 index 0000000000000000000000000000000000000000..ed977952b6896f5046af8aa8df423d71f06eba05 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day3/readme.md" @@ -0,0 +1,86 @@ +# 作业说明 + +要求:编写代码上传至git仓库,程序需要体现出信号量、互斥量、事件集、邮箱、消息队列、信号的作用(上传6个C文件,每个文件体现一种功能)。 + +## 1.工程编译和运行 + +前面我们学习过利用scons的构建脚本将代码纳入编译路径,今天我们用RT-thread工程测试和验证我们的代码 + +首先进入之前的工程将applications目录下打开然后右键选择在资源管理器中打开。 + +![1753274092708](images/readme/1753274092708.png) + +进入之后创建IPC_demo目录将IPC1和IPC2目录拷贝过去 + +![1753274220908](images/readme/1753274220908.png) + +然后回到RT-studio工具点击左上角小锤子:构建配置->C++常规->路径和符号->源代码->添加文件夹,然后将我们刚刚添加的IPC1和IPC2目录添加进去。 + +![1753274335229](images/readme/1753274335229.png) + +然后应用并关闭,可以看到我们之前添加的目录和文件已经被纳入编译路径了。 + +![1753274466555](images/readme/1753274466555.png) + +然后编译并运行,在控制台输入`semaphore_demo`回车查看运行结果如下 + +``` + \ | / +- RT - Thread Operating System + / | \ 4.1.0 build Jul 23 2025 20:28:35 + 2006 - 2022 Copyright by RT-Thread team +main run conut +msh >semaphore_demo +msh >Produced: 1 +Produced: 2 +Produced: 3 +Produced: 4 +Produced: 5 +Produced: 6 +Produced: 7 +Produced: 8 +Produced: 9 +Produced: 10 +Producer: release semaphore +Consumer: consumed 10 products +Produced: 11 +``` + +## 2.运行结果展示 + + +### 2.1 信号量示例(semaphore\_demo.c) + +**功能**:实现生产者 - 消费者模型,生产者每生产 10 个产品后释放信号量,消费者等待信号量后消费产品。 + +![1753274796350](images/readme/1753274796350.png) + +### 2.2 互斥量示例(mutex\_demo.c) + +**功能**:保护共享变量,确保两个线程对共享变量的操作不会出现数据不一致。 + +![1753275087433](images/readme/1753275087433.png) + +### 2.3 事件集示例(event\_demo.c) + +**功能**:线程 1 等待特定事件组合(或 / 与逻辑),线程 2 发送事件触发线程 1。 + +![1753275282059](images/readme/1753275282059.png) + +### 2.4 邮箱示例(mailbox\_demo.c) + +**功能**:通过邮箱传递字符串指针,实现线程间消息传递。 + +![1753275443413](images/readme/1753275443413.png) + +### 2.5 消息队列示例(msgqueue\_demo.c) + +**功能**:线程 2 发送普通消息和紧急消息,线程 1 接收消息并处理(紧急消息优先)。 + +![1753275529048](images/readme/1753275529048.png) + +### 2.6 信号示例(signal\_demo.c) + +**功能**:线程 1 注册信号处理函数,主线程发送信号触发处理函数。 + +![1753275621637](images/readme/1753275621637.png) diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/drv_vir_sensor/drv_vir_sensor.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/drv_vir_sensor/drv_vir_sensor.c" new file mode 100644 index 0000000000000000000000000000000000000000..bf4b12f394e079e09c56d7d4e5cc12c9fa2501cc --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/drv_vir_sensor/drv_vir_sensor.c" @@ -0,0 +1,52 @@ +#include +#include "drv_vir_sensor.h" + + + + +// 定义传感器实例 +struct vir_sensor_dev vir_sensor; + +// 打印传感器信息 +void vir_sensor_print_info(struct rt_device *device, rt_uint8_t *str) +{ + rt_kprintf("vir_sensor info: %s\n", str); +} + +// 设置传感器数据 +void vir_sensor_set_data(struct rt_device *device, rt_uint32_t data) +{ + struct vir_sensor_dev *sensor = (struct vir_sensor_dev *)device; + sensor->sensor_data = data; + rt_kprintf("vir_sensor set data: %d\n", data); +} + +// 获取传感器数据 +void vir_sensor_get_data(struct rt_device *device, rt_uint32_t *data) +{ + struct vir_sensor_dev *sensor = (struct vir_sensor_dev *)device; + *data = sensor->sensor_data; +} + +// 传感器操作函数集 +static struct rt_vir_sensor_ops vir_sensor_ops = { + vir_sensor_print_info, + vir_sensor_set_data, + vir_sensor_get_data, +}; + +// 传感器初始化 +static int rt_hw_vir_sensor_init(void) +{ + // 初始化设备数据 + vir_sensor.sensor_data = 0; + vir_sensor.info = "Virtual Sensor (Temperature/Humidity)"; + + // 注册传感器设备 + rt_hw_vir_sensor_register(&vir_sensor.parent, "vir_sensor", &vir_sensor_ops, (void*)vir_sensor.info); + return RT_EOK; +} + +INIT_DEVICE_EXPORT(rt_hw_vir_sensor_init); // 设备初始化导出 + + diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/drv_vir_sensor/drv_vir_sensor.h" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/drv_vir_sensor/drv_vir_sensor.h" new file mode 100644 index 0000000000000000000000000000000000000000..f8097c56dccbb79d0377536b6042551a2f97b625 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/drv_vir_sensor/drv_vir_sensor.h" @@ -0,0 +1,15 @@ +#ifndef __DRV_VIR_SENSOR_H__ +#define __DRV_VIR_SENSOR_H__ + +#include +#include "../vir_sensor/vir_sensor.h" + +// 具体虚拟传感器设备结构体 +struct vir_sensor_dev +{ + struct rt_vir_sensor_device parent; // 继承虚拟传感器设备基类 + rt_uint32_t sensor_data; // 传感器数据存储 + char *info; // 设备描述信息 +}; + +#endif diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/images/readme/1753363156448.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/images/readme/1753363156448.png" new file mode 100644 index 0000000000000000000000000000000000000000..9bcf953762aa6a3982cc328f71232bd82ffca94c Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/images/readme/1753363156448.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/images/readme/1753364902108.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/images/readme/1753364902108.png" new file mode 100644 index 0000000000000000000000000000000000000000..d2014c53cca2cebaa1077f0639d4d67f6fc8d9af Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/images/readme/1753364902108.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/images/readme/1753364921066.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/images/readme/1753364921066.png" new file mode 100644 index 0000000000000000000000000000000000000000..857a860353897f387a7dab259a7a2fc245ebe48f Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/images/readme/1753364921066.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/readme.md" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/readme.md" new file mode 100644 index 0000000000000000000000000000000000000000..c7866435c939a17f4ba5ec02dc429a6f2e640247 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/readme.md" @@ -0,0 +1,29 @@ +打开RT-studio工具我们之前的RSOC工程,在applications目录下新建DRIVE_demo目录如下 + +![1753363156448](images/readme/1753363156448.png) + +点击构建,构建成功如下图 + +![1753364902108](images/readme/1753364902108.png) + +编译运行,输入vir_sensor_test回车 + +![1753364921066](images/readme/1753364921066.png) + + +``` + \ | / +- RT - Thread Operating System + / | \ 4.1.0 build Jul 24 2025 20:41:59 + 2006 - 2022 Copyright by RT-Thread team +main run conut +msh >vir_sensor_test +vir_sensor init +vir_sensor open +vir_sensor set data: 255 +device read: 255 +vir_sensor set data: 600 +special api read: 600 +vir_sensor close +msh > +``` diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/vir_sensor/vir_sensor.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/vir_sensor/vir_sensor.c" new file mode 100644 index 0000000000000000000000000000000000000000..cb7c2a5b24f809b15b5c8ccb2c5213cd0d4ac4ea --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/vir_sensor/vir_sensor.c" @@ -0,0 +1,104 @@ +#include +#include +#include "vir_sensor.h" +#include + + +// 设备初始化 +static rt_err_t _vir_sensor_init(rt_device_t dev) +{ + rt_kprintf("vir_sensor init\n"); + return RT_EOK; +} + +// 设备打开 +static rt_err_t _vir_sensor_open(rt_device_t dev, rt_uint16_t oflag) +{ + rt_kprintf("vir_sensor open\n"); + return RT_EOK; +} + +// 设备关闭 +static rt_err_t _vir_sensor_close(rt_device_t dev) +{ + rt_kprintf("vir_sensor close\n"); + return RT_EOK; +} + +// 设备读操作 +static rt_size_t _vir_sensor_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + rt_vir_sensor_device_t sensor = (rt_vir_sensor_device_t)dev; + if (sensor->ops->get_data && buffer != RT_NULL && size >= sizeof(rt_uint32_t)) + { + sensor->ops->get_data(dev, (rt_uint32_t*)buffer); + return sizeof(rt_uint32_t); + } + return -RT_ERROR; +} + +// 设备写操作 +static rt_size_t _vir_sensor_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + rt_vir_sensor_device_t sensor = (rt_vir_sensor_device_t)dev; + if (sensor->ops->set_data && buffer != RT_NULL && size >= sizeof(rt_uint32_t)) + { + sensor->ops->set_data(dev, *(rt_uint32_t*)buffer); + return sizeof(rt_uint32_t); + } + return -RT_ERROR; +} + +// 设备控制 +static rt_err_t _vir_sensor_control(rt_device_t dev, int cmd, void *args) +{ + rt_kprintf("vir_sensor control cmd: %d\n", cmd); + return RT_EOK; +} + +// 传感器注册函数 +rt_err_t rt_hw_vir_sensor_register(rt_vir_sensor_device_t device, const char *name, + const struct rt_vir_sensor_ops *ops, const void *user_data) +{ + RT_ASSERT(device != RT_NULL && ops != RT_NULL); + rt_err_t result; + + device->ops = ops; + // 绑定设备操作函数 + device->parent.init = _vir_sensor_init; + device->parent.open = _vir_sensor_open; + device->parent.close = _vir_sensor_close; + device->parent.read = _vir_sensor_read; + device->parent.write = _vir_sensor_write; + device->parent.control = _vir_sensor_control; + + // 注册到RT-Thread设备框架 + result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); + return result; +} + +// 传感器读接口 +rt_err_t rt_vir_sensor_read(rt_vir_sensor_device_t device, rt_uint32_t *data) +{ + RT_ASSERT(device != RT_NULL && device->ops != RT_NULL && data != RT_NULL); + if (device->ops->get_data) + { + device->ops->get_data((rt_device_t)device, data); + return RT_EOK; + } + return -RT_ERROR; +} + +// 传感器写接口 +rt_err_t rt_vir_sensor_write(rt_vir_sensor_device_t device, rt_uint32_t data) +{ + RT_ASSERT(device != RT_NULL && device->ops != RT_NULL); + if (device->ops->set_data) + { + device->ops->set_data((rt_device_t)device, data); + return RT_EOK; + } + return -RT_ERROR; +} + + diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/vir_sensor/vir_sensor.h" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/vir_sensor/vir_sensor.h" new file mode 100644 index 0000000000000000000000000000000000000000..a6ff12f5dc299df51173bfe566f5ae03661db564 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/vir_sensor/vir_sensor.h" @@ -0,0 +1,29 @@ +#ifndef __VIR_SENSOR_H__ +#define __VIR_SENSOR_H__ + +#include +#include + +// 虚拟传感器操作函数集 +struct rt_vir_sensor_ops +{ + void (*print_info)(struct rt_device *device, rt_uint8_t *str); // 打印信息 + void (*set_data)(struct rt_device *device, rt_uint32_t data); // 设置传感器数据 + void (*get_data)(struct rt_device *device, rt_uint32_t *data); // 获取传感器数据 +}; + +// 虚拟传感器设备结构体 +struct rt_vir_sensor_device +{ + struct rt_device parent; // 继承RT-Thread设备基类 + const struct rt_vir_sensor_ops *ops; // 操作函数集 +}; +typedef struct rt_vir_sensor_device *rt_vir_sensor_device_t; + +// 注册及操作函数声明 +rt_err_t rt_hw_vir_sensor_register(rt_vir_sensor_device_t device, const char *name, + const struct rt_vir_sensor_ops *ops, const void *user_data); +rt_err_t rt_vir_sensor_read(rt_vir_sensor_device_t device, rt_uint32_t *data); +rt_err_t rt_vir_sensor_write(rt_vir_sensor_device_t device, rt_uint32_t data); + +#endif \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/vir_sensor_test.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/vir_sensor_test.c" new file mode 100644 index 0000000000000000000000000000000000000000..929a59bef0192c1431de84bca815c7b69c48a526 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day4/vir_sensor_test.c" @@ -0,0 +1,50 @@ +#include +#include +#include "vir_sensor/vir_sensor.h" +#include "drv_vir_sensor/drv_vir_sensor.h" + + +#define RT_USING_VIR_SENSOR 1 + +int vir_sensor_test(void) +{ + rt_device_t sensor_dev; + rt_uint32_t data, read_data; + rt_size_t ret; + + // 查找设备 + sensor_dev = rt_device_find("vir_sensor"); + if (sensor_dev == RT_NULL) + { + rt_kprintf("find vir_sensor device failed!\n"); + return -RT_ERROR; + } + + // 打开设备 + if (rt_device_open(sensor_dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) + { + rt_kprintf("open vir_sensor device failed!\n"); + return -RT_ERROR; + } + + // 写入数据(设备接口) + data = 255; // 示例数据(可表示25.5℃等) + ret = rt_device_write(sensor_dev, 0, &data, sizeof(data)); + if (ret != sizeof(data)) + rt_kprintf("write vir_sensor failed!\n"); + + // 读取数据(设备接口) + ret = rt_device_read(sensor_dev, 0, &read_data, sizeof(read_data)); + if (ret == sizeof(read_data)) + rt_kprintf("device read: %d\n", read_data); + + // 专用接口操作 + rt_vir_sensor_write((rt_vir_sensor_device_t)sensor_dev, 600); // 示例数据 + rt_vir_sensor_read((rt_vir_sensor_device_t)sensor_dev, &read_data); + rt_kprintf("special api read: %d\n", read_data); + + // 关闭设备 + rt_device_close(sensor_dev); + return RT_EOK; +} +MSH_CMD_EXPORT(vir_sensor_test, vir_sensor test command); // 导出为shell命令 diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/MQTT.md" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/MQTT.md" new file mode 100644 index 0000000000000000000000000000000000000000..36f4bf3a8828c5f064af85cce8bfa801ab798443 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/MQTT.md" @@ -0,0 +1,90 @@ +Day5作业:MQTT + +![1753434944991](images/MQTT/1753434944991.png) + +根据作业要求我们来查看以下源代码mqtt_test源代码 + +![1753435761949](images/MQTT/1753435761949.png) + +我们发现其中有两个函数其中绿色框是pub发布函数每四秒会调用一次用于像mqtt服务器上报数据,而红色框是sub订阅函数 会打印服务器下发的消息那么,现在我们需要做的工具就是将pub函数中的内容替换成JSON格式并加入我们想要的字段即可。 +添加如下代码并修改pub函数 + +``` +#ifndef PUB_NAME +#define PUB_NAME "XiyaoMa" +#endif +#ifndef PUB_STUDY +#define PUB_STUDY "keep up the good work" +#endif + + +//······· +//其余代码不变 +//······· + +static int mqtt_publish_handle1(mqtt_client_t *client) +{ + mqtt_message_t msg; + memset(&msg, 0, sizeof(msg)); + msg.qos = QOS0; +// 拼接修改后的JSON字符串(修正语法并调整键值对) +static const char *json_data = "{" \ + "\"name\": \"" PUB_NAME "\"," \ + "\"study\": \""PUB_STUDY "\"" +"}"; + // 赋值给msg.payload + msg.payload = (void *)json_data; + msg.payloadlen = strlen(json_data); + return mqtt_publish(client, KAWAII_MQTT_PUBTOPIC, &msg); +} + +``` + +![1753436918726](images/MQTT/1753436918726.png) + +然后编译先测试以下康康,是否正确。编译运行并打开MQTTX查看没有任何问题。 + +![1753437251330](images/MQTT/1753437251330.png) + +那么接下来我们就需要解决Kconfig语法配置name字段和study的字段问题啦,这里我们九二一把这个Kconfig配置放到driver目录下的Kconfig中也是可以的,因为我们只是用于实验,之研究语法所以不用刻意去设置,当然也可以参考我在上面讲到的操作将田间一个Kconfig文件然后将其纳入最外层Kconfig文件的搜索路径中,不过这里我想带大家尝试第三种就是直接修改我们下载的软件包中的Kconfig也可以让大家对软件包的开发有点感觉。 + +我们进入env工具的packegs目录下可以看到里面有一个Kconfig文件![1753437819390](images/MQTT/1753437819390.png) + +可以打开看一眼就只有语句,意思是将当前目录下的packegs目录下的Kconfig目录纳入搜索路径 + +![1753437896787](images/MQTT/1753437896787.png) + +进入packegs目录下可以看到里面还有一个Kconfig文件而当前目录下就是存放了我们之前所选择 的软件包的种类目录,那不用看也知道这个Kconfig是包含了不同中种类目录下的Kconfig文件,然后不同种类下的Kconfig文件又包含了具体软件包的Kconfig文件(俄罗斯套娃)那我们直接找到kawai_mqtt软件包的Kconfig文件打开。 + +![1753438404962](images/MQTT/1753438404962.png) + +在里面的使能test中添加如下代码然后保存 + +``` + config PUB_NAME + string "name" + default "xiaoming" + config PUB_STUDY + string "study" + default "Keep" +``` + +![1753438678985](images/MQTT/1753438678985.png) + +输入`menuconfig`打开配置界面找到mqtt软件包的配置发现我们添加的代码已经生效。 + +![1753439026038](images/MQTT/1753439026038.png) + +按后修改以以下这两个字段和我们上面宏定义相同 + +![1753439249021](images/MQTT/1753439249021.png) + +然后退出保存。到rtconfig.h中查看配置配置是否生效 + +![1753439354314](images/MQTT/1753439354314.png) + +然后编译运行,输入ka_mqtt启动,然后打开MQTTX查看运行结果和终端输出如下 + +![1753439709966](images/MQTT/1753439709966.png) + +![1753439818566](images/MQTT/1753439818566.png) diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753434944991.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753434944991.png" new file mode 100644 index 0000000000000000000000000000000000000000..93307a66bd64471868860086e836aa757188be18 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753434944991.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753435761949.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753435761949.png" new file mode 100644 index 0000000000000000000000000000000000000000..52ba88e3324d8207418e9755fe6b35344a5e995e Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753435761949.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753436918726.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753436918726.png" new file mode 100644 index 0000000000000000000000000000000000000000..437b994af95e4420af5563fb4d0c139f582659ec Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753436918726.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753437251330.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753437251330.png" new file mode 100644 index 0000000000000000000000000000000000000000..e85088756fd317986c9aa019d4d2fb6de9a2c6ac Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753437251330.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753437819390.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753437819390.png" new file mode 100644 index 0000000000000000000000000000000000000000..62a37d94f8990390c8c84ed043f35d7490cf4b13 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753437819390.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753437896787.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753437896787.png" new file mode 100644 index 0000000000000000000000000000000000000000..22165f40af887645d0bbd9578aa0f4277aa2a93f Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753437896787.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753438404962.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753438404962.png" new file mode 100644 index 0000000000000000000000000000000000000000..28663f25c703adfa9af2af0a7095d40dc2d56cf7 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753438404962.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753438678985.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753438678985.png" new file mode 100644 index 0000000000000000000000000000000000000000..2c86245df56c1c3b934a0031f76e0dfdb4be01a6 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753438678985.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439026038.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439026038.png" new file mode 100644 index 0000000000000000000000000000000000000000..23f45b97c671f0fd82e3a093e09cea28b813eae8 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439026038.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439249021.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439249021.png" new file mode 100644 index 0000000000000000000000000000000000000000..1ea59d601cba8591de2a8be566024eec9ee92a3e Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439249021.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439354314.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439354314.png" new file mode 100644 index 0000000000000000000000000000000000000000..78a6013d1736092ae553ff6976aa83361eb4d342 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439354314.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439709966.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439709966.png" new file mode 100644 index 0000000000000000000000000000000000000000..737a3c8116c96c27afc485043626dfe2c8735e3a Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439709966.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439818566.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439818566.png" new file mode 100644 index 0000000000000000000000000000000000000000..1641ad83b20d2b07dbf0c97969dbcc43efd90144 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\344\275\234\344\270\232/day5/images/MQTT/1753439818566.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753155683355.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753155683355.png" new file mode 100644 index 0000000000000000000000000000000000000000..3875334d6fa1f1c505f940db69d23c08213da3e8 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753155683355.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753155823461.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753155823461.png" new file mode 100644 index 0000000000000000000000000000000000000000..beb4a418aec57213f9ce44f7f7497564041a3aa1 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753155823461.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753155966120.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753155966120.png" new file mode 100644 index 0000000000000000000000000000000000000000..6ef45527da13b7bf6818f59bce32a6893dfb211f Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753155966120.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156125970.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156125970.png" new file mode 100644 index 0000000000000000000000000000000000000000..e3647310369a9e395ee7d5d0a5c240cbc2ed89f0 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156125970.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156351872.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156351872.png" new file mode 100644 index 0000000000000000000000000000000000000000..c885a243d0e6e73a3414b36604c426fba146a68e Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156351872.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156490789.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156490789.png" new file mode 100644 index 0000000000000000000000000000000000000000..12164b87cd14be92c982237b74f306d2bbed46ec Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156490789.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156632718.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156632718.png" new file mode 100644 index 0000000000000000000000000000000000000000..112d02d754d12df57d7a06a3f3edb4d16725a900 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156632718.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156706609.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156706609.png" new file mode 100644 index 0000000000000000000000000000000000000000..64f015d7ed89e15298d8a22427c18b136cfe6315 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156706609.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156829136.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156829136.png" new file mode 100644 index 0000000000000000000000000000000000000000..0e1cc01a83d5b96d923bd896ba9bc93fb609478d Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753156829136.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753157755057.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753157755057.png" new file mode 100644 index 0000000000000000000000000000000000000000..ace9d00fcac457cfc9d51c00f9217447b5b28308 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753157755057.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753158320939.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753158320939.png" new file mode 100644 index 0000000000000000000000000000000000000000..b863a7fa766ec6d21f97bec2087c6875ae7f0a76 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753158320939.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753158740464.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753158740464.png" new file mode 100644 index 0000000000000000000000000000000000000000..b59097fa3c16596ff374a041acb13de58b919b22 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753158740464.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753176072844.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753176072844.png" new file mode 100644 index 0000000000000000000000000000000000000000..02814cd4bb437f15b19c9b1cbe0eada06282a809 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753176072844.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753178489017.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753178489017.png" new file mode 100644 index 0000000000000000000000000000000000000000..cddd5ed3da5c97bf0efdf0f8222f6251c83a0012 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753178489017.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753178806755.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753178806755.png" new file mode 100644 index 0000000000000000000000000000000000000000..143253ba66d3ca7556fb52546be7db626c2cd2e2 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753178806755.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179024941.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179024941.png" new file mode 100644 index 0000000000000000000000000000000000000000..71827fb65616cb43cc2592d2a43cbcc6222aea05 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179024941.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179061231.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179061231.png" new file mode 100644 index 0000000000000000000000000000000000000000..daec767d1011429503fd0cb9895b26fa67336186 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179061231.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179200663.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179200663.png" new file mode 100644 index 0000000000000000000000000000000000000000..17700a4960242a4a874d6c3fa8a186829ba46de7 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179200663.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179446661.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179446661.png" new file mode 100644 index 0000000000000000000000000000000000000000..0b3346a26ab1fcb8feab442b1e9f358543e2501c Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179446661.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179663732.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179663732.png" new file mode 100644 index 0000000000000000000000000000000000000000..7345fc0ddd8339f25320212ab8d7605a5b8bc86e Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179663732.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179997633.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179997633.png" new file mode 100644 index 0000000000000000000000000000000000000000..ead49e7af6267eab0b508f3b29afffb6fcad0679 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753179997633.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753180187070.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753180187070.png" new file mode 100644 index 0000000000000000000000000000000000000000..9d2523ebcd2122bcc597f699bc672976508bc0cc Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753180187070.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753181531962.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753181531962.png" new file mode 100644 index 0000000000000000000000000000000000000000..216c0b32f3845c1dd0bf220076703c7b40bd8ea3 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753181531962.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753182120380.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753182120380.png" new file mode 100644 index 0000000000000000000000000000000000000000..e4b851e69aa0a51e35d4c39813ea3b6d974bcb23 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753182120380.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753185070376.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753185070376.png" new file mode 100644 index 0000000000000000000000000000000000000000..61cb25a9024bc7e71ba80606ff51dff0e070933c Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day2\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250/1753185070376.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753253733110.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753253733110.png" new file mode 100644 index 0000000000000000000000000000000000000000..78d6d3774be534cdeddbdacae223c79ff683a8b8 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753253733110.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753253856146.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753253856146.png" new file mode 100644 index 0000000000000000000000000000000000000000..9b8a71ba093799955455f5bb2b73fa905d85dba4 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753253856146.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753254441739.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753254441739.png" new file mode 100644 index 0000000000000000000000000000000000000000..ee0b6c2869214c2042769cf87593b11c6687b19a Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753254441739.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753256363664.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753256363664.png" new file mode 100644 index 0000000000000000000000000000000000000000..5a2e8bada6390d66b727eb493a1746302b2515b3 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753256363664.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753256492146.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753256492146.png" new file mode 100644 index 0000000000000000000000000000000000000000..547434239ef0bcb932d04337ee2fa05d9ec1748a Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753256492146.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753257508246.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753257508246.png" new file mode 100644 index 0000000000000000000000000000000000000000..74888dbb2eebc1f96fb8528041ee6aa24f1d2726 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753257508246.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753260901700.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753260901700.png" new file mode 100644 index 0000000000000000000000000000000000000000..35f28d5dbe6b2559b8ff4c38447cbff10c99a8b3 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753260901700.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753262204665.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753262204665.png" new file mode 100644 index 0000000000000000000000000000000000000000..cb78659bfef94b40ee79d887cecad1f15789b532 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753262204665.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753262686072.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753262686072.png" new file mode 100644 index 0000000000000000000000000000000000000000..4eb8053bd4501b53f82f30d5c0fe785169a3fdd7 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753262686072.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753263093267.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753263093267.png" new file mode 100644 index 0000000000000000000000000000000000000000..5cee37ad4eaf83c647aa00c18caf1dcd4e40666d Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753263093267.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753263472313.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753263472313.png" new file mode 100644 index 0000000000000000000000000000000000000000..3bd3b7715e393d401783d0fe73ff9b689c7ffc67 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753263472313.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753263606087.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753263606087.png" new file mode 100644 index 0000000000000000000000000000000000000000..b268c3c16788e78231176dda0dbc53b648672598 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753263606087.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753264589379.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753264589379.png" new file mode 100644 index 0000000000000000000000000000000000000000..6807d4c8d8d8661e4821131e2bd06d81a2234877 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753264589379.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753265395259.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753265395259.png" new file mode 100644 index 0000000000000000000000000000000000000000..2c19237b7c7175731bd97285a58bfef26a5e09dc Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day3\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257/1753265395259.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753344289839.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753344289839.png" new file mode 100644 index 0000000000000000000000000000000000000000..788f26ba132e35b423becb998c37bcc76420a2f5 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753344289839.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753344300187.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753344300187.png" new file mode 100644 index 0000000000000000000000000000000000000000..86537a9db052ade9ae24912733274f401344e582 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753344300187.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753352384121.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753352384121.png" new file mode 100644 index 0000000000000000000000000000000000000000..cd54e7416496b453b829381b0ad532ae8dd443d6 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753352384121.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753352824716.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753352824716.png" new file mode 100644 index 0000000000000000000000000000000000000000..c4c587b36ec00a355251f2b5db2163907ff6ba24 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753352824716.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753353298708.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753353298708.png" new file mode 100644 index 0000000000000000000000000000000000000000..142a5422ba4c3560907eb238b6c65650e34669a0 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753353298708.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753353773782.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753353773782.png" new file mode 100644 index 0000000000000000000000000000000000000000..f14faa22ce988f9b55fad9a8f7d80554cf797063 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753353773782.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753356049790.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753356049790.png" new file mode 100644 index 0000000000000000000000000000000000000000..1c241e7e7ed341e5324575163966933a774fac34 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753356049790.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753356440964.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753356440964.png" new file mode 100644 index 0000000000000000000000000000000000000000..a0659ddf09175b61a2ea6b7cd1fbfc977dbc8490 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753356440964.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753356538752.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753356538752.png" new file mode 100644 index 0000000000000000000000000000000000000000..299557a1952ed6fa5b06720c44dc4f04c77bcd51 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753356538752.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753357551798.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753357551798.png" new file mode 100644 index 0000000000000000000000000000000000000000..e0f402c23abdc362fbbb25e248b7829ad8bde4d5 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753357551798.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753357615173.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753357615173.png" new file mode 100644 index 0000000000000000000000000000000000000000..a6e63997700e1bf576f1a59bc3947d126145ae2e Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753357615173.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753357838842.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753357838842.png" new file mode 100644 index 0000000000000000000000000000000000000000..6c2ceb7bfb8eaed57df2b6be48967c33539e8316 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753357838842.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753358280740.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753358280740.png" new file mode 100644 index 0000000000000000000000000000000000000000..cd898951ea69c1783b45891ad7179a04d372d841 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753358280740.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753362539230.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753362539230.png" new file mode 100644 index 0000000000000000000000000000000000000000..8368123f8e55b0454d5792890ff1c034a96c0695 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753362539230.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753362638355.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753362638355.png" new file mode 100644 index 0000000000000000000000000000000000000000..0ff1b4aee9116c763c4223a048d57470c20d48ef Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753362638355.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753362782846.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753362782846.png" new file mode 100644 index 0000000000000000000000000000000000000000..aa2d19c51724bc822a8342daea11dde8a985ace4 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day4\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230/1753362782846.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753426232711.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753426232711.png" new file mode 100644 index 0000000000000000000000000000000000000000..04fcf0771ad967d36edda7a4cf8e1cf7d0b7026f Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753426232711.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753428620261.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753428620261.png" new file mode 100644 index 0000000000000000000000000000000000000000..2870e31c6f6412038ebfb2ff932dd0d2dee01d47 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753428620261.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753429146564.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753429146564.png" new file mode 100644 index 0000000000000000000000000000000000000000..ce45f58ae8a22331cbf105df322a84c7105669c7 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753429146564.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753430302854.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753430302854.png" new file mode 100644 index 0000000000000000000000000000000000000000..3a43958798caf8ff43fdca64fb3f40b76c8ed57d Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753430302854.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753430511937.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753430511937.png" new file mode 100644 index 0000000000000000000000000000000000000000..c3989666d8063147e0d436b18744392cac7cad0e Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753430511937.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753430902190.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753430902190.png" new file mode 100644 index 0000000000000000000000000000000000000000..5b7f18f4734381af2ac0968220963646708c5e61 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753430902190.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431038811.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431038811.png" new file mode 100644 index 0000000000000000000000000000000000000000..65f12183d329ef8b8a1fcc5e794b077720fc1c36 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431038811.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431152132.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431152132.png" new file mode 100644 index 0000000000000000000000000000000000000000..9416916725677b0ddd8fb403bd9a9ff0c3325a3a Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431152132.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431251967.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431251967.png" new file mode 100644 index 0000000000000000000000000000000000000000..d51f81a44e7230ab4edcac2834003ec14ebbfe87 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431251967.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431327531.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431327531.png" new file mode 100644 index 0000000000000000000000000000000000000000..fc239ad78d3e6521e85aadbce1229b803b240a8d Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431327531.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431602791.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431602791.png" new file mode 100644 index 0000000000000000000000000000000000000000..51442b16609d45912bc7d936cd1fe5a8ccb76bdb Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431602791.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431646514.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431646514.png" new file mode 100644 index 0000000000000000000000000000000000000000..26d60f738e0efc89fe8f7c968d5d9dcef8da10ab Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431646514.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431813359.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431813359.png" new file mode 100644 index 0000000000000000000000000000000000000000..102ecc21aea8cd229a61a6548d1155b9cc5cba47 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431813359.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431886077.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431886077.png" new file mode 100644 index 0000000000000000000000000000000000000000..6b10e740a7fea37f7891d94cbda9f2b57109b869 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753431886077.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753432061113.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753432061113.png" new file mode 100644 index 0000000000000000000000000000000000000000..9f202e6f928d66bea91adb55fbfadf68509aaff0 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753432061113.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753432128450.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753432128450.png" new file mode 100644 index 0000000000000000000000000000000000000000..d95d826c84dbac226c88cfabdc2fa3c217f157e5 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753432128450.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753432823335.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753432823335.png" new file mode 100644 index 0000000000000000000000000000000000000000..1a5908095ad80335b2794768253304fecf9a3602 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753432823335.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433295046.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433295046.png" new file mode 100644 index 0000000000000000000000000000000000000000..f889d65c65b3efeb36a3d13b62fe35a75ffe9387 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433295046.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433620368.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433620368.png" new file mode 100644 index 0000000000000000000000000000000000000000..3afb801903e88134f877fb7be72ab18b9d9e535c Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433620368.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433797185.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433797185.png" new file mode 100644 index 0000000000000000000000000000000000000000..c839fed4b978820a8af63afe5efacd8bc9ae7d63 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433797185.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433876655.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433876655.png" new file mode 100644 index 0000000000000000000000000000000000000000..747fa9f499b1cd150d2f2e7ec6a34786dae660fc Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433876655.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433960461.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433960461.png" new file mode 100644 index 0000000000000000000000000000000000000000..e1f8d0304cc94cb66346e71a5c09149791bdab7d Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753433960461.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434035985.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434035985.png" new file mode 100644 index 0000000000000000000000000000000000000000..e5d7ea853f28557b19b7395faa7973392db8832f Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434035985.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434233532.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434233532.png" new file mode 100644 index 0000000000000000000000000000000000000000..1acc655c210bb91f2ac6f3938cfc04d525fd04c9 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434233532.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434291084.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434291084.png" new file mode 100644 index 0000000000000000000000000000000000000000..d2fc6091bb319b0dcaefde69431848e4fb6077cb Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434291084.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434532474.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434532474.png" new file mode 100644 index 0000000000000000000000000000000000000000..bd0df5e86f1aace2bad8b3b7f2c51d258ff6c92b Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434532474.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434579704.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434579704.png" new file mode 100644 index 0000000000000000000000000000000000000000..2fbae972d9001f5f08123664091c84fc56a1fb12 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434579704.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434619402.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434619402.png" new file mode 100644 index 0000000000000000000000000000000000000000..624c8a0be31d08cac2771c17c023bb44eb2244f0 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434619402.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434757421.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434757421.png" new file mode 100644 index 0000000000000000000000000000000000000000..7286ce48d940a445d5ac3ced5dbf619a88259ec6 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434757421.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434837756.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434837756.png" new file mode 100644 index 0000000000000000000000000000000000000000..bb7046a4354f609a3d7a879ab306e3fdbfb408df Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434837756.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434944991.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434944991.png" new file mode 100644 index 0000000000000000000000000000000000000000..93307a66bd64471868860086e836aa757188be18 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753434944991.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753435761949.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753435761949.png" new file mode 100644 index 0000000000000000000000000000000000000000..52ba88e3324d8207418e9755fe6b35344a5e995e Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753435761949.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753436918726.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753436918726.png" new file mode 100644 index 0000000000000000000000000000000000000000..437b994af95e4420af5563fb4d0c139f582659ec Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753436918726.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753437251330.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753437251330.png" new file mode 100644 index 0000000000000000000000000000000000000000..e85088756fd317986c9aa019d4d2fb6de9a2c6ac Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753437251330.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753437819390.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753437819390.png" new file mode 100644 index 0000000000000000000000000000000000000000..62a37d94f8990390c8c84ed043f35d7490cf4b13 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753437819390.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753437896787.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753437896787.png" new file mode 100644 index 0000000000000000000000000000000000000000..22165f40af887645d0bbd9578aa0f4277aa2a93f Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753437896787.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753438404962.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753438404962.png" new file mode 100644 index 0000000000000000000000000000000000000000..28663f25c703adfa9af2af0a7095d40dc2d56cf7 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753438404962.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753438678985.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753438678985.png" new file mode 100644 index 0000000000000000000000000000000000000000..2c86245df56c1c3b934a0031f76e0dfdb4be01a6 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753438678985.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439026038.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439026038.png" new file mode 100644 index 0000000000000000000000000000000000000000..23f45b97c671f0fd82e3a093e09cea28b813eae8 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439026038.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439249021.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439249021.png" new file mode 100644 index 0000000000000000000000000000000000000000..1ea59d601cba8591de2a8be566024eec9ee92a3e Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439249021.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439354314.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439354314.png" new file mode 100644 index 0000000000000000000000000000000000000000..78a6013d1736092ae553ff6976aa83361eb4d342 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439354314.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439709966.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439709966.png" new file mode 100644 index 0000000000000000000000000000000000000000..737a3c8116c96c27afc485043626dfe2c8735e3a Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439709966.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439818566.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439818566.png" new file mode 100644 index 0000000000000000000000000000000000000000..1641ad83b20d2b07dbf0c97969dbcc43efd90144 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/images/\343\200\220RSOC25\343\200\221Day5\350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237/1753439818566.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day1 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272\344\270\216GIT\344\275\277\347\224\250.md" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day1 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272\344\270\216GIT\344\275\277\347\224\250.md" index 38e2f158600364b80532fa3d3446aad86b0bbb3b..98d2f4b938a983097dbd238e83d04643d2dc25ea 100644 --- "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day1 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272\344\270\216GIT\344\275\277\347\224\250.md" +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day1 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\345\274\200\345\217\221\347\216\257\345\242\203\346\220\255\345\273\272\344\270\216GIT\344\275\277\347\224\250.md" @@ -1,6 +1,6 @@ # 【RSOC25】Day1 课程笔记:开发环境搭建与GIT使用 -# 1. git工具的下载和配置 +## 1. git工具的下载和配置 ### 1.1 git工具下载 @@ -38,7 +38,7 @@ cat ~/.ssh/id_rsa_gitee.pub #### 2.1.1 RT-thread源码拉取 -创建一个文件件作为本次项目的主文件夹,进入文件夹右键在git bash中打开输入 +创建一个文件件作为本次项目的主文件夹,进入文件夹右键在git bash中打开输入以下命令 ``` git clone https://gitee.com/rtthread/rt-thread.git @@ -124,7 +124,7 @@ git clone --recursive --depth 1 https://gitee.com/mirrors_RT-Thread/env-windows. ![1753095516501](images/【RSOC25】Day1课程笔记:开发环境搭建与GIT使用/1753095516501.png) -### 2.3.3 Hello RT-thread工程编译和运行 +#### 2.3.3 Hello RT-thread工程编译和运行 接上一小节,找到mian.c中的mian函数可以简单做修改我们这里改为Hello RT-thread!2025。 @@ -144,7 +144,7 @@ git clone --recursive --depth 1 https://gitee.com/mirrors_RT-Thread/env-windows. (退出:Ctrl+A +X,自己尝试反正对我的电脑没用只会出现几个表情包) -### 2.3.4 LVGL demo工程编译和运行 +#### 2.3.4 LVGL demo工程编译和运行 接上一节工程退出后执行`menuconfig`命令Hardware Drivers Config->Onboard Peripheral Drivers-> @@ -158,7 +158,7 @@ git clone --recursive --depth 1 https://gitee.com/mirrors_RT-Thread/env-windows. ## 3.git工具的使用 -关于git工具使用,虽然自己以前页用过但只是会简单的拉取代码,今天学习之后也算小有成就,关于该工具的学习放在这里太过啰嗦就不做讲解了,但git工具和linux操作系统学习方法类似,死记硬背无用多用就顺手了,忘了就查,不会就AI,百度。远比自己盯着那几行晦涩难懂的命令有用,故在此推荐两篇夏令营中大佬推荐的博文供大家参考学习: +关于git工具使用,虽然自己以前也用过但只是会简单的拉取代码,今天学习之后也算小有成就,关于该工具的学习放在这里太过啰嗦就不做讲解了,但git工具和linux操作系统学习方法类似,死记硬背无用多用就顺手了,忘了就查,不会就AI,百度。远比自己盯着那几行晦涩难懂的命令有用,故在此推荐两篇夏令营中大佬推荐的博文供大家参考学习: Git学习和使用教程(来自本次夏令营中叶大佬推荐的教程) diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day2 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250.md" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day2 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..959f84428c17c84c6a816cc05ae2e7c069e40fba --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day2 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232RTT\345\267\245\345\205\267\344\275\277\347\224\250\345\222\214\345\206\205\346\240\270\345\205\245\351\227\250.md" @@ -0,0 +1,458 @@ +# 【RSOC25】Day2 课程笔记:RTT工具使用和内核入门 + +## 1. RT-thread STtudio配置和使用 + +### 1.1 RTT工具下载和SDK资源包下载 + +#### 1.1.1 RT studio工具下载 + +前往[RTT官网](https://www.rt-thread.org/download.html#download-rt-thread-studio)下载RT-studio工具最新版本,下载后安装双击打开登录即可。 + +![1753155683355](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753155683355.png) + +#### 1.1.1 SDK资源包管理 + +右上角打开SDK资源管理器选择STM32下拉找到STM32F407勾选最新版本然后点击安装。 + +![1753155823461](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753155823461.png) + +安装完成之后在debug下面找到QEMU工具栏勾选最新版本下载安装 + +![1753155966120](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753155966120.png) + +耐心等待安装完成 + +### 1.2 RT-studio新建工程和QEMU模拟运行 + +#### 1.2.1 新建工程和编译 + +左上角文件->新建工程->新建RTT工程 + +![1753156125970](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753156125970.png) + +选择基于开发板创建->开发板:STM32F407-ATK-EXPLORER->调试器:QEMU 然后点击完成。 + +![1753156351872](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753156351872.png) + +创建完后选择我们创建的工程RTT_RSOC点击左上角的小锤子构建 + +![1753156490789](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753156490789.png) + +构建完成如下图 + +![1753156632718](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753156632718.png) + +#### 1.2.2 QEMU模拟运行 + +点击工具栏的下载->选择模拟器:STM32F407-ATK-EXPLORER + +![1753156706609](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753156706609.png) + +下载完成后会自动运行系统控制台终端显示如下,可输入`PC`指令查看当前任务状态 + +![1753156829136](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753156829136.png) + +## 2. RT-Thread内核入门 + +[写在前:本章节内容简略详细教程可查看[RTT官网教程](https://www.rt-thread.org/document/site/#/)理解和阅读] + +内核介绍 + +内核是一个操作系统的核心,是操作系统最基础也是最重要的部分。它负责管理系统的线程、线程间通信、系统时钟、中断及内存等。下图为 RT-Thread 内核架构图,可以看到内核处于硬件层之上,内核部分包括内核库、实时内核实现。 + +![RT-Thread 内核及底层结构](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/basic/figures/03kernel_Framework.png) + +内核库是为了保证内核能够独立运行的一套小型的类似 C 库的函数实现子集。这部分根据编译器的不同自带 C 库的情况也会有些不同,当使用 GNU GCC 编译器时,会携带更多的标准 C 库实现。 + +实时内核的实现包括:对象管理、线程管理及调度器、线程间通信管理、时钟管理及内存管理等等,内核最小的资源占用情况是 3KB ROM,1.2KB RAM。 + +### 2.1 RT-Thread内核入门1:启动流程分析 + +#### 2.1.1 RT-thread启动流程概括 + +一般了解一份代码大多从启动部分开始,同样这里也采用这种方式,先寻找启动的源头。RT-Thread 支持多种平台和多种编译器,而 rtthread\_startup() 函数是 RT-Thread 规定的统一启动入口。一般执行顺序是:系统先从启动文件开始运行,然后进入 RT-Thread 的启动函数 rtthread\_startup() ,最后进入用户入口函数 main(),如下图所示: + +![启动流程](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/basic/figures/rtt_startup.png) + +#### 2.1.2 RT-thread启动流程分析 + +我们可以打开我们之前的工程进入RT_RSOC\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\Templates\gcc\startup_stm32f407xx.s汇编启动文件113行查看,上面的代码执行几乎与裸机启动文件没有任何区别。而操作系统和裸机启动最大的区别便是在这里,当完成上述操作后裸机会直接跳转到mian()函数和RTOS还需要进行操作系统初始化和启动,如rt-thread就需要进入上一节启动流程概述图的rtthread_startup()函数完成操作系统初始化后,蔡会进入main()函数。 + +![1753157755057](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753157755057.png) + +而rtthread_startup()函数由上述的概述图可知,在进入该函数之前还会调用一个函数 在该函数中会调用rtthread_startup(),关于这个我们可以进入\RT_RSOC\rt-thread\src\components.c中查看139行到165的内容可以看到这里对应概述图中根据编译器选择汇编调用的操作系统初始化函数入口函数,因为RT-thread studio本身也就是利用GCC编译器完成构建,所以我们这里可以看到只要entry函数被编译,这也就可以解释在上述启动文件中的113行为什么是 `bl entry` + +![1753158320939](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753158320939.png) + +到这里简单的启动流程已经结束,调用rtthread_startup()函数进入操作系统初始化,因代码过多就不一一查看了,我们可以关注一下启动流程中重点完成了那些操作会和我们后续的开发有关: + +首先我们关注系统调度器初始化后的三个线程初始化函数,这三个函数会分别创建main主线程,time时间线程,idel空闲线程,然后会开启系统调度,也就是说在我们系统启动完成之后会自动创建三个线程。而其中main()主线程最终会进入main()主函数也就是完成系统初始化进入用户程序。 + +然后我们会发现在rt_hw_board_init()和main()中都会调用两个带compoents的函数rt\_components\_board\_init() 与 rt\_components\_init()其后掉调用的蓝色方框的函数我们称为自动初始化函数,其中rt\_components\_board\_init()进入的函数主要完成硬件自动初始化,而rt\_components\_init()进入的函数主要完成组件应用程序等自动初始化,这个机制称之为自动初始化机制,是指初始化函数不需要被显式调用,只需要在函数定义处通过宏定义的方式进行申明,就会在系统启动过程中被执行。 + +举个简单的例子我们现在需要开发一个lvgl_demo,那么我们就可以将显示屏硬件初始化的函数启用rt\_components\_board\_init()调用的硬件自动初始化,然后将lvgl初始化函数启用rt\_components\_init()的组件自动初始化,最后在main()主函数中直接调用lvgl ui相关的函数即可,而显示屏硬件初始化函数和lvgl组件初始化函数会在系统启动过程中执行到rt\_components\_board\_init() 与 rt\_components\_init()两个函数时候就被初始化,这样在开发时候就可以减少代码的冗余和依赖。 + +具体详细教程可参考[rh-thread内核启动过程中的自动初始化机制](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/basic/basic?id=rt-thread-%e8%87%aa%e5%8a%a8%e5%88%9d%e5%a7%8b%e5%8c%96%e6%9c%ba%e5%88%b6) + +![1753158740464](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753158740464.png) + +系统线程和空闲线程介绍可看PPT说明 + +![1753176072844](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753176072844.png) + +### 2.2 RT-Thread内核入门2:线程管理和调度 + +RT-Thread 线程管理的主要功能是对线程进行管理和调度,系统中总共存在两类线程,分别是系统线程和用户线程,系统线程是由 RT-Thread 内核创建的线程,用户线程是由应用程序创建的线程,这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会被从对象容器中删除。 + +![对象容器与线程对象](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/thread/figures/04Object_container.png) + +RT-Thread 的线程调度器是抢占式的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,最高优先级的任务一旦就绪,总能得到 CPU 的使用权。 + +当一个运行着的线程使一个比它优先级高的线程满足运行条件,当前线程的 CPU 使用权就被剥夺了,或者说被让出了,高优先级的线程立刻得到了 CPU 的使用权。 + +如果是中断服务程序使一个高优先级的线程满足运行条件,中断完成时,被中断的线程挂起,优先级高的线程开始运行。 + +当调度器调度线程切换时,先将当前线程上下文保存起来,当再切回到这个线程时,线程调度器将该线程的上下文信息恢复。 + +对于线程的介绍和线程工作机制重要属性这里不再做介绍内容比较深大家仔细前往[RT-thread官网:线程的工作机制及重要属性介绍](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/thread/thread?id=%e7%ba%bf%e7%a8%8b%e7%9a%84%e5%b7%a5%e4%bd%9c%e6%9c%ba%e5%88%b6)查看,接下来我们主要将线程管理和调度的方式。 + +#### 2.2.1 线程的管理方式 + +##### 2.2.1.1 线程管理方式及其对线程状态的影响 + +线程的相关操作,包含:创建 / 初始化线程、启动线程、运行线程、删除 / 脱离线程。可以使用 rt\_thread\_create() 创建一个动态线程,使用 rt\_thread\_init() 初始化一个静态线程,动态线程与静态线程的区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化 heap 之后才能使用 create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。 + +![线程相关操作](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/thread/figures/04thread_ops.png) + +对于线程管理中我们所需要注意的两点: + +1.线程管理的方式有哪些具体开发如何使用 + +2.线程管理方式对线程状态会产生什么影响 + +不同线程管理操作对于线程状态之间的变化如下 + +![1753178489017](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753178489017.png) + +在这里我们需要区别以下静态创建线程rt_thread_init()和动态创建线程rt_thread_create()的区别 + +- 动态创建线程时,系统会初始化线程控制块(TCB)和栈空间,但未立即加入调度队列。调用 `rt_thread_startup()` 后,线程才被加入调度队列参与系统调度。 +- 静态创建线程时,需手动分配栈空间(数组),并通过 `rt_thread_init()` 初始化线程控制块。 + +##### 2.2.1.2 线程创建和应用示例 + +打开RT-studio软件,进入之前创建的工程rtthread-setting->软件包->杂项软件包->找到rt-thread内核示例勾选thread + +![1753178806755](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753178806755.png) + +然后Ctrl+s保存并关闭,等待系统下载软件包。 + +![1753179024941](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753179024941.png) + +在pakges软件包下课查看thread_sample函数中实现了创建/初始化,启动,运行和删除/脱离的示例。 + +![1753179061231](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753179061231.png) + +编译并运行工程,在控制台输入t然后tab可以看到返回了thread_sample然后回车。 + +![1753179200663](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753179200663.png) + +可以看到系统已经调用thread_sample函数创建线程1初始化线程2,然后运行线程2 10次之后脱离线程,运行线程1。 + +![1753179446661](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753179446661.png) + +运行结果应如下 + +``` + \ | / +- RT - Thread Operating System + / | \ 3.1.0 build Aug 24 2018 + 2006 - 2018 Copyright by rt-thread team +msh >thread_sample +msh >thread2 count: 0 +thread2 count: 1 +thread2 count: 2 +thread2 count: 3 +thread2 count: 4 +thread2 count: 5 +thread2 count: 6 +thread2 count: 7 +thread2 count: 8 +thread2 count: 9 +thread2 exit +thread1 count: 0 +thread1 count: 1 +thread1 count: 2 +thread1 count: 3 +… + +``` + +#### 2.2.2 线程的调度方式 + +在RT-thread系统中线程的调度和任务切换工作主要由调度器来完成 + +![1753179663732](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753179663732.png) + +##### 2.2.2.1 优先级抢占调度 + +在不同优先级下,调度器执行优先级抢占调度,高优先级会抢占低优先级的线程运行 + +![1753179997633](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753179997633.png) + +优先级抢占式调度示例工程 + +在上一节的main.c代码中修改如下创建一个优先级比mian()的线程并启动 + +``` +#include +#include +#include + + + +rt_thread_t thread1 =RT_NULL; +void _thread1(void) +{ + int count=10; + for(int i=0;i +``` + +##### 2.2.2.2 时间片轮转调度 + +在相同优先级下,存在两个或多个线程就处于就绪状态时,调度器执行时间片轮转调度,按照预设时间片进行调度。 + +![1753180187070](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753180187070.png) + +时间片轮转调度示例工程 + +编写代码创建两个相同优先级的工程 + +``` +#include +#include +#include + + +rt_thread_t thread1 =RT_NULL; +void _thread1(void) +{ + + + while(1){ + rt_kprintf("thread1 run \n"); + } +} + +rt_thread_t thread2 =RT_NULL; +void _thread2(void) +{ + + while(1){ + rt_kprintf("thread2 run \n"); + } +} +int main(void) +{ + + thread1 = rt_thread_create("thread1", _thread1, RT_NULL, 1024, 9, 5); + thread2 = rt_thread_create("thread2", _thread2, RT_NULL, 1024, 9, 5); + if(thread1 != RT_NULL&&thread2 != RT_NULL) + { + rt_thread_startup(thread1); + rt_thread_startup(thread2); + } + rt_kprintf("main run conut \n"); +} + +``` + +更具代码:我们创建了相关相同优先级的线程,运行系统应该按照时间片轮转的方法依次调度两个线程运行并打印日志。 + +我们编译并运行代码查看结果 + +![1753181531962](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753181531962.png) + +发现结果好像和我们想的并不一样,为什么只有线程1在运行呢?我们仔细再看以下代码,之前说过mian()线程的优先级是10而我们创建的两个线程的优先级是9,貌似没有问题,但仔细深究就会发现在我们创建线程1和线程2,相要的是启动线程1和线程2,但我们启动了线程1之后由于其优先级大于main()线程,也就是此时thread1线程已经抢占了main()线程的运行都还没有来得及启动thread2线程,所以只有线程1在运行,那我们要等main()线程成功启动两个线程,并被打断,所以我们要将两个线程的优先级改为比main()线程要小,我们修改为11。 + +``` +#include +#include +#include + + +rt_thread_t thread1 =RT_NULL; +void _thread1(void) +{ + + while(1){ + rt_kprintf("thread1 run \n"); + } +} + +rt_thread_t thread2 =RT_NULL; +void _thread2(void) +{ + + while(1){ + rt_kprintf("thread2 run \n"); + } +} +int main(void) +{ + + thread1 = rt_thread_create("thread1", _thread1, RT_NULL, 1024, 11, 5); + thread2 = rt_thread_create("thread2", _thread2, RT_NULL, 1024, 11, 5); + if(thread1 != RT_NULL&&thread2 != RT_NULL) + { + rt_thread_startup(thread1); + rt_thread_startup(thread2); + } + rt_kprintf("main run conut \n"); +} + +``` + +编译运行结果如下:系统更具时间片在轮询调度打印日志 + +![1753182120380](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753182120380.png) + +## 3.课后作业 + +今日作业: +1.在论坛发文章描述对今天内容的总结与收获 +2.编写代码上传至git仓库,创建至少3个线程,能体现抢占与时间片轮转,在今天的工程的mian.c中实现,其他同学拿到该文件可以直接运行。 + +自行研究: +1.ARM函数调用规范 + +代码图解: + +![1753185070376](images/【RSOC25】Day2课程笔记:RTT工具使用和内核入门/1753185070376.png) + +``` +#include +#include +#include + +// 线程控制块指针声明 +rt_thread_t thread1 = RT_NULL; +rt_thread_t thread2 = RT_NULL; +rt_thread_t thread3 = RT_NULL; + +/** + * 线程1入口函数 + * 功能:循环打印"thread1 run",并在特定计数时延时 + */ +void _thread1(void) +{ + int i = 0; // 计数变量,用于控制延时时机 + + while(1) // 线程主循环,持续运行 + { + rt_kprintf("thread1 run\n"); // 打印线程1运行信息 + + // 当计数达到10、100、1000、10000时执行延时(原代码此处i=10000为笔误,保持原样) + if(i == 10 || i == 100 || i == 1000 || i=10000) + { + rt_thread_mdelay(1000); // 延时1000ms,便于观察输出结果 + } + + i++; // 计数自增 + } +} + +/** + * 线程2入口函数 + * 功能:循环打印"thread2 run" + */ +void _thread2(void) +{ + while(1) // 线程主循环,持续运行 + { + rt_kprintf("thread2 run \n"); // 打印线程2运行信息 + } +} + +/** + * 线程3入口函数 + * 功能:循环打印"thread3 run" + */ +void _thread3(void) +{ + while(1) // 线程主循环,持续运行 + { + rt_kprintf("thread3 run \n"); // 打印线程3运行信息 + } +} + +/** + * 主函数 + * 功能:创建并启动三个线程,打印主函数运行信息 + */ +int main(void) +{ + // 创建线程1:名称"thread1",入口函数_thread1,无参数,栈大小1024,优先级9,时间片5 + thread1 = rt_thread_create("thread1", _thread1, RT_NULL, 1024, 9, 5); + // 创建线程2:名称"thread2",入口函数_thread2,无参数,栈大小1024,优先级11,时间片5 + thread2 = rt_thread_create("thread2", _thread2, RT_NULL, 1024, 11, 5); + // 创建线程3:名称"thread3",入口函数_thread3,无参数,栈大小1024,优先级11,时间片5 + thread3 = rt_thread_create("thread3", _thread3, RT_NULL, 1024, 11, 5); + + // 若线程1创建成功,则启动线程1 + if(thread1 != RT_NULL) + { + rt_thread_startup(thread1); + } + + // 若线程2和线程3均创建成功,则启动这两个线程 + if(thread2 != RT_NULL && thread3 != RT_NULL) + { + rt_thread_startup(thread2); + rt_thread_startup(thread3); + } + + rt_kprintf("main run conut \n"); // 打印主函数运行信息 + + return 0; // 主函数返回(RT-Thread中主函数退出后仍会运行线程) +} + +``` diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day3 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257.md" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day3 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257.md" new file mode 100644 index 0000000000000000000000000000000000000000..450c548c6e99f966a8e760bc4075246c90c0b1c4 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day3 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\272\277\347\250\213\351\227\264\347\232\204\345\220\214\346\255\245\345\222\214\351\200\232\350\256\257.md" @@ -0,0 +1,991 @@ +# 【RSOC25】Day3 课程笔记:线程间的同步和通讯 + +## [写在前面] + +这一篇其实大多是理论,主要内容来源于[RT-thread教程IPC部分](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/ipc1/ipc1)中的线程同步和线程通讯部分,这是这部分像比如前面一篇文章里的启动流程和线程会好理解的多,但是内容太多过于繁琐,关于理论部分,可以不用死记,只需要知道同步和通讯都有那些方式,具体的使用在以后的开发中一步步巩固就好了,大可不要仔细阅读通文,课直接到每个例程的演示部分自己动手做一遍,看看运行效果,然后自己看看代码若有不同的结合本篇文章和[RT-thread教程IPC部分](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/ipc1/ipc1)进行理解即可。 + +## 1.线程间的同步 + +线程的同步方式有很多种,其核心思想都是:**在访问临界区的时候只允许一个 (或一类) 线程运行。进入 / 退出临界区的方式有很多种: + +(1)调用 rt\_hw\_interrupt\_disable() 进入临界区,调用 rt\_hw\_interrupt\_enable() 退出临界区;详见《中断管理》的全局中断开关内容。 + +(2)调用 rt\_enter\_critical() 进入临界区,调用 rt\_exit\_critical() 退出临界区。 + +本章将介绍多种同步方式:**信号量**(semaphore)、**互斥量**(mutex)、和**事件集**(event)。学习完本章,大家将学会如何使用信号量、互斥量、事件集这些对象进行线程间的同步。 + +### 1.1 信号量 + +#### 1.1.1 信号量简介 + +##### 1.1.1.1 概念 + +以生活中的停车场为例来理解信号量的概念: + +①当停车场空的时候,停车场的管理员发现有很多空车位,此时会让外面的车陆续进入停车场获得停车位; + +②当停车场的车位满的时候,管理员发现已经没有空车位,将禁止外面的车进入停车场,车辆在外排队等候; + +③当停车场内有车离开时,管理员发现有空的车位让出,允许外面的车进入停车场;待空车位填满后,又禁止外部车辆进入。 + +在此例子中,管理员就相当于信号量,管理员手中空车位的个数就是信号量的值(非负数,动态变化);停车位相当于公共资源(临界区),车辆相当于线程。车辆通过获得管理员的允许取得停车位,就类似于线程通过获得信号量访问公共资源。 + +##### 1.1.1.2 工作机制 + +信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到同步或互斥的目的。 + +信号量工作示意图如下图所示,每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值对应了信号量对象的实例数目、资源数目,假如信号量值为 5,则表示共有 5 个信号量实例(资源)可以被使用,当信号量实例数目为零时,再申请该信号量的线程就会被挂起在该信号量的等待队列上,等待可用的信号量实例(资源)。 + +![信号量工作示意图](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc1/figures/06sem_work.png) + +##### 1.1.1.3 管理方式 + +信号量控制块中含有信号量相关的重要参数,在信号量各种状态间起到纽带的作用。信号量相关接口如下图所示,对一个信号量的操作包含:创建 / 初始化信号量、获取信号量、释放信号量、删除 / 脱离信号量。 + +![信号量相关接口](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc1/figures/06sem_ops.png) + +##### 1.1.1.4 信号量类别 + +类型:互斥信号量(解决互斥问题)、二值信号量(取值范围0/1,解决同步问题)、计数信号量(管理资源数量)   + +功能:线程/中断间同步,通过获取/释放操作实现资源控制。 + +#### 1.1.2 信号量例程 + +打开RT-thread配置,选中信号量(semaphore)、**互斥量**(mutex)、和**事件集**(event)的例程Ctrl+C保存 + +![1753253733110](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753253733110.png) + +然后打开例程代码,可查看有关信号量的创建和使用 + +![1753253856146](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753253856146.png) + +然后编译并运行,在控制台输入semaphore_sample 即可启动例程,运行结果如下: + +![1753254441739](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753254441739.png) + +``` +D:\Workstudio\IDE\RT-ThreadStudio\workspace\RT_RSOC>D:/Workstudio/IDE/RT-ThreadStudio/repo/Extract/Debugger_Support_Packages/RealThread/QEMU/4.2.0.4/qemu-system-arm.e +xe -M stm32f407-atk-explorer -sd sd.bin -nographic --kernel Debug/rtthread.bin -serial stdio -monitor null -show-cursor +WARNING: Image format was not specified for 'sd.bin' and probing guessed raw. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. + + \ | / +- RT - Thread Operating System + / | \ 4.1.0 build Jul 23 2025 10:13:44 + 2006 - 2022 Copyright by RT-Thread team +main run conut +msh >semaphore_sample +create done. dynamic semaphore value = 0. +msh >thread1 release a dynamic semaphore. +thread2 take a dynamic semaphore. number = 1 +thread1 release a dynamic semaphore. +thread2 take a dynamic semaphore. number = 2 +thread1 release a dynamic semaphore. +thread2 take a dynamic semaphore. number = 3 +thread1 release a dynamic semaphore. +``` + +### 1.2 互斥量 + +#### 1.2.1 互斥量简介 + +##### 1.2.1.1 概念 + +互斥量又叫相互排斥的信号量,是一种特殊的二值信号量。互斥量类似于只有一个车位的停车场:当有一辆车进入的时候,将停车场大门锁住,其他车辆在外面等候。当里面的车出来时,将停车场大门打开,下一辆车才可以进入。 + +##### 1.2.1.2 工作机制 + +互斥量和信号量不同的是:拥有互斥量的线程拥有互斥量的所有权,互斥量支持递归访问且能防止线程优先级翻转;并且互斥量只能由持有线程释放,而信号量则可以由任何线程释放。 + +互斥量的状态只有两种,开锁或闭锁(两种状态值)。当有线程持有它时,互斥量处于闭锁状态,由这个线程获得它的所有权。相反,当这个线程释放它时,将对互斥量进行开锁,失去它的所有权。当一个线程持有互斥量时,其他线程将不能够对它进行开锁或持有它,持有该互斥量的线程也能够再次获得这个锁而不被挂起,如下图时所示。这个特性与一般的二值信号量有很大的不同:在信号量中,因为已经不存在实例,线程递归持有会发生主动挂起(最终形成死锁)。 + +![互斥量工作示意图](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc1/figures/06mutex_work.png) + +##### 1.2.1.3 管理方式 + +互斥量控制块中含有互斥相关的重要参数,在互斥量功能的实现中起到重要的作用。互斥量相关接口如下图所示,对一个互斥量的操作包含:创建 / 初始化互斥量、获取互斥量、释放互斥量、删除 / 脱离互斥量。 + +![互斥量相关接口](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc1/figures/06mutex_ops.png) + +##### 1.2.1.4 互斥量和信号量的区别 + +信号量:可能造成优先级反转问题 + +![优先级反转 (M 为信号量)](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc1/figures/06priority_inversion.png) + +互斥量:解决优先级反转问题 + +![优先级继承 (M 为互斥量)](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc1/figures/06priority_inherit.png) + +##### 1.2.1.5 互斥量使用场景 + +互斥量的使用比较单一,因为它是信号量的一种,并且它是以锁的形式存在。在初始化的时候,互斥量永远都处于开锁的状态,而被线程持有的时候则立刻转为闭锁的状态。互斥量更适合于: + +(1)线程多次持有互斥量的情况下。这样可以避免同一线程多次递归持有而造成死锁的问题。 + +(2)可能会由于多线程同步而造成优先级翻转的情况。 + +#### 1.2.2 互斥量例程 + +在mutex_sample.c文件夹可以查看互斥量例程的代码 + +![1753256363664](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753256363664.png) + +我我们编译代码并运行,在控制台终端输入mutex_sample启动例程结果如下 + +![1753256492146](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753256492146.png) + +``` + +D:\Workstudio\IDE\RT-ThreadStudio\workspace\RT_RSOC>D:/Workstudio/IDE/RT-ThreadStudio/repo/Extract/Debugger_Support_Packages/RealThread/QEMU/4.2.0.4/qemu-system-arm.e +xe -M stm32f407-atk-explorer -sd sd.bin -nographic --kernel Debug/rtthread.bin -serial stdio -monitor null -show-cursor +WARNING: Image format was not specified for 'sd.bin' and probing guessed raw. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. + + \ | / +- RT - Thread Operating System + / | \ 4.1.0 build Jul 23 2025 10:13:44 + 2006 - 2022 Copyright by RT-Thread team +main run conut +msh >mutex_sample +msh >mutex protect ,number1 = mumber2 is 1 +mutex protect ,number1 = mumber2 is 2 +mutex protect ,number1 = mumber2 is 3 +mutex protect ,number1 = mumber2 is 4 +mutex protect ,number1 = mumber2 is 5 +mutex protect ,number1 = mumber2 is 6 +mutex protect ,number1 = mumber2 is 7 +mutex protect ,number1 = mumber2 is 8 +``` + +### 1.3 事件集 + +#### 1.3.1 事件集简介 + +##### 1.3.1.1 概念 + +事件集也是线程间同步的机制之一,一个事件集可以包含多个事件,利用事件集可以完成一对多,多对多的线程间同步。下面以坐公交为例说明事件,在公交站等公交时可能有以下几种情况: + +①P1 坐公交去某地,只有一种公交可以到达目的地,等到此公交即可出发。 + +②P1 坐公交去某地,有 3 种公交都可以到达目的地,等到其中任意一辆即可出发。 + +③P1 约另一人 P2 一起去某地,则 P1 必须要等到 “同伴 P2 到达公交站” 与“公交到达公交站”两个条件都满足后,才能出发。 + +这里,可以将 P1 去某地视为线程,将 “公交到达公交站”、“同伴 P2 到达公交站” 视为事件的发生,情况①是特定事件唤醒线程;情况②是任意单个事件唤醒线程;情况③是多个事件同时发生才唤醒线程。 + +##### 1.3.1.2 工作机制 + +事件集主要用于线程间的同步,与信号量不同,它的特点是可以实现一对多,多对多的同步。即一个线程与多个事件的关系可设置为:其中任意一个事件唤醒线程,或几个事件都到达后才唤醒线程进行后续的处理;同样,事件也可以是多个线程同步多个事件。这种多个事件的集合可以用一个 32 位无符号整型变量来表示,变量的每一位代表一个事件,线程通过 “逻辑与” 或“逻辑或”将一个或多个事件关联起来,形成事件组合。事件的 “逻辑或” 也称为是独立型同步,指的是线程与任何事件之一发生同步;事件 “逻辑与” 也称为是关联型同步,指的是线程与若干事件都发生同步。 + +RT-Thread 定义的事件集有以下特点: + +1)事件只与线程相关,事件间相互独立:每个线程可拥有 32 个事件标志,采用一个 32 bit 无符号整型数进行记录,每一个 bit 代表一个事件; + +2)事件仅用于同步,不提供数据传输功能; + +3)事件无排队性,即多次向线程发送同一事件 (如果线程还未来得及读走),其效果等同于只发送一次。 + +在 RT-Thread 中,每个线程都拥有一个事件信息标记,它有三个属性,分别是 RT\_EVENT\_FLAG\_AND(逻辑与),RT\_EVENT\_FLAG\_OR(逻辑或)以及 RT\_EVENT\_FLAG\_CLEAR(清除标记)。当线程等待事件同步时,可以通过 32 个事件标志和这个事件信息标记来判断当前接收的事件是否满足同步条件。 + +![事件集工作示意图](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc1/figures/06event_work.png) + +##### 1.3.1.3 管理方式 + +事件集控制块中含有与事件集相关的重要参数,在事件集功能的实现中起重要的作用。事件集相关接口如下图所示,对一个事件集的操作包含:创建 / 初始化事件集、发送事件、接收事件、删除 / 脱离事件集。 + +![事件相关接口](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc1/figures/06event_ops.png) + +#### 1.3.2 事件集例程 + +在event_sample.c文件下可查看有关事件集例程的代码 + +![1753257508246](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753257508246.png) + +编译运行后在控制台输入event_sample 然后回车 + +``` + +D:\Workstudio\IDE\RT-ThreadStudio\workspace\RT_RSOC>D:/Workstudio/IDE/RT-ThreadStudio/repo/Extract/Debugger_Support_Packages/RealThread/QEMU/4.2.0.4/qemu-system-arm.e +xe -M stm32f407-atk-explorer -sd sd.bin -nographic --kernel Debug/rtthread.bin -serial stdio -monitor null -show-cursor +WARNING: Image format was not specified for 'sd.bin' and probing guessed raw. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. + + \ | / +- RT - Thread Operating System + / | \ 4.1.0 build Jul 23 2025 10:13:44 + 2006 - 2022 Copyright by RT-Thread team +main run conut +msh >event_sample +thread2: send event3 +thread1: OR recv event 0x8 +thread1: delay 1s to prepare the second event +msh >thread2: send event5 +thread2: send event3 +thread2 leave. +thread1: AND recv event 0x28 +thread1 leave. +``` + +## 2.线程间的通讯 + +在裸机编程中,经常会使用全局变量进行功能间的通信,如某些功能可能由于一些操作而改变全局变量的值,另一个功能对此全局变量进行读取,根据读取到的全局变量值执行相应的动作,达到通信协作的目的。RT-Thread 中则提供了更多的工具帮助在不同的线程中间传递信息,本章会详细介绍这些工具。 + +### 2.1 邮箱 + +#### 2.1.1 邮箱介绍 + +##### 2.1.1.1 概念 + +邮箱服务是实时操作系统中一种典型的线程间通信方法。举一个简单的例子,有两个线程,线程 1 检测按键状态并发送,线程 2 读取按键状态并根据按键的状态相应地改变 LED 的亮灭。这里就可以使用邮箱的方式进行通信,线程 1 将按键的状态作为邮件发送到邮箱,线程 2 在邮箱中读取邮件获得按键状态并对 LED 执行亮灭操作。 + +这里的线程 1 也可以扩展为多个线程。例如,共有三个线程,线程 1 检测并发送按键状态,线程 2 检测并发送 ADC 采样信息,线程 3 则根据接收的信息类型不同,执行不同的操作。 + +##### 2.1.1.2 工作机制 + +![邮箱工作示意图](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc2/figures/07mb_work.png) + +当一个线程向邮箱发送邮件时,如果邮箱没满,将把邮件复制到邮箱中。如果邮箱已经满了,发送线程可以设置超时时间,选择等待挂起或直接返回 - RT\_EFULL。如果发送线程选择挂起等待,那么当邮箱中的邮件被收取而空出空间来时,等待挂起的发送线程将被唤醒继续发送。 + +当一个线程从邮箱中接收邮件时,如果邮箱是空的,接收线程可以选择是否等待挂起直到收到新的邮件而唤醒,或可以设置超时时间。当达到设置的超时时间,邮箱依然未收到邮件时,这个选择超时等待的线程将被唤醒并返回 - RT\_ETIMEOUT。如果邮箱中存在邮件,那么接收线程将复制邮箱中的 4 个字节邮件到接收缓存中 + +##### 2.1.1.3 管理方式 + +邮箱控制块是一个结构体,其中含有事件相关的重要参数,在邮箱的功能实现中起重要的作用。邮箱的相关接口如下图所示,对一个邮箱的操作包含:创建 / 初始化邮箱、发送邮件、接收邮件、删除 / 脱离邮箱。 + +![邮箱相关接口](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc2/figures/07mb_ops.png) + +#### 2.1.2 邮箱例程 + +在rt-thread配置中勾选邮箱,信号,消息队列的示例工程,然后Crtl+S保存 + +![1753260901700](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753260901700.png) + +可在mailbox_sample.c中查看示例代码 + +![1753262686072](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753262686072.png) + +然后编译,出现报错如下 + +![1753262204665](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753262204665.png) + +定位问题出现在后面会用到的消息队列例程,是旧版本例程和新版本不匹配造成的我们进入消息队列msgq_sample.c文件在开头加入 + +``` +// 手动定义版本转换宏,适配旧版本 RT-Thread +#ifndef RT_VERSION_CHECK +#define RT_VERSION_CHECK(major, minor, patch) \ + ((major) * 10000 + (minor) * 100 + (patch)) +#endif +``` + +然后编译通过,输入mailbox_sample运行例程 + +![1753263093267](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753263093267.png) + +``` + \ | / +- RT - Thread Operating System + / | \ 4.1.0 build Jul 23 2025 17:02:30 + 2006 - 2022 Copyright by RT-Thread team +main run conut +msh >mailbox_sample +thread1: try to recv a mail +thread1: get a mail from mailbox, the content:I'm a mail! +msh >thread1: try to recv a mail +thread1: get a mail from mailbox, the content:this is another mail! +thread1: try to recv a mail +thread1: get a mail from mailbox, the content:I'm a mail! +thread1: try to recv a mail +thread1: get a mail from mailbox, the content:this is another mail! +thread1: try to recv a mail +thread1: get a mail from mailbox, the content:I'm a mail! +``` + +### 2.2 消息队列 + +#### 2.2.1 消息队列介绍 + +##### 2.2.1.1 概念 + +消息队列是另一种常用的线程间通讯方式,是邮箱的扩展。可以应用在多种场合:线程间的消息交换、使用串口接收不定长数据等 + +##### 2.2.1.2 工作机制 + +消息队列能够接收来自线程或中断服务例程中不固定长度的消息,并把消息缓存在自己的内存空间中。其他线程也能够从消息队列中读取相应的消息,而当消息队列是空的时候,可以挂起读取线程。当有新的消息到达时,挂起的线程将被唤醒以接收并处理消息。消息队列是一种异步的通信方式。 + +如下图所示,线程或中断服务例程可以将一条或多条消息放入消息队列中。同样,一个或多个线程也可以从消息队列中获得消息。当有多个消息发送到消息队列时,通常将先进入消息队列的消息先传给线程,也就是说,线程先得到的是最先进入消息队列的消息,即先进先出原则 (FIFO)。 + +![消息队列工作示意图](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc2/figures/07msg_work.png) + +##### 2.2.1.3 管理方式 + +消息队列控制块是一个结构体,其中含有消息队列相关的重要参数,在消息队列的功能实现中起重要的作用。消息队列的相关接口如下图所示,对一个消息队列的操作包含:创建消息队列 - 发送消息 - 接收消息 - 删除消息队列。 + +![消息队列相关接口](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc2/figures/07msg_ops.png) + +##### 2.2.1.4 消息队列使用场合 + +消息队列可以应用于发送不定长消息的场合,包括线程与线程间的消息交换,以及中断服务例程中给线程发送消息(中断服务例程不能接收消息)。下面分发送消息和同步消息两部分来介绍消息队列的使用。 + +发送消息 + +消息队列和邮箱的明显不同是消息的长度并不限定在 4 个字节以内;另外,消息队列也包括了一个发送紧急消息的函数接口。但是当创建的是一个所有消息的最大长度是 4 字节的消息队列时,消息队列对象将蜕化成邮箱。这个不限定长度的消息,也及时的反应到了代码编写的场合上,同样是类似邮箱的代码: + +``` +struct msg +{ + rt_uint8_t *data_ptr; /* 数据块首地址 */ + rt_uint32_t data_size; /* 数据块大小 */ +};复制错误复制成功 +``` + +和邮箱例子相同的消息结构定义,假设依然需要发送这样一个消息给接收线程。在邮箱例子中,这个结构只能够发送指向这个结构的指针(在函数指针被发送过去后,接收线程能够正确的访问指向这个地址的内容,通常这块数据需要留给接收线程来释放)。而使用消息队列的方式则大不相同: + +``` +void send_op(void *data, rt_size_t length) +{ + struct msg msg_ptr; + + msg_ptr.data_ptr = data; /* 指向相应的数据块地址 */ + msg_ptr.data_size = length; /* 数据块的长度 */ + + /* 发送这个消息指针给 mq 消息队列 */ + rt_mq_send(mq, (void*)&msg_ptr, sizeof(struct msg)); +}复制错误复制成功 +``` + +注意,上面的代码中,是把一个局部变量的数据内容发送到了消息队列中。在接收线程中,同样也采用局部变量进行消息接收的结构体: + +``` +void message_handler() +{ + struct msg msg_ptr; /* 用于放置消息的局部变量 */ + + /* 从消息队列中接收消息到 msg_ptr 中 */ + if (rt_mq_recv(mq, (void*)&msg_ptr, sizeof(struct msg), RT_WAITING_FOREVER) > 0) + { + /* 成功接收到消息,进行相应的数据处理 */ + } +}复制错误复制成功 +``` + +因为消息队列是直接的数据内容复制,所以在上面的例子中,都采用了局部变量的方式保存消息结构体,这样也就免去动态内存分配的烦恼了(也就不用担心,接收线程在接收到消息时,消息内存空间已经被释放)。 + +同步消息 + +在一般的系统设计中会经常遇到要发送同步消息的问题,这个时候就可以根据当时状态的不同选择相应的实现:两个线程间可以采用 **[消息队列 + 信号量或邮箱]** 的形式实现。发送线程通过消息发送的形式发送相应的消息给消息队列,发送完毕后希望获得接收线程的收到确认,工作示意图如下图所示: + +![同步消息示意图](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc2/figures/07msg_syn.png) + +根据消息确认的不同,可以把消息结构体定义成: + +``` +struct msg +{ + /* 消息结构其他成员 */ + struct rt_mailbox ack; +}; +/* 或者 */ +struct msg +{ + /* 消息结构其他成员 */ + struct rt_semaphore ack; +};复制错误复制成功 +``` + +第一种类型的消息使用了邮箱来作为确认标志,而第二种类型的消息采用了信号量来作为确认标志。邮箱作为确认标志,代表着接收线程能够通知一些状态值给发送线程;而信号量作为确认标志只能够单一的通知发送线程,消息已经确认接收。 + +#### 2.2.2 消息队列例程 + +在msgq_sample.c中课查看关于消息队列例程的代码 + +![1753263472313](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753263472313.png) + +编译运行,在终端输入msgq_sample启动例程。 + +![1753263606087](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753263606087.png) + +``` + \ | / +- RT - Thread Operating System + / | \ 4.1.0 build Jul 23 2025 17:02:30 + 2006 - 2022 Copyright by RT-Thread team +main run conut +msh >msgq_sample +msh >thread2: send message - A +thread1: recv msg from msg queue, the content:A +thread2: send message - B +thread2: send message - C +thread2: send message - D +thread2: send message - E +thread2: send message - F +thread2: send message - G +thread2: send message - H +thread2: send urgent message - I +thread2: send message - J +thread2: send message - K +thread1: recv msg from msg queue, the content:I +thread2: send message - L +thread2: send message - M +thread2: send message - N +thread2: send message - O +thread2: send message - P +thread2: send message - Q +thread2: send message - R +thread2: send message - S +thread2: send message - T +message queue stop send, thread2 quit +thread1: recv msg from msg queue, the content:B +thread1: recv msg from msg queue, the content:C +thread1: recv msg from msg queue, the content:D +thread1: recv msg from msg queue, the content:E +thread1: recv msg from msg queue, the content:F +thread1: recv msg from msg queue, the content:G +thread1: recv msg from msg queue, the content:H +thread1: recv msg from msg queue, the content:J +thread1: recv msg from msg queue, the content:K +thread1: recv msg from msg queue, the content:L +thread1: recv msg from msg queue, the content:M +thread1: recv msg from msg queue, the content:N +thread1: recv msg from msg queue, the content:O +thread1: recv msg from msg queue, the content:P +thread1: recv msg from msg queue, the content:Q +thread1: recv msg from msg queue, the content:R +thread1: recv msg from msg queue, the content:S +thread1: recv msg from msg queue, the content:T +thread1: detach mq +``` + +### 2.3 信号 + +#### 2.3.1 信号介绍 + +##### 2.3.1.1 概念 + +信号(又称为软中断信号),在软件层次上是对中断机制的一种模拟,在原理上,一个线程收到一个信号与处理器收到一个中断请求可以说是类似的。 + +##### 2.3.1.2 工作机制 + +信号在 RT-Thread 中用作异步通信,POSIX 标准定义了 sigset\_t 类型来定义一个信号集,然而 sigset\_t 类型在不同的系统可能有不同的定义方式,在 RT-Thread 中,将 sigset\_t 定义成了 unsigned long 型,并命名为 rt\_sigset\_t,应用程序能够使用的信号为 SIGUSR1(10)和 SIGUSR2(12)。 + +信号本质是软中断,用来通知线程发生了异步事件,用做线程之间的异常通知、应急处理。一个线程不必通过任何操作来等待信号的到达,事实上,线程也不知道信号到底什么时候到达,线程之间可以互相通过调用 rt\_thread\_kill() 发送软中断信号。 + +收到信号的线程对各种信号有不同的处理方法,处理方法可以分为三类: + +第一种是类似中断的处理程序,对于需要处理的信号,线程可以指定处理函数,由该函数来处理。 + +第二种方法是,忽略某个信号,对该信号不做任何处理,就像未发生过一样。 + +第三种方法是,对该信号的处理保留系统的默认值。 + +如下图所示,假设线程 1 需要对信号进行处理,首先线程 1 安装一个信号并解除阻塞,并在安装的同时设定了对信号的异常处理方式;然后其他线程可以给线程 1 发送信号,触发线程 1 对该信号的处理。 + +![信号工作机制](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc2/figures/07signal_work.png) + +当信号被传递给线程 1 时,如果它正处于挂起状态,那会把状态改为就绪状态去处理对应的信号。如果它正处于运行状态,那么会在它当前的线程栈基础上建立新栈帧空间去处理对应的信号,需要注意的是使用的线程栈大小也会相应增加。 + +2.3.1.3 管理方式 + +对于信号的操作,有以下几种:安装信号、阻塞信号、阻塞解除、信号发送、信号等待。信号的接口详见下图: + +![信号相关接口](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc2/figures/07signal_ops.png) + +#### 2.3.2 信号例程 + +在signal_sample.c中可查看古纳于signal_sample.c中的示例代码 + +![1753264589379](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753264589379.png) + +编译运行输入signal_sample启动例程 + +![1753265395259](images/【RSOC25】Day3课程笔记:线程间的同步和通讯/1753265395259.png) + +``` + \ | / +- RT - Thread Operating System + / | \ 4.1.0 build Jul 23 2025 17:02:30 + 2006 - 2022 Copyright by RT-Thread team +main run conut +msh >signal_sample +thread1 count : 0 +thread1 count : 1 +thread1 count : 2 +msh >thread1 received signal 30 +thread1 count : 3 +thread1 count : 4 +thread1 count : 5 +thread1 count : 6 +thread1 count : 7 +thread1 count : 8 +thread1 count : 9 + +``` + +## 3.课后作业 + +编写代码上传至git仓库,程序需要体现出信号量、互斥量、事件集、邮箱、消息队列、信号的作用(上传6个C文件,每个文件体现一种功能)。 + +作业在代码在day3/IPC1和IPC2目录下 + +### 3.1 IPC1 + +#### 3.1.1 信号量示例(semaphore\_demo.c) + +**功能**:实现生产者 - 消费者模型,生产者每生产 10 个产品后释放信号量,消费者等待信号量后消费产品。 + +``` +#include + +#define THREAD_PRIORITY 25 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_sem_t sem = RT_NULL; +static rt_uint32_t product_count = 0; + +/* 生产者线程 */ +static void producer_thread(void *param) +{ + while (1) + { + product_count++; + rt_kprintf("Produced: %d\n", product_count); + + /* 每生产10个产品,释放一次信号量 */ + if (product_count % 10 == 0) + { + rt_kprintf("Producer: release semaphore\n"); + rt_sem_release(sem); + } + rt_thread_mdelay(100); + } +} + +/* 消费者线程 */ +static void consumer_thread(void *param) +{ + rt_uint32_t consumed = 0; + while (1) + { + /* 等待信号量(永久等待) */ + if (rt_sem_take(sem, RT_WAITING_FOREVER) == RT_EOK) + { + consumed += 10; + rt_kprintf("Consumer: consumed %d products\n", consumed); + } + } +} + +int semaphore_demo(void) +{ + /* 创建信号量,初始值为0 */ + sem = rt_sem_create("sem_demo", 0, RT_IPC_FLAG_PRIO); + if (sem == RT_NULL) + { + rt_kprintf("Create semaphore failed!\n"); + return -1; + } + + /* 创建生产者线程 */ + rt_thread_t producer = rt_thread_create("producer", + producer_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (producer) rt_thread_startup(producer); + + /* 创建消费者线程 */ + rt_thread_t consumer = rt_thread_create("consumer", + consumer_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (consumer) rt_thread_startup(consumer); + + return 0; +} +MSH_CMD_EXPORT(semaphore_demo, semaphore demo); +``` + +#### 3.1.2 互斥量示例(mutex\_demo.c) + +**功能**:保护共享变量,确保两个线程对共享变量的操作不会出现数据不一致。 + +``` +#include + +#define THREAD_PRIORITY 20 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_mutex_t mutex = RT_NULL; +static rt_int32_t shared_var = 0; // 共享变量 + +/* 线程1:对共享变量加1 */ +static void thread1_entry(void *param) +{ + while (1) + { + rt_mutex_take(mutex, RT_WAITING_FOREVER); + shared_var++; + rt_kprintf("Thread1: shared_var = %d\n", shared_var); + rt_thread_mdelay(100); // 模拟耗时操作 + rt_mutex_release(mutex); + rt_thread_mdelay(100); + } +} + +/* 线程2:对共享变量加1并检查一致性 */ +static void thread2_entry(void *param) +{ + rt_int32_t last_val = 0; + while (1) + { + rt_mutex_take(mutex, RT_WAITING_FOREVER); + shared_var++; + if (shared_var != last_val + 2) // 检查是否连续递增 + { + rt_kprintf("Thread2: Data race detected! shared_var = %d\n", shared_var); + } + last_val = shared_var; + rt_kprintf("Thread2: shared_var = %d\n", shared_var); + rt_mutex_release(mutex); + rt_thread_mdelay(100); + } +} + +int mutex_demo(void) +{ + /* 创建互斥量 */ + mutex = rt_mutex_create("mutex_demo", RT_IPC_FLAG_PRIO); + if (mutex == RT_NULL) + { + rt_kprintf("Create mutex failed!\n"); + return -1; + } + + /* 创建线程1 */ + rt_thread_t tid1 = rt_thread_create("thread1", + thread1_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1) rt_thread_startup(tid1); + + /* 创建线程2 */ + rt_thread_t tid2 = rt_thread_create("thread2", + thread2_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid2) rt_thread_startup(tid2); + + return 0; +} +MSH_CMD_EXPORT(mutex_demo, mutex demo); +``` + +#### 3.1.3 事件集示例(event\_demo.c) + +**功能**:线程 1 等待特定事件组合(或 / 与逻辑),线程 2 发送事件触发线程 1。 + +``` +#include + +#define THREAD_PRIORITY 20 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_mutex_t mutex = RT_NULL; +static rt_int32_t shared_var = 0; // 共享变量 + +/* 线程1:对共享变量加1 */ +static void thread1_entry(void *param) +{ + while (1) + { + rt_mutex_take(mutex, RT_WAITING_FOREVER); + shared_var++; + rt_kprintf("Thread1: shared_var = %d\n", shared_var); + rt_thread_mdelay(100); // 模拟耗时操作 + rt_mutex_release(mutex); + rt_thread_mdelay(100); + } +} + +/* 线程2:对共享变量加1并检查一致性 */ +static void thread2_entry(void *param) +{ + rt_int32_t last_val = 0; + while (1) + { + rt_mutex_take(mutex, RT_WAITING_FOREVER); + shared_var++; + if (shared_var != last_val + 2) // 检查是否连续递增 + { + rt_kprintf("Thread2: Data race detected! shared_var = %d\n", shared_var); + } + last_val = shared_var; + rt_kprintf("Thread2: shared_var = %d\n", shared_var); + rt_mutex_release(mutex); + rt_thread_mdelay(100); + } +} + +int mutex_demo(void) +{ + /* 创建互斥量 */ + mutex = rt_mutex_create("mutex_demo", RT_IPC_FLAG_PRIO); + if (mutex == RT_NULL) + { + rt_kprintf("Create mutex failed!\n"); + return -1; + } + + /* 创建线程1 */ + rt_thread_t tid1 = rt_thread_create("thread1", + thread1_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1) rt_thread_startup(tid1); + + /* 创建线程2 */ + rt_thread_t tid2 = rt_thread_create("thread2", + thread2_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid2) rt_thread_startup(tid2); + + return 0; +} +MSH_CMD_EXPORT(mutex_demo, mutex demo); +``` + +### 3.2 IPC2 + +#### 3.2.1 邮箱示例(mailbox\_demo.c) + +**功能**:通过邮箱传递字符串指针,实现线程间消息传递。 + +``` + +#include + +#define THREAD_PRIORITY 10 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +/* 邮箱控制块和内存池 */ +static struct rt_mailbox mb; +static char mb_pool[64]; // 邮箱内存池(存放指针) + +/* 邮件内容 */ +static char msg1[] = "Hello, Mailbox!"; +static char msg2[] = "RT-Thread IPC"; +static char msg3[] = "Exit"; + +/* 接收邮件线程 */ +static void recv_mail_thread(void *param) +{ + char *msg; + while (1) + { + rt_kprintf("Waiting for mail...\n"); + /* 接收邮件(永久等待) */ + if (rt_mb_recv(&mb, (rt_ubase_t *)&msg, RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("Received: %s\n", msg); + if (msg == msg3) // 收到退出消息 + { + rt_kprintf("Exit recv thread\n"); + break; + } + } + } + rt_mb_detach(&mb); // 脱离邮箱 +} + +/* 发送邮件线程 */ +static void send_mail_thread(void *param) +{ + rt_mb_send(&mb, (rt_ubase_t)msg1); + rt_thread_mdelay(1000); + + rt_mb_send(&mb, (rt_ubase_t)msg2); + rt_thread_mdelay(1000); + + rt_mb_send(&mb, (rt_ubase_t)msg3); // 发送退出消息 +} + +int mailbox_demo(void) +{ + /* 初始化邮箱 */ + if (rt_mb_init(&mb, "mb_demo", + mb_pool, sizeof(mb_pool)/sizeof(rt_ubase_t), + RT_IPC_FLAG_PRIO) != RT_EOK) + { + rt_kprintf("Init mailbox failed!\n"); + return -1; + } + + /* 创建接收线程 */ + rt_thread_t tid1 = rt_thread_create("recv_mail", + recv_mail_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1) rt_thread_startup(tid1); + + /* 创建发送线程 */ + rt_thread_t tid2 = rt_thread_create("send_mail", + send_mail_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY + 1, THREAD_TIMESLICE); + if (tid2) rt_thread_startup(tid2); + + return 0; +} +MSH_CMD_EXPORT(mailbox_demo, mailbox demo); +``` + +#### 3.2.2 消息队列示例(msgqueue\_demo.c) + +**功能**:线程 2 发送普通消息和紧急消息,线程 1 接收消息并处理(紧急消息优先)。 + +``` +#include +#define THREAD_PRIORITY 20 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +/* 消息队列控制块和内存池 */ +static struct rt_messagequeue mq; +static char msg_pool[256]; // 消息队列内存池 + +/* 接收消息线程 */ +static void recv_msg_thread(void *param) +{ + char msg_buf; + rt_uint8_t count = 0; + + while (count < 5) + { + /* 接收消息(永久等待) */ + if (rt_mq_recv(&mq, &msg_buf, sizeof(msg_buf), RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("Received message: %c\n", msg_buf); + count++; + } + } + rt_mq_detach(&mq); // 脱离消息队列 +} + +/* 发送消息线程 */ +static void send_msg_thread(void *param) +{ + char msg = 'A'; + rt_thread_mdelay(500); + + /* 发送普通消息 */ + rt_mq_send(&mq, &msg, 1); + rt_kprintf("Sent: %c\n", msg); + msg++; + + /* 发送紧急消息(插入队列头部) */ + rt_mq_urgent(&mq, &msg, 1); + rt_kprintf("Sent urgent: %c\n", msg); + msg++; + + /* 继续发送普通消息 */ + rt_mq_send(&mq, &msg, 1); + rt_kprintf("Sent: %c\n", msg); +} + +int msgqueue_demo(void) +{ + /* 初始化消息队列 */ + if (rt_mq_init(&mq, "mq_demo", + msg_pool, 1, // 每个消息1字节 + sizeof(msg_pool), + RT_IPC_FLAG_PRIO) != RT_EOK) + { + rt_kprintf("Init msgqueue failed!\n"); + return -1; + } + + /* 创建接收线程 */ + rt_thread_t tid1 = rt_thread_create("recv_msg", + recv_msg_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1) rt_thread_startup(tid1); + + /* 创建发送线程 */ + rt_thread_t tid2 = rt_thread_create("send_msg", + send_msg_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY + 1, THREAD_TIMESLICE); + if (tid2) rt_thread_startup(tid2); + + return 0; +} +MSH_CMD_EXPORT(msgqueue_demo, message queue demo); +``` + +#### 3.2.3 信号示例(signal\_demo.c) + +**功能**:线程 1 注册信号处理函数,主线程发送信号触发处理函数。 + +``` +#include + +#define THREAD_PRIORITY 25 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_thread_t tid = RT_NULL; + +/* 信号处理函数 */ +void signal_handler(int sig) +{ + rt_kprintf("Received signal: %d, handling...\n", sig); + /* 信号处理逻辑:例如清理资源 */ +} + +/* 线程入口:等待信号 */ +static void signal_thread(void *param) +{ + /* 安装信号处理函数 */ + rt_signal_install(SIGUSR1, signal_handler); + rt_signal_unmask(SIGUSR1); // 解除信号屏蔽 + + rt_kprintf("Signal thread running, wait for signal...\n"); + while (1) + { + rt_thread_mdelay(500); // 线程正常运行逻辑 + } +} + +int signal_demo(void) +{ + /* 创建线程 */ + tid = rt_thread_create("signal_thread", + signal_thread, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid) rt_thread_startup(tid); + + /* 延迟1秒后发送信号 */ + rt_thread_mdelay(1000); + rt_kprintf("Sending SIGUSR1 to thread...\n"); + rt_thread_kill(tid, SIGUSR1); // 发送信号 + + /* 再延迟1秒后发送第二次信号 */ + rt_thread_mdelay(1000); + rt_kprintf("Sending SIGUSR1 again...\n"); + rt_thread_kill(tid, SIGUSR1); + + return 0; +} +MSH_CMD_EXPORT(signal_demo, signal demo); +``` diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day4 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230.md" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day4 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230.md" new file mode 100644 index 0000000000000000000000000000000000000000..0d9fa9e46e3b73ccb64d064f56fe03ade9fc61fd --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day4 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232IO\350\256\276\345\244\207\346\250\241\345\236\213\344\270\216\350\256\276\345\244\207\351\251\261\345\212\250\346\241\206\346\236\266\345\256\236\346\210\230.md" @@ -0,0 +1,418 @@ +# 【RSOC25】Day4 课程笔记:IO设备与设备驱动框架实战 + +[写在前面] + +参考内容[RTT设备和驱动](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/README)这部分内容比较难以理解多动手多实践,在开发中慢慢熟悉,最后的实验一定要自己尝试写一写加深印象。 + +该笔记围绕 RT-Thread 的 I/O 设备模型与设备驱动框架展开,介绍了 I/O 设备模型的三层架构(I/O 设备管理层、设备驱动框架层、设备驱动层)及其作用,以 PIN 设备为例分析了框架对接流程,包括各层代码位置、初始化与注册过程及 API 调用链路;还讲解了设备驱动框架的作用,并通过虚拟温湿度传感器设备的开发实例(含驱动层、管理层、测试代码的实现及实验结果),展示了新增设备时参照 PIN 设备流程创建相关文件以实现上下层接口衔接的方法。 + +## 1.IO设备模型介绍 + +绝大部分的嵌入式系统都包括一些 I/O(Input/Output,输入 / 输出)设备,例如仪器上的数据显示屏、工业设备上的串口通信、数据采集设备上用于保存数据的 Flash 或 SD 卡,以及网络设备的以太网接口等,都是嵌入式系统中容易找到的 I/O 设备例子。 + +### 1.1 IO设备模型框架概述 + +##### 1.1.1 IO设备模型框架的介绍 + +RT-Thread 提供了一套简单的 I/O 设备模型框架,如下图所示,它位于硬件和应用程序之间,共分成三层,从上到下分别是 I/O 设备管理层、设备驱动框架层、设备驱动层。 + +![I/O 设备模型框架补充图](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/device/figures/io-dev-ex.png) + +应用程序通过 I/O 设备管理接口获得正确的设备驱动,然后通过这个设备驱动与底层 I/O 硬件设备进行数据(或控制)交互。 + +I/O 设备管理层实现了对设备驱动程序的封装。应用程序通过图中的"I/O设备管理层"提供的标准接口访问底层设备,设备驱动程序的升级、更替不会对上层应用产生影响。这种方式使得设备的硬件操作相关的代码能够独立于应用程序而存在,双方只需关注各自的功能实现,从而降低了代码的耦合性、复杂性,提高了系统的可靠性。 + +设备驱动框架层是对同类硬件设备驱动的抽象,将不同厂家的同类硬件设备驱动中相同的部分抽取出来,将不同部分留出接口,由驱动程序实现。 + +设备驱动层是一组驱使硬件设备工作的程序,实现访问硬件设备的功能。它负责创建和注册 I/O 设备,对于操作逻辑简单的设备,可以不经过设备驱动框架层,直接将设备注册到 I/O 设备管理器中, + +##### 1.1.2 IO设备框架的作用 + +![1753344289839](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753344289839.png) + +![1753344300187](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753344300187.png) + +不同MCU厂商的API设计差异导致代码复用困难,阿里IO框架通过统一接口解决该问题。 +框架采用分层设计:设备驱动层对接厂商SDK,IO管理层提供标准API(如GPIO、I2C、SPI)。 +设备分类为字符设备(顺序访问,如串口)和块设备(随机访问,如Flash),便于组件依赖管理。 + +##### 1.1.3 IO设备模型的结构 + +RT-Thread 的设备模型是建立在内核对象模型基础之上的,设备被认为是一类对象,被纳入对象管理器的范畴。每个设备对象都是由基对象派生而来,每个具体设备都可以继承其父类对象的属性,并派生出其私有属性,下图是设备对象的继承和派生关系示意图。 + +![设备继承关系图](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/device/figures/io-parent.png) + +##### 1.1.4 IO设备访问和管理 + +应用程序通过 I/O 设备管理接口来访问硬件设备,当设备驱动实现后,应用程序就可以访问该硬件。I/O 设备管理接口与 I/O 设备的操作方法的映射关系下图所示: + +![I/O 设备管理接口与 I/O 设备的操作方法的映射关系](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/device/figures/io-fun-call.png) + +### 1.2 IO设备模型框架分析 + +1.2.1 PIN设备框架对接分析 + +我们以PIN设备为例分析IO设备模型框架下,对于不同芯片平台bsp(官方适配芯片包)是如何与设备驱动层和IO管理层对接的。我们打开之前的RSOC目录,为了查看代码方便我们在目录下选择在Vscode中打开工程然后进入rt-thread/components/drivrs目录下。 + +![1753352384121](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753352384121.png) + +仔细查看这部分的几个目录不知道你有没有感觉,看上去有点眼熟,但其实这个drivers目录下存放的代码就是设备和驱动部分的内容,而每个目录对应的就是官网的介绍的几个设备种类,而相应目录下则是存放了属于IO管理层的各类设备源代码。 + +![1753352824716](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753352824716.png) + +但却没有找到我们的PIN设备这时候我们可以打开misc目录下可以看到其中有一个pin.c代码而我们要找的PIN设备的IO管理层代码就在这里面,可以看到ADC与DAC还有PWM设备的代码都在这里面,想必这是因为这些设备都比较简单而且这三类设备都只需要一个接口而且是通过接口复用实现,然后我们可以看到在include文件夹下还存在drivers里面存放的是该目录下所有的头文件,rtdevice.h里面定义的是设备的头文件条件编译我们在下一章会用到。 + +![1753353298708](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753353298708.png) + +打开pin.c然后退回到libraries目录下可以查看改目录下有两个目录其中HAL_drivers目录下存放的便是设备驱动框架层的代码,然后下面的STM32F4xx_HAL大家应该不陌生了,stm32hal库的SDK。 + +![1753353773782](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753353773782.png) + +然后我们打开HAL_drivers中的drv_gpio.c文件最后可以看到两个函数,这两个函数想来应该不陌生了rt_hw_pin_init()函数将pin设备注册到设备驱动框架,然后调用rt_device_pin_register()函数。 + +![1753356049790](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753356049790.png) + +我们选中rt_device_pin_register()函数有点跳转到定义。 + +![1753356440964](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753356440964.png) + +发现他跳转回到了我们的pin.c文件中rt_device_pin_register()中调用了rt_device_register()接口将设备注册到IO管理器中程序才能访问PIN设备 + +![1753356538752](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753356538752.png) + +接下来我们来看看系统提供的PIN设备的api函数,在pin.c的最下面 + +![1753357615173](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753357615173.png) + +我们来研究以下这个rt_pin_write函数发现他最后在写入的时候,调用了_hw_pin_ops->pin_write这个函数指针,跳转到定义也并没有找找这个函数究竟在哪里实现了。 + +![1753357838842](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753357838842.png) + +但是别着急我们刚才和打开了drv_gpio.c文件在这里我们看到有stm32_pin_write函数,虽然不知道为什么,但是今天老师在讲解调试的时候确实就跳转到了这里,我想应该是rt官方做适配的时候一小调整,那么之前的函数指针指向这里调用了这个函数,又在这个函数中调用了底层驱动中的HAL库中的HAL_GPIO_WritePin()函数那么一切的流程就跑通了。 + +![1753358280740](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753358280740.png) + +## 2.设备驱动框架 + +### 2.1 设备驱动框架介绍 + +![I/O 设备模型框架](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/device/figures/io-dev.png) + +更具上一节的介绍,我们bsp适配其实就是完成了设备驱动框架到设备驱动层的适配,保证上层接口一致性,修改和适配下层接口,从而提高代码的可复用性和开发的快捷性。 + +### 2.2 虚拟设备框架开发 + +节上一张IO模型框架分析,那么我们想要新添加一个设备,就只需要更具PIN设备的流程创建和完善drv_xxx_.c/h与xx.c/h文件即可,在xx.c文件中定义上层api并调用drv_xx.c中的相应函数,并完成drv_xx.c中相应函数对底层库函数的调用即可。 + +那么本节我们将仿照PIN设备创建一个虚拟温湿度设备,具体实现如下(自己看代码把,和我上面讲的差不多) + +#### 2.2.1 虚拟温湿度传感器设备框架 + +drv_vir_sensor.c + +``` +#include +#include "drv_vir_sensor.h" + + + + +// 定义传感器实例 +struct vir_sensor_dev vir_sensor; + +// 打印传感器信息 +void vir_sensor_print_info(struct rt_device *device, rt_uint8_t *str) +{ + rt_kprintf("vir_sensor info: %s\n", str); +} + +// 设置传感器数据 +void vir_sensor_set_data(struct rt_device *device, rt_uint32_t data) +{ + struct vir_sensor_dev *sensor = (struct vir_sensor_dev *)device; + sensor->sensor_data = data; + rt_kprintf("vir_sensor set data: %d\n", data); +} + +// 获取传感器数据 +void vir_sensor_get_data(struct rt_device *device, rt_uint32_t *data) +{ + struct vir_sensor_dev *sensor = (struct vir_sensor_dev *)device; + *data = sensor->sensor_data; +} + +// 传感器操作函数集 +static struct rt_vir_sensor_ops vir_sensor_ops = { + vir_sensor_print_info, + vir_sensor_set_data, + vir_sensor_get_data, +}; + +// 传感器初始化 +static int rt_hw_vir_sensor_init(void) +{ + // 初始化设备数据 + vir_sensor.sensor_data = 0; + vir_sensor.info = "Virtual Sensor (Temperature/Humidity)"; + + // 注册传感器设备 + rt_hw_vir_sensor_register(&vir_sensor.parent, "vir_sensor", &vir_sensor_ops, (void*)vir_sensor.info); + return RT_EOK; +} + +INIT_DEVICE_EXPORT(rt_hw_vir_sensor_init); // 设备初始化导出 +``` + +drv_vir_sensor.h + +``` +#ifndef __DRV_VIR_SENSOR_H__ +#define __DRV_VIR_SENSOR_H__ + +#include +#include "../vir_sensor/vir_sensor.h" + +// 具体虚拟传感器设备结构体 +struct vir_sensor_dev +{ + struct rt_vir_sensor_device parent; // 继承虚拟传感器设备基类 + rt_uint32_t sensor_data; // 传感器数据存储 + char *info; // 设备描述信息 +}; + +#endif + +``` + +vir_sensor.c + +``` +#include +#include +#include "vir_sensor.h" +#include + + +// 设备初始化 +static rt_err_t _vir_sensor_init(rt_device_t dev) +{ + rt_kprintf("vir_sensor init\n"); + return RT_EOK; +} + +// 设备打开 +static rt_err_t _vir_sensor_open(rt_device_t dev, rt_uint16_t oflag) +{ + rt_kprintf("vir_sensor open\n"); + return RT_EOK; +} + +// 设备关闭 +static rt_err_t _vir_sensor_close(rt_device_t dev) +{ + rt_kprintf("vir_sensor close\n"); + return RT_EOK; +} + +// 设备读操作 +static rt_size_t _vir_sensor_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + rt_vir_sensor_device_t sensor = (rt_vir_sensor_device_t)dev; + if (sensor->ops->get_data && buffer != RT_NULL && size >= sizeof(rt_uint32_t)) + { + sensor->ops->get_data(dev, (rt_uint32_t*)buffer); + return sizeof(rt_uint32_t); + } + return -RT_ERROR; +} + +// 设备写操作 +static rt_size_t _vir_sensor_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + rt_vir_sensor_device_t sensor = (rt_vir_sensor_device_t)dev; + if (sensor->ops->set_data && buffer != RT_NULL && size >= sizeof(rt_uint32_t)) + { + sensor->ops->set_data(dev, *(rt_uint32_t*)buffer); + return sizeof(rt_uint32_t); + } + return -RT_ERROR; +} + +// 设备控制 +static rt_err_t _vir_sensor_control(rt_device_t dev, int cmd, void *args) +{ + rt_kprintf("vir_sensor control cmd: %d\n", cmd); + return RT_EOK; +} + +// 传感器注册函数 +rt_err_t rt_hw_vir_sensor_register(rt_vir_sensor_device_t device, const char *name, + const struct rt_vir_sensor_ops *ops, const void *user_data) +{ + RT_ASSERT(device != RT_NULL && ops != RT_NULL); + rt_err_t result; + + device->ops = ops; + // 绑定设备操作函数 + device->parent.init = _vir_sensor_init; + device->parent.open = _vir_sensor_open; + device->parent.close = _vir_sensor_close; + device->parent.read = _vir_sensor_read; + device->parent.write = _vir_sensor_write; + device->parent.control = _vir_sensor_control; + + // 注册到RT-Thread设备框架 + result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); + return result; +} + +// 传感器读接口 +rt_err_t rt_vir_sensor_read(rt_vir_sensor_device_t device, rt_uint32_t *data) +{ + RT_ASSERT(device != RT_NULL && device->ops != RT_NULL && data != RT_NULL); + if (device->ops->get_data) + { + device->ops->get_data((rt_device_t)device, data); + return RT_EOK; + } + return -RT_ERROR; +} + +// 传感器写接口 +rt_err_t rt_vir_sensor_write(rt_vir_sensor_device_t device, rt_uint32_t data) +{ + RT_ASSERT(device != RT_NULL && device->ops != RT_NULL); + if (device->ops->set_data) + { + device->ops->set_data((rt_device_t)device, data); + return RT_EOK; + } + return -RT_ERROR; +} + + + + +``` + +vir_sensor.h + +``` +#ifndef __VIR_SENSOR_H__ +#define __VIR_SENSOR_H__ + +#include +#include + +// 虚拟传感器操作函数集 +struct rt_vir_sensor_ops +{ + void (*print_info)(struct rt_device *device, rt_uint8_t *str); // 打印信息 + void (*set_data)(struct rt_device *device, rt_uint32_t data); // 设置传感器数据 + void (*get_data)(struct rt_device *device, rt_uint32_t *data); // 获取传感器数据 +}; + +// 虚拟传感器设备结构体 +struct rt_vir_sensor_device +{ + struct rt_device parent; // 继承RT-Thread设备基类 + const struct rt_vir_sensor_ops *ops; // 操作函数集 +}; +typedef struct rt_vir_sensor_device *rt_vir_sensor_device_t; + +// 注册及操作函数声明 +rt_err_t rt_hw_vir_sensor_register(rt_vir_sensor_device_t device, const char *name, + const struct rt_vir_sensor_ops *ops, const void *user_data); +rt_err_t rt_vir_sensor_read(rt_vir_sensor_device_t device, rt_uint32_t *data); +rt_err_t rt_vir_sensor_write(rt_vir_sensor_device_t device, rt_uint32_t data); + +#endif + +``` + +vir_sensor_test.c + +``` +#include +#include +#include "vir_sensor/vir_sensor.h" +#include "drv_vir_sensor/drv_vir_sensor.h" + + + + +int vir_sensor_test(void) +{ + rt_device_t sensor_dev; + rt_uint32_t data, read_data; + rt_size_t ret; + + // 查找设备 + sensor_dev = rt_device_find("vir_sensor"); + if (sensor_dev == RT_NULL) + { + rt_kprintf("find vir_sensor device failed!\n"); + return -RT_ERROR; + } + + // 打开设备 + if (rt_device_open(sensor_dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) + { + rt_kprintf("open vir_sensor device failed!\n"); + return -RT_ERROR; + } + + // 写入数据(设备接口) + data = 255; // 示例数据(可表示25.5℃等) + ret = rt_device_write(sensor_dev, 0, &data, sizeof(data)); + if (ret != sizeof(data)) + rt_kprintf("write vir_sensor failed!\n"); + + // 读取数据(设备接口) + ret = rt_device_read(sensor_dev, 0, &read_data, sizeof(read_data)); + if (ret == sizeof(read_data)) + rt_kprintf("device read: %d\n", read_data); + + // 专用接口操作 + rt_vir_sensor_write((rt_vir_sensor_device_t)sensor_dev, 600); // 示例数据 + rt_vir_sensor_read((rt_vir_sensor_device_t)sensor_dev, &read_data); + rt_kprintf("special api read: %d\n", read_data); + + // 关闭设备 + rt_device_close(sensor_dev); + return RT_EOK; +} +MSH_CMD_EXPORT(vir_sensor_test, vir_sensor test command); // 导出为shell命令 + +``` + +#### 2.2.2 虚拟温湿度传感器设备实验 + +打开RT-studio工具我们之前的RSOC工程,在applications目录下新建DRIVE_demo目录如下 + +![1753362539230](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753362539230.png) + +点击构建,构建成功如下图 + +![1753362638355](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753362638355.png) + +编译运行,输入vir_sensor_test回车 + +![1753362782846](images/【RSOC25】Day4课程笔记:IO设备模型与设备驱动框架实战/1753362782846.png) + +``` + \ | / +- RT - Thread Operating System + / | \ 4.1.0 build Jul 24 2025 20:41:59 + 2006 - 2022 Copyright by RT-Thread team +main run conut +msh >vir_sensor_test +vir_sensor init +vir_sensor open +vir_sensor set data: 255 +device read: 255 +vir_sensor set data: 600 +special api read: 600 +vir_sensor close +msh > +``` diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day5 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237.md" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day5 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237.md" new file mode 100644 index 0000000000000000000000000000000000000000..b41d9e143dd9c1e7f1644b0d82292e3d003ed5e6 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\351\251\254\351\224\241\345\260\247/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221Day5 \350\257\276\347\250\213\347\254\224\350\256\260\357\274\232\347\273\204\344\273\266\344\270\216\350\275\257\344\273\266\345\214\205\345\217\212\346\236\204\345\273\272\347\263\273\347\273\237.md" @@ -0,0 +1,489 @@ +# 【RSOC25】Day5 课程笔记:组件与软件包及构建系统 + +## 1.构建与配置系统介绍 + +![1753426232711](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753426232711.png) + +### 1.1Kconfig工作机制 + +C语言项目的裁剪配置本质上通过条件编译和宏的展开来实现的,RT-Thread借助Kconfig这套机制更方便的实现了这一功能。当前以Windows下Env工具中的使用为例,简述Kconfig在RT-Thread的工作机制。 + +Kconfig机制包括了Kconfig文件和配置UI界面(如menuconfig,pyconfig等)。Kconfig机制有如下特点: + +Kconfig文件中的配置项会映射至rtconfig.h中 + +Kconfig文件可以随源码分散至各级子目录,便于灵活修改。 + +``` +# .config片段 +CONFIG_RT_USING_TIMER_SOFT=y +CONFIG_RT_TIMER_THREAD_PRIO=4 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 +CONFIG_RT_DEBUG=y + + +``` + +``` +// 相对应的rtconfig.h片段 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 512 +#define RT_DEBUG + +``` + +当我们运行menuconfig图形化界面之后会遍历所有的kconfig文件待我们配置玩之后保存会生成新的.config文件和rtconfig.h文件。![构建配置系统](https://www.rt-thread.org/document/site/development-tools/build-config-system/figures/buildconfig2.png)Kconfig文件在源码中呈现树形结构,需要**在工程的根目录下存在一份顶层Kconfig文件**,顶层Kconfig文件在文件中通过source语句显示地调用各子目录下的Kconfig文件。Env在根目录下执行menuconfig命令后会递归解析各级Kconfig文件,然后提供如下配置界面,完成相应的配置后并保存,根目录下会存在一份.config文件保存当前选择的配置项,并将.config文件转为RT-Thread的系统配置文件rtconfig.h。 + +### 1.2 Kconfig示例讲解 + +这里我们可以打开工程最外层的kconfig文件查看可以看到这里标注了几个kconfig的字文件地址我们去看一看driver/kconfig(因为另外两个我没有找到) + +![1753428620261](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753428620261.png) + +看一下这些配置其实就是我们之前menconfig运行后的"Hardware Drivers Config"菜单关于Kconfig的语法[Kconfig在RTT中的使用](https://www.rt-thread.org/document/site/#/development-tools/build-config-system/Kconfig)自己查看即可,其实也很简单。![1753429146564](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753429146564.png) + +### 1.2 Scons构建系统 + +SCons 是一套由 Python 语言编写的开源构建系统,类似于 GNU Make。它采用不同于通常 Makefile 文件的方式,而是使用 SConstruct 和 SConscript 文件来替代。这些文件也是 Python 脚本,能够使用标准的 Python 语法来编写。所以在 SConstruct、SConscript 文件中可以调用 Python 标准库进行各类复杂的处理,而不局限于 Makefile 设定的规则。 + +关于这部分查看官网的[Scons构建工具](https://www.rt-thread.org/document/site/#/development-tools/build-config-system/SCons)没什么好讲的,后面会带大家编写一个代码实验。不懂得查看官网教程即可。 + +#### 1.2.1RT-Thread中Scons的脚本结构 + +SCons 使用 SConscript 和 SConstruct 文件来组织源码结构并进行构建,SConstruct是scons构建的主脚本,SConscript存放在源代码的子目录下,通常放在项目的子目录,以达到分层构建的目的。一个项目 (BSP) 只有一 SConstruct,但是会有多个 SConscript。一般情况下,每个存放有源代码的子目录下都会放置一个 SConscript。 + +``` +/ + -- rtconfig.py ---- 控制SCons构建的配置文件,存放了如工具链,构建参数等配置。 + -- SConscript + -- SConstruct ---- SCons的入口脚本,初始化了SCons构建rt-thread所需的必要环境 + -- Kconfig ---- 顶层Kconfig文件,menuconfig的入口Kconfig文件 + -- rt-thread/ + --- src/ + ---- SConscript ---- 各级源码的scons子脚本,控制当前级别下的源码构建行为 + ---- Kconfig ---- 各级源码的Kconfig子脚本,存放当前级别下的配置项 + ---- **.c + +``` + +如上图所示,为了方便开发者使用SCons,RT-Thread搭建了如图所示的构建框架,其中包括了一份SCons的入口脚本(SConstruct),以及分散在各级源码的SCons子脚本(SConscript),还有一份便于配置构建行为的配置脚本(rtconfig.py)同时,RT-Thread也在SCons标准接口的基础上,提供了一组用于组织源码工程的扩展接口。开发者在使用时,可以借助RT-Thread提供的扩展接口,更方便的完成源码的组织与配置。 + +![构建配置系统](https://www.rt-thread.org/document/site/development-tools/build-config-system/figures/buildconfig19.png) + +为了使 RT-Thread 更好的支持多种编译器,以及方便的调整构建参数,RT-Thread 为每个 BSP 单独创建了一个名为 rtconfig.py 的配置文件。因此每一个 RT-Thread BSP 目录下都会存在下面三个文件:rtconfig.py、SConstruct 和 SConscript,它们控制 BSP 的构建。一个 BSP 中只有一个 SConstruct 文件,但是却会有多个 SConscript 文件,可以说 SConscript 文件是组织源码的主力军。 + +RT-Thread当前的构建系统由以下几个部分组成: + +``` +flowchart LR + A(RT-Thread构建系统)-->Kconfig + A(RT-Thread构建系统)-->rtconfig.py + A(RT-Thread构建系统)-->SCons + SCons --> SConscript + SCons --> SConstruct + SConscript --> Scons标准函数 + SConscript --> RT-Thread自定义函数 + SConscript --> Python函数 +``` + +#### 1.2.2 Scons 函数在 SConscript 中的经典示例 + +下面我们将以几个 SConscript 为例讲解 scons 构建工具的使用方法。 + +##### 1.2.2.1 构建一个基本的 Group + +导入RT-Thread的自定义构建函数,几乎每一个RT-Thread的Sconscript都需要这么做。 + +只有导入了building模块,才可以使用2.2.2介绍的RT-Thread自定义Scons函数 + +``` +from building import * + +cwd = GetCurrentDir() # 获取当前脚本的路径 +CPPPATH = [cwd] # 将当前路径加入构建搜索的头文件路径 +src = Split(''' +shell.c +msh.c +''') + +#也可以等效成:src = ['shell.c', 'msh.c'] + +if GetDepend('MSH_USING_BUILT_IN_COMMANDS'): # 判断是否启用MSH的内建命令 +src += ['cmd.c'] + +if GetDepend('DFS_USING_POSIX'): # 判断是否启用文件系统的POSIX接口 +src += ['msh_file.c'] +``` + +使用DefineGroup创建一个名为Finsh的组 + +该Group是否被添加到工程中,参与编译,取决于depend的宏是否在Kconfig中被使能。 + +即上述的头文件路径和C文件是否被编译,取决于用户在Kconfig中是否使能了RT_USING_FINSH + +group = DefineGroup('Finsh', src, depend = ['RT_USING_FINSH'], CPPPATH = CPPPATH) + +Return('group') # 将当前脚本指定的构建对象返回上级SCons脚本复制错误复制成功 +这里需要注意: + +1. src 和 depends参数是必选项,即便你不想添加任何C文件,也需要定义一个空的列表。例如: + ``` + src = [] + group = DefineGroup('Finsh', src, depend = [''], CPPPATH = CPPPATH) 复制错误复制成功 + ``` +2. 头文件路径的参数不是必选项,如果不想添加头文件目录,就不需要填写 `CPPPATH` 参数 +3. 最后一行使用 DefineGroup 创建一个名为 Finsh 的组,这个组也就对应 MDK 或者 IAR 中的分组。这个组的源代码文件为 src 指定的文件,如果 depend 为空表示该组不依赖任何 rtconfig.h 的宏。 +4. `CPPPATH =CPPPATH` 表示将当前路径添加到系统的头文件路径中。左边的 CPPPATH 是 DefineGroup 中内置参数,表示头文件路径。右边的 CPPPATH 是本文件上面一行定义的。这样我们就可以在其他源码中引用 drivers 目录下的头文件了。 +5. 如果有其他 Sconscript 文件也创建了相同的组名(例如,都叫 `Finsh`),Scons 会自动将这两个组的信息并入到一起。 + +##### 1.2.2.2 桥接文件 + +在一些文件夹内的 Sconscript 脚本中,会发现有如下的代码。这些代码并没有实际去将某些C文件或者头文件路径加入到工程中。它所起到的作用是桥接,即让 Scons 继续读取其子文件夹内的 Sconscript 脚本,进而继续构建工程: + +``` +# RT-Thread building script for bridge + +import os # 使用Python标准库,用于文件以及路径相关的操作 +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs')复制错误复制成功 +``` + +##### 1.2.2.3 全局宏定义的定义 + +下面的代码展示了如何定义全局宏定义: + +``` +from building import * + +src = ['ipc.c'] # 添加C文件 + +CPPDEFINES = ['__RTTHREAD__'] # 全局宏定义 + +# depend 为空表示该组不依赖任何 rtconfig.h 的宏 +group = DefineGroup('Kernel', src, depend = [''], CPPDEFINES = CPPDEFINES) + +Return('group')复制错误复制成功 +``` + +所谓全局宏定义,就是即便不引用任何 RT-Thread 的头文件,你也可以使用直接使用 `__RTTHREAD__` 这个宏定义。 + +##### 1.2.2.4 与编译器相关 + +如下的 Sconscript 脚本展示了如何判断不同的编译器,并根据不同的编译器来进行不同的处理: + +``` +if rtconfig.CROSS_TOOL == 'iar': # 判断是否使用IAR编译器 +if rtconfig.CROSS_TOOL == 'keil': # 判断是否使用Keil编译器 +if rtconfig.CROSS_TOOL == 'msvc': # 判断是否使用Visual Studio编译器 +if rtconfig.PLATFORM == 'armcc': # 判断是否使用Keil-AC5,即armcc编译工具链 +if rtconfig.PLATFORM == 'armclang': # 判断是否使用Keil-AC6,即armclang编译工具链 +if rtconfig.PLATFORM == 'iar': # 判断是否使用IAR编译器的工具链 +if rtconfig.PLATFORM == 'gcc': # 判断是否使用gcc编译工具链复制错误复制成功 +``` + +下面的例子中,展示了针对不同的编译器/工具链,来进行设置不同的编译标志: + +源码位置:[https://github.com/mysterywolf/RTduino/blob/master/core/SConscript](https://github.com/mysterywolf/RTduino/blob/master/core/SConscript) + +``` +from building import * +import rtconfig + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +inc = [cwd] + +LOCAL_CCFLAGS = '' +LOCAL_CFLAGS = '' +LOCAL_CXXFLAGS = '' + +if rtconfig.PLATFORM == 'gcc' or rtconfig.PLATFORM == 'armclang': # GCC or Keil AC6 + LOCAL_CFLAGS += ' -std=c99' + LOCAL_CXXFLAGS += ' -std=c++11' # support C++11, like non-static data member initializers +elif rtconfig.PLATFORM == 'armcc': # Keil AC5 + LOCAL_CCFLAGS += ' --gnu -g -W' + LOCAL_CFLAGS += ' --c99' # cannot use --c99 symbol for C++ files, pertically in Keil + LOCAL_CXXFLAGS += ' --cpp11' # support C++11 + +group = DefineGroup('Arduino', src, + depend = ['PKG_USING_RTDUINO'], + CPPPATH = inc, + CPPDEFINES = ['ARDUINO=100', 'ARDUINO_ARCH_RTTHREAD'], + LOCAL_CCFLAGS = LOCAL_CCFLAGS, + LOCAL_CFLAGS = LOCAL_CFLAGS, + LOCAL_CXXFLAGS = LOCAL_CXXFLAGS) + +Return('group')复制错误复制成功 +``` + +##### 1.2.2.5 添加模块 + +前文提到在自己源代码文件不多的情况下,建议所有源代码文件都放在 applications 文件夹里面。如果用户源代码很多了,并且想创建自己的工程模块,或者需要使用自己获取的其他模块,怎么做会比较合适呢? + +同样以上文提到的 hello.c 和 hello.h 为例,这两个文件将会放到一个单独的文件夹里管理,并且在 MDK 工程文件里有自己的分组,且可以通过 menuconfig 选择是否使用这个模块。在 BSP 下新增 hello 文件夹。 + +![新增 hello 文件夹](https://www.rt-thread.org/document/site/development-tools/build-config-system/figures/f42ee8cdfd03c1782679c759f70f072f.png) + +大家注意到文件夹里多了一个 SConscript 文件,如果想要将自己的一些源代码加入到 SCons 编译环境中,一般可以创建或修改已有的 SConscript 文件。参考上文对 RT-Thread 源代码的一些对 SConscript 文件的分析,这个新增的 hello 模块 SConscript 文件内容如下所示: + +``` +from building import * + +cwd = GetCurrentDir() +include_path = [cwd] +src = [] + +if GetDepend(['RT_USING_HELLO']): + src += ['hello.c'] + +group = DefineGroup('hello', src, depend = [''], CPPPATH = include_path) + +Return('group')复制错误复制成功 +``` + +通过上面几行简单的代码,就创建了一个新组 hello,并且可以通过宏定义控制要加入到组里面的源文件,还将这个组所在的目录添加到了系统头文件路径中。那么自定义宏 RT\_USING\_HELLO 又是通过怎样的方式定义呢?这里要介绍一个新的文件 Kconfig。Kconfig 用来配置内核,使用 Env 配置系统时使用的 menuconfig 命令生成的配置界面就依赖 Kconfig 文件。menuconfig 命令通过读取工程的各个 Kconfig 文件,生成配置界面供用户配置内核,最后所有配置相关的宏定义都会自动保存到 BSP 目录里的 rtconfig.h 文件中,每一个 BSP 都有一个 rtconfig.h 文件,也就是这个 BSP 的配置信息。 + +在 stm32f10x-HAL BSP 目录下已经有了关于这个 BSP 的 Kconfig 文件,我们可以基于这个文件添加自己需要的配置选项。关于 hello 模块添加了如下配置选项,# 号后面为注释。 + +![hello 模块相关配置选项](https://www.rt-thread.org/document/site/development-tools/build-config-system/figures/caef0674c4a148411789c42f8f8b70b7.png) + +## 2.软件包介绍和使用实践 + +### 2.1 软件包介绍 + +关于软件包,其实就是官方和大佬写好的可以直接使用的库,当大家开使用RTT开发某项功能的古城中如果遇到了一些困难,大家可以尝试打开软件包搜索一下看看,希望大家也能够一起加入软件包的贡献和使用中来。 + +![1753430302854](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753430302854.png) + +![1753430511937](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753430511937.png) + +### 2.2 LLM软件包实践 + +#### 2.2.1 LLM软件包下载和配置 + +进入rt-thread的bsp目录找到如下平台然后在env中打开 + +![1753430902190](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753430902190.png) + +然后输入`menuconfig`打开图形化界面在软件包目录下找到LLM模型软件包目录如图并勾选 + +![1753431038811](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753431038811.png) + +然后进入配置选项如下。 + +![1753431152132](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753431152132.png) + +我们进入第一项是选择模型,我们选择qwen llm(通义千文) + +![1753431251967](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753431251967.png) + +然后返回接着填写apikey可以到[通义千文官网](https://bailian.console.aliyun.com/?tab=model#/model-market)获取,然后是大模型名称课随意填写,最后使能http流式对话,然后退到初始菜单界面。 + +![1753431327531](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753431327531.png) + +#### 2.2.2 LLM软件包依赖配置 + +因为LLM软件包还有一些依赖,所以我们也需要进行配置,如下面三图图所示照相相应配置选择即可。 + +![1753431602791](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753431602791.png) + +![1753431646514](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753431646514.png) + +![1753431813359](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753431813359.png) + +配置好直接保存退出即可系统会自动下载软件包和依赖包,等待下载完成即可。 + +![1753431886077](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753431886077.png) + +#### 2.2.3 LLM软件包使用实验演示 + +下载完整之后输入`scons-j4`编译等待编译完成然后`qemu-nographic.bat`回车运行然后tab键可以查看命令。我们看到llm命令就是例程启动命令。 + +![1753432061113](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753432061113.png) + +输入`llm`!然后对话框内输入对话内容并回车即可。 + +[1753432128450](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753432128450.png) + +## 3.组件介绍和使用实践 + +### 3.1 组件介绍 + +其实组件和软件包在功能上大同小异,只不过组件的来源都是官方,而软件包来自用户,但是组件和RT-thread操作系统息息相关,比如我们用的msh控制台,网络组件其实这都是属于RT-thread操作系统的一部分,类比linux操作系统来说桌面和网络功能都是操作系统完整的一部分,但是其实你不联网或者无桌面我们依旧可以使用我们的操作系统,这也就是为啥我说在功能上类似软件包,但实际性质上是不一样的,但既然是可有可无的东西,那么我们按自己的需求裁剪就可以啦,这就是RTT操作系统轻量化可裁剪的优势所在。 + +### 3.2 网络组件介绍与实践 + +#### 3.2.1 网络组件介绍 + +[RTT网络组件官方介绍](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/net/net_introduce) + +作为一款在 RTOS 领域对网络支持很丰富的 RT-Thread,对设备联网功能的支持的工具就是接下来要讨论的 net 组件。它位于 `./rt-thread/components/net` 路径下;作为一款基础组件, env 与 Studio 的工程配置界面的配置项都依赖该目录下的 Kconfig 文件。我们对网络功能的选择,或者其配置都属于该 Kconfig 的管理范畴。 + +![1753432823335](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753432823335.png) + +从图片中的信息也可以了解到,AT,Lwip,Netdev,SAL 这些我们相对熟悉的功能也位于该目录中。这四个基础组件,可以驱动的网络设备的种类多到各个方面。从有线网络的各种 ETH 的方式,带 PHY 的 enc28j60,纯接口的 RJ45,还有自带网络协议栈的 W5500都可以直接经过配置,通过我们的 net 组件实现设备联网的需求;除了有线网络的接入方式,无线网络的接入方式则更多,2G模块,3G模块,4G模块,Cat-1模块,Cat-4模块,NB-IOT模块,乃至 5G 模块这些依赖基站运营商的入网方式,例如 SIM800,EC20,AIR720,L610,N58,M5311 等,这些不同厂家,不同工作频率的模组均可以通过 NET 组件入网;WIFI 这种无需运营商直接提供的网络的入网方式,例如 ESP8266,W60x,rw007 等。 + +通过上面的简单介绍,大家应该可以基本了解 Net 组件的作用,即为使用 RT-Thread 的设备提供上网能力。上面的联网设备,品类繁多,方式各异,但其实追踪到依赖的基础 net 能力其实也没有多复杂。实际上大部分的功能依赖的基础能力,只有两组而已,即 AT ,Lwip;而到用户,也就开发者层面,大部分就只用到 SAL 这一个概念。 + +![](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/net/docs/network_frame.jpg) + +相信大家看过这份[文档](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/sal/sal),主要描述了 SAL 提供的编程接口,也就是大家常用的 socket 接口;通过 SAL 接口大家已经可以实现 MQTT,NTP,TFTP,TCP Client,TCP Server,webclient,UDP Client,UDP Server,webnet 等这些大家经常会使用的工具。像浏览器一样访问网站,webclient;模拟一个网站,webnet;连接各种云平台,Mqtt;获取准确授时,NTP ;通过网络传输文件 ,TFTP ;诸如此类功能, SAL 提供了轻松访问网络的一把钥匙。你可以理解这把钥匙是向上的,但是这篇文章现在要讲的,是向下的,看看 SAL 这样组件,又是谁在支撑着它。 + +Net 组件的主要内容有 4 个方面,分别是 sal ,AT,lwip 与 netdev,我们先从 AT 和 lwIP 讲起,在不同的方式中介绍 sal 的用途;然后讲 netdev 的作用。 + +#### 3.2.2 网络组件实践 + +接下来我们介绍两个实践分别是网络管理器工具实践与MQTT连接实践,因为这两个实验都需要用到用到网络组件下的lwip协议的tcp/ip协议栈,我们`menuconfig`进入配置界面,进入组件—>网络—>lwip—>tcp/ip stack配置文件下做出修改如下: + +![1753433620368](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753433620368.png) + +##### 3.2.2.1 实践1:网络管理器工具 + +接着上一节的工程我们打开`menuconfig`到软件包找到网络管理器工具并选择。 + +![1753433295046](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753433295046.png) + +并进入配置文件选择所有功能 + +![1753433797185](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753433797185.png) + +然后退出保存,编译运行,对应功能可在pakges目录下的相应软件包目录下的remadme.md中查看。 + +![1753433876655](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753433876655.png) + +我们演示以下NTP功能和PING功能如下(图一的PIN运行结果是有点小问题原因是之前没有修改tcp/ip协议栈大小,剩余资源不够,正确运行结果一个如图二) + +![1753433960461](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753433960461.png) + +![1753434035985](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753434035985.png) + +##### 3.2.2.1 实践2:MQTT连接实践 + +MQTT在物联网中的作用就不需要多说了,话不多说,直接上操作,首先下载安装一下MQTTX工具https://mqttx.app/zh/downloads + +![1753434233532](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753434233532.png) + +然后创建服务器id,用户名,密码全为rtthread,然后连接。 +![1753434291084](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753434291084.png) + +输入`menuconfig`选择mqtt软件包。 + +![1753434532474](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753434532474.png) + +进入配置填写配置项如下 + +![1753434579704](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753434579704.png) + +然后编译运行代码,输入ka_mqtt启动例程 + +![1753434619402](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753434619402.png) + +订阅rtt-pub主题并且像rtt-sub发布消息 + +![1753434757421](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753434757421.png) + +终端输出消息如下 + +![1753434837756](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753434837756.png) + +## 4.课后作业 + +![1753434944991](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753434944991.png) + +根据作业要求我们来查看以下源代码mqtt_test源代码 + +![1753435761949](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753435761949.png) + +我们发现其中有两个函数其中绿色框是pub发布函数每四秒会调用一次用于像mqtt服务器上报数据,而红色框是sub订阅函数 会打印服务器下发的消息那么,现在我们需要做的工具就是将pub函数中的内容替换成JSON格式并加入我们想要的字段即可。 +添加如下代码并修改pub函数 + +``` +#ifndef PUB_NAME +#define PUB_NAME "XiyaoMa" +#endif +#ifndef PUB_STUDY +#define PUB_STUDY "keep up the good work" +#endif + + +//······· +//其余代码不变 +//······· + +static int mqtt_publish_handle1(mqtt_client_t *client) +{ + mqtt_message_t msg; + memset(&msg, 0, sizeof(msg)); + msg.qos = QOS0; +// 拼接修改后的JSON字符串(修正语法并调整键值对) +static const char *json_data = "{" \ + "\"name\": \"" PUB_NAME "\"," \ + "\"study\": \""PUB_STUDY "\"" +"}"; + // 赋值给msg.payload + msg.payload = (void *)json_data; + msg.payloadlen = strlen(json_data); + return mqtt_publish(client, KAWAII_MQTT_PUBTOPIC, &msg); +} + +``` + +![1753436918726](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753436918726.png) + +然后编译先测试以下康康,是否正确。编译运行并打开MQTTX查看没有任何问题。 + +![1753437251330](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753437251330.png) + +那么接下来我们就需要解决Kconfig语法配置name字段和study的字段问题啦,这里我们九二一把这个Kconfig配置放到driver目录下的Kconfig中也是可以的,因为我们只是用于实验,之研究语法所以不用刻意去设置,当然也可以参考我在上面讲到的操作将田间一个Kconfig文件然后将其纳入最外层Kconfig文件的搜索路径中,不过这里我想带大家尝试第三种就是直接修改我们下载的软件包中的Kconfig也可以让大家对软件包的开发有点感觉。 + +我们进入env工具的packegs目录下可以看到里面有一个Kconfig文件![1753437819390](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753437819390.png) + +可以打开看一眼就只有语句,意思是将当前目录下的packegs目录下的Kconfig目录纳入搜索路径 + +![1753437896787](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753437896787.png) + +进入packegs目录下可以看到里面还有一个Kconfig文件而当前目录下就是存放了我们之前所选择 的软件包的种类目录,那不用看也知道这个Kconfig是包含了不同中种类目录下的Kconfig文件,然后不同种类下的Kconfig文件又包含了具体软件包的Kconfig文件(俄罗斯套娃)那我们直接找到kawai_mqtt软件包的Kconfig文件打开。 + +![1753438404962](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753438404962.png) + +在里面的使能test中添加如下代码然后保存 + +``` + config PUB_NAME + string "name" + default "xiaoming" + config PUB_STUDY + string "study" + default "Keep" +``` + +![1753438678985](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753438678985.png) + +输入`menuconfig`打开配置界面找到mqtt软件包的配置发现我们添加的代码已经生效。 + +![1753439026038](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753439026038.png) + +按后修改以以下这两个字段和我们上面宏定义相同 + +![1753439249021](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753439249021.png) + +然后退出保存。到rtconfig.h中查看配置配置是否生效 + +![1753439354314](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753439354314.png) + +然后编译运行,输入ka_mqtt启动,然后打开MQTTX查看运行结果和终端输出如下 + +![1753439709966](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753439709966.png) + +![1753439818566](images/【RSOC25】Day5课程笔记:组件与软件包及构建系统/1753439818566.png)