RT-Thread线程相关及遇到的问题

一、线程相关函数

rt_err_t rt_thread_init(struct rt_thread *thread,
                        const char       *name,
                        void (*entry)(void *parameter),
                        void             *parameter,
                        void             *stack_start,
                        rt_uint32_t       stack_size,
                        rt_uint8_t        priority,
                        rt_uint32_t       tick);//静态线程的创建
rt_err_t rt_thread_detach(rt_thread_t thread);//将指定的静态线程脱离等待队列
rt_thread_t rt_thread_create(const char *name,
                             void (*entry)(void *parameter),
                             void       *parameter,
                             rt_uint32_t stack_size,
                             rt_uint8_t  priority,
                             rt_uint32_t tick);//创建动态线程
rt_thread_t rt_thread_self(void);//获取当前正在运行的线程
rt_thread_t rt_thread_find(char *name);//查找指定的线程
rt_err_t rt_thread_startup(rt_thread_t thread);//使指定线程进入等待队列
rt_err_t rt_thread_delete(rt_thread_t thread);//删除动态线程并释放空间

rt_err_t rt_thread_yield(void);//当前线程让出控制权
rt_err_t rt_thread_delay(rt_tick_t tick);//当前线程休眠tick时间
rt_err_t rt_thread_mdelay(rt_int32_t ms);//当前线程休眠指定时间,单位为ms
rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg);//线程控制函数,可修改优先级等参数
rt_err_t rt_thread_suspend(rt_thread_t thread);//将指定线程挂起
rt_err_t rt_thread_resume(rt_thread_t thread);//恢复指定线程到等待队列
void rt_thread_timeout(void *parameter);//线程超时函数,通常是内部调用

二、静态创建和动态创建

创建线程函数的各个参数可以在rtconfig.h文件里找到对应:

1/RT_TICK_PER_SECOND是一个时钟节拍的时间,这里为1ms

1、动态创建

动态创建比较简单,会在堆区自动分配存储空间,先使用rt_thread_t定义一个控制块,使用的函数:

//返回值是线程控制块的地址
rt_thread_t rt_thread_create(const char *name,//线程的名称
                             void (*entry)(void *parameter),//回调函数,线程被调用后会进入这个函数,需自己定义
                             void       *parameter,//传入回调函数的参数,没用可填NULL
                             rt_uint32_t stack_size,//分配栈的大小,在堆区
                             rt_uint8_t  priority,//线程的优先级,数字越低优先级越高
                             rt_uint32_t tick);//时间片,时钟节拍数大小,当两个或多个线程的优先级一样时,一个线程执行tick时间,轮流执行

由于是线程创建后是在堆区,所以要删除线程的时候会释放存储空间,使用 rt_thread_delete(rt_thread_t thread)函数。

2、静态创建

静态创建要自己分配存储空间,在栈空间,需要先使用struct rt_thread创建控制块和一个数组用作栈空间,使用的函数:

//返回的是是否创建成功的值
rt_err_t rt_thread_init(struct rt_thread *thread,//线程控制块
                        const char       *name,//线程名称
                        void (*entry)(void *parameter),//回调函数
                        void             *parameter,//回调函数参数
                        void             *stack_start,//栈的起始地址
                        rt_uint32_t       stack_size,//栈的大小
                        rt_uint8_t        priority,//线程优先级
                        rt_uint32_t       tick);//时间片

由于在栈区,删除时只能脱离,使用rt_thread_detach(rt_thread_t thread)函数。

三、简单实例

使用沁恒的ch32v307vct6开发板,使开发板上的两个led灯交替闪灭。

main.c:

int main(void)
{
    rt_kprintf("MCU: CH32V307\n");
    rt_kprintf("SysClk: %dHz\n",SystemCoreClock);
    rt_kprintf("www.wch.cn\n");

    LedInit();//初始化led连接的引脚并创建线程
    rt_thread_startup(led1);//开启led1线程调度
    rt_thread_startup(led2);//开启哦led2线程调度
}

led.c:

/*
 * led.c
 *
 *  Created on: Aug 5, 2023
 *      Author: L
 */
#include <rtthread.h>
#include "ch32v30x.h"
#include <rtdbg.h>
#include "led.h"

rt_thread_t led1 = NULL;
rt_thread_t led2 = NULL;

