diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\345\217\266\350\247\202\345\213\207/\344\275\234\344\270\232/main.c" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\345\217\266\350\247\202\345\213\207/\344\275\234\344\270\232/main.c" new file mode 100644 index 0000000000000000000000000000000000000000..5c5710972d7b7fa1e01936946ca687a182d7464e --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\345\217\266\350\247\202\345\213\207/\344\275\234\344\270\232/main.c" @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-11-06 SummerGift first version + * 2018-11-19 flybreak add stm32f407-atk-explorer bsp + */ + +#include +#include +#include + + +rt_thread_t led_thread; +rt_thread_t print_thread; +rt_thread_t thread3; + +void led_thread_task(void*parm) +{ + while(1) + { + rt_kprintf("led wink\r\n"); + rt_thread_delay(1000); + } +} +void print_thread_task(void*parm) +{ + while(1) + { + rt_kprintf("print_thread\r\n"); + rt_thread_delay(500); + } +} +void thread3_task(void*parm) +{ + while(1) + { + rt_kprintf("run the thread3\r\n"); + rt_thread_delay(500); + } +} + +int main(void) +{ + + led_thread = rt_thread_create("led_thread", led_thread_task, RT_NULL, 1024, 2, 10); + print_thread = rt_thread_create("print_thread", print_thread_task, RT_NULL, 1024, 3, 10); + thread3 = rt_thread_create("thread3", thread3_task, RT_NULL, 1024, 3 ,10); + + if(led_thread !=RT_NULL) + { + rt_thread_startup(led_thread); + } + if(print_thread !=RT_NULL) + { + rt_thread_startup(print_thread); + } + if(thread3 !=RT_NULL) + { + rt_thread_startup(thread3); + } + return RT_EOK; +} diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\345\217\266\350\247\202\345\213\207/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221DAY1 GIT.md" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\345\217\266\350\247\202\345\213\207/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221DAY1 GIT.md" new file mode 100644 index 0000000000000000000000000000000000000000..f1712c88f3dc98c4c4238062523e3131663bdc22 --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\345\217\266\350\247\202\345\213\207/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221DAY1 GIT.md" @@ -0,0 +1,176 @@ +### 1. 简介 + +Git是当前最先进、最主流的**分布式**版本控制系统,免费、开源!核心能力就是版本控制。任何修改历史都会被记录管理起来,可以恢复到到以前的任意时刻状态。支持跨区域多人协作编辑. + +Git是当前最先进、最主流的**分布式**版本控制系统,免费、开源!核心能力就是版本控制。再具体一点,就是面向代码文件的版本控制,代码的任何修改历史都会被记录管理起来,意味着可以恢复到到以前的任意时刻状态。支持跨区域多人协作编辑,是团队项目开发的必备基础,所以Git也就成了程序员的必备技能 + +![图片](https://mmbiz.qpic.cn/mmbiz_png/icRxcMBeJfcica7gffGOjKOmZxDUxtCX70j5nE6x9lN2IBTXxYm0DO7JL92Vr4icZVLRjC1lBwicq5WtuOGW1KpKhQ/640?wx_fmt=png&wxfrom=13&tp=wxpic) + +### 2. 概念 + +![图片](https://mmbiz.qpic.cn/mmbiz_png/icRxcMBeJfcica7gffGOjKOmZxDUxtCX70bEHNf1a2eicl3WOISXYibugT8VwltkBzvWf4FqOmKUI7CicRA8aoT5Uag/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1&tp=wxpic) + ++ **工作区**(Workspace)电脑里能看到的工程目录,新增、修改的文件会提交到暂存区。在这里新增文件、修改文件内容,或删除文件。 ++ **暂存区**(stage或index) 用于临时存放文件的修改,实际上上它只是一个文件(.git/index),保存待提交的文件列表信息。用git add 命令将工作区的修改保存到暂存区。 ++ **版本库/仓库**(Repository /rɪˈpɑːzətɔːri/ 仓库)Git的管理仓库,管理版本的数据库,记录文件/目录状态的地方,所有内容的修改记录(版本)都在这里。就是工作区目录下的隐藏文件夹.git,包含暂存区、分支、历史记录等信息。git commit 命令将暂存区的内容正式提交到版本库。 ++ **头**(HEAD)HEAD类似一个“指针”,指向当前活动 **分支** 的 **最新版本**。默认指向最新的master + +### 3. 安装 + +[参照此链接](https://blog.csdn.net/qq_42547733/article/details/129956784?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168621416716800188513333%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168621416716800188513333&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-129956784-null-null.142^v88^insert_down38v5,239^v2^insert_chatgpt&utm_term=git%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE&spm=1018.2226.3001.4187) + +### 4. 版本管理(仅讲述本地版本,不包含服务器或云端) + +#### 4.1 创建版本库。 + +什么是版本库?版本库又名仓库,英文名repository,你可以简单的理解一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改,删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻还可以将文件”还原”。 + +首先要明确下,所有的版本控制系统,**只能跟踪文本文件的改动**,比如txt文件,网页,所有程序的代码等,Git也不列外,版本控制系统可以告诉你每次的改动,但**是图片,视频这些二进制文件,虽能也能由版本控制系统管理,但没法跟踪文件的变化**,只能把二进制文件每次改动串起来,也就是知道图片从1kb变成2kb,但是到底改了啥,版本控制也不知道。 + +如下我是D盘目录下新建一个testgit工程目录,现需要在这个目录下做版本管理。 + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5HicxZ1eRbXtTvZ2Qft46WlGBWIX54aR0uszSiaFIuKncPO8SuicCOEGog/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +通过命令 git init 把这个目录变成git可以管理的仓库,如下: + + + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5B5Pg32kcWqiaWe88On5EV1fDvPh0Tk2tfiaSDWYyDsUaZlhkQmmkib2Wg/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +这时候你当前testgit目录下会多一个.git的目录,这个目录是Git来跟踪管理版本的,千万不要改这个目录里面的文件,否则,会破坏git仓库。如下: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5kqQdLicsnIh9GnvcDWLcIia9pdNFGNiaKpKOKeiaUEPVUXRFEjTTGVawTA/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + + + +下面先看下demo如下演示: + +在版本库testgit目录下新建一个记事本文件 readme.txt 内容如下:11111111 + +1. 使用命令 git add readme.txt添加到暂存区里面去。如果和上面一样,没有任何提示,说明已经添加成功了。 + + ![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5HbDUa3gjxzMPnL6CZn45eAiaaoXBPxKWKQXNLAq2lGQviaorfjov2ricg/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +2. 命令 git commit告诉Git,把文件提交到仓库。现在我们已经提交了一个readme.txt文件了 + + ![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5UqCmrljibmDwu1j9ZGXlQbuib3VCZtWRWPdia1m1DYwsicbxszFALVicfxA/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +3. 查看状态,可以通过命令git status来查看是否还有文件未提交,如下: + + ![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG57dngQHBvlEVs1JpLIULiaAA0VfCGk0QvEicgoJ07lLVpficfia9Bag0Elw/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + + 说明没有任何文件未提交,但是我现在继续来改下readme.txt内容,比如我在下面添加一行2222222222内容,继续使用git status来查看下结果,如下: + + ![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5Sg4wDBia1EKhxnicHuj56nYemTsQiaR1eiaykATqvYdEINyd7XXandDsVw/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + + 上面的log告诉我们 readme.txt文件已被修改,但是未被提交的修改 + +4. 查看修改内容可以使用如下命令:git diff readme.txt 如下: + + ![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5AwXDlSXu7ru2cBbhnXnPNuEVlDjSibRe8ZME89DNTQoK88tzBs0rpNQ/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + + 如上可以看到,readme.txt文件内容从一行11111111改成 二行 添加了一行22222222内容。 + + 知道了对readme.txt文件做了什么修改后,我们可以放心的提交到仓库了,提交修改和提交文件是一样的2步(第一步是git add 第二步是:git commit)。 + + ![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5222u8ffPMNKl12tcXyBCaQjWlc6lnWpp2l3F18OPgJPAyAqpRYuMwg/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +#### 4.2 版本回退 + +如上,我们已经学会了修改文件,现在我继续对readme.txt文件进行修改,再增加一行内容为33333333333333.继续执行命令如下 + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5ibsCS5wE7BFkcwxI9X9uWJBL4iaWA9V2uUaLeM7WiaWpXayrmlHCicR4eQ/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +现在我已经对readme.txt文件做了三次修改了,那么我现在想查看下历史记录,如何查呢?我们现在可以使用命令 git log 演示如下所示: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5bK8UvEvC4JeCus9iajXfXZibqrZibobHp5XEhT0mY0icLl7LBJbxic4rrow/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +git log命令显示从最近到最远的显示日志,我们可以看到最近三次提交,最近的一次是,增加内容为333333.上一次是添加内容222222,第一次默认是 111111.如果嫌上面显示的信息太多的话,我们可以使用命令 git log –pretty=oneline 演示如下: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5SoF8wmUl5XI8Q7G19Ikp0fyIewjvKZYJl7IuY8ib8LjkEwPRIoQogyQ/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +现在我想使用版本回退操作,我想把当前的版本回退到上一个版本,可以使用如下2种命令,第一种是:git reset --hard HEAD^ 那么如果要回退到上上个版本只需把HEAD^ 改成 HEAD^^ 以此类推。那如果要回退到前100个版本的话,使用上面的方法肯定不方便,我们可以使用下面的简便命令操作:git reset --hard HEAD~100 即可。未回退之前的readme.txt内容如下: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5KD2o2JKAe9hmvn2iahSBuibzOG25AicXLItXjAOjTOXlfew8iaBnLJvYoA/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +如果想回退到上一个版本的命令如下操作: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5D4Ap4nfYD5qxxCPFw2KddwbbxicNT7yfHpAk9BSKGrpcedJrJmFuKMw/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +再来查看下 readme.txt内容如下:通过命令cat readme.txt查看 + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5gD0U32cauFtWbMpwLgfUmpC4KuP6Wiclj5XC0bl6L4oxus3FUOjA6NA/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +可以看到,内容已经回退到上一个版本了。我们可以继续使用git log 来查看下历史记录信息,如下: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG51EMrf3GKiaQ1HGd7NKS4pxm6d3XYSgptyBWEKicr94FFBfjVibg2GduJw/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +我们看到 增加333333 内容我们没有看到了,但是现在我想回退到最新的版本,如:有333333的内容要如何恢复呢?我们可以通过版本号回退,使用命令方法如下: + +git reset --hard 版本号 ,但是现在的问题假如我已经关掉过一次命令行或者333内容的版本号我并不知道呢?要如何知道增加3333内容的版本号呢?可以通过如下命令即可获取到版本号:git reflog 演示如下: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG557d9v2elWeic0fC8KmI4NuvCqib9ImyneRf9Sjyc4mBu3iaG1t8GdDSaQ/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +通过上面的显示我们可以知道,增加内容3333的版本号是 6fcfc89.我们现在可以命令 + +git reset --hard 6fcfc89来恢复了。演示如下: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG58ricQA1J7LtHCGIu5qCY32ibXSozwibqqRCENeyqYz8hcpFAxia5soHVOg/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +可以看到 目前已经是最新的版本了。 + +#### 4.3 Git撤销修改和删除文件操作 + +##### 4.3.1 撤销修改 + +比如我现在在readme.txt文件里面增加一行 内容为555555555555,我们先通过命令查看如下: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5D1XaiaBrn6nhJ8wshTrviaqIRanLC5WiaiakImsvWfrhkrgLxAUVvtZNicA/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +在我未提交之前,我发现添加5555555555555内容有误,所以我得马上恢复以前的版本,现在我可以有如下几种方法可以做修改: + +1. 如果我知道要删掉那些内容的话,直接手动更改去掉那些需要的文件,然后add添加到暂存区,最后commit掉。 +2. 我可以按以前的方法直接恢复到上一个版本。使用 git reset --hard HEAD^ + +但是现在我不想使用上面的2种方法,我想直接想使用撤销命令该如何操作呢?首先在做撤销之前,我们可以先用 git status 查看下当前的状态。如下所示: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG54zD80VuBe7kro7ibjE0wxvahYA8jsEiaHmAD4xic7xpQiaKjBXiadXCFcMw/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +可以发现,Git会告诉你,git checkout -- file 可以丢弃工作区的修改,如下命令: + +git checkout -- readme.txt,如下所示: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5Xic7fd92kJzibzb3KFyVaDZrjYSIjHiaFKnH5oS9AdDyggrmR1czjbf8Q/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +命令 git checkout --readme.txt 意思就是,把readme.txt文件在工作区做的修改全部撤销,这里有2种情况,如下: + +1. readme.txt自动修改后,还没有放到暂存区,使用 撤销修改就回到和版本库一模一样的状态。 +2. 另外一种是readme.txt已经放入暂存区了,接着又作了修改,撤销修改就回到添加暂存区后的状态 + +对于第二种情况,我想我们继续做demo来看下,假如现在我对readme.txt添加一行 内容为6666666666666,我git add 增加到暂存区后,接着添加内容7777777,我想通过撤销命令让其回到暂存区后的状态。如下所示: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5lRKfQ4JDLpdBobLgLvBk9bsPhiczQkxPRWFJS9EZ8Z3yMDZ6XiaNAQCw/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +注意:命令git checkout -- readme.txt 中的 -- 很重要,如果没有 -- 的话,那么命令变成创建分支了。 + +##### 4.3.2 删除文件 + +假如我现在版本库testgit目录添加一个文件b.txt,然后提交。如下: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5ibctkic4CtvO0Pu4iarqO36ic4ukjWB3CTGiaautj7sMhSu2PAojTIlzINA/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +如上:一般情况下,可以直接在文件目录中把文件删了,或者使用如上rm命令:rm b.txt ,如果我想彻底从版本库中删掉了此文件的话,可以再执行commit命令 提交掉,现在目录是这样的, + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5RO9TQSZxtBAbDTXrdKONlQ1sTnkO3k9M8KNYcGwTWMAaVGNw0OdicCA/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + + + +只要没有commit之前,如果我想在版本库中恢复此文件如何操作呢? + +可以使用如下命令 git checkout -- b.txt,如下所示: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5fWaGGlwiamiabDs8LOib0gUiaCrpqIDicOckbQhzX23hEQdhEtpG0EUmNzQ/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) + +再来看看我们testgit目录,添加了3个文件了。如下所示: + +![图片](https://mmbiz.qpic.cn/mmbiz_jpg/eZzl4LXykQwdIze8xZ74YQ859KfNjHG5F5tZr38F4y9GkNCibXzkHkA8Et4kPO5uPCSy117gLhw3lUMJibH3Qorw/640?wx_fmt=jpeg&tp=wxpic&wxfrom=5&wx_lazy=1&wx_co=1) \ No newline at end of file diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\345\217\266\350\247\202\345\213\207/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221DAY2_TASK_note.md" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\345\217\266\350\247\202\345\213\207/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221DAY2_TASK_note.md" new file mode 100644 index 0000000000000000000000000000000000000000..38400e75be7b020f0c6d251915be1289322a35cb --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\345\217\266\350\247\202\345\213\207/\347\254\224\350\256\260/\343\200\220RSOC25\343\200\221DAY2_TASK_note.md" @@ -0,0 +1,169 @@ +## 一、线程基础认知 + +- **线程地位**:线程是 RT-Thread 操作系统中最小的调度单位,基于**优先级的全抢占式多线程调度算法**。 +- **调度特性**:除中断处理函数、调度器上锁代码、禁止中断代码外,系统其他部分均可被抢占(包括调度器自身)。 +- **优先级支持**:默认支持 256 个线程优先级(0 最高,255 最低),可通过配置文件改为 32 个或 8 个;最低优先级默认分配给空闲线程。 +- **同优先级调度**:相同优先级线程采用**时间片轮转调度算法**,按设定时间片轮流执行。 +- **核心作用**:将复杂应用分解为多个小的、可调度的程序单元,满足实时系统性能与时间要求(如传感器数据采集与显示的任务拆分)。 + +## 二、线程管理功能特点 + +### 1. 线程分类:两类线程均从内核对象容器分配线程对象,删除时从容器中移除 + +- **系统线程**:由 RT-Thread 内核创建(如空闲线程、主线程)。 +- **用户线程**:由应用程序创建。 + +### 2. 调度器核心工作 + +- 从就绪线程列表中查找**最高优先级线程**并调度其运行,确保高优先级线程就绪后立即获得 CPU 使用权。 +- 线程切换时,先保存当前线程上下文,恢复时读取上下文信息。 + +## 三、线程工作机制 + +### 1. 线程控制块(TCB) + +- 定义:由`struct rt_thread`表示,是操作系统管理线程的数据结构。 + +- 核心成员(部分): + + | 成员 | 作用 | + | ---------------------------------- | ----------------------------------------------------------- | + | `name` | 线程名称(长度受`RT_NAME_MAX`限制) | + | `current_priority`/`init_priority` | 当前优先级 / 初始优先级(初始优先级创建时指定,可手动修改) | + | `sp`/`stack_addr`/`stack_size` | 栈指针 / 栈地址 / 栈大小 | + | `entry` | 线程入口函数指针 | + | `stat` | 线程状态(初始、就绪、运行等) | + | `cleanup` | 线程退出时的清理函数(由空闲线程回调) | + +### 2. 线程重要属性 + +#### (1)线程栈 + +- 作用:保存线程上下文(寄存器、堆栈等)、存放函数局部变量。 +- 增长方向:与芯片架构相关(如 ARM Cortex-M 架构栈从高地址向低地址增长)。 +- 大小设置:初始可设较大值(如 1K/2K 字节),通过`list_thread`命令查看最大栈深度,加余量后确定最终大小。 + +#### (2)线程状态(5 种) + +| 状态 | 宏定义 | 说明 | +| -------- | ------------------- | ------------------------------------------------------------ | +| 初始状态 | `RT_THREAD_INIT` | 线程创建 / 初始化后未启动,不参与调度 | +| 就绪状态 | `RT_THREAD_READY` | 线程已启动,按优先级排队等待调度 | +| 运行状态 | `RT_THREAD_RUNNING` | 线程正在执行(单核系统中仅`rt_thread_self()`返回的线程处于此状态) | +| 挂起状态 | `RT_THREAD_SUSPEND` | 因等待资源或主动延时挂起,不参与调度(又称阻塞态) | +| 关闭状态 | `RT_THREAD_CLOSE` | 线程运行结束,不参与调度 | + +#### (3)线程优先级 + +- 数值越小优先级越高(0 最高),支持 256/32/8 级(可配置);ARM Cortex-M 系列常用 32 级。 +- 高优先级线程就绪时,立即抢占当前线程的 CPU 使用权。 + +#### (4)时间片 + +- 仅对同优先级就绪线程有效,约束线程单次运行时长(单位:系统节拍 OS Tick)。 +- 例:优先级相同的线程 A(时间片 10)和 B(时间片 5),轮流执行 10 节拍和 5 节拍。 + +#### (5)入口函数 + +- 无限循环模式:实时系统常用,线程被动等待事件并处理(需包含让出 CPU 的操作,如延时)。 + + ```c + void thread_entry(void* parameter) { + while (1) { + /* 等待事件并处理 */ + } + } + ``` + +- 顺序执行模式:一次性线程,执行完毕后自动删除。 + + ```c + static void thread_entry(void* parameter) { + /* 处理事务 #1 */ + /* 处理事务 #2 */ + } + ``` + +#### (6)错误码 + +| 错误码 | 含义 | +| ------------- | -------- | +| `RT_EOK` | 无错误 | +| `RT_ERROR` | 普通错误 | +| `RT_ETIMEOUT` | 超时错误 | +| `RT_ENOMEM` | 无内存 | +| `RT_EINVAL` | 非法参数 | + +### 3. 线程状态切换 + +- **初始态 → 就绪态**:调用`rt_thread_startup()`。 +- **就绪态 → 运行态**:调度器调度最高优先级就绪线程。 +- **运行态 → 挂起态**:调用`rt_thread_delay()`、获取资源失败等。 +- **挂起态 → 就绪态**:等待超时、被其他线程释放资源。 +- **运行态 / 挂起态 → 关闭态**:运行结束(自动调用`rt_thread_exit()`)、被删除 / 脱离。 + +## 四、系统线程 + +### 1. 空闲线程(idle) + +- 特性:系统创建的最低优先级线程,状态永远为就绪态。 +- 作用: + - 回收**僵尸线程**(处于关闭状态、资源未回收的线程)的资源。 + - 运行用户设置的钩子函数(如功耗管理、看门狗喂狗)。 +- 约束:必须有执行机会(其他线程不可一直死循环,需调用阻塞函数)。 + +### 2. 主线程 + +- 系统启动时创建,入口函数为`main_thread_entry()`,用户应用入口`main()`函数从此开始执行。 + +## 五、线程管理接口 + +### 1. 线程创建与删除(动态线程) + +- **创建**:`rt_thread_t rt_thread_create(...)` + - 参数:线程名、入口函数、参数、栈大小、优先级、时间片。 + - 返回:成功返回线程句柄,失败返回`RT_NULL`。 + - 说明:从动态堆分配线程句柄和栈空间(需使能`RT_USING_HEAP`)。 +- **删除**:`rt_err_t rt_thread_delete(rt_thread_t thread)` + - 作用:将线程状态改为关闭态,放入僵尸队列,由空闲线程回收资源。 + - 返回:`RT_EOK`(成功)或`-RT_ERROR`(失败)。 + +### 2. 线程初始化与脱离(静态线程) + +- **初始化**:`rt_err_t rt_thread_init(...)` + - 参数:线程句柄(用户提供)、线程名、入口函数、参数、栈起始地址、栈大小、优先级、时间片。 + - 说明:线程句柄和栈由用户提供(全局变量),需对齐(如 ARM 4 字节对齐)。 +- **脱离**:`rt_err_t rt_thread_detach(rt_thread_t thread)` + - 作用:与`rt_thread_delete`对应,用于初始化的静态线程,从队列和对象管理器中脱离。 + +### 3. 线程启动 + +- 函数:`rt_err_t rt_thread_startup(rt_thread_t thread)` +- 作用:将初始态线程转为就绪态,放入优先级队列;若优先级高于当前线程,立即切换。 + +### 4. 其他常用接口 + +| 功能 | 函数 | 说明 | +| ------------- | ------------------------------------------------------------ | ---------------------------------------------- | +| 获取当前线程 | `rt_thread_t rt_thread_self()` | 调度器未启动返回`RT_NULL` | +| 让出 CPU 资源 | `rt_thread_yield()` | 当前线程挂到就绪队列尾部,调度同优先级下一线程 | +| 线程睡眠 | `rt_thread_sleep(tick)`、`rt_thread_delay(tick)`、`rt_thread_mdelay(ms)` | 挂起指定时间后返回就绪态 | +| 线程挂起 | `rt_thread_suspend(thread)` | 仅允许挂起自身,后需调用`rt_schedule()`切换 | +| 线程恢复 | `rt_thread_resume(thread)` | 将挂起线程转为就绪态,可能触发调度 | +| 线程控制 | `rt_thread_control(thread, cmd, arg)` | 支持修改优先级、启动、关闭等(`cmd`指定操作) | + +### 5. 钩子函数 + +- **空闲钩子**:`rt_thread_idle_sethook(hook)`/`rt_thread_idle_delhook(hook)` + - 约束:钩子函数不可调用阻塞函数、内存相关函数(如`malloc`)。 +- **调度器钩子**:`void rt_scheduler_sethook(void (*hook)(struct rt_thread* from, struct rt_thread* to))` + - 作用:线程切换时调用,参数为切换前后的线程句柄。 + - 约束:不可调用系统 API,不可导致当前上下文挂起。 + +## 六、关键注意事项 + +- 优先级:数值越小优先级越高,高优先级线程可抢占低优先级线程。 +- 同优先级调度:时间片轮转,时间片单位为 OS Tick。 +- 挂起操作:仅允许线程自身挂起,不可跨线程挂起(避免系统实时性问题)。 +- 空闲线程:必须有执行机会,否则无法回收僵尸线程资源。 +- 钩子函数:需谨慎编写,避免影响系统稳定性。 \ No newline at end of file