目录概述1 信号量概述2 FreeRTOS信号量类型2.1 二进制信号量Binary Semaphore2.2 计数信号量Counting Semaphore2.3 互斥信号量Mutex2.4 递归互斥量Recursive Mutex3 信号量API函数详解3.1 创建信号量3.2 获取/释放信号量3.3 中断服务程序中的信号量操作3.4 其他函数4 使用示例4.1 二进制信号量示例任务同步4.2 计数信号量示例资源池管理4.3 互斥量示例保护共享资源4.4 递归互斥量示例4.5 ISR中使用信号量概述FreeRTOS中信号量是用于任务间同步和资源管理的重要机制。信号量分为二进制信号量、计数型信号量和互斥信号量互斥锁。下面将详细说明它们的使用方法。1 信号量概述信号量是FreeRTOS中用于任务间同步和互斥的重要机制主要用于任务同步通知某个事件发生资源管理控制对共享资源的访问任务通信在任务间传递状态信息信号量选择原则场景推荐信号量类型任务同步二进制信号量资源计数计数信号量保护共享资源互斥量任务可能多次获取同一锁递归互斥量2 FreeRTOS信号量类型2.1 二进制信号量Binary Semaphore只有0和1两种状态常用于任务同步2.2 计数信号量Counting Semaphore计数器值可以从0到最大值用于管理多个相同的资源2.3 互斥信号量Mutex特殊的二进制信号量具有优先级继承机制防止优先级反转2.4 递归互斥量Recursive Mutex允许同一任务多次获取锁必须释放相同次数才能完全解锁3 信号量API函数详解3.1 创建信号量/* 创建二进制信号量 */ SemaphoreHandle_t xSemaphoreCreateBinary(void); /* 创建计数信号量 */ SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, /* 最大计数值 */ UBaseType_t uxInitialCount /* 初始计数值 */ ); /* 创建互斥量 */ SemaphoreHandle_t xSemaphoreCreateMutex(void); /* 创建递归互斥量 */ SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void);3.2 获取/释放信号量/* 获取信号量阻塞 */ BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, /* 信号量句柄 */ TickType_t xTicksToWait /* 超时时间 */ ); /* 获取信号量非阻塞 */ xSemaphoreTake(xSemaphore, 0); /* 获取信号量无限等待 */ xSemaphoreTake(xSemaphore, portMAX_DELAY); /* 释放信号量 */ BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore); /* 获取递归互斥量 */ BaseType_t xSemaphoreTakeRecursive( SemaphoreHandle_t xMutex, TickType_t xTicksToWait ); /* 释放递归互斥量 */ BaseType_t xSemaphoreGiveRecursive(SemaphoreHandle_t xMutex);3.3 中断服务程序中的信号量操作/* 在ISR中释放信号量 */ BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken ); /* 在ISR中获取信号量 */ BaseType_t xSemaphoreTakeFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );3.4 其他函数/* 删除信号量 */ void vSemaphoreDelete(SemaphoreHandle_t xSemaphore); /* 获取信号量计数值 */ UBaseType_t uxSemaphoreGetCount(SemaphoreHandle_t xSemaphore);4 使用示例4.1 二进制信号量示例任务同步#include FreeRTOS.h #include task.h #include semphr.h /* 定义信号量句柄 */ SemaphoreHandle_t xBinarySemaphore; /* 任务1等待事件 */ void vTask1(void *pvParameters) { for(;;) { /* 等待信号量 */ if(xSemaphoreTake(xBinarySemaphore, portMAX_DELAY) pdTRUE) { /* 收到信号量执行相应操作 */ printf(Task1: Event received!\n); } vTaskDelay(100 / portTICK_PERIOD_MS); } } /* 任务2触发事件 */ void vTask2(void *pvParameters) { for(;;) { /* 每隔1秒触发一次事件 */ vTaskDelay(1000 / portTICK_PERIOD_MS); /* 释放信号量 */ xSemaphoreGive(xBinarySemaphore); printf(Task2: Event triggered!\n); } } /* 主函数 */ int main(void) { /* 创建二进制信号量初始值为0 */ xBinarySemaphore xSemaphoreCreateBinary(); if(xBinarySemaphore ! NULL) { /* 创建任务 */ xTaskCreate(vTask1, Task1, configMINIMAL_STACK_SIZE, NULL, 1, NULL); xTaskCreate(vTask2, Task2, configMINIMAL_STACK_SIZE, NULL, 2, NULL); /* 启动调度器 */ vTaskStartScheduler(); } /* 如果调度器启动失败会执行到这里 */ for(;;); }4.2 计数信号量示例资源池管理/* 模拟有3个可用资源 */ #define MAX_RESOURCES 3 SemaphoreHandle_t xCountingSemaphore; /* 资源使用者任务 */ void vResourceUserTask(void *pvParameters) { char *pcTaskName (char *)pvParameters; for(;;) { /* 请求资源 */ printf(%s: Requesting resource...\n, pcTaskName); if(xSemaphoreTake(xCountingSemaphore, portMAX_DELAY) pdTRUE) { /* 获取到资源使用一段时间 */ printf(%s: Got resource, using...\n, pcTaskName); vTaskDelay(500 / portTICK_PERIOD_MS); /* 释放资源 */ xSemaphoreGive(xCountingSemaphore); printf(%s: Released resource\n, pcTaskName); } vTaskDelay(1000 / portTICK_PERIOD_MS); } } int main(void) { /* 创建计数信号量初始有3个资源可用 */ xCountingSemaphore xSemaphoreCreateCounting(MAX_RESOURCES, MAX_RESOURCES); if(xCountingSemaphore ! NULL) { /* 创建多个资源使用者任务 */ xTaskCreate(vResourceUserTask, User1, configMINIMAL_STACK_SIZE, User1, 1, NULL); xTaskCreate(vResourceUserTask, User2, configMINIMAL_STACK_SIZE, User2, 1, NULL); xTaskCreate(vResourceUserTask, User3, configMINIMAL_STACK_SIZE, User3, 1, NULL); xTaskCreate(vResourceUserTask, User4, configMINIMAL_STACK_SIZE, User4, 1, NULL); vTaskStartScheduler(); } for(;;); }4.3 互斥量示例保护共享资源#include stdio.h /* 共享资源 */ int iSharedVariable 0; SemaphoreHandle_t xMutex; /* 任务访问共享资源 */ void vAccessSharedResource(void *pvParameters) { char *pcTaskName (char *)pvParameters; int iLocalCopy; for(;;) { /* 获取互斥锁 */ if(xSemaphoreTake(xMutex, portMAX_DELAY) pdTRUE) { /* 临界区开始 */ iLocalCopy iSharedVariable; printf(%s: Read value %d\n, pcTaskName, iLocalCopy); vTaskDelay(50 / portTICK_PERIOD_MS); /* 模拟处理时间 */ iLocalCopy; iSharedVariable iLocalCopy; printf(%s: Updated value %d\n, pcTaskName, iSharedVariable); /* 临界区结束 */ /* 释放互斥锁 */ xSemaphoreGive(xMutex); } vTaskDelay(100 / portTICK_PERIOD_MS); } } int main(void) { /* 创建互斥量 */ xMutex xSemaphoreCreateMutex(); if(xMutex ! NULL) { /* 创建两个任务同时访问共享资源 */ xTaskCreate(vAccessSharedResource, TaskA, configMINIMAL_STACK_SIZE, TaskA, 2, NULL); xTaskCreate(vAccessSharedResource, TaskB, configMINIMAL_STACK_SIZE, TaskB, 1, NULL); vTaskStartScheduler(); } for(;;); }4.4 递归互斥量示例SemaphoreHandle_t xRecursiveMutex; void vRecursiveFunction(int depth) { char buffer[50]; /* 获取递归锁 */ if(xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) pdTRUE) { sprintf(buffer, Depth %d: Got lock, depth); printf(%s\n, buffer); if(depth 3) { /* 递归调用 */ vRecursiveFunction(depth 1); } /* 释放递归锁 */ xSemaphoreGiveRecursive(xRecursiveMutex); sprintf(buffer, Depth %d: Released lock, depth); printf(%s\n, buffer); } } void vRecursiveTask(void *pvParameters) { for(;;) { vRecursiveFunction(1); vTaskDelay(1000 / portTICK_PERIOD_MS); } } int main(void) { xRecursiveMutex xSemaphoreCreateRecursiveMutex(); if(xRecursiveMutex ! NULL) { xTaskCreate(vRecursiveTask, RecTask, configMINIMAL_STACK_SIZE, NULL, 1, NULL); vTaskStartScheduler(); } for(;;); }4.5 ISR中使用信号量/* 定义信号量句柄 */ SemaphoreHandle_t xSemaphoreFromISR; /* 中断服务程序 */ void vExampleInterruptHandler(void) { BaseType_t xHigherPriorityTaskWoken pdFALSE; /* 在ISR中释放信号量 */ xSemaphoreGiveFromISR(xSemaphoreFromISR, xHigherPriorityTaskWoken); /* 如果需要任务切换 */ portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } /* 任务处理中断事件 */ void vISRHandlerTask(void *pvParameters) { for(;;) { /* 等待来自ISR的信号量 */ if(xSemaphoreTake(xSemaphoreFromISR, portMAX_DELAY) pdTRUE) { /* 处理中断事件 */ printf(ISR event handled in task\n); } } } int main(void) { /* 创建二进制信号量 */ xSemaphoreFromISR xSemaphoreCreateBinary(); if(xSemaphoreFromISR ! NULL) { /* 配置中断 */ // configure_interrupt(); /* 创建处理任务 */ xTaskCreate(vISRHandlerTask, ISRHandler, configMINIMAL_STACK_SIZE, NULL, 3, NULL); vTaskStartScheduler(); } for(;;); }