第22讲:RTOS简易任务原型快速验证逻辑可行性
CSDN专栏嵌入式程序开发实战嵌入式双范式AI编程嵌入式开发必掌握嵌入式求职面试技术资料第22讲RTOS简易任务原型快速验证逻辑可行性一、RTOS原型验证的意义RTOS环境下任务逻辑的正确性至关重要。在正式开发前快速验证任务逻辑的可行性可以避免后期大量返工。1.1 RTOS开发的难点难点一任务并发问题多任务并发执行执行顺序不确定问题难以复现难点二资源竞争问题多任务访问共享资源数据竞争死锁风险难点三优先级配置问题任务优先级设置优先级反转实时性保证1.2 原型验证的价值价值一快速验证逻辑通过原型验证任务逻辑是否正确任务间通信是否正常资源访问是否安全价值二发现潜在问题原型阶段发现死锁风险优先级问题资源竞争价值三降低开发风险避免后期大量返工难以定位的问题系统性设计错误二、RTOS原型快速搭建2.1 基础RTOS原型需求FreeRTOS两个任务 - 任务1LED闪烁 - 任务2串口输出Prompt生成STM32F103 FreeRTOS原型 - 使用FreeRTOS - 任务1LED闪烁PA5周期500ms - 任务2串口输出Task2 Running周期1秒 - 使用HAL库AI生成#includestm32f1xx_hal.h#includeFreeRTOS.h#includetask.hUART_HandleTypeDef huart1;voidSystemClock_Config(void);voidMX_GPIO_Init(void);voidMX_USART1_UART_Init(void);voidTask1_LED(void*argument);voidTask2_UART(void*argument);intmain(void){HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART1_UART_Init();xTaskCreate(Task1_LED,LED,128,NULL,1,NULL);xTaskCreate(Task2_UART,UART,128,NULL,1,NULL);vTaskStartScheduler();while(1);}voidTask1_LED(void*argument){while(1){HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);vTaskDelay(pdMS_TO_TICKS(500));}}voidTask2_UART(void*argument){while(1){char*msgTask2 Running\r\n;HAL_UART_Transmit(huart1,(uint8_t*)msg,strlen(msg),100);vTaskDelay(pdMS_TO_TICKS(1000));}}// 其他函数略2.2 任务间通信原型需求任务间通过队列通信 - 任务1生产数据 - 任务2消费数据Prompt生成FreeRTOS原型 - 任务1生产数据计数器发送到队列 - 任务2从队列接收数据串口输出 - 使用队列通信AI生成#includeFreeRTOS.h#includetask.h#includequeue.hQueueHandle_t xQueue;voidTask1_Producer(void*argument);voidTask2_Consumer(void*argument);intmain(void){// 初始化略xQueuexQueueCreate(10,sizeof(uint32_t));xTaskCreate(Task1_Producer,Producer,128,NULL,1,NULL);xTaskCreate(Task2_Consumer,Consumer,128,NULL,1,NULL);vTaskStartScheduler();while(1);}voidTask1_Producer(void*argument){uint32_tcounter0;while(1){counter;xQueueSend(xQueue,counter,portMAX_DELAY);vTaskDelay(pdMS_TO_TICKS(100));}}voidTask2_Consumer(void*argument){uint32_treceivedData;while(1){if(xQueueReceive(xQueue,receivedData,portMAX_DELAY)pdPASS){printf(Received: %d\r\n,receivedData);}}}2.3 互斥锁保护原型需求多任务访问共享资源使用互斥锁保护Prompt生成FreeRTOS原型 - 共享资源全局计数器 - 任务1增加计数器 - 任务2减少计数器 - 使用互斥锁保护AI生成#includeFreeRTOS.h#includetask.h#includesemphr.huint32_tg_counter0;SemaphoreHandle_t xMutex;voidTask1_Increment(void*argument);voidTask2_Decrement(void*argument);intmain(void){// 初始化略xMutexxSemaphoreCreateMutex();xTaskCreate(Task1_Increment,Inc,128,NULL,1,NULL);xTaskCreate(Task2_Decrement,Dec,128,NULL,1,NULL);vTaskStartScheduler();while(1);}voidTask1_Increment(void*argument){while(1){if(xSemaphoreTake(xMutex,portMAX_DELAY)pdTRUE){g_counter;printf(Increment: %d\r\n,g_counter);xSemaphoreGive(xMutex);}vTaskDelay(pdMS_TO_TICKS(100));}}voidTask2_Decrement(void*argument){while(1){if(xSemaphoreTake(xMutex,portMAX_DELAY)pdTRUE){g_counter--;printf(Decrement: %d\r\n,g_counter);xSemaphoreGive(xMutex);}vTaskDelay(pdMS_TO_TICKS(150));}}三、逻辑验证方法3.1 任务执行验证方法一串口日志voidTask1(void*argument){while(1){printf(Task1 executing at tick: %d\r\n,xTaskGetTickCount());// 任务逻辑vTaskDelay(pdMS_TO_TICKS(100));}}方法二LED指示voidTask1(void*argument){while(1){HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);// LED指示任务执行// 任务逻辑vTaskDelay(pdMS_TO_TICKS(100));}}方法三计数器统计uint32_ttask1_counter0;voidTask1(void*argument){while(1){task1_counter;// 统计任务执行次数// 任务逻辑vTaskDelay(pdMS_TO_TICKS(100));}}// 在另一个任务中打印统计voidMonitor_Task(void*argument){while(1){printf(Task1 executed %d times\r\n,task1_counter);vTaskDelay(pdMS_TO_TICKS(1000));}}3.2 任务间通信验证验证队列通信voidTask1_Producer(void*argument){uint32_tdata0;while(1){data;if(xQueueSend(xQueue,data,0)pdPASS){printf(Sent: %d\r\n,data);}else{printf(Queue full\r\n);}vTaskDelay(pdMS_TO_TICKS(100));}}voidTask2_Consumer(void*argument){uint32_tdata;while(1){if(xQueueReceive(xQueue,data,portMAX_DELAY)pdPASS){printf(Received: %d\r\n,data);}}}验证互斥锁voidTask1(void*argument){while(1){printf(Task1 trying to take mutex\r\n);if(xSemaphoreTake(xMutex,pdMS_TO_TICKS(1000))pdTRUE){printf(Task1 got mutex\r\n);// 访问共享资源xSemaphoreGive(xMutex);printf(Task1 gave mutex\r\n);}else{printf(Task1 failed to get mutex\r\n);}vTaskDelay(pdMS_TO_TICKS(100));}}3.3 优先级验证验证优先级抢占voidTask_High(void*argument){while(1){printf(High priority task running\r\n);vTaskDelay(pdMS_TO_TICKS(100));}}voidTask_Low(void*argument){while(1){printf(Low priority task start\r\n);HAL_Delay(200);// 模拟长时间运行printf(Low priority task end\r\n);vTaskDelay(pdMS_TO_TICKS(100));}}// 创建任务xTaskCreate(Task_High,High,128,NULL,2,NULL);// 高优先级xTaskCreate(Task_Low,Low,128,NULL,1,NULL);// 低优先级观察日志期望输出 Low priority task start High priority task running // 高优先级任务抢占 Low priority task end四、典型问题验证4.1 死锁验证场景SemaphoreHandle_t mutexA,mutexB;voidTask1(void*argument){while(1){xSemaphoreTake(mutexA,portMAX_DELAY);printf(Task1 got A\r\n);vTaskDelay(pdMS_TO_TICKS(100));xSemaphoreTake(mutexB,portMAX_DELAY);printf(Task1 got B\r\n);xSemaphoreGive(mutexB);xSemaphoreGive(mutexA);vTaskDelay(pdMS_TO_TICKS(100));}}voidTask2(void*argument){while(1){xSemaphoreTake(mutexB,portMAX_DELAY);printf(Task2 got B\r\n);vTaskDelay(pdMS_TO_TICKS(100));xSemaphoreTake(mutexA,portMAX_DELAY);printf(Task2 got A\r\n);xSemaphoreGive(mutexA);xSemaphoreGive(mutexB);vTaskDelay(pdMS_TO_TICKS(100));}}验证方法观察日志 Task1 got A Task2 got B 卡死死锁发生 修复 统一加锁顺序先A后B4.2 优先级反转验证场景SemaphoreHandle_t mutex;voidTask_High(void*argument){while(1){vTaskDelay(pdMS_TO_TICKS(10));printf(High trying to get mutex\r\n);xSemaphoreTake(mutex,portMAX_DELAY);printf(High got mutex\r\n);xSemaphoreGive(mutex);vTaskDelay(pdMS_TO_TICKS(100));}}voidTask_Medium(void*argument){while(1){printf(Medium running\r\n);vTaskDelay(pdMS_TO_TICKS(1));}}voidTask_Low(void*argument){while(1){printf(Low trying to get mutex\r\n);xSemaphoreTake(mutex,portMAX_DELAY);printf(Low got mutex\r\n);vTaskDelay(pdMS_TO_TICKS(100));// 长时间持有xSemaphoreGive(mutex);vTaskDelay(pdMS_TO_TICKS(100));}}// 创建任务xTaskCreate(Task_High,High,128,NULL,3,NULL);xTaskCreate(Task_Medium,Medium,128,NULL,2,NULL);xTaskCreate(Task_Low,Low,128,NULL,1,NULL);验证方法观察日志 Low got mutex Medium running // 中优先级任务抢占低优先级任务 High trying to get mutex // 高优先级任务等待 高优先级任务被阻塞 修复 使用互斥锁带优先级继承4.3 队列溢出验证场景QueueHandle_t xQueue;voidTask_Producer(void*argument){uint32_tdata0;while(1){data;if(xQueueSend(xQueue,data,0)!pdPASS){printf(Queue overflow\r\n);}vTaskDelay(pdMS_TO_TICKS(10));// 生产速度快}}voidTask_Consumer(void*argument){uint32_tdata;while(1){xQueueReceive(xQueue,data,portMAX_DELAY);printf(Received: %d\r\n,data);vTaskDelay(pdMS_TO_TICKS(100));// 消费速度慢}}验证方法观察日志 Received: 1 Received: 2 Queue overflow // 队列溢出 Queue overflow 修复 增大队列长度或提高消费速度五、本讲核心要点5.1 记住这三句话RTOS原型验证价值快速验证逻辑、发现潜在问题、降低开发风险验证方法串口日志、LED指示、计数器统计典型问题死锁、优先级反转、队列溢出原型阶段发现并修复5.2 实践建议对于新手学习RTOS基础概念实践原型验证理解典型问题对于有经验工程师建立RTOS原型模板建立问题验证用例提高验证效率5.3 下讲预告第23讲将深入讲解传感器驱动快速试错温湿度、红外、超声波如何快速试错验证传感器驱动下一讲将以具体传感器为例详细讲解快速试错方法。
