μC/OS-II系统中信号量的使用

以下内容主要注重应用,对源码不做分析,对源码有兴趣的可参考官方具体文档,相关链接:https://doc.micrium.com/display/ucos/

编译环境:Atollic TrueSTUDIO for STM32 9.3.0

硬件:基于STM32F103VET6单片机(使用HAL库)

一、创建一个信号量,OSSemCreate()

  信号量需要创建才能被使用,通过调用OSSemCreate()函数创建信号量,并指定初始信号量的数目,初始信号量的取值范围是0~65535。如果您使用信号量来表示一个或多个事件的发生,您通常会将信号量初始化为0。如果您使用这个信号量来访问一个共享资源,那么您需要将这个信号量初始化为1(也就是说,将它用作二进制信号量)。如果该信号量允许应用程序获得n个相同资源中的任何一个,则将该信号量初始化为n,并将其用作计数信号量。函数的原型为:

  1、OS_EVENT  *OSSemCreate (INT16U cnt)。

  • cnt是指初始可用信号量的数目;
  • 返回与信号量相关联的指向事件控制块的指针。

二、发送一个信号量,OSSemPost()

  发送信号量,函数原型为:

  1、INT8U  OSSemPost (OS_EVENT *pevent)。

  • pevent是信号量相关联的指向事件控制块的指针;
  • 返回值是错误类型。

三、等待一个信号量,OSSemPend()

  如果没有可用的信号量,则等待信号量,函数原型为:

  1、void  OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)。

  • pevent是信号量相关联的指向事件控制块的指针;
  • timeout等待时长(如果是0将一直等下去,直到有可用的信号量);
  • err保存错误类型。

四、示例代码(非中断方式)

  1、定义一个信号量事件指针:

/* 定义一个信号量事件指针 */
OS_EVENT *Semp;

  2、创建信号量,初始可用的信号量为0:

/* 创建信号量,初始可用的信号量为0 */
Semp = OSSemCreate(0);

  3、在一个任务中发送信号量

static void AppTask1(void *p_arg)
{
    (void)p_arg;

    while(1)
    {
        /* 发送一个信号量 */
        OSSemPost(Semp);
        OSTimeDlyHMSM(0, 0, 1, 0);
    }
}

  4、在一个任务中接收信号量

static void AppTaskLed(void *p_arg)
{
    INT8U err;

    (void)p_arg;

    while(1)
    {
        /* 等待一个信号量 */
        OSSemPend(Semp, 0, &err);
        if(err == OS_ERR_NONE)
        {
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
        }
    }
}

 

五、示例代码(中断方式)

  1、定义信号量事件指针:

/* 定义信号量事件指针 */
OS_EVENT *Semp1;
OS_EVENT *Semp2;

  2、创建信号量,初始可用的信号量为0:

/* 创建两个信号量,初始可用的信号量都为0 */
Semp1 = OSSemCreate(0);
Semp2 = OSSemCreate(0);

  3、中断函数中进行针对μC/OS系统的处理:

/**
  * @brief This function handles EXTI line0 interrupt.
  */
void EXTI0_IRQHandler(void)
{
#if uCOS_EN == 1

#if OS_CRITICAL_METHOD == 3u                 /* Allocate storage for CPU status register               */
    OS_CPU_SR   cpu_sr = 0u;
#endif

    OS_ENTER_CRITICAL();
    OSIntEnter();
    OS_EXIT_CRITICAL();
#endif

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

#if uCOS_EN == 1
    OSIntExit();
#endif

}

/**
  * @brief This function handles EXTI line[15:10] interrupts.
  */
void EXTI15_10_IRQHandler(void)
{
#if uCOS_EN == 1

#if OS_CRITICAL_METHOD == 3u                 /* Allocate storage for CPU status register               */
    OS_CPU_SR   cpu_sr = 0u;
#endif

    OS_ENTER_CRITICAL();
    OSIntEnter();
    OS_EXIT_CRITICAL();
#endif

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);

#if uCOS_EN == 1
    OSIntExit();
#endif
}

  4、在中断的回调函数中发送信号量,针对不同端口引脚被触发发送不同的信号量:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin == GPIO_PIN_0)
    {
        /* 发送信号量 */
        OSSemPost(Semp1);
    }

    if(GPIO_Pin == GPIO_PIN_13)
    {
        /* 发送信号量 */
        OSSemPost(Semp2);
    }
}

  5、在两个任务分别去接收中断发出的信号量:

static void AppTaskLed1(void *p_arg)
{
    INT8U err;

    (void)p_arg;

    while(1)
    {
        /* 等待可用的信号量 */
        OSSemPend(Semp1, 0, &err);
        if(err == OS_ERR_NONE)
        {
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);
        }
    }
}

static void AppTaskLed2(void *p_arg)
{
    INT8U err;

    (void)p_arg;

    while(1)
    {
        /* 等待可用的信号量 */
        OSSemPend(Semp2, 0, &err);
        if(err == OS_ERR_NONE)
        {
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
        }
    }
}

 

#endif

posted @ 2020-10-11 14:46  不要让自己太懒  阅读(730)  评论(0编辑  收藏  举报