【FreeRTOS 信号量】二值信号量

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

1. 二值信号量

/* 信号量句柄 */
static SemaphoreHandle_t  xSemaphore = NULL;

static void vTaskTaskUserIF(void *pvParameters)
{
    
    
    while(1)
    {
    
    
    	vTaskDelay(20);
    	/* 参数说明:信号量句柄 */
		xSemaphoreGive(xSemaphore);	//释放信号量API
	}
}

static void vTaskMsgPro(void *pvParameters)
{
    
    
	BaseType_t xResult;
	const TickType_t xMaxBlockTime = pdMS_TO_TICKS(300); /* 设置最大等待时间为300ms */
  
    while(1)
    {
    
    
    	/* 参数说明:信号量句柄,最大等待时间 */
		xResult = xSemaphoreTake(xSemaphore, (TickType_t)xMaxBlockTime);	//信号量等待API,在规定的时间等不到信号量,任务将永久挂起
		if(xResult == pdTRUE)
		{
    
    
			/* 接收到同步信号 */
			printf("接收到同步信号\r\n");
		}
}

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();

	/* 创建二值信号量,首次创建信号量计数值是0 */
	xSemaphore = xSemaphoreCreateBinary();
	if(xSemaphore == NULL)
    {
    
    
        /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
    }
    
    /* 启动调度,开始执行任务 */
    vTaskStartScheduler();

	/* 
	  如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
	  heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
	  #define configTOTAL_HEAP_SIZE	      ( ( size_t ) ( 17 * 1024 ) )
	*/
	while(1);
} 


/* 以上函数 vTaskTaskUserIF 中的 xSemaphoreGive 释放API是在普通任务下使用,在中断中要使用以下两个函数释放*/
static void TIMx_IRQHandler(void)
{
    
    
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	/* 发送同步信号 */
	xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
	/* 如果 xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

STM32CubeMX 二值信号量创建及运行

/* Private variables ---------------------------------------------------------*/
osSemaphoreId myBinarySem01Handle;
/* USER CODE BEGIN PV */

/* USER CODE BEGIN 4 */
void StartDefaultTask(void const * argument)
{
    
    
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  int count = 0;
	
  for(;;)
  {
    
    
		osDelay(2000);
		HAL_UART_Transmit(&huart1,"hello world\r\n",strlen("hello world\r\n"),1000);
		count++;
		if(count == 5)
		{
    
    
			count = 0;
			/* 参数说明:信号量句柄 */
	  		/* STM32CubeMX 在 osSemaphoreRelease 函数体中封装好了 xSemaphoreGiveFromISR 函数体,可以直接在中断中调用 */
			osSemaphoreRelease(myBinarySem01Handle);
		}
  }
  /* USER CODE END 5 */
}
void SemTask02(void const * argument)
{
    
    
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
	
  int32_t ret;
  for(;;)
  {
    
    
  		/* 参数说明:信号量句柄,最大等待时间 */
  		/* STM32CubeMX 在 osSemaphoreWait 函数体中封装好了 xSemaphoreTakeFromISR 函数体,可以直接在中断中调用 */
  		/* #define osWaitForever     0xFFFFFFFF     ///< wait forever timeout value*/
		ret = osSemaphoreWait (myBinarySem01Handle, osWaitForever);	
		if(ret == osOK)
			HAL_UART_Transmit(&huart1,"SemTask02 SemaphoreRelease\r\n",strlen("SemTask02 SemaphoreRelease\r\n"),1000);
		osDelay(10);
  }
  /* USER CODE END 5 */
}
/* USER CODE END 4 */


int main(void)
{
    
    
  /* Create the semaphores(s) */
  /* definition and creation of myBinarySem01 */
  /* 参数说明: 宏展开的的方式定义一个信号量的结构体(名字可以自定义,无需声明)*/
  osSemaphoreDef(myBinarySem01);
  /* 参数说明: 使用宏展开的方式取定义好的结构体地址, 等于1默认是创建二值信号量,大于1是计数信号量*/
  /* 这里注意:STM32CubeMX生的代码二值信号好在创建成功后会默认释放一次信号量,需要不需要释放,请以下操作 */
  /*
	在 semphr.h 文件中 注释以下语句:

	#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
		#define vSemaphoreCreateBinary( xSemaphore )																							\
			{																																	\
				( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE );	\
				if( ( xSemaphore ) != NULL )																									\
				{																																\
					( void ) xSemaphoreGive( ( xSemaphore ) );			//请注释或者删除此条语句,在二值信号量创建成功后不在释放信号量																		\
				}																																\
			}
	#endif
 */
  myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);
  /* USER CODE END RTOS_SEMAPHORES */
  
  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
	
  osThreadDef(defaultTask, StartDefaultTask, osPriorityLow, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  osThreadDef(SemTask02, SemTask02, osPriorityHigh, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(SemTask02), NULL);
  /* USER CODE END RTOS_THREADS */
  
  /* Start scheduler */
  osKernelStart();
}

猜你喜欢

转载自blog.csdn.net/shileiwu0505/article/details/114487163