在FreeRTOS中使用LinkedList无法保存值的问题咨询
我在搭载Atmel 328P和2560的Arduino上运行FreeRTOS 10.0时,也碰到过几乎一模一样的问题——LinkedList(甚至换QList库)在标准Arduino的loop()里工作完全正常,但放到RTOS任务中后,虽然size()计数器能正常递增,可调用get()返回的结果全是0。
结合你提供的代码和输出来看,核心问题出在任务栈空间不足上,下面是具体的分析和解决步骤:
问题根源分析
你创建TaskTest任务时指定的栈大小是128,但在AVR架构的FreeRTOS中,栈大小的单位是字(Word),每个字占2字节,所以128字实际只有256字节的栈空间。而你在任务函数里创建的LinkedList<byte> list是栈上对象,再加上循环中频繁add()操作需要的临时变量、函数调用栈帧,这点空间完全不够,会直接导致栈溢出,覆盖链表节点存储的真实数据,最终出现get()返回0的异常。
而标准Arduino的loop()函数使用的是主栈,主栈大小通常远大于RTOS任务栈(比如AVR的主栈一般有几KB),所以不会触发这个问题。
解决步骤
1. 优先增大任务栈空间
修改xTaskCreate中的栈大小参数,至少调整到512(对应1024字节),如果是Arduino Mega 2560这类内存更大的板子,可以直接调到1024:
xTaskCreate( TaskTest , (const portCHAR *)"Test" , 512 , NULL , 2 , NULL );
2. 优化链表对象的存储位置
如果增大栈后还是有异常,可以把链表对象从任务栈移到全局空间,或者用动态分配放在堆上:
- 全局对象方式:
#include <Arduino_FreeRTOS.h> #include <LinkedList.h> LinkedList<byte> list; // 全局声明链表对象 void TaskTest( void *pvParameters ); void setup() { Serial.begin(115200); while (!Serial) { ; } xTaskCreate( TaskTest , (const portCHAR *)"Test" , 256 , NULL , 2 , NULL ); } void loop() { } void TaskTest( void *pvParameters __attribute__((unused)) ) { for (int i = 0; i < 256; i++) { list.add(i); Serial.print(i); Serial.print(','); Serial.print(list.get(list.size() - 1)); Serial.print(','); Serial.println(list.size()); } for (;;) { vTaskDelay(1); } }
- 堆分配方式:
void TaskTest( void *pvParameters __attribute__((unused)) ) { LinkedList<byte>* list = new LinkedList<byte>(); // 在堆上分配链表对象 for (int i = 0; i < 256; i++) { list->add(i); Serial.print(i); Serial.print(','); Serial.print(list->get(list->size() - 1)); Serial.print(','); Serial.println(list->size()); } for (;;) { vTaskDelay(1); } }
3. 确认FreeRTOS内存堆配置
如果链表内部使用了动态内存分配(比如malloc),要确保FreeRTOS的堆配置足够。可以在FreeRTOSConfig.h中调整configTOTAL_HEAP_SIZE的值,比如设置为2048(2KB):
#define configTOTAL_HEAP_SIZE ( ( size_t ) 2048 )
验证结果
按照上述方法修改后,任务应该能正确保存链表值,输出会和标准Arduino代码一致:
249,249,250
250,250,251
251,251,252
...
内容的提问来源于stack exchange,提问作者kfriede

