全球最实用的IT互联网信息网站!

AI人工智能P2P分享&下载搜索网页发布信息网站地图

当前位置:诺佳网 > 电子/半导体 > 处理器/DSP >

TThread完整版学习(RCEA考试练习)之信号量使用

时间:2023-07-26 16:43

人气:

作者:admin

标签: GPIO  信号量  led灯  定时器 

导读:信号量是线程间同步的一种方式。在rtthread中用于线程间同步的还有互斥量和事件集。...

信号量是线程间同步的一种方式。在rtthread中用于线程间同步的还有互斥量和事件集。

什么是进程间同步,简单点的类比就是工厂中的生产线,如果想要执行B工序就必须等待A工序的完成,那么工序A和工序B就是同步的关系,在程序中也是一样。只不过是工序变成了线程。在RTThread的文档里有这样的描述:同步是指按预定的先后次序进行运行,线程同步是指多个线程通过特定的机制(如互斥量,事件对象,临界区)来控制线程之间的执行顺序,也可以说是在线程之间通过同步建立起执行顺序的关系,如果没有同步,那线程之间将是无序的。

然后就是解释一下信号量,一个经典的解释

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

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

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

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

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

最后信号量的使用。其实如果不追究内核的话,操作系统只需要调用api就可以了。具体就是创建信号量(rt_sem_create)、删除信号量(rt_sem_delete)获取信号量( rt_sem_take)、释放信号量( rt_sem_release)详细使用手册可以参考这里

接下来就是一个实验,使用信号量控制LED以500ms的间隔闪烁。

思路:使用一个定时器:每500毫秒释放一次信号量,在创建一个线程用来反转LED灯,当有信号量的时候就执行反转LED灯。

程序部分

/* defined the LED0 pin: PB1 */
#define LED0_PIN    GET_PIN(H, 11)


//定义信号量
static rt_sem_t led_sem = RT_NULL; 
//定义线程
static char led_stack[512];
static struct rt_thread led_thread;
//定时器定义
static rt_timer_t timer_res;

void task_init(void); //线程初始化函数
static void led_entry(void *parameter);//LED反转线程
static void timer(void *parameter);//定时器任务


int main(void)
{
    /* set LED0 pin mode to output */
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
  task_init();
    while (1)
    {
        rt_thread_mdelay(1000);
    }


}


void task_init(void)
{


  /* 创建一个动态信号量,初始值是 0,先进先出*/
    led_sem = rt_sem_create("led on sem", 0, RT_IPC_FLAG_FIFO);
    if (led_sem == RT_NULL)
    {
        rt_kprintf("create led on semaphore failed.n");
        return ;
    }
  //静态创建任务
  rt_thread_init(&led_thread, //线程句柄 
                   "led on", //线程的描述
                   led_entry, //线程入口函数
                   RT_NULL, //线程入口参数
                   &led_stack[0],//线程的栈的起始地址
                   sizeof(led_stack),//线程的栈大小
                   3, 10);//线程的优先级和时间片大小
    rt_thread_startup(&led_thread);//启动线程

  timer_res = rt_timer_create("led sem",//定时器描述
                     timer,//定时器入口函数
                     RT_NULL,//定时器入口参数
                     500,//定时时间
                     RT_TIMER_FLAG_PERIODIC);//循环  
  if(timer_res != RT_NULL)
  {
    rt_timer_start(timer_res);//定时器开始
    rt_kprintf("timer start. n");
  }
}


static void timer(void *parameter)
{
  rt_sem_release(led_sem);//释放信号量
}




static void led_entry(void *parameter)
{
  while(1)
  {
    /*以永远阻塞的形式等待信号量*/
    if(rt_sem_take (led_sem, RT_WAITING_FOREVER) == RT_EOK)
    {
      HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_11);//反转LED
      rt_kprintf("led toggle.tick:%d n",rt_tick_get());
    }
  }
}

下面就是运行结果

图片

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信