关于wokwi运行程序出错,而实机运行正常的问题
## 先说结论# 由于wokwi的时间流速和现实不一致所以rtos的调度可能会有一点差异导致一些“逻辑有问题但是时序正好能运行”的代码时序改变然后挂掉了。可以通过backtraceaddr2line寻找出错代码然后检查逻辑解决### 事发经过今天给ESP32-S3编程用wokwi仿真时出现了报错但是实机运行正常报错如下assert failed: xQueueGenericSend queue.c:820 (pxQueue) Backtrace: 0x403777f6:0x3fcee660 0x4037b341:0x3fcee680 0x40380d31:0x3fcee6a0 0x4037bbaf:0x3fcee7d0 0x42002a99:0x3fcee810 0x42002ab3:0x3fcee830可以看到FreeRTOS的队列出了问题。但是这里只告诉我们队列不对劲而不是这里的代码错了。所以我们应该排查此时使用到队列的函数。下面的backtrace告诉我们事发时正在运行的函数们都有哪些。通过addr2line工具ESP32框架自带我们得到了这个 addr2line -pfiaC -e my_firmware.elf 0x403777f6:0x3fcee660 ......(懒得写其他地址) 0x403777f6: panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c:408 0x4037b341: esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c:137 0x40380d31: __assert_func at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/assert.c:85 0x4037bbaf: xQueueGenericSend at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:821 (discriminator 2) 0x42002a99: sendDisplayData(menu*) at C:\Users\admin\Desktop\VScode\ESP32\C\menu_v2/lib/menu_v2/3_core/1_task/task.cpp:35 0x42002ab3: menuLoop(void*) at C:\Users\admin\Desktop\VScode\ESP32\C\menu_v2/lib/menu_v2/3_core/1_task/task.cpp:46我们发现问题出在sendDisplayData中代码大概是这样// 初始化函数 void initDisplay(){ xTaskCreate( // 创建rtos任务执行menuLoop Loop, Loop, 8192, param, 1, menuLoopTaskHandle ); DisplayQueueHandle xQueueCreate( // 创建队列 2, sizeof(data) ); } // 发送显示到队列 的函数 bool sendDisplayData(void* data){ return xQueueSend(DisplayQueueHandle,Data,0); } // 循环函数,作为freertos任务运行 void Loop(void* dataToRun){ ... sendDisplayData(dataToRun); ... }可以看到逻辑大概是这样╭→ 初始化队列初始化 → 创建任务╰→ 执行循环menuLoop这时执行循环和初始化队列这两个函数并列执行。如果在队列初始化之前在循环中先发送了队列就会挂真机没挂是因为发送队列前任务运行的够快每次都能在任务开始前执行掉队列初始化wokwi挂了是因为wokwi执行代码慢一点同时由于它的时间片用的是本地时间来计数的所以每个时间片执行的代码更少才让初始化没来得及执行解决方案就是在任务创建前初始化队列像这样// 修改版 初始化函数 void initDisplay(){ DisplayQueueHandle xQueueCreate( // 提前创建队列防止没初始化就运行 2, sizeof(data) ); xTaskCreate( // 创建rtos任务执行menuLoop Loop, Loop, 8192, param, 1, menuLoopTaskHandle ); }
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2495008.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!