跳到主要内容

ESP32应用笔记

阅读量: 101
阅读人次: 102

开发 ESP32 需要持续关注官方帮助手册

esp32s3 在中断不能执行耗时操作,例如写flash。那么 esp32s3 是如何实现当程序crash时,将coredump写入flash的呢?

在终端使用 idf 工具:

$env:IDF_TOOLS_PATH = "D:\Espressif\.espressif"
D:\Espressif\esp\v5.4.2\esp-idf\export.ps1


export IDF_TOOLS_PATH="/opt/Espressif/.espressif"
source "/opt/Espressif/esp/v5.4.2/esp-idf/export.sh"

idf.py monitor -p /dev/ttyUSB0 --timestamps --timestamp-format "%H:%M:%S"

生成反汇编代码:

xtensa-esp32s3-elf-objdump -S build/geminai.elf > build/disassembly.lst

将 ESP32-S3 的内存地址转换为对应的源代码位置,用于软件触发Panic时打印的函数调用栈信息,在使用 IDF 提供的串口 Monitor 工具时,会自动帮我做如下命令解析:

xtensa-esp32s3-elf-addr2line -pfiaC -e build\geminai.elf \
0x4005625d:0x3fcb5d90 0x40385b49:0x3fcb5dc0

避免过多创建任务

SRAM比较有限,在官方手册也提到了 PSRAM 最好不要作为任务栈的限制。其实很多任务都形如:

void task_handler(void *args) {
while(1) {
wait_something();
do_something();
sleep();
}
}

这时可以考虑使用 ESP 定时器事件循环库 进行减少任务创建数量以及程序框架优化。

FreeRTOS 队列元素不能过大。

FreeRTOS 的 pvPortMalloc() 函数申请内存来自 SRAM,所以 xQueueCreate() 等申请的内存都来自 SRAM。例如如下创建 log_queue 队列就消耗了 10KB 的SRAM:

typedef struct {
char message[1024];
} log_entry_t;

QueueHandle_t log_queue = xQueueCreate(10, sizeof(log_entry_t)); // 这里消耗了10k的SRAM

可以使用 xQueueCreateStatic() 自行设置 PSRAM 为队列的存储空间,减少SRAM开销。或者队列保存的元素大小应该尽可能的小。

stdlib 的内存申请函数 malloc() 都是调用 heap_caps_malloc_default() ,存在一个 malloc_alwaysinternal_limit 变量控制是从sram 还是 psram 分配。

可以在 Kconfig 中做如下配置以使堆内存都从 PSRAM 中申请:

CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0

FreeRTOS 事件组

在许多情况下,可以使用 任务通知 xTaskNotifyWait()/xTaskNotify() 作为事件组的轻量级替代方案。

Linux开发环境

安装:

sudo apt install python3-pip python3-venv libusb-1.0-0

WSL2开发环境

直接在 Windows 下编译项目非常慢,打开任务管理器可以看到 CPU 压根没跑满。这个时候我们可以使用 WSL2 结合 usbipd-win 进行开发。

通过如下命令,我们获取到串口 USB-SERIAL CH340K (COM4) 的 BUSID。

usbipd list

输出:

Connected:
BUSID VID:PID DEVICE STATE
5-3 303a:1001 USB 串行设备 (COM3), USB JTAG/serial debug unit Not shared
5-4 1a86:7522 USB-SERIAL CH340K (COM4) Not shared

Persisted:
GUID DEVICE

通过如下命令绑定USB(需要管理员权限):

usbipd bind --busid=<BUSID>

#例如
usbipd bind --busid=5-4

然后通过 usbipd 将 USB 设备转发至 WSL:

usbipd attach --wsl --busid=<BUSID>

例如:

PS C:\Users\amass> usbipd attach --wsl --busid=5-4
usbipd: info: Using WSL distribution 'Ubuntu' to attach; the device will be available in all WSL 2 distributions.
usbipd: info: Detected networking mode 'nat'.
usbipd: info: Using IP address 172.17.96.1 to reach the host.

这个时候就能在 WSL 看到设备节点了,通常为 /dev/ttyUSB*

去除转发:

usbipd detach --busid=5-2

将用户加入 dialout 组:

sudo usermod -a -G dialout $USER