精华内容
下载资源
问答
  • 互斥信号量

    2020-10-26 21:01:00
    互斥信号量用于共享资源需要互斥访问的场合,可以理解为初始值为 TRUE 的带优先级天花板和优先级继承机制(意在解决优先级反转问题)的二进制信号量,只有拥有互斥信号量的线程才有权释放互斥信号量。 ...

    目录

    1、Creat

    2、Delete

    3、Wait

    4、Post

    5、Statu


    互斥信号量

    在介绍二进制信号量时,曾讨论到如果二进制信号量创建时设置参数 bInitValue 为TRUE,则可以用于互斥访问共享资源。实际上,SylixOS 的二进制信号量实现的互斥性是将一个变量初始化标记为 1,等待信号量(Wait)时将该变量减 1(此时等于 0),如果另一个线程再次等待该信号量将阻塞,直到该信号量被释放(变量加 1),这样就实现了共享资源的互斥访问。

    如果系统中只有两个线程,上面的过程是没有问题的。但是一旦有多个线程介入,上面过程将出现以下问题:

    一个高优先级的线程可能也要访问同一个共享资源(这是完全有可能的),此时只能阻塞等待,但是可能会有另一个中等优先级的线程将占有信号量的线程抢占。这个过程导致了高优先级线程很长时间得不到运行(这是 SylixOS 不允许出现的情况)。

    以上过程出现的问题就是经典的优先级反转问题。

    互斥信号量用于共享资源需要互斥访问的场合,可以理解为初始值为 TRUE 的带优先级天花板和优先级继承机制(意在解决优先级反转问题)的二进制信号量,只有拥有互斥信号量的线程才有权释放互斥信号量。

     

    1、Creat

    一个 SylixOS 互斥信号量必须要调用 Lw_SemaphoreM_Create 函数创建之后才能使用,如果创建成功,该函数将返回一个互斥信号量的句柄。

    #include <SylixOS.h>
    LW_HANDLE Lw_SemaphoreM_Create(CPCHAR pcName,
         UINT8 ucCeilingPriority,
         ULONG ulOption,
         LW_OBJECT_ID *pulId);

    函数 Lw_SemaphoreM_Create 原型分析:

    • 此函数成功返回互斥信号量的句柄,失败返回 NULL 并设置错误号;
    • 参数 pcName 是互斥信号量的名字;
    • 参数 ucCeilingPriority 在使用优先级天花板算法时有效,此参数为天花板优先级;
    • 参数 ulOption 是互斥信号量的创建选项;
    • 输出参数 pulId 返回互斥信号量的句柄(同返回值),可以为 NULL

    创建选项包含了二进制信号的创建选项,此外还可以使用,如下表所示的互斥信号量特有的创建选项。

    需要注意,LW_OPTION_INHERIT_PRIORITY 和 LW_OPTION_PRIORITY_CEILING只能二选一,同样 LW_OPTION_NORMAL LW_OPTION_ERRORCHECK 及LW_OPTION_RECURSIVE 只能三选一。

     

    2、Delete

    一个不再使用的互斥信号量,可以调用以下函数将其删除。删除后的信号量系统自动回收其占用的系统资源(试图使用被删除的互斥信号量将出现未知的错误)

    #include <SylixOS.h>
    ULONG Lw_SemaphoreM_Delete(LW_HANDLE *pulId);
    函数 Lw_SemaphoreM_Delete 原型分析:
    • 此函数返回错误号;
    • 参数 pulId 是互斥信号量的句柄。
       

    3、Wait

    线程如果需要等待一个互斥信号量,可以调用 Lw_SemaphoreM_Wait 函数。

    #include <SylixOS.h>
    ULONG Lw_SemaphoreM_Wait(LW_HANDLE ulId, ULONG ulTimeout);

    函数 Lw_SemaphoreM_Wait 原型分析:

    • 此函数成功返回 0,失败返回错误号;
    • 参数 ulId 是互斥信号量的句柄;
    • 参数 ulTimeout 是等待的超时时间,单位为时钟嘀嗒 Tick

    4、Post

    释放一个互斥信号量使用 Lw_SemaphoreM_Post 函数。
     
     
    #include <SylixOS.h>
    ULONG Lw_SemaphoreM_Post(LW_HANDLE ulId);

    函数 Lw_SemaphoreM_Post 原型分析:

    • 此函数成功返回 0,失败返回错误号;
    • 参数 ulId 是互斥信号量的句柄。

    需要注意的是,只有互斥信号量的拥有者才能释放该互斥信号量。

    5、Statu

    下面函数可以获得互斥信号量的状态信息。
     
    #include <SylixOS.h>
    ULONG Lw_SemaphoreM_Status(LW_HANDLE ulId,
         BOOL *pbValue,
         ULONG *pulOption,
         ULONG *pulThreadBlockNum);
    ULONG Lw_SemaphoreM_StatusEx(LW_HANDLE ulId,
         BOOL *pbValue,
         ULONG *pulOption,
         ULONG *pulThreadBlockNum,
         LW_HANDLE *pulOwnerId);
    以上两个函数原型分析:
    • 函数成功返回 0,失败返回错误号;
    • 参数 ulId 是互斥信号量的句柄;
    • 输出参数 pbValue 用于接收互斥信号量当前的状态;
    • 输出参数 pulOption 用于接收互斥信号量的创建选项;
    • 输出参数 pulThreadBlockNum 用于接收当前阻塞在该互斥信号量的线程数。
    • 输出参数 pulOwnerId 用于接收当前拥有该互斥信号量的线程的句柄。
     
    获得一个互斥信号量的名字,可以调用以下函数:
    #include <SylixOS.h>
    ULONG Lw_SemaphoreM_GetName(LW_HANDLE ulId, PCHAR pcName);
    函数 Lw_SemaphoreM_GetName 原型分析:
    • 此函数成功返回 0,失败返回错误号;
    • 参数 ulId 是互斥信号量的句柄;
    • 输出参数 pcName 是互斥信号量的名字,pcName 应该指向一个大小为LW_CFG_OBJECT_NAME_SIZE 的字符数组。
     
     
     
    展开全文
  • **信号量的主要目的有两个:共享资源访问。... 在互斥访问中互斥信号量相当于一个钥匙,当任务想要使用资源的时候就必须先获得这个钥匙,当使用完资源以后就必须归还这个钥匙,这样其他的任务就可以拿着这

    **信号量的主要目的有两个:共享资源访问。 与任务同步。

    FreeRTOS中信号量分为如下几种:
    1、二值信号量
    2、计数型信号量
    3、互斥信号量
    4、递归互斥信号量**

    3.互斥信号量

    互斥信号量其实就是一个拥有优先级继承的二值信号量, 在同步的应用中(任务与任务或中断与任务之间的同步)二值信号量最适合。 互斥信号量适合用于那些需要互斥访问的应用中。 在互斥访问中互斥信号量相当于一个钥匙,当任务想要使用资源的时候就必须先获得这个钥匙,当使用完资源以后就必须归还这个钥匙,这样其他的任务就可以拿着这个钥匙去使用资源。互斥信号量可以可以降低优先级翻转带来的影响

    优先级翻转:
    在使用二值信号量的时候会遇到很常见的一个问题——优先级翻转,优先级翻转在可剥夺内核中是非常常见的,在实时系统中不允许出现这种现象,这样会破坏任务的预期顺序,可能会导致严重的后果。
    如图例子:由于高优先级任务在等低优先级任务释放信号量的过程中,低优先级被中优先级任务抢夺CPU,最终导致中优先级任务比高优先级任务先运行,也就是优先级翻转
    在这里插入图片描述
    而互斥信号量就可以将这个影响降到最低,当高优先级任务发现需要信号量被低级信号量占用需要等待时,就将低优先级任务变成和自己同级优先级,就不至于在等待的过程中被中优先级抢夺CPU。

    互斥信号量创建函数
    在这里插入图片描述
    3.递归互斥信号量
    递归互斥信号量,其实就是互斥信号量里面嵌套互斥信号量,实现层层保护
    eg:

    static void vTaskMsgPro(void *pvParameters)
    {
        TickType_t xLastWakeTime;
        const TickType_t xFrequency = 1500;
    
        /* 获取当前的系统时间 */
        xLastWakeTime = xTaskGetTickCount();
        
        while(1)
        {
            /* 递归互斥信号量,其实就是互斥信号量里面嵌套互斥信号量 */
            xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY);
            {
                /* -------------------------------------- */
                   //假如这里是被保护的资源,第1层被保护的资源,用户可以在这里添加被保护资源
                /* ---------------------------------------------------------------------------- */
                printf("任务vTaskMsgPro在运行,第1层被保护的资源,用户可以在这里添加被保护资源\r\n");
                
                /* 第1层被保护的资源里面嵌套被保护的资源 */
                xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY);
                {
                    /* ------------------------------------------------------------------------ */
                    //假如这里是被保护的资源,第2层被保护的资源,用户可以在这里添加被保护资源
                    /* ------------------------------------------------------------------------ */
                    printf("任务vTaskMsgPro在运行,第2层被保护的资源,用户可以在这里添加被保护资源\r\n");
                    
                    /* 第2层被保护的资源里面嵌套被保护的资源 */
                    xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY);
                    {
                        printf("任务vTaskMsgPro在运行,第3层被保护的资源,用户可以在这里添加被保护资源\r\n");
                        bsp_LedToggle(1);
                        bsp_LedToggle(4);
                    }
                    xSemaphoreGiveRecursive(xRecursiveMutex);
                }
                xSemaphoreGiveRecursive(xRecursiveMutex);    
            }
            xSemaphoreGiveRecursive(xRecursiveMutex);
            
            /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
            vTaskDelayUntil(&xLastWakeTime, xFrequency);
        }
    }
    
    展开全文
  • 互斥信号量与二值信号量类似 但是互斥信号量可以解决二值信号量出现的优先级翻转问题,解决办法就是优先级继承 普通互斥信号量创建及运行,参阅安富莱电子demo /* 互斥信号量句柄 */ static SemaphoreHandle_t ...

    互斥信号量与二值信号量类似
    但是互斥信号量可以解决二值信号量出现的优先级翻转问题,解决办法就是优先级继承

    普通互斥信号量创建及运行,参阅安富莱电子demo

    /* 互斥信号量句柄 */
    static SemaphoreHandle_t  xMutex = NULL;
    
    static void vTaskTaskUserIF(void *pvParameters)
    {
        while(1)
        {
        	/* 参数说明:信号量句柄,等待信号量可用的最大等待时间 */
       	 	/* 互斥信号量,xSemaphoreTake和xSemaphoreGive一定要成对的调用 */
    		xSemaphoreTake(xMutex, portMAX_DELAY);					
    		printf("vTaskTaskUserIF\r\n");
    		/* 参数说明:信号量句柄 */
    		xSemaphoreGive(xMutex);	
    		vTaskDelay(20);
    	}
    }
    
    static void vTaskLED(void *pvParameters)
    {
    	TickType_t xLastWakeTime;
    	const TickType_t xFrequency = 200;
    
    	/* 获取当前的系统时间 */
        xLastWakeTime = xTaskGetTickCount();
    	
        while(1)
        {
           	/* 互斥信号量,xSemaphoreTake和xSemaphoreGive一定要成对的调用 */
    		xSemaphoreTake(xMutex, portMAX_DELAY);
    		printf("任务vTaskLED在运行\r\n");
    		xSemaphoreGive(xMutex);
    		/* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
            vTaskDelayUntil(&xLastWakeTime, xFrequency);
        }
    }
    int main(void)
    {
    	/* 
    	  在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
    	  这样做的好处是:
    	  1. 防止执行的中断服务程序中有FreeRTOS的API函数。
    	  2. 保证系统正常启动,不受别的中断影响。
    	  3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
    	  在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
    	  和cpsie i是等效的。
         */
    	__set_PRIMASK(1);  
    	
    	/* 创建任务 ,具体创建任务参阅上一篇【FreeRTOS 任务】任务创建及运行 */
    	AppTaskCreate();
    
    	/* 创建互斥信号量 */
        xMutex = xSemaphoreCreateMutex();
    	if(xMutex == NULL)
        {
            /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
        }
        
        /* 启动调度,开始执行任务 */
        vTaskStartScheduler();
    
    	/* 
    	  如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
    	  heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
    	  #define configTOTAL_HEAP_SIZE	      ( ( size_t ) ( 17 * 1024 ) )
    	*/
    	while(1);
    } 
    

    STM32CubeMX 互斥信号量创建及运行

    /* Private variables ---------------------------------------------------------*/
    osMutexId	myMutexIdHandle = NULL;
    /* USER CODE BEGIN PV */
    
    /* USER CODE BEGIN 4 */
    void MutexTask(void const * argument)
    {
      /* USER CODE BEGIN 5 */
      /* Infinite loop */
    	
    	int32_t ret;
      for(;;)
      {
        	/* 参数说明:信号量句柄,等待信号量可用的最大等待时间 */
       	 	/* 互斥信号量,xSemaphoreTake和xSemaphoreGive一定要成对的调用 */
    		ret = osMutexWait (myMutexIdHandle,osWaitForever);
    		if(ret == osOK)
    		{
    			HAL_UART_Transmit(&huart1,"MutexTask osMutexRelease\r\n",strlen("MutexTask osMutexRelease\r\n"),1000);
    		}
    		/* 参数说明:信号量句柄 */
    		osMutexRelease(myMutexIdHandle);
    		osDelay(2000);
      }
      /* USER CODE END 5 */
    }
    
    
    void StartDefaultTask(void const * argument)
    {
      /* USER CODE BEGIN 5 */
      /* Infinite loop */
    	int32_t ret;
      for(;;)
      {
          	/* 参数说明:信号量句柄,等待信号量可用的最大等待时间 */
       	 	/* 互斥信号量,xSemaphoreTake和xSemaphoreGive一定要成对的调用 */
    		ret = osMutexWait (myMutexIdHandle,osWaitForever);
    		if(ret == osOK)
    		{
    			HAL_UART_Transmit(&huart1,"StartDefaultTask\r\n",strlen("StartDefaultTask\r\n"),1000);	
    		}
    		/* 参数说明:信号量句柄 */
    		osMutexRelease(myMutexIdHandle);
    	  osDelay(500);	
      }
      /* USER CODE END 5 */
    }
    /* USER CODE END 4 */
    
    
    int main(void)
    {
      /* USER CODE BEGIN RTOS_MUTEX */
      /* add mutexes, ... */
     
      /* 参数说明: 宏展开的的方式定义一个互斥信号量的结构体(名字可以自定义,无需声明)*/
      osMutexDef(myMutex);
      /* 参数说明: 使用宏展开的方式取定义好的互斥信号量结构体地址*/
      myMutexIdHandle = osMutexCreate(osMutex(myMutex));
     /* USER CODE END RTOS_MUTEX */
      
      /* USER CODE BEGIN RTOS_THREADS */
      /* add threads, ... */
    	
      osThreadDef(defaultTask, StartDefaultTask, osPriorityLow, 0, 128);
      defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
    
      osThreadDef(MutexTask, MutexTask, osPriorityHigh, 0, 128);
      defaultTaskHandle = osThreadCreate(osThread(MutexTask), NULL);
      /* USER CODE END RTOS_THREADS */
      
      /* Start scheduler */
      osKernelStart();
    }
    
    展开全文
  • ucos 互斥信号量

    2018-08-16 11:58:11
    ucosIII示例-互斥信号量,初始化和使用方法,可直接运行
  • FreeRTOS互斥信号量本文完整版地址:...注意,建议初学者学习完前两个章节的信号量后再学习本章节的互斥信号量。FreeRTOS中互斥信号量的源码实现是基于消息队列实现的。本章教程配套的例子...

    FreeRTOS互斥信号量

    本文完整版地址:http://http://bbs.armfly.com/read.php?tid=21381

    本章节讲解FreeRTOS重要的资源共享机制---互斥信号量(Mutex,即Mutual Exclusion的缩写)。注意,建议初学者学习完前两个章节的信号量后再学习本章节的互斥信号量。

    FreeRTOS中互斥信号量的源码实现是基于消息队列实现的。

    本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407以及F429。

    23.1 互斥信号量

    23.2 互斥信号量API函数

    23.3 实验例程说明

    23.4 总结

    23.1互斥信号量

    23.1.1 互斥信号量的概念及其作用

    互斥信号量的主要作用是对资源实现互斥访问,使用二值信号量也可以实现互斥访问的功能,不过互斥信号量与二值信号量有区别。下面我们先举一个通过二值信号量实现资源独享,即互斥访问的例子,让大家有一个形象的认识,进而引出要讲解的互斥信号量。

    运行条件:

    u 让两个任务Task1和Task2都运行串口打印函数printf,这里我们就通过二值信号量实现对函数printf的互斥访问。如果不对函数printf进行互斥访问,串口打印容易出现乱码。

    u 用计数信号量实现二值信号量只需将计数信号量的初始值设置为1即可。

    代码实现:

    u 创建二值信号量

    static SemaphoreHandle_t  xSemaphore = NULL;

    static void AppObjCreate (void)

    {

    xSemaphore = xSemaphoreCreateBinary();

    if(xSemaphore == NULL)

    {

    }

    xSemaphoreGive(xSemaphore);

    }

    u 通过二值信号量实现对printf函数互斥访问的两个任务

    static void vTaskLED(void *pvParameters)

    {

    TickType_t xLastWakeTime;

    const TickType_t xFrequency = 300;

    xLastWakeTime = xTaskGetTickCount();

    while(1)

    {

    xSemaphoreTake(xSemaphore, portMAX_DELAY);

    printf("任务vTaskLED在运行rn");

    bsp_LedToggle(1);

    bsp_LedToggle(4);

    xSemaphoreGive(xSemaphore);

    vTaskDelayUntil(&xLastWakeTime, xFrequency);

    }

    }

    static void vTaskMsgPro(void *pvParameters)

    {

    TickType_t xLastWakeTime;

    const TickType_t xFrequency = 300;

    xLastWakeTime = xTaskGetTickCount();

    while(1)

    {

    xSemaphoreTake(xSemaphore, portMAX_DELAY);

    printf("任务vTaskMsgPro在运行rn");

    bsp_LedToggle(2);

    bsp_LedToggle(3);

    xSemaphoreGive(xSemaphore);

    vTaskDelayUntil(&xLastWakeTime, xFrequency);

    }

    }

    有了上面二值信号量的认识之后,互斥信号量与二值信号量又有什么区别呢?互斥信号量可以防止优先级翻转,而二值信号量不支持,下面我们就讲解一下优先级翻转问题。

    23.1.2优先级翻转问题

    下面我们通过如下的框图来说明一下优先级翻转的问题,让大家有一个形象的认识。

     

    运行条件:

    u创建3个任务Task1,Task2和Task3,优先级分别为3,2,1。也就是Task1的优先级最高。

    u任务Task1和Task3互斥访问串口打印printf,采用二值信号实现互斥访问。

    u起初Task3通过二值信号量正在调用printf,被任务Task1抢占,开始执行任务Task1,也就是上图的起始位置。

    运行过程描述如下:

    u任务Task1运行的过程需要调用函数printf,发现任务Task3正在调用,任务Task1会被挂起,等待Task3释放函数printf。

    u在调度器的作用下,任务Task3得到运行,Task3运行的过程中,由于任务Task2就绪,抢占了Task3的运行。优先级翻转问题就出在这里了,从任务执行的现象上看,任务Task1需要等待Task2执行完毕才有机会得到执行,这个与抢占式调度正好反了,正常情况下应该是高优先级任务抢占低优先级任务的执行,这里成了高优先级任务Task1等待低优先级任务Task2完成。所以这种情况被称之为优先级翻转问题。

    u任务Task2执行完毕后,任务Task3恢复执行,Task3释放互斥资源后,任务Task1得到互斥资源,从而可以继续执行。

    上面就是一个产生优先级翻转问题的现象。

    23.1.3FreeRTOS互斥信号量的实现

    FreeRTOS互斥信号量是怎么实现的呢?其实相对于二值信号量,互斥信号量就是解决了一下优先级翻转的问题。下面我们通过如下的框图来说明一下FreeRTOS互斥信号量的实现,让大家有一个形象的认识。

    运行条件:

    u创建2个任务Task1和Task2,优先级分别为1和3,也就是任务Task2的优先级最高。

    u任务Task1和Task2互斥访问串口打印printf。

    u使用FreeRTOS的互斥信号量实现串口打印printf的互斥访问。

    运行过程描述如下:

    u低优先级任务Task1执行过程中先获得互斥资源printf的执行。此时任务Task2抢占了任务Task1的执行,任务Task1被挂起。任务Task2得到执行。

    u任务Task2执行过程中也需要调用互斥资源,但是发现任务Task1正在访问,此时任务Task1的优先级会被提升到与Task2同一个优先级,也就是优先级3,这个就是所谓的优先级继承(Priority inheritance),这样就有效地防止了优先级翻转问题。任务Task2被挂起,任务Task1有新的优先级继续执行。

    u任务Task1执行完毕并释放互斥资源后,优先级恢复到原来的水平。由于互斥资源可以使用,任务Task2获得互斥资源后开始执行。

    上面就是一个简单的FreeRTOS互斥信号量的实现过程。

    23.1.4FreeRTOS中断方式互斥信号量的实现

    互斥信号量仅支持用在FreeRTOS的任务中,中断函数中不可使用。

    23.2互斥信号量API函数

    使用如下18个函数可以实现FreeRTOS的信号量(含计数信号量,二值信号量和互斥信号):

    (1)     xSemaphoreCreateBinary()

    (2)    xSemaphoreCreateBinaryStatic()

    (3)    vSemaphoreCreateBinary()

    (4)    xSemaphoreCreateCounting()

    (5)    xSemaphoreCreateCountingStatic()

    (6)    xSemaphoreCreateMutex()

    (7)    xSemaphoreCreateMutexStatic()

    (8)    xSem"CreateRecursiveMutex()

    (9)    xSem"CreateRecursiveMutexStatic()

    (10)    vSemaphoreDelete()

    (11)    xSemaphoreGetMutexHolder()

    (12)    uxSemaphoreGetCount()

    (13)    xSemaphoreTake()

    (14)    xSemaphoreTakeFromISR()

    (15)    xSemaphoreTakeRecursive()

    (16)    xSemaphoreGive()

    (17)    xSemaphoreGiveRecursive()

    (18)    xSemaphoreGiveFromISR()

    关于这18个函数的讲解及其使用方法可以看FreeRTOS在线版手册:

    上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:

    #define tskBLOCKED_CHAR         ( "B" )任务阻塞

    #define tskREADY_CHAR         ( "R" )任务就绪

    #define tskDELETED_CHAR          ( "D" )任务删除

    #define tskSUSPENDED_CHAR  ( "S" )任务挂起

    程序设计:

    u任务栈大小分配:

    vTaskUserIF任务:2048字节

    vTaskLED任务:2048字节

    vTaskMsgPro任务 :2048字节

    vTaskStart任务:2048字节

    任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的

    #define configTOTAL_HEAP_SIZE       ( ( size_t ) ( 17 * 1024 ) )

    u系统栈大小分配:

    uFreeROTS初始化:

    int main(void)

    {

    __set_PRIMASK(1);

    bsp_Init();

    vSetupSysInfoTest();

    AppTaskCreate();

    AppObjCreate();

    vTaskStartScheduler();

    while(1);

    }

    u硬件外设初始化

    硬件外设的初始化是在bsp.c文件实现:

    void bsp_Init(void)

    {

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

    bsp_InitUart();

    bsp_InitLed();

    bsp_InitKey();

    }

    uFreeRTOS任务创建:

    static void AppTaskCreate (void)

    {

    xTaskCreate( vTaskTaskUserIF,

    "vTaskUserIF",

    512,

    NULL,

    1,

    &xHandleTaskUserIF ); /*任务句柄*/

    xTaskCreate( vTaskLED,

    "vTaskLED",

    512,

    NULL,

    2,

    &xHandleTaskLED );

    xTaskCreate( vTaskMsgPro,

    "vTaskMsgPro",

    512,

    NULL,

    3,

    &xHandleTaskMsgPro ); /*任务句柄*/

    xTaskCreate( vTaskStart,

    "vTaskStart",

    512,

    NULL,

    4,

    &xHandleTaskStart );

    }

    uFreeRTOS互斥信号量创建:

    static void AppObjCreate (void)

    {

    xMutex = xSemaphoreCreateMutex();

    if(xMutex == NULL)

    {

    }

    }

    u四个FreeRTOS任务的实现:

    static void vTaskTaskUserIF(void *pvParameters)

    {

    uint8_t ucKeyCode;

    uint8_t pcWriteBuffer[500];

    while(1)

    {

    ucKeyCode = bsp_GetKey();

    if (ucKeyCode != KEY_NONE)

    {

    switch (ucKeyCode)

    {

    case KEY_DOWN_K1:

    xSemaphoreTake(xMutex, portMAX_DELAY);

    printf("=================================================rn");

    printf("任务名任务状态 优先级剩余栈 任务序号rn");

    vTaskList((char *)&pcWriteBuffer);

    printf("%srn", pcWriteBuffer);

    printf("rn任务名运行计数使用率rn");

    vTaskGetRunTimeStats((char *)&pcWriteBuffer);

    printf("%srn", pcWriteBuffer);

    xSemaphoreGive(xMutex);

    break;

    default:

    break;

    }

    }

    vTaskDelay(20);

    }

    }

    static void vTaskLED(void *pvParameters)

    {

    TickType_t xLastWakeTime;

    const TickType_t xFrequency = 200;

    xLastWakeTime = xTaskGetTickCount();

    while(1)

    {

    xSemaphoreTake(xMutex, portMAX_DELAY);

    printf("任务vTaskLED在运行rn");

    bsp_LedToggle(2);

    bsp_LedToggle(3);

    xSemaphoreGive(xMutex);

    vTaskDelayUntil(&xLastWakeTime, xFrequency);

    }

    }

    static void vTaskMsgPro(void *pvParameters)

    {

    TickType_t xLastWakeTime;

    const TickType_t xFrequency = 300;

    xLastWakeTime = xTaskGetTickCount();

    while(1)

    {

    xSemaphoreTake(xMutex, portMAX_DELAY);

    printf("任务vTaskMsgPro在运行rn");

    bsp_LedToggle(1);

    bsp_LedToggle(4);

    xSemaphoreGive(xMutex);

    vTaskDelayUntil(&xLastWakeTime, xFrequency);

    }

    }

    static void vTaskStart(void *pvParameters)

    {

    while(1)

    {

    bsp_KeyScan();

    vTaskDelay(10);

    }

    }

    FreeRTOS互斥信号量相关教程

    展开全文
  • 互斥信号量 计数器信号量 SylixOS 信号量 多个线程在读写某个共享数据(全局变量等)时必须通过某种方法实现共享数据的互斥访问或者同步访问(例如线程 B 等待线程 A 的结果以继续运行)。其中,信号量是一种最...
  • 信号量与互斥信号量

    2019-05-22 20:03:47
    信号量 ucos中,信号量的用处还是蛮多的,它就像开锁的钥匙,用于对共享资源的访问保护。...互斥信号量 1.优先级反转: 在低优先级任务在使用信号量时,高优先级任务也想使用信号量只能等待低优先级使...
  • ucosii 互斥信号量

    2016-07-17 11:36:58
    ucosii 互斥信号量
  • FreeRTOS 分别提供了二值信号量和计数信号量,其中二值信号量可以理解成计数信号量的一种特殊形式,即初始化为仅有一个资源可以使用,只不过 FreeRTOS 对这两种都提供了 API函数,而像 RTX,uCOS-II 和 III 是仅提供...
  • 三 互斥量(互斥信号量)常用函数 四 使用互斥信号量访问共享资源 五 任务内置信号量相关函数 六 使用任务内置信号量 一 ucos-iii 信号量相关函数 创建信号量 OSSemCreate() OS_CFG_SEM_EN OS_SEM...
  • 第十章 UCOSIII信号量和互斥信号量前言 前言 在 UCOSIII中有可能会有多个任务会访问共享资源,因此信号量最早用来控制任务存取共 享资源,现在信号量也被用来实现任务间的同步以及任务和 ISR间同步。在可剥夺的内核...
  • 1 、互 斥 信 号 量1.1 互斥信号量的概念及其作用互斥信号量的主要作用是对资源实现互斥访问,使用二值信号量也可以实现互斥访问的功能,不过互斥信号量与二值信号量有区别。下面我们先举一个通过二值信号量实现资源...
  • 互斥信号量(mutex)的获取是完全互斥的,即同一时刻,mutex只能被一个任务获取。而信号量(sem)按照起始count的配置,存在多个任务获取同一信号量的情况,直到count减为0,则后续任务无法再获取信号量,当然sem的count...
  • 第16讲 UCOSIII信号量和互斥信号量(下)ppt,ALIENTEK UCOS学习视频(课件)
  • 互斥信号量作用:任务通过OSMutexPend()函数获得互斥信号量,如果互斥信号有效(不为0)则继续运行,否则进入等待。 那么他们之间区别在哪? 假设有三个任务A,B,C,他们的优先级分别为10、20、30,而任务A和C共同...
  • 互斥信号量和二进制信号量的区别 互斥量用于线程的互斥,信号量用于线程的同步。这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。 互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性...
  • 1.互斥信号量 互斥信号量的申请与释放是要在同一个任务中进行的,不能在一个任务中申请而在另一个任务中释放。 互斥信号量主要解决的是,我在用的时候,别人都不能用。举个例子,我在像一段内存中写数据的时候,不...
  • 本章节讲解 FreeRTOS 任务间的同步和资源共享机制...FreeRTOS 分别提供了二值信号量和计数信号量,其中二值信号量可以理解成计数信号量的一种特殊形式,即初始化为仅有一个资源可以使用,只不过 FreeRTOS 对这两种都...
  • 信号量和互斥信号量的理解

    千次阅读 2019-04-09 08:26:11
    信号量和互斥信号量的记住和理解应用是不一样的哦,面试常问。 做下本人理解和参考他人后的笔记 对于互斥锁(Mutex)来说,只要有线程占有了该资源,那么不好意思,其他线程就是优先级再高,您也得等着,等我用完...
  • UCOSIII互斥信号量

    2020-07-22 14:52:49
    1、 0 1 创建一个互斥信号量 作用相当于linux互斥锁
  • ucosIII 互斥信号量、内嵌信号量

    千次阅读 2015-12-20 20:59:09
    第一部分:互斥信号量,用于解决信号量优先级反转问题 第二部分:内嵌信号量 信号量的优先级反转问题 信号量在一定情况下会造成高优先级的任务反而之后才执行 解决方法:可以将需要等待的任务L优先级上调到和...
  • 8、互斥信号量

    2018-02-05 10:19:00
    互斥信号量 1、互斥信号量的原理与创建 互斥信号量类型 typedef struct _tMutex { //事件控制块 tEvent event; //已被锁定的次数 uint32_t lockedCount; //拥有者 tTask * owner; //拥有原始的...
  • 本文介绍了递归互斥信号量的概念和API函数源码分析、以及递归互斥信号量的使用实例
  • 1. 互斥信号量的原理与创建 1.1 问题概述 1.1.1 计数信号量的不足 1.1.2 优先级反转现象说明 1.2 设计原理 1.2.1 互斥信号量组件 1.2.2 锁定计数器原理 1.2.3 优先级继承原理 1.3 设计实现 1.3.1 定义互斥...
  • 互斥信号量的初值一般设为1 2、用途 (1)同步信号量的用途:防止被抢占 初始为空 低优先级的任务持有信号量,高优先级的任务需要这个信号量,只有当低优先级的任务give(释放)信号量,高优先级的任务才能take...
  • 为了解决这个问题,引出了互斥信号量的概念。 1:信号量   信号量是一种上锁机制,该任务必须获得相应的钥匙才能进入,直至代码执行结束,释放钥匙,程序才退出。信号量分两种,一种是二进制信号量,一种是计数型
  • 1 、互 斥 信 号 量1.1 互斥信号量的概念及其作用互斥信号量的主要作用是对资源实现互斥访问,使用二值信号量也可以实现互斥访问的功能,不过互斥信号量与二值信号量有区别。下面我们先举一个通过二值信号量实现资源...
  • UCOSIII中的互斥信号量

    2019-09-14 10:50:15
    文章目录序言优先级反转优先级反转实验互斥信号量互斥信号量实验任务内嵌信号量任务内嵌信号量实验 序言 我的上一篇文章介绍了信号量的基础知识并利用这些基础知识进行了一个小实验以此来增进对信号量这个概念的感性...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,069
精华内容 4,427
关键字:

互斥信号量