【RT-thread studio 下使用STM32F103-学习sem-信号量-初步使用-线程之间控制-基础样例】
- 1、前言
- 2、环境
- 3、事项了解
- (1)了解sem概念-了解官网消息
- (2)根据自己理解,设计几个使用方式
- (3)不建议运行中,反复删除,在运行线程。
- 4、实验过程
- 实验说明
- 1、第一部分实验
- (1)实验说明-创建工程
- (2)编写代码
- (3)验证结果
- 2、第二部分实验
- (1)实验说明
- (2)编写代码
- (3)验证结果
- 3、第三部分实验
- (1)实验说明
- (2)编写代码
- (3)验证结果
- 5、代码链接
- 6、细节部分
- 1、dome 文件报错
- 7、总结
1、前言
最近,在使用rt-thread的时候,想要用一个线程控制另一个线程的暂停与运行,
但看资料的时候,发现删除线程和重启线程的时候,好像不太理想,这么弄是容易出现问题的,但通过信号量的方式,比较好,所以这次咱们一起来学习下sem。
自己也从新手的角度,一点点学习。整个rt-thread 还是挺大的,不是深耕多年,很难面面聚到,不过用那学哪里。
2、环境
3、事项了解
(1)了解sem概念-了解官网消息
大概看了一遍整个资料,还是挺多的,当你想要使用的时候,其实多少还是有些摸不到头脑的。
但既然要使用Rt-thread的,官方的文档还是要读一下。
链接:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/ipc1/ipc1?id=%e4%bf%a1%e5%8f%b7%e9%87%8f
(2)根据自己理解,设计几个使用方式
我们使用某种RT-thread带有的功能,是为了解决我们自己出现的问题。
设计实验1:
通过使用sem信号量,当一个线程先运行后,再运行另一个线程。这样其实就是让线程之间形成先后关系,适合一定是某个线程完成后,在运行另一个线程。
设计实验2:
通过使用sem信号量,用一个线程,或者一个变量,控制或者暂停另一个线程。这样其实就是有个主线程,或不一定是主线程,可以控制其他线程运行。
以上都是小的功能模块,但是大的项目,都是小模块一点点搭建起来,这算是其中一个砖块,使用的时候,根据自己情况再调整下。
(3)不建议运行中,反复删除,在运行线程。
在看网上资料是,看到有说到,其实不建议反复挂起或删除创建线程,很容易出现问题。
当时看到了资料忘记去哪里,不过本片将有关sem信号量的。
4、实验过程
实验说明
1、第一部分实验
万事皆有要基础,一步一个脚印,如果环境不能使用的话,后续代码都是无用的,所以第一步是要搭建一个可以运行的程序。自己这块没注意,认为软件装好后,随便创建一个工程,就可以运行,没想到卡了一下。
(1)实验说明-创建工程
(2)编写代码
以下内容,RT-Thread Studio工具会自动生成的。
int main(void)
{
int count = 1;
while (count++)
{
LOG_D("Hello RT-Thread!");
rt_thread_mdelay(1000);
}
return RT_EOK;
}
(3)验证结果
这块其实遇到一个内存相关报错,更细节部分可以看细节说明部分。
上述问题解决后,然后连接硬件代码,进行下载验证。
2、第二部分实验
(1)实验说明
此部分,主要是让一个线程先运行,运行完毕,再运行了另一个线程。在现实应用中,很多情况下,都是需要的,并且有实际意义的。
举个例子,现实中,有很多测温需求,温度过高过低,都需要做些事情,相当触发异常,这个时候,温度异常,必须先出现,才做后面事情,可以用这样逻辑解决。
(2)编写代码
/*
* Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-06-21 RT-Thread first version
*/
#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
//第一步
//#include <rtthread.h>
static rt_sem_t sem; // 信号量
//第二步
void sem1_init(void)
{
// 创建一个信号量,初始值为 0
sem = rt_sem_create("sem", 0, RT_IPC_FLAG_FIFO);
if (sem == RT_NULL)
{
rt_kprintf("create semaphore failed.\n");
}
}
//第三步
void thread1_entry(void *parameter)
{
while (1)
{
// 尝试获取信号量,如果信号量值为 0,则线程将被阻塞
rt_sem_take(sem, RT_WAITING_FOREVER);
rt_kprintf("Thread 1 is running.\n");
rt_thread_mdelay(1000); // 模拟线程工作
}
}
//第四步
void thread2_entry(void *parameter)
{
while (1)
{
rt_thread_mdelay(3000); // 等待 3 秒
rt_kprintf("Thread 2 releases semaphore.\n");
rt_sem_release(sem); // 释放信号量
}
}
int main(void)
{
int count = 1;
//第五步 应用
sem1_init();
// 创建线程 1
rt_thread_t tid1 = rt_thread_create("thread1",
thread1_entry, RT_NULL,
1024, 10, 10);
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
// 创建线程 2
rt_thread_t tid2 = rt_thread_create("thread2",
thread2_entry, RT_NULL,
1024, 10, 10);
if (tid2 != RT_NULL)
rt_thread_startup(tid2);
while (count++)
{
//LOG_D("Hello RT-Thread!");
rt_thread_mdelay(1000);
}
return RT_EOK;
}
(3)验证结果
如下为具体实验验证,必须是线程2运行完,才会运行线程1,是按照顺序运行。
3、第三部分实验
(1)实验说明
这种情况,更为复杂些,需要一个线程控制另一个线程,虽然实现方式很多,不一定非要使用这种,但是工具给你准备好了,使不使用看自己,并且是实现比较简单,实际项目,根据自己需求使用。
(2)编写代码
简单讲解下,本实验中,主要是根据a的值,来决定是否运行线程1。
/*
* Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-06-21 RT-Thread first version
*/
#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
//第一步
static rt_sem_t sem; // 信号量
volatile int a = 0; // 控制变量
//第二步
void sem_init(void)
{
// 创建一个信号量,初始值为 0
sem = rt_sem_create("sem", 0, RT_IPC_FLAG_FIFO);
if (sem == RT_NULL)
{
rt_kprintf("create semaphore failed.\n");
}
}
//第三步
void thread1_entry(void *parameter)
{
while (1)
{
// 尝试获取信号量,如果信号量值为 0,则线程将被阻塞
rt_sem_take(sem, RT_WAITING_FOREVER);
rt_kprintf("Thread 1 is running.\n");
rt_thread_mdelay(1000); // 模拟线程工作
}
}
//第四步
void thread2_entry(void *parameter)
{
while (1)
{
rt_thread_mdelay(1000); // 每秒检查一次变量 a 的值
if (a == 1)
{
// 如果 a == 1,则释放信号量,允许线程 1 运行
if (rt_sem_release(sem) == RT_EOK)
{
rt_kprintf("Thread 2 releases semaphore.\n");
}
}
else
{
// 如果 a == 0,则确保信号量不会释放,线程 1 将被暂停
rt_kprintf("Thread 2: a is 0, thread 1 will pause.\n");
}
}
}
void set_a(int value)
{
a = value;
rt_kprintf("Variable a set to %d\n", a);
}
int main(void)
{
int count = 1;
// 初始化信号量
sem_init();
// 创建线程 1
rt_thread_t tid1 = rt_thread_create("thread1",
thread1_entry, RT_NULL,
1024, 10, 10);
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
// 创建线程 2
rt_thread_t tid2 = rt_thread_create("thread2",
thread2_entry, RT_NULL,
1024, 10, 10);
if (tid2 != RT_NULL)
rt_thread_startup(tid2);
while (count++)
{
set_a(0);
rt_thread_mdelay(10000);
set_a(1);
//LOG_D("Hello RT-Thread!");
rt_thread_mdelay(10000);
}
return RT_EOK;
}
(3)验证结果
5、代码链接
代码链接:https://download.csdn.net/download/qq_22146161/89466496
6、细节部分
1、dome 文件报错
7、总结
一个砖一个砖,垒起来。