普通二值信号量创建创建及运行,参阅安富莱电子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();
}