一、现象
调用函数 f_open() 后,程序崩溃,调试后发现,单片机产生硬件中断,即软件跳入如下部分:
1 2 3 4 5 6 7 8
| void HardFault_Handler(void) { while (1) { BSP_LED_Toggle(LED3); } }
|
二、错误代码
代码错误处如下,就是简单的使用 f_read() 函数打开一个文件,并将这个文件的前 32 个字节打印出来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| void show_file(uint8_t idx) { FIL fil; uint8_t data[32]; uint8_t bytecounts; uint8_t ret;
printf("show file\n");
if((ret = f_open(&fil,(const TCHAR *)File_path,FA_READ)) != FR_OK) { printf("ret : %d\n",ret); SD_Error_Handler(); } else { if(f_read(&fil, data, sizeof(data), (UINT *)&bytecounts) != FR_OK) { SD_Error_Handler(); } else { for(int i=0;i<32;i++) { printf(" %02x ",data[i]); } f_close(&fil); } } }
|
三、解决方法
看了网上的资料,在使用该函数时出现了硬件中断,一般都是单片机内存访问出现了错误。
也就是说在 f_read(&fil,(const TCHAR *)File_path,FA_READ) 的参数中,无法找到 fil 的地址。将 FIL fil; 从函数外拿出,定义为全局变量,即可解决。
这是因为函数内的变量是定义在栈里面的,而 FIL 是 fatfs 中对文件定义的结构体变量,这个变量的内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
typedef struct { #if !_FS_TINY union{ UINT d32[_MAX_SS/4]; BYTE d8[_MAX_SS]; }buf; #endif FATFS* fs; WORD id; BYTE flag; BYTE err; DWORD fptr; DWORD fsize; DWORD sclust; DWORD clust; DWORD dsect; #if !_FS_READONLY DWORD dir_sect; BYTE* dir_ptr; #endif #if _USE_FASTSEEK DWORD* cltbl; #endif #if _FS_LOCK UINT lockid; #endif
} FIL;
|
可见在最前面有一个共用体,用作读写数据的缓冲,这个其中 _MAX_SS 定义为4096。整个结构体的大小,可使用 sizeof(fil) 查看,肯定多余4096。可是一般栈都不会有这么大,所以这个问题是由于栈溢出造成的。在函数内部一般不设置大数组,但是保不齐结构体内部有数组。
参考链接
原文链接:本人CSDN博客