Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
2024-RSOC
[2024-RSOC]多线程的学习分享
发布于 2024-07-23 21:33:27 浏览:139
订阅该版
[tocm] ## RT-Thread 夏令营心得 主要学习了关于 RT-Thread 的启动流程、线程的状态转换、线程的使用及源码分析等内容。以下是我对今天培训的心得总结。 ### 1. RT-Thread 启动流程 RT-Thread 的启动流程是理解操作系统如何运行的基础。整个启动流程包括硬件初始化、系统初始化以及用户应用程序的启动。 - **硬件初始化**:系统启动后,首先进行硬件初始化,包括时钟、内存、串口等外设的初始化。 - **系统初始化**:接下来是 RT-Thread 内核的初始化,主要包括线程调度器的初始化、中断管理器的初始化、内存管理的初始化等。 - **应用程序启动**:最后是用户应用程序的启动,通常是在一个用户线程中运行的。用户可以在这个阶段添加自己的应用逻辑。 在 RT-Thread 的源码中,这个过程主要在 `main.c` 文件中实现。理解这个启动流程有助于我们更好地调试和开发基于 RT-Thread 的应用程序,下图是RT-Thread 启动流程图。MDK 的**扩展功能 `$Sub$$` 和 `$Super$$`**。可以给 main 添加 `$Sub$$` 的前缀符号作为一个新功能函数 `$Sub$$main`,这个 `$Sub$$main` 可以先调用一些要补充在 main 之前的功能函数(这里添加 RT-Thread 系统启动,进行系统一系列初始化),再调用 `$Super$$main` 转到 main() 函数执行,这样可以让用户不用去管 main() 之前的系统初始化操作。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240723/9ac75fb6b6e30af38c5c46eb95f9d279.png.webp) ### 2. 线程状态转换 线程是 RT-Thread 中最基本的执行单元,每个线程都有其生命周期和状态转换。主要的线程状态包括: - **初始状态(Init)**:线程被创建后,处于初始状态。 - **就绪状态(Ready)**:线程已经准备好执行,等待被调度。 - **运行状态(Running)**:线程正在被 CPU 执行。 - **挂起状态(Suspended)**:线程暂时停止执行,等待某个事件发生。 - **终止状态(Terminated)**:线程执行结束,进入终止状态。 线程状态转换是由线程调度器控制的。理解线程的状态转换有助于我们更好地设计和调试多线程应用程序。线程状态转换图如下。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240723/14e5d90ca79aa0e3a1f05660ba3e2b87.png) ### 3. 线程使用及源码分析 在 RT-Thread 中,创建和管理线程非常方便。以下是创建一个线程的基本步骤: 1. 定义线程入口函数。 2. 使用 `rt_thread_create` 函数动态创建线程或 `rt_thread_init`函数静态创建线程,这里线程进入初始状态。 3. 使用 `rt_thread_startup` 函数启动线程,这里线程进入就绪状态。 在源码中,可以看到线程控制块 `rt_thread` 的定义,其中包含了线程的状态、优先级、栈指针等信息,其中线程控制块 `rt_thread` 的的父类`rt_object` 。通过阅读源码,可以深入了解 RT-Thread 对线程的管理机制。 ### 4. RT-Thread 启动流程调试 调试 RT-Thread 的启动流程是开发过程中必不可少的一部分。常见的调试技巧包括: - 使用调试工具设置断点,逐步跟踪启动流程。 - 使用 RT-Thread 的调试接口,查看线程的状态和系统资源的使用情况。 通过调试,可以发现并解决启动过程中可能存在的问题,确保系统能够稳定运行。 ### 5. Markdown 基本语法 Markdown 是一种轻量级的标记语言,用于编写格式化的文档。以下是一些基本的 Markdown 语法: - **标题**:使用 `#` 表示标题,`#` 的数量表示标题的级别。 - **列表**:使用 `-` 表示无序列表,使用数字表示有序列表。 - **链接**:使用 `[链接文本](链接地址)` 表示链接。 - **图片**:使用 `![图片描述](图片地址)` 表示图片。 - **代码块**:使用三个反引号(```)包围代码块。 通过使用 Markdown,可以方便地编写和维护技术文档。了解更多参考官方文档:https://markdown.com.cn/basic-syntax/ ### 6. 调试技巧 调试是开发过程中不可或缺的环节。以下是一些调试 RT-Thread 的技巧: - **设置断点**:在关键代码处设置断点,逐步调试程序。 - **查看变量**:在调试工具中查看变量的值,分析程序的运行状态。。 - **内存检查**:检查内存的分配和释放,防止内存泄漏和越界访问。 通过这些调试技巧,可以快速定位和解决问题,提高开发效率。 ### 7. 导师嵌入式经验分享 在今天的培训中,导师还分享了他们在嵌入式开发中的一些宝贵经验。主要内容包括团队协作、代码错误处理以及常用工具。 #### 7.1. 团队协同的问题 团队协作在软件开发中至关重要,特别是对于嵌入式系统开发。以下是几种提高团队协作的方法: - **软件开发管理**:使用版本控制、代码review、BUG管理的开发方法,进行项目管理,确保团队成员了解项目进展和问题。 - **引入 CI/CD**:持续集成(CI)和持续交付(CD)能够自动化构建、测试和部署流程,减少手动操作,提升效率和代码质量。 #### 7.2. 代码 Bug 解决方法 - **首先是要了解代码执行流程;** - **还原并找到错误发生的过程、 分析出原因**; - **然后进行优化, 并做进一步的调试。** #### 7.3. 嵌入式工程师常用工具 嵌入式工程师在开发过程中会使用到各种工具,以下是一些常用的工具: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240723/931e5e95713a59809b929159ac0341ee.png.webp) ## 8.线程代码练习 实现红灯亮灭10次,之后蓝灯闪烁。使用动态和静态两种方法创建线程,保证亮灯互不影响引入互斥操作 ### 实验代码 ``` 'c' /* * 程序清单:创建、初始化/脱离线程 * * 这个例子会创建两个线程,一个动态线程,一个静态线程。 * 静态线程在运行完毕后自动被系统脱离,动态线程一直打印计数。 */ #include
#include
#include
#define THREAD_PRIORITY 25 #define THREAD_STACK_SIZE 512 #define THREAD_TIMESLICE 5 static rt_mutex_t dynamic_mutex = RT_NULL; static rt_thread_t tid1 = RT_NULL; #define GPIO_LED_B GET_PIN(F, 11) #define GPIO_LED_R GET_PIN(F, 12) /* 线程1的入口函数 */ static void thread1_entry(void *parameter) { rt_uint32_t count = 0; rt_pin_mode(GPIO_LED_B, PIN_MODE_OUTPUT); while (1) { rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER); rt_pin_write(GPIO_LED_B, PIN_LOW); rt_thread_mdelay(500); // 延时 500 毫秒 // 关闭 LED rt_pin_write(GPIO_LED_B, PIN_HIGH); rt_thread_mdelay(500); // 延时 500 毫秒 /* 线程1采用低优先级运行,一直打印计数值 */ rt_kprintf("蓝灯亮灭次数: %d\n", ++count); rt_mutex_release(dynamic_mutex); rt_thread_mdelay(500); // 延时500毫秒 } } static char thread2_stack[1024]; static struct rt_thread thread2; /* 线程2入口 */ static void thread2_entry(void *param) { rt_uint32_t count = 0; rt_pin_mode(GPIO_LED_R, PIN_MODE_OUTPUT); /* 线程2拥有较高的优先级,以抢占线程1而获得执行 */ rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER); for (count = 0; count < 10 ; count++) { rt_pin_write(GPIO_LED_R, PIN_LOW); rt_thread_mdelay(500); // 延时 500 毫秒 // 关闭 LED rt_pin_write(GPIO_LED_R, PIN_HIGH); rt_thread_mdelay(500); // 延时 500 毫秒 /* 线程1采用低优先级运行,一直打印计数值 */ /* 线程2打印计数值 */ rt_kprintf("红灯亮灭次数: %d\n", count); } rt_mutex_release(dynamic_mutex); //rt_thread_mdelay(500); rt_kprintf("thread2 exit\n"); /* 线程2运行结束后也将自动被系统脱离 */ } /* 线程示例 */ int thread_sample(void) { /* 创建一个动态互斥量 */ dynamic_mutex = rt_mutex_create("dmutex", RT_IPC_FLAG_PRIO); if (dynamic_mutex == RT_NULL) { rt_kprintf("create dynamic mutex failed.\n"); return -1; } /* 创建线程1,名称是thread1,入口是thread1_entry */ tid1 = rt_thread_create("thread1", thread1_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); /* 如果获得线程控制块,启动这个线程 */ if (tid1 != RT_NULL) rt_thread_startup(tid1); /* 初始化线程2,名称是thread2,入口是thread2_entry */ rt_thread_init(&thread2, "thread2", thread2_entry, RT_NULL, &thread2_stack[0], sizeof(thread2_stack), THREAD_PRIORITY - 2, THREAD_TIMESLICE); /* 启动线程2 */ rt_thread_startup(&thread2); return 0; } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(thread_sample, thread sample); ``` ### 实验现象 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240723/df1436f543cd70966d46ea2461b03b06.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240723/4e427ae08629700dd7cb27039d6b8ee0.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240723/38c943d50463faab9dbc86680117949f.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240723/5243d097c6ff58feba201920a279d321.png.webp) ### 总结 今天的培训内容非常丰富,通过对 RT-Thread 启动流程、线程状态转换、线程使用及源码分析的学习,我对 RT-Thread 有了更深入的理解。同时,通过实际的调试操作,我掌握了很多实用的调试技巧。导师的经验分享也让我受益匪浅,了解到团队协作的重要性和解决代码错误的方法。这些知识和技能将对我今后的开发工作大有帮助。
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
猪的行独
这家伙很懒,什么也没写!
文章
7
回答
0
被采纳
0
关注TA
发私信
相关文章
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
xusiwei1236
8
个答案
2
次被采纳
踩姑娘的小蘑菇
1
个答案
2
次被采纳
用户名由3_15位
9
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
RTT_逍遥
3
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
15
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
4
次点赞
Ghost_Girls
1
篇文章
7
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部