RT-thread初学

线程

在这里插入图片描述

动态创建线程

/*任务回调函数*/
void rtt1_entry(void *parameter)
{
    for(int i = 0;i<5;i++)
    {
        rt_kprintf("run1:%d\n",i);
        rt_thread_delay(1000);
    }
}
	/*动态创建函数*/
    rtt1_ptr = rt_thread_create("rtt1",rtt1_entry,NULL,1024,1,5);
    if(rtt1_ptr == RT_NULL){
        LOG_E("Thread creation 1 failure\n");
    }
    else{
        LOG_D("Thread created 1 successfully\n");
        rt_thread_startup(rtt1_ptr);
    }

静态创建线程

/*简要:任务2回调函数*/
void rtt2_entry(void *parameter)
{
    for(int i = 0;i<5;i++)
    {
        rt_kprintf("run2:%d\n",i);
        rt_thread_delay(1000);
    }
    //rt_thread_delete(rtt1_ptr);
}
	/*静态创建函数*/
    int ret = rt_thread_init(&rtt2_ptr,"rtt2",rtt2_entry,NULL,rtt2_stack,sizeof(rtt2_stack),2,5);
    if(ret == 0){
        LOG_D("Thread created 2 successfully\n");
        rt_thread_startup(&rtt2_ptr);
    }
    else {
        LOG_E("Thread creation 2 failure\n");
    }

钩子函数

在整个系统的运行时,系统都处于线程运行、中断触发 - 响应中断、切换到其他线程,甚至是线程间的切换过程中,或者说系统的上下文切换是系统中最普遍的事件。有时用户可能会想知道在一个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数。在系统线程切换时,这个钩子函数将被调用

/*简要:钩子函数*/
void scheduler_hook(struct rt_thread *from, struct rt_thread *to)
{
    //rt_kprintf("from:%s ---> to:%s\n",from->name,to->name);
}
rt_scheduler_sethook(scheduler_hook);

定时器

RT-Thread 的定时器提供两类定时器机制:第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。第二类是周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动的停止,否则将永远持续执行下去。

获取系统时间

int main(void)
{
    for(int i = 0;i<10;i++)
    {
        /*获取系统时间*/
        rt_tick_t num = rt_tick_get();
        rt_kprintf("tick : %u\n",num);
        rt_thread_mdelay(500);
    }
    return 0;
}

动态创建定时器

/*
 * 简要:动态定时器的回调函数
 */
void tim1_demo(void *parameter)
{
    rt_kprintf("tim1 run\n");
}
	rt_timer_t tim_1 = NULL;
	
    /*动态创建定时器(周期)*/
    tim_1 = rt_timer_create("tim1",tim1_demo,RT_NULL,3000,RT_TIMER_FLAG_PERIODIC);

    /*启动定时器*/
    if(tim_1 != RT_NULL)rt_timer_start(tim_1);

静态创建定时器

/*
 * 简要:静态定时器的回调函数
 */
void tim2_demo(void *parameter)
{
    rt_kprintf("tim2 run\n");
}
	struct rt_timer tim_2;
	
    /*静态创建定时器(单次)*/
    rt_timer_init(&tim_2,"tim2",tim2_demo,RT_NULL,3000,RT_TIMER_FLAG_ONE_SHOT);

    /*启动定时器*/
    rt_timer_start(&tim_2);

信号量

以生活中的停车场为例来理解信号量的概念:

①当停车场空的时候,停车场的管理员发现有很多空车位,此时会让外面的车陆续进入停车场获得停车位;

②当停车场的车位满的时候,管理员发现已经没有空车位,将禁止外面的车进入停车场,车辆在外排队等候;

③当停车场内有车离开时,管理员发现有空的车位让出,允许外面的车进入停车场;待空车位填满后,又禁止外部车辆进入。

在此例子中,管理员就相当于信号量,管理员手中空车位的个数就是信号量的值(非负数,动态变化);停车位相当于公共资源(临界区),车辆相当于线程。车辆通过获得管理员的允许取得停车位,就类似于线程通过获得信号量访问公共资源。

静态创建与动态创建信号量

rt_sem_t rs1 = NULL;
struct rt_semaphore rs2;
int main(void)
{
    /*动态创建信号量*/
    rs1 = rt_sem_create("dsem",0,RT_IPC_FLAG_PRIO);
    if(rs1 == RT_NULL)
    {
        LOG_E("dsem no\n");
        return -1;
    }
    else
    {
        LOG_D("dsem yes\n");
    }
    /*静态创建信号量*/
    rt_sem_init(&rs2,"dsem2",0,RT_IPC_FLAG_PRIO);

    return RT_EOK;
}

信号量实例

/*全局变量*/
rt_sem_t rs1 = NULL;
rt_sem_t rs2 = NULL;
rt_thread_t rm1 = NULL;
rt_thread_t rm2 = NULL;
int num = 0;

