【FreeRTOS 信号量】互斥信号量

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

普通互斥信号量创建及运行,参阅安富莱电子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();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值