1. 问题现象与初步定位
最近在调试杰理AC692X系列芯片的U盘播放功能时,遇到了一个棘手的死机问题:当U盘中的第一首歌曲播放结束后,系统会触发死机断言(assertion)。这个问题在量产前的压力测试中被发现,表现为设备完全无响应,需要重新上电才能恢复。
从现象来看,死机发生在播放状态切换的时刻。通过串口日志可以观察到,在播放完第一首歌曲后,系统尝试切换到下一首时,触发了内存访问越界的断言错误。错误指向了fs_op.c文件中的某个文件操作函数,错误码为0x80030005。
提示:在嵌入式系统中,断言错误通常意味着程序执行到了开发者认为"不可能"到达的状态,这类错误往往与边界条件处理不当有关。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 杰理文件系统处理机制分析
杰理芯片采用自研的NORFS文件系统管理U盘内容,其工作流程大致如下:
- 插入U盘后,系统调用
usbh_init()初始化USB Host控制器 - 通过
fatfs_mount()挂载U盘文件系统 - 创建文件遍历句柄
dir_handle = opendir("/USB") - 读取目录内容并构建播放列表
- 播放时通过
f_open()打开文件,f_read()读取数据
问题可能出在以下几个环节:
- 文件句柄未正确关闭导致资源泄漏
- 播放列表索引越界
- 文件系统事件回调处理不当
- 内存管理异常(如DMA缓冲区溢出)
3. 死机断言的根因定位
通过JTAG调试器获取的调用栈显示,断言发生在media_player_task()任务中,具体是在调用f_lseek()时触发了异常。进一步分析发现:
3.1 文件句柄生命周期问题
在播放结束处理逻辑中,存在以下代码缺陷:
c复制void play_finish_callback() {
f_close(¤t_file); // 关闭当前文件
play_next(); // 立即播放下一首
}
而play_next()中直接使用了已经关闭的current_file结构体:
c复制void play_next() {
f_lseek(¤t_file, 0); // 对已关闭的文件操作
// .
