FreeRTOS队列异常:发送0-4整数,接收值却全为5的问题排查
问题原因分析
你的问题核心是队列中存储的是指向同一个局部变量的指针,而非实际数值,具体逻辑如下:
任务3中,
Value指针始终指向局部变量count,每次调用xQueueSend时,你传递的是&Value(即指针变量自身的地址),队列会将Value的值(也就是&count,即count的内存地址)复制到队列元素中。因此队列的5个元素存储的都是同一个地址:&count。当for循环结束后,
count的值会变为5(因为循环条件是count < 5,最后一次循环执行完count++后,count的值为5才会退出循环)。任务4读取队列时,每次拿到的都是
&count这个地址,解引用*RxValue得到的就是count当前的值5,因此所有读取结果都是5。
修正方案
方案一:发送实际数值(推荐,适合简单整数场景)
这种方式直接将整数的数值存入队列,不需要使用指针:
修改任务3代码
void task_3(void *args) { uint32_t count = 0; ESP_EARLY_LOGI(TAG, "Task 3 entered.."); if (myQueue_2 == NULL) { printf("myQueue_2 could not be created !\n"); } ESP_EARLY_LOGI("TASK 3", "Data waiting in myQueue_2_1 : %d, Space available : %d", uxQueueMessagesWaiting(myQueue_2), uxQueueSpacesAvailable(myQueue_2)); for (count = 0; count < 5;count++) { ESP_EARLY_LOGI("TASK 3", "Value = %d\n", count); // 直接发送count的地址,队列会复制count的数值到队列中 xQueueSend(myQueue_2, &count, (TickType_t)0); } ESP_EARLY_LOGI("TASK 3", "Data waiting in myQueue_2_1 : %d, Space available : %d", uxQueueMessagesWaiting(myQueue_2), uxQueueSpacesAvailable(myQueue_2)); while (1) { vTaskDelay(pdMS_TO_TICKS(500)); } }
修改任务4代码
void task_4(void *args) { // 用普通变量接收数值,不再用指针 uint32_t RxValue; while (1) { vTaskDelay(pdMS_TO_TICKS(500)); if (uxQueueMessagesWaiting(myQueue_2) > 0) { xQueueReceive(myQueue_2, &RxValue, (TickType_t)5); // 直接输出RxValue,不需要解引用 ESP_EARLY_LOGI("TASK 4", "Received from myQueue_2 = %d\n", RxValue); ESP_EARLY_LOGI("TASK 4", "Data waiting in myQueue_2 : %d, Space available : %d", uxQueueMessagesWaiting(myQueue_2), uxQueueSpacesAvailable(myQueue_2)); } } }
注意
确保队列myQueue_2创建时,元素大小设置为sizeof(uint32_t),例如:
myQueue_2 = xQueueCreate(5, sizeof(uint32_t));
方案二:发送独立内存的指针(适合复杂数据场景)
如果必须使用指针传递数据,需要为每个数值分配独立的动态内存,避免所有指针指向同一个变量:
修改任务3代码
void task_3(void *args) { uint32_t count = 0; ESP_EARLY_LOGI(TAG, "Task 3 entered.."); if (myQueue_2 == NULL) { printf("myQueue_2 could not be created !\n"); } ESP_EARLY_LOGI("TASK 3", "Data waiting in myQueue_2_1 : %d, Space available : %d", uxQueueMessagesWaiting(myQueue_2), uxQueueSpacesAvailable(myQueue_2)); for (count = 0; count < 5;count++) { // 为每个数值分配独立内存 uint32_t *pValue = (uint32_t*)pvPortMalloc(sizeof(uint32_t)); if (pValue != NULL) { *pValue = count; ESP_EARLY_LOGI("TASK 3", "Value = %d\n", *pValue); // 发送指针本身的值(即分配的内存地址) xQueueSend(myQueue_2, &pValue, (TickType_t)0); } } ESP_EARLY_LOGI("TASK 3", "Data waiting in myQueue_2_1 : %d, Space available : %d", uxQueueMessagesWaiting(myQueue_2), uxQueueSpacesAvailable(myQueue_2)); while (1) { vTaskDelay(pdMS_TO_TICKS(500)); } }
修改任务4代码
void task_4(void *args) { uint32_t *RxValue = NULL; while (1) { vTaskDelay(pdMS_TO_TICKS(500)); if (uxQueueMessagesWaiting(myQueue_2) > 0) { xQueueReceive(myQueue_2, &RxValue, (TickType_t)5); if (RxValue != NULL) { ESP_EARLY_LOGI("TASK 4", "Received from myQueue_2 = %d\n", *RxValue); // 使用完内存后释放,避免内存泄漏 vPortFree(RxValue); RxValue = NULL; } ESP_EARLY_LOGI("TASK 4", "Data waiting in myQueue_2 : %d, Space available : %d", uxQueueMessagesWaiting(myQueue_2), uxQueueSpacesAvailable(myQueue_2)); } } }
注意
队列创建时元素大小要设置为sizeof(uint32_t*):
myQueue_2 = xQueueCreate(5, sizeof(uint32_t*));
内容的提问来源于stack exchange,提问作者Softtoon
相关产品推荐
相关产品推荐

