RT_Thread 调试笔记:信号量,互斥量,事件集 的创建和使用流程

2024-01-07 21:01:09

说明:记录日常使用?RT_Thread 开发时做的笔记。

持续更新中,欢迎收藏。

1. 信号量

1. 使用流程

/* 信号量的定义和使用流程 */

/*step1: 定义用于接收消息的信号量*/
static struct rt_semaphore rx_sem;  或者 static rt_sem_t rx_sem;

/*step2: 初始化信号量 */
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);

/*step3:获取信号量函数,阻塞等待接收信号量,等到信号量后再次读取数据,RT_WAITING_FOREVER参数,永远阻塞,直到获得资源 */
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);

/*step4:释放信号量可以唤醒挂起在该信号量上的线程。释放信号量使用下面的函数。可以在中断或线程内使用*/
rt_sem_release(&rx_sem);
//示例:rt_sem_release(&rx_sem_adc_dma);//释放信号量

2.rt_sem_control()

rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg)

????????rt_sem_release释放信号量后会将挂起在sem_ack上的线程唤醒并重新调度,rt_sem_control是有可能等下次该线程运行时才会被执行的。在rt_sem_release后使用rt_sem_control的目的是因为在某些应用中必须rt_sem_take和rt_sem_release依次出现,而不允许rt_sem_release被连续多次调用,一旦出现这种情况会被认为是出现了异常,通过调用rt_sem_control接口来重新初始化sem_ack,恢复异常。

2. 互斥量

/* 互斥量的使用:
 * 1:当线程完成互斥资源的访问后,应尽快释放它占据的互斥量,使得其他线程能及时获取该互斥量。
 * 2:互斥量的 flag 标志设置为 RT_IPC_FLAG_PRIO,表示在多个线程等待资源时,将由优先级高的线程优先获得资源。
 * 3:互斥量的 flag 标志设置为 RT_IPC_FLAG_FIFO,表示在多个线程等待资源时,将按照先来先得的顺序获得资源。
 * 4:当不再使用互斥量时,通过删除互斥量以释放系统资源,适用于动态创建的互斥量。
 * .删除互斥量使用下面的函数接口:rt_err_t rt_mutex_delete (rt_mutex_t mutex);
 * */

/*step1: 定义指向互斥量的指针*/
static rt_mutex_t dynamic_mutex = RT_NULL;

/*step2: 创建一个动态互斥量 */
dynamic_mutex = rt_mutex_create("dmutex", RT_IPC_FLAG_FIFO);

/*step3: 获取互斥量: rt_err_t rt_mutex_take (rt_mutex_t mutex, rt_int32_t time);time 可以是等待具体时间也可以是永远等待*/
rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);

/*step4: 释放互斥量:*/
rt_mutex_release(dynamic_mutex);

3. 事件集

1. 事件集使用流程及案例:看门狗 事件 控制线程?

/* 看门狗 事件 控制线程 */

#define EVENT_FLAG3 (1 << 3)
#define EVENT_FLAG4 (1 << 4)
#define EVENT_FLAG5 (1 << 5)
#define EVENT_FLAG6 (1 << 5)

#define WDT_EVENT (EVENT_FLAG3 | EVENT_FLAG4 |EVENT_FLAG5 | EVENT_FLAG6) /* 开启的事件打包 */

/* 事件集的管理方式 */
/* step1: 创建事件控制块 */
/* step2: 初始化事件对象 */
/* step3: 发送事件 */
/* step4: 接收事件 */
/* step5: 删除,脱离事件 */

/* step1: 创建事件控制块 */
static struct rt_event wdt_event;

/* 事件应用 线程 入口函数 */
static void thread_recv_event(void *param)
{
    rt_uint32_t e;      /* 接收事件的变量 */

    rt_err_t result;

    /* step2: 初始化事件对象 */
    result = rt_event_init(&wdt_event, "wdt_event", RT_IPC_FLAG_FIFO);
    if (result != RT_EOK)
    {
        rt_kprintf("init event failed.\n");
        return -1;
    }

    while(1)
    {
        /* step4:接收事件,事件 WD_ENENT 打包的事件全部收集后 ....,接收完后清除事件标志 */
        if (rt_event_recv(&wdt_event,  /* 事件集对象的句柄 */
                          WDT_EVENT,  /* 接收线程感兴趣的事件 */
                          RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, /* 接收选项 ,事件逻辑与,接收后清除事件标志 */
                          RT_WAITING_FOREVER, /* 指定超时时间 */
                          &e)                /* 指向接收到的事件 */
                          == RT_EOK)
        {
            rt_kprintf("thread1: AND recv event 0x%x\n", e);
        }

        /* 收到事件后要执行的代码 */


    }


    /* step3: 发送事件 */
    /* 发送事件函数使用实例 (此处仅做使用方法记录,本行代码并非使用在此处)*/
    rt_event_send(&wdt_event, EVENT_FLAG5); /* 发送事件函数,事件控制块,事件标志位 */


}

/* 接以上 */

文章来源:https://blog.csdn.net/yutian0606/article/details/135436000
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。