网站开发一般用哪种语言2015网站设计趋势
2026/4/6 4:15:46 网站建设 项目流程
网站开发一般用哪种语言,2015网站设计趋势,盐城最专业网站建设网站排名优化,手机app下载安装免费下载对于上一张讲过的优先级反转的的问题的时候我们引入了互斥量#xff08;也叫互斥锁#xff09;的概念#xff0c;其实互斥量就是特俗的信号量。那互斥量怎么去使用呢#xff1f;很简单#xff0c;和信号量一样创建用 xSemaphoreCreateMutex()#xff0c;获取用 xSemaphor…对于上一张讲过的优先级反转的的问题的时候我们引入了互斥量也叫互斥锁的概念其实互斥量就是特俗的信号量。那互斥量怎么去使用呢很简单和信号量一样创建用xSemaphoreCreateMutex()获取用xSemaphoreTake()释放用xSemaphoreGive()保持保护区域尽量短FreeRTOS会自动处理优先级反转。互斥量是一种特殊的二进制信号量但是特殊的点是二进制信号量和计数信号量获取者和释放者可以不是同一个任务但是互斥信号量获取者和释放者必须是同一个人。函数创建互斥量的函数有2种动态分配内存静态分配内存函数原型如下/* 创建一个互斥量返回它的句柄。 * 此函数内部会分配互斥量结构体 * 返回值: 返回句柄非NULL表示成功 */ SemaphoreHandle_t xSemaphoreCreateMutex( void ); /* 创建一个互斥量返回它的句柄。 * 此函数无需动态分配内存所以需要先有一个StaticSemaphore_t结构体并传入它的指针 * 返回值: 返回句柄非NULL表示成功 */ SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer );要想使用互斥量需要在配置文件FreeRTOSConfig.h中定义#define configUSE_MUTEXES 1要注意的是互斥量不能在ISR中使用。各类操作函数比如删除、give/take跟一般是信号量是一样的。/* * xSemaphore: 信号量句柄你要删除哪个信号量, 互斥量也是一种信号量 */ void vSemaphoreDelete( SemaphoreHandle_t xSemaphore ); /* 释放 */ BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore ); /* 获得 */ BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );但是在使用时也会遇到别的问题比如在嵌套或者递归函数中遇到了信号量冲突比如任务A拿也互斥量M但是任务A内部的嵌套函数需要信号量M但是拿不到这样就会阻塞卡死这是就需要用到递归锁递归锁允许同一任务多次获取同一锁通过内部计数机制避免自我死锁必须使用TakeRecursive/GiveRecursive配套函数获取N次就必须释放N次其他使用方式就和互斥锁一样最重要的就是获取N次就必须释放N次获取N次就必须释放N次获取N次就必须释放N次递归锁一般互斥量创建xSemaphoreCreateRecursiveMutexxSemaphoreCreateMutex获得xSemaphoreTakeRecursivexSemaphoreTake释放xSemaphoreGiveRecursivexSemaphoreGive/* 创建一个递归锁返回它的句柄。* * 此函数内部会分配互斥量结构体* * 返回值: 返回句柄非NULL表示成功* */ SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void ); */ 释放 */ BaseType_t xSemaphoreGiveRecursive( SemaphoreHandle_t xSemaphore ); */ 获得 */ BaseType_t xSemaphoreTakeRecursive( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );我们每次建立一个任务只能触发一个任务函数那有没有什么方法可以一个任务触发多个函数话或者信号量呢。有的兄弟有的这个就是事件组使用事件组必须要引用的头文件#include event_groups.h主要特点每个事件由事件位bit表示最多32个事件32位支持或任意事件发生和与所有事件发生两种等待模式事件标志被设置后不会自动清除需要手动清除线程安全可在任务和中断中使用事件组的使用主要分为4个主要的部分就是创建设置等待和是释放首先是创建事件组// 创建事件组 EventGroupHandle_t xEventGroupCreate(void); // 示例 EventGroupHandle_t xEventGroup xEventGroupCreate(); if (xEventGroup NULL) { // 创建失败处理 }其次设置事件组c // 在任务中设置事件位 EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet); // 在中断中设置事件位带中断安全版本 BaseType_t xEventGroupSetBitsFromISR(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken);然后是等待事件组EventBits_t xEventGroupWaitBits( const EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, // pdTRUE: 等待成功后清除事件位 const BaseType_t xWaitForAllBits, // pdTRUE: 等待所有位; pdFALSE: 等待任意位 TickType_t xTicksToWait);最后是释放事件组也叫清除事件组// 清除指定事件位 EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear); // 在中断中清除事件位 BaseType_t xEventGroupClearBitsFromISR(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear); // 获取当前事件位值不修改 EventBits_t xEventGroupGetBits(EventGroupHandle_t xEventGroup); EventBits_t xEventGroupGetBitsFromISR(EventGroupHandle_t xEventGroup);就这四部使用起来也比较简单给大家一个一般的使用格式// 定义事件位建议使用1左移方式 #define BIT_0 (1 0) #define BIT_1 (1 1) #define BIT_2 (1 2) // 创建事件组 EventGroupHandle_t xEventGroup; void vTask1(void *pvParameters) { EventBits_t uxBits; for (;;) { // 等待BIT_0或BIT_1任意一个事件发生 uxBits xEventGroupWaitBits( xEventGroup, // 事件组句柄 BIT_0 | BIT_1, // 等待的事件位 pdTRUE, // 成功等待后清除这些位 pdFALSE, // 任意一个事件即可 portMAX_DELAY); // 无限等待 if ((uxBits BIT_0) ! 0) { // BIT_0被设置 } if ((uxBits BIT_1) ! 0) { // BIT_1被设置 } } } void vTask2(void *pvParameters) { for (;;) { // 执行某些操作后设置事件 xEventGroupSetBits(xEventGroup, BIT_0); vTaskDelay(pdMS_TO_TICKS(1000)); } }第一步宏定义的操作可有可无但是这样会大大提高代码的可读性对于这个串代码进行变种就能变成任务的与操作// 必需的头文件 #include FreeRTOS.h #include task.h #include event_groups.h // 可选用于调试输出 #include stdio.h // 定义事件位 #define BIT_0 (1 0) #define BIT_1 (1 1) #define BIT_2 (1 2) // 事件组句柄 EventGroupHandle_t xEventGroup; void vSenderTask(void *pvParameters) { for (;;) { // 设置事件位 xEventGroupSetBits(xEventGroup, BIT_0); // 任务延迟 vTaskDelay(pdMS_TO_TICKS(1000)); } } void vReceiverTask(void *pvParameters) { EventBits_t uxBits; for (;;) { // 等待事件位 uxBits xEventGroupWaitBits( xEventGroup, BIT_0 | BIT_1, pdTRUE, // 清除事件位 pdFALSE, // 等待任意位 portMAX_DELAY // 无限等待 ); if (uxBits BIT_0) { printf(BIT_0 received\n); } } } int main(void) { // 创建事件组 xEventGroup xEventGroupCreate(); // 创建任务 xTaskCreate(vSenderTask, Sender, configMINIMAL_STACK_SIZE, NULL, 1, NULL); xTaskCreate(vReceiverTask, Receiver, configMINIMAL_STACK_SIZE, NULL, 1, NULL); // 启动调度器 vTaskStartScheduler(); return 0; }然后也可以改成在中断中使用的样子// 必需的头文件 #include FreeRTOS.h #include task.h #include event_groups.h // 可选硬件相关头文件 #include stm32f4xx.h // 示例STM32 MCU EventGroupHandle_t xEventGroup; // 中断服务程序 void TIM2_IRQHandler(void) { BaseType_t xHigherPriorityTaskWoken pdFALSE; if (TIM_GetITStatus(TIM2, TIM_IT_Update) ! RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 在中断中设置事件位 xEventGroupSetBitsFromISR( xEventGroup, BIT_0, xHigherPriorityTaskWoken ); // 如果需要执行上下文切换 portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } }我在配置的过程中遇到了一些错误在这分享给大家七、常见错误排查错误1未找到头文件错误信息fatal error: event_groups.h: No such file or directory 解决方案确保include路径正确 在MX或IDE中正确设置include路径 例如-I../FreeRTOS/Source/include错误2未启用事件组功能//确保在FreeRTOSConfig.h中启用 #define configUSE_EVENT_GROUPS 1 // 必须为1错误3链接错误错误undefined reference to xEventGroupCreate解决方案确保链接了FreeRTOS库文件在Makefile中添加freertos.c 或相应的库文件

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询