Linux 4.14下VS1053播放MP3提示:设备无剩余空间写入错误
首先得明确一个关键误区:你遇到的No space left on device和磁盘空间/Inode完全无关——字符设备本身没有实际的存储介质,这个错误是驱动程序在write函数里主动返回的ENOSPC错误码,和磁盘状态没关系。结合你WAV播放正常、MP3报错的现象,问题大概率出在驱动对VS1053硬件解码逻辑的处理上,下面给你梳理排查方向和解决方案:
可能的核心原因
VS1053是硬件解码器,WAV是无压缩的PCM数据,驱动处理时可以直接把数据喂给解码缓冲区;但MP3是压缩格式,需要解码器先解析帧结构再解码,驱动如果没有适配MP3的流处理逻辑,就会出现缓冲区"假满"的误判。
具体排查步骤
1. 检查驱动write函数的实现逻辑
直接去看基于rvp-nl/vs10xx-linux修改的驱动代码,重点看write函数里什么时候返回-ENOSPC:
- 有没有忽略VS1053的
DREQ信号?VS1053的SCI_REG_STATUS寄存器里的DREQ位表示解码器是否准备好接收新数据,驱动必须等待DREQ为高时才能写入数据。如果驱动处理WAV时是硬编码了缓冲区大小,没做DREQ等待,MP3的压缩数据写入时因为解码耗时更长,缓冲区会更快被填满,驱动就直接返回空间不足。 - 有没有区分音频格式的处理逻辑?比如驱动默认只初始化了WAV解码模式,没有切换到MP3解码模式,导致解码器无法处理MP3数据,缓冲区数据无法被消耗,最终触发错误。
2. 验证VS1053的解码器初始化状态
VS1053需要通过SPI配置寄存器来切换解码模式,你可以在驱动初始化或第一次写入数据时,检查是否正确设置了MP3相关参数:
- 确认
SCI_MODE寄存器的设置是否开启了MP3解码支持(VS1053原生支持MP3,但需要正确配置模式位)。 - 可以尝试在写入MP3文件前,通过SPI手动发送MP3解码初始化命令,再测试写入。
3. 给驱动添加调试日志
在驱动的write函数里添加打印信息,输出每次写入的字节数、当前SCI_REG_STATUS寄存器的DREQ位状态,看报错时是不是真的缓冲区满了,还是驱动逻辑误判。比如:
dev_info(vs1053_dev, "Write count: %zu, DREQ status: %d\n", count, !!(vs1053_read_reg(SCI_REG_STATUS) & SCI_STATUS_DREQ));
针对性解决方案
1. 修复write函数的等待逻辑
修改驱动的write函数,实现循环写入+DREQ等待的逻辑,确保解码器准备好后再继续写入数据,示例代码如下:
ssize_t vs1053_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { ssize_t total_written = 0; unsigned char local_buf[32]; // VS1053单次最多接收32字节数据 size_t write_chunk; while (count > 0) { // 等待DREQ信号,确保解码器可以接收数据 while (!(vs1053_read_reg(SCI_REG_STATUS) & SCI_STATUS_DREQ)) { msleep(1); // 短延时等待,避免CPU空转 } write_chunk = min(count, sizeof(local_buf)); if (copy_from_user(local_buf, buf + total_written, write_chunk)) { return -EFAULT; } // 写入VS1053的数据缓冲区 vs1053_write_data(local_buf, write_chunk); total_written += write_chunk; count -= write_chunk; } return total_written; }
2. 确保MP3解码模式正确初始化
在驱动的probe函数或open函数中,添加MP3解码器的初始化代码:
// 设置SCI_MODE寄存器,开启MP3解码 vs1053_write_reg(SCI_REG_MODE, SM_SDINEW | SM_RESET); msleep(100); // 等待复位完成 vs1053_write_reg(SCI_REG_MODE, SM_SDINEW); // 可以根据需要设置解码音量等参数 vs1053_write_reg(SCI_REG_VOL, 0x2020);
3. 检查MP3文件的兼容性
少数情况下,某些特殊编码的MP3文件(比如非标准采样率、比特率)可能导致VS1053解码异常,缓冲区无法释放。可以换几个标准的MP3文件测试,排除文件本身的问题。
内容的提问来源于stack exchange,提问作者Gerald




