FAT12开发任务中HAL层读扇区函数返回0字节 求无extern变量解决方案
FAT12读扇区故障排查与解决方案
故障核心原因排查
按优先级依次检查以下问题:
- 缓冲区指针非法:main函数中定义的
uint8_t *buff = NULL直接传入读扇区接口,fread尝试向NULL地址写入数据触发非法访问,多数平台下fread遇到目标地址无效时会直接返回0,这是最高概率的触发原因。 - 镜像文件未正常打开:当前
kmc_open_img_file仅打印打开失败提示,未向上层返回错误状态,若floppy.img不存在、路径不匹配、权限不足,s_pimage仍为NULL,后续fseek/fread操作非法指针也会返回0。 - 偏移寻址失败:当前未校验
fseek返回值,若传入的扇区index超出镜像文件总扇区范围,fseek执行失败后fread无法读取到有效数据,也会返回0。
修复实现(符合不使用extern变量要求)
所有文件操作状态都封装在HAL.c内部的静态变量中,对外仅暴露函数接口,无需使用extern变量。
HAL.c修改后代码
#define SIZE_OF_SECTOR 512 static FILE* s_pimage = NULL; // 新增返回值,向上层传递文件打开结果 int32_t kmc_open_img_file() { s_pimage = fopen("floppy.img", "rb"); if(NULL == s_pimage) { printf("Can not open file!"); return -1; } return 0; } int32_t kmc_read_sector(uint32_t index, uint8_t *buff) { // 前置参数合法性校验 if (s_pimage == NULL || buff == NULL) { printf("Invalid parameter or image file not open\n"); return -1; } uint32_t offset = SIZE_OF_SECTOR * index; // 校验寻址结果 if (fseek(s_pimage, offset, SEEK_SET) != 0) { printf("Seek to sector %u failed\n", index); return -1; } int32_t num_of_bytes = (int32_t)fread(buff, 1, SIZE_OF_SECTOR, s_pimage); if (num_of_bytes != SIZE_OF_SECTOR) { printf("Read sector failed: got %d bytes, expect %d\n", num_of_bytes, SIZE_OF_SECTOR); } return num_of_bytes; } // 补全关闭接口的空指针校验 void kmc_close_img_file() { if (s_pimage != NULL) { fclose(s_pimage); s_pimage = NULL; } }
main函数修改后代码
int main() { // 先判断文件打开结果,失败直接退出 if (kmc_open_img_file() != 0) { return -1; } // 栈上分配512字节扇区缓冲区,无需手动释放 uint8_t buff[SIZE_OF_SECTOR] = {0}; // 若需要堆分配可替换为:uint8_t *buff = malloc(SIZE_OF_SECTOR); 用完记得free int32_t read_cnt = kmc_read_sector(0, buff); printf("Read %d bytes from sector 0\n", read_cnt); kmc_close_img_file(); // 堆分配场景加:free(buff); return 0; }
内容的提问来源于stack exchange,提问作者Nguyễn Phùng Thái Cường
相关产品推荐
相关产品推荐

