/* * FreeRTOS队列验证示例 * * 本示例演示了如何使用CodeDetect系统验证FreeRTOS队列操作的安全性。 * 包括队列创建、发送、接收、溢出处理和并发访问验证。 */ #include "FreeRTOS.h" #include "queue.h" #include "task.h" /* 队列配置参数 */ #define QUEUE_LENGTH 10 #define ITEM_SIZE sizeof(uint32_t) #define MAX_QUEUE_ITEMS 100 /* 任务优先级定义 */ #define PRODUCER_PRIORITY (tskIDLE_PRIORITY + 1) #define CONSUMER_PRIORITY (tskIDLE_PRIORITY + 2) #define MONITOR_PRIORITY (tskIDLE_PRIORITY + 3) /* 队列消息类型 */ typedef struct { uint32_t message_id; uint32_t data_value; TickType_t timestamp; BaseType_t is_critical; } QueueMessage_t; /* 队列统计信息 */ typedef struct { uint32_t total_sent; uint32_t total_received; uint32_t queue_full_errors; uint32_t queue_empty_errors; uint32_t checksum_errors; } QueueStats_t; /* 全局变量 */ QueueHandle_t xMessageQueue = NULL; QueueHandle_t xStatsQueue = NULL; QueueStats_t xQueueStats = {0}; TaskHandle_t xProducerTaskHandle = NULL; TaskHandle_t xConsumerTaskHandle = NULL; TaskHandle_t xMonitorTaskHandle = NULL; /** * @brief 生产者任务 - 向队列发送消息 * * 该任务演示了: * 1. 队列发送操作的错误处理 * 2. 队列满状态的处理 * 3. 消息序列号生成 * 4. 关键消息的优先处理 * * @param pvParameters 任务参数 */ void vProducerTask(void *pvParameters) { QueueMessage_t xMessage; BaseType_t xSendResult; uint32_t ulMessageCounter = 0; /* 参数验证 */ configASSERT(pvParameters != NULL); configASSERT(xMessageQueue != NULL); for (;;) { /* 构建消息 */ xMessage.message_id = ulMessageCounter++; xMessage.data_value = ulMessageCounter * 2; /* 简单的数据计算 */ xMessage.timestamp = xTaskGetTickCount(); xMessage.is_critical = (ulMessageCounter % 10 == 0); /* 每10个消息一个关键消息 */ /* 尝试发送消息 */ if (xMessage.is_critical) { /* 关键消息使用更长等待时间 */ xSendResult = xQueueSend(xMessageQueue, &xMessage, pdMS_TO_TICKS(100)); } else { /* 普通消息使用较短等待时间 */ xSendResult = xQueueSend(xMessageQueue, &xMessage, pdMS_TO_TICKS(10)); } /* 更新统计信息 */ taskENTER_CRITICAL(); xQueueStats.total_sent++; if (xSendResult != pdPASS) { xQueueStats.queue_full_errors++; } taskEXIT_CRITICAL(); /* 如果发送失败,记录错误但继续运行 */ if (xSendResult != pdPASS) { /* 队列满,等待一段时间再试 */ vTaskDelay(pdMS_TO_TICKS(50)); } /* 控制消息生成速率 */ vTaskDelay(pdMS_TO_TICKS(100)); /* 防止消息计数器溢出 */ if (ulMessageCounter >= MAX_QUEUE_ITEMS) { ulMessageCounter = 0; } } } /** * @brief 消费者任务 - 从队列接收消息 * * 该任务演示了: * 1. 队列接收操作的阻塞和非阻塞模式 * 2. 队列空状态的处理 * 3. 消息验证和处理 * 4. 统计信息更新 * * @param pvParameters 任务参数 */ void vConsumerTask(void *pvParameters) { QueueMessage_t xReceivedMessage; BaseType_t xReceiveResult; uint32_t ulExpectedId = 0; /* 参数验证 */ configASSERT(pvParameters != NULL); configASSERT(xMessageQueue != NULL); for (;;) { /* 尝试从队列接收消息 */ xReceiveResult = xQueueReceive(xMessageQueue, &xReceivedMessage, pdMS_TO_TICKS(200)); if (xReceiveResult == pdPASS) { /* 成功接收消息,进行验证 */ taskENTER_CRITICAL(); xQueueStats.total_received++; /* 验证消息序列号 */ if (xReceivedMessage.message_id != ulExpectedId) { xQueueStats.checksum_errors++; /* 重新同步序列号 */ ulExpectedId = xReceivedMessage.message_id + 1; } else { ulExpectedId++; } taskEXIT_CRITICAL(); /* 处理消息(这里只是简单验证) */ if (xReceivedMessage.data_value % 2 == 0) { /* 偶数值处理 */ } else { /* 奇数值处理 */ } /* 如果是关键消息,记录到统计队列 */ if (xReceivedMessage.is_critical && xStatsQueue != NULL) { xQueueSend(xStatsQueue, &xReceivedMessage, 0); } } else { /* 接收超时,记录空队列错误 */ taskENTER_CRITICAL(); xQueueStats.queue_empty_errors++; taskEXIT_CRITICAL(); } /* 控制处理速率 */ vTaskDelay(pdMS_TO_TICKS(50)); } } /** * @brief 监控任务 - 监控队列状态和统计信息 * * @param pvParameters 任务参数 */ void vMonitorTask(void *pvParameters) { QueueStats_t local_stats; UBaseType_t uxItemsWaiting; QueueMessage_t critical_message; /* 参数验证 */ configASSERT(pvParameters != NULL); configASSERT(xMessageQueue != NULL); for (;;) { /* 获取队列状态 */ uxItemsWaiting = uxQueueMessagesWaiting(xMessageQueue); /* 复制统计信息 */ taskENTER_CRITICAL(); local_stats = xQueueStats; taskEXIT_CRITICAL(); /* 检查队列健康状态 */ if (uxItemsWaiting > QUEUE_LENGTH * 0.8) { /* 队列接近满,需要关注 */ } if (local_stats.queue_full_errors > 0 || local_stats.queue_empty_errors > 0) { /* 有错误发生,可能需要调整 */ } /* 处理关键消息统计 */ if (xStatsQueue != NULL) { while (xQueueReceive(xStatsQueue, &critical_message, 0) == pdPASS) { /* 处理关键消息统计 */ } } /* 定期报告 */ vTaskDelay(pdMS_TO_TICKS(1000)); } } /** * @brief 创建队列验证系统 * * @return BaseType_t 创建结果 */ BaseType_t xCreateQueueVerificationSystem(void) { BaseType_t xReturn = pdPASS; /* 创建主消息队列 */ xMessageQueue = xQueueCreate(QUEUE_LENGTH, ITEM_SIZE); if (xMessageQueue == NULL) { return pdFAIL; } /* 创建统计信息队列 */ xStatsQueue = xQueueCreate(QUEUE_LENGTH / 2, sizeof(QueueMessage_t)); if (xStatsQueue == NULL) { vQueueDelete(xMessageQueue); xMessageQueue = NULL; return pdFAIL; } /* 初始化统计信息 */ memset(&xQueueStats, 0, sizeof(QueueStats_t)); /* 创建生产者任务 */ xReturn = xTaskCreate( vProducerTask, "Producer", configMINIMAL_STACK_SIZE, NULL, PRODUCER_PRIORITY, &xProducerTaskHandle ); if (xReturn != pdPASS) { goto cleanup; } /* 创建消费者任务 */ xReturn = xTaskCreate( vConsumerTask, "Consumer", configMINIMAL_STACK_SIZE, NULL, CONSUMER_PRIORITY, &xConsumerTaskHandle ); if (xReturn != pdPASS) { goto cleanup; } /* 创建监控任务 */ xReturn = xTaskCreate( vMonitorTask, "Monitor", configMINIMAL_STACK_SIZE, NULL, MONITOR_PRIORITY, &xMonitorTaskHandle ); if (xReturn != pdPASS) { goto cleanup; } return pdPASS; cleanup: /* 清理已创建的资源 */ if (xProducerTaskHandle != NULL) { vTaskDelete(xProducerTaskHandle); xProducerTaskHandle = NULL; } if (xConsumerTaskHandle != NULL) { vTaskDelete(xConsumerTaskHandle); xConsumerTaskHandle = NULL; } if (xMonitorTaskHandle != NULL) { vTaskDelete(xMonitorTaskHandle); xMonitorTaskHandle = NULL; } vQueueDelete(xStatsQueue); xStatsQueue = NULL; vQueueDelete(xMessageQueue); xMessageQueue = NULL; return pdFAIL; } /** * @brief 停止队列验证系统 */ void vStopQueueVerificationSystem(void) { /* 删除所有任务 */ if (xProducerTaskHandle != NULL) { vTaskDelete(xProducerTaskHandle); xProducerTaskHandle = NULL; } if (xConsumerTaskHandle != NULL) { vTaskDelete(xConsumerTaskHandle); xConsumerTaskHandle = NULL; } if (xMonitorTaskHandle != NULL) { vTaskDelete(xMonitorTaskHandle); xMonitorTaskHandle = NULL; } /* 删除队列 */ if (xStatsQueue != NULL) { vQueueDelete(xStatsQueue); xStatsQueue = NULL; } if (xMessageQueue != NULL) { vQueueDelete(xMessageQueue); xMessageQueue = NULL; } } /** * @brief 获取队列统计信息 * * @param pxStats 输出统计信息 * @return BaseType_t 操作结果 */ BaseType_t xGetQueueStats(QueueStats_t *pxStats) { if (pxStats == NULL) { return pdFAIL; } taskENTER_CRITICAL(); *pxStats = xQueueStats; taskEXIT_CRITICAL(); return pdPASS; } /** * @brief 主函数 - 演示队列验证系统 */ int main(void) { BaseType_t xResult; QueueStats_t xStats; /* 创建队列验证系统 */ xResult = xCreateQueueVerificationSystem(); if (xResult != pdPASS) { /* 系统创建失败 */ return -1; } /* 让系统运行一段时间 */ vTaskDelay(pdMS_TO_TICKS(5000)); /* 获取统计信息 */ xResult = xGetQueueStats(&xStats); if (xResult == pdPASS) { /* 可以在这里处理统计信息 */ (void)xStats; /* 避免未使用变量警告 */ } /* 停止系统 */ vStopQueueVerificationSystem(); return 0; } /* * CodeDetect验证要点: * * 1. 队列安全验证: * - 队列创建和删除的正确性 * - 队列满和空状态的处理 * - 队列大小和消息大小的验证 * * 2. 并发访问验证: * - 多任务并发访问队列的安全性 * - 关键区域的保护 * - 统计信息的一致性 * * 3. 内存安全验证: * - 消息结构的边界检查 * - 队列缓冲区溢出检测 * - NULL指针验证 * * 4. 错误处理验证: * - 队列操作失败的处理 * - 资源不足的情况处理 * - 任务同步和通信 * * 5. CBMC规范生成: * - 队列操作的前置条件 * - 消息完整性约束 * - 并发访问的安全性保证 * - 错误恢复路径 */