/***********************************************
* @brief : 初始化led灯,连接到板子上的PC13--led1和PB10--led2引脚
* @param : void
* @return: void
* @date  : 2023.8.4
* @author: L
************************************************/
void LedInit(void)
{
    GPIO_InitTypeDef gpio_initstruct = {0};//gpio句柄结构体
    //PC13引脚
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//开启APB2的GPIOC时钟
    gpio_initstruct.GPIO_Pin = GPIO_Pin_13;//13号引脚
    gpio_initstruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
    gpio_initstruct.GPIO_Speed = GPIO_Speed_10MHz;//速度10MHz
    GPIO_Init(GPIOC, &gpio_initstruct);//初始化PC13

    led1 = rt_thread_create("led1", LedThread1, NULL, 1024, 3, 5);//初始化LED1的线程
    //PB10引脚
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启APB2的GPIOB时钟
    gpio_initstruct.GPIO_Pin = GPIO_Pin_10;//10号引脚
    GPIO_Init(GPIOB, &gpio_initstruct);//初始化PB2

    led2 = rt_thread_create("led2", LedThread2, NULL, 1024, 4, 5);//初始化LED2的线程
}
/***********************************************
* @brief : LED1回调函数
* @param : parameter:需要传入的参数
* @return: void
* @date  : 2023.8.4
* @author: L
************************************************/
void LedThread1(void *parameter)
{
    while(1)
    {
        GPIO_ResetBits(GPIOC, GPIO_Pin_13);//灯亮
        rt_kprintf("led1 on\r\n");
        rt_thread_mdelay(1000);
        GPIO_SetBits(GPIOC, GPIO_Pin_13);//灯灭
        rt_kprintf("led1 off\r\n");
        rt_thread_mdelay(1000);
    }
}
/***********************************************
* @brief : LED2回调函数
* @param : parameter:需要传入的参数
* @return: void
* @date  : 2023.8.4
* @author: L
************************************************/
void LedThread2(void *parameter)
{
    while(1)
    {
        GPIO_SetBits(GPIOB, GPIO_Pin_10);//灯灭
        rt_kprintf("led2 on\r\n");
        rt_thread_mdelay(1000);
        GPIO_ResetBits(GPIOB, GPIO_Pin_10);//灯亮
        rt_kprintf("led2 off\r\n");
        rt_thread_mdelay(1000);
    }
}


led.h:

/*
 * led.h
 *
 *  Created on: Aug 5, 2023
 *      Author: L
 */

#ifndef USER_LED_H_
#define USER_LED_H_

extern rt_thread_t led1;
extern rt_thread_t led2;

void LedInit(void);
void LedThread1(void *parameter);
void LedThread2(void *parameter);

#endif /* USER_LED_H_ */

四、遇到的问题

在led.c里面动态创建了两个线程,下载之后却一直只有一个灯出现了该有的现象,在串口调试助手发送list_thread命令,只能看到一个创建了的线程,并且提示如下错误,查了资料后才知道有个宏定义可以修改堆区的大小。

在board.c文件里面:

修改RT_HEAP_SIZE的大小,由于我一个线程分配的是1024的大小,所以创建两个的时候最后创建的那个线程就失败了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RT-Thread 是一个实时操作系统,支持多线程操作。线程RT-Thread 中的基本执行单元,可以通过 RT-Thread 的 API 来创建和管理线程RT-Thread 线程创建 API 主要有以下几个: 1. rt_thread_t rt_thread_create(const char *name, void (*entry)(void *parameter), void *parameter, size_t stack_size, rt_uint8_t priority, rt_uint32_t tick); 该函数用于创建一个线程,参数如下: - name:线程的名称(必填)。 - entry:线程的入口函数(必填)。 - parameter:传递给线程入口函数的参数。 - stack_size:线程栈的大小,以字节为单位。 - priority:线程的优先级,取值范围是 0~31,数值越小优先级越高。 - tick:线程的时间片长度,以系统时钟节拍为单位。 2. void rt_thread_startup(rt_thread_t thread); 该函数用于启动一个线程,参数是线程句柄。 3. rt_thread_t rt_thread_self(void); 该函数返回当前线程的句柄。 4. rt_err_t rt_thread_delete(rt_thread_t thread); 该函数用于删除一个线程,参数是线程句柄。 5. rt_err_t rt_thread_yield(void); 该函数用于让出当前线程的时间片,让其他线程执行。 6. rt_err_t rt_thread_suspend(rt_thread_t thread); 该函数用于挂起一个线程,使其暂停执行。 7. rt_err_t rt_thread_resume(rt_thread_t thread); 该函数用于恢复一个被挂起的线程,使其继续执行。 以上是 RT-Thread 线程创建的几个基本 API,可以根据实际需求选择使用。需要注意的是,线程的优先级和时间片长度是影响线程执行顺序的重要因素,需要根据实际情况进行设置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值