/*任务1*/
void dome1_task(void *parameter)
{
    while(1)
    {
        rt_sem_take(rs1,RT_WAITING_FOREVER);
        num++;
        rt_kprintf("[num: %d]dome1_task run\n",num);
        if(num == 100)
        {
           num = 0;
        }
        rt_sem_release(rs2);
        rt_thread_mdelay(1000);
    }
}

/*任务2*/
void dome2_task(void *parameter)
{
    while(1)
    {
        rt_sem_take(rs2,RT_WAITING_FOREVER);
        if(num > 0)
        {
            num--;
            rt_kprintf("[num: %d]dome2_task run\n",num);
        }
        rt_sem_release(rs1);
        rt_thread_mdelay(3000);
    }
}

/*主函数*/
int main(void)
{
    /*创建信号量1*/
    rs1 = rt_sem_create("dsem1",1,RT_IPC_FLAG_PRIO);
    if(rs1 == RT_NULL)
    {
        LOG_E("dsem1 no\n");
        return -1;
    }
    else
    {
        LOG_D("dsem1 yes\n");
    }

    /*创建信号量2*/
    rs2 = rt_sem_create("dsem2",0,RT_IPC_FLAG_PRIO);
    if(rs2 == RT_NULL)
    {
        LOG_E("dsem2 no\n");
        return -1;
    }
    else
    {
        LOG_D("dsem2 yes\n");
    }

    /*创建线程1*/
    rm1 = rt_thread_create("dome1",dome1_task,NULL,512,20,5);
    if(rm1 == RT_NULL)
    {
        LOG_E("dome1 rt_thread_create NO\n");
        return -1;
    }
    else
    {
        LOG_D("dome1 rt_thread_create YES\n");
        rt_thread_startup(rm1);
    }

    /*创建线程2*/
    rm2 = rt_thread_create("dome2",dome2_task,NULL,512,20,5);
    if(rm2 == RT_NULL)
    {
        LOG_E("dome2 rt_thread_create NO\n");
        return -1;
    }
    else
    {
        LOG_D("dome2 rt_thread_create YES\n");
        rt_thread_startup(rm2);
    }

    return -1;
}

互斥量(互斥锁)

在这里插入图片描述

互斥量又叫相互排斥的信号量,是一种特殊的二值信号量。互斥量类似于只有一个车位的停车场:当有一辆车进入的时候,将停车场大门锁住,其他车辆在外面等候。当里面的车出来时,将停车场大门打开,下一辆车才可以进入。

动态创建互斥量

	rt_mutex_t Motor = NULL;
    /*动态创建互斥锁*/
    Motor = rt_mutex_create("Motor",0);
    if (Motor == RT_NULL)
    {
        rt_kprintf("Motor rt_mutex_create NO");
        return -1;
    }

互斥量实例

/*全局变量*/
rt_thread_t t1 = NULL;
rt_thread_t t2 = NULL;
rt_mutex_t Motor = NULL;
int num1 = 0,num2 = 0;

/*线程1回调函数*/
void task1_main(void *parameter)
{
    while(1)
    {
        rt_mutex_take(Motor,RT_WAITING_FOREVER);
        num1++;
        rt_thread_mdelay(500);
        num2++;
        rt_mutex_release(Motor);
    }
}

/*线程2回调函数*/
void task2_main(void *parameter)
{
    while(1)
    {
        rt_mutex_take(Motor,RT_WAITING_FOREVER);
        if(num1 != num2){
            rt_kprintf("num1:%d != num2:%d\n",num1,num2);
        }
        else {
            rt_kprintf("num1:%d == num2:%d\n",num1,num2);
        }
        rt_thread_mdelay(500);
        rt_mutex_release(Motor);

        if(num1>58)
        {
            return;
        }
    }
}

int main(void)
{
    /*动态创建互斥锁*/
    Motor = rt_mutex_create("Motor",0);
    if (Motor == RT_NULL)
    {
        rt_kprintf("Motor rt_mutex_create NO");
        return -1;
    }

    /*动态创建线程1*/
    t1 = rt_thread_create("task1",task1_main,RT_NULL,512,15,500);
    if(t1 != RT_NULL){
        LOG_D("task1 rt_thread_create YES");
        rt_thread_startup(t1);
    }
    else {
        LOG_E("task1 rt_thread_create NO");
        return -1;
    }

    /*动态创建线程2*/
    t2 = rt_thread_create("task2",task2_main,RT_NULL,512,17,500);
    if(t2 != RT_NULL){
        LOG_D("task2 rt_thread_create YES");
        rt_thread_startup(t2);
    }
    else {
        LOG_E("task2 rt_thread_create NO");
        return -1;
    }
    return RT_EOK;
}

注意

  • 线程任务执行完,线程不是挂起,而是删除了
  • 在获得互斥量后,请尽快释放互斥量,并且在持有互斥量的过程中,不得再行更改持有互斥量线程的优先级,否则可能人为引入无界优先级反转的问题。
  • 需要切记的是互斥量不能在中断服务例程中使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值