互斥信号量与二值信号量类似
但是互斥信号量可以解决二值信号量出现的优先级翻转问题,解决办法就是优先级继承
普通互斥信号量创建及运行,参阅安富莱电子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();
}