硬汉嵌入式论坛

 找回密码
 立即注册
查看: 429|回复: 9
收起左侧

[技术讨论] FATFS写SD卡偶尔出现写失败和打开文件失败

[复制链接]

5

主题

165

回帖

180

积分

初级会员

积分
180
发表于 2023-12-14 11:32:19 | 显示全部楼层 |阅读模式
本帖最后由 DX3906 于 2023-12-14 11:34 编辑

我在at32f435上用fatfs周期写16KB数据到sd卡,偶尔会出现写文件失败和打开文件失败,有时候重新上电几次之后又能长时间稳定写入,fatfs报错是FR_DISK_ERR,但是sdio驱动和fatfs都是直接用的官方的,换了几张卡都有一定几率出现
想问下各位大佬这可能是哪些方面的问题呢?
QQ截图20231214113348.png


这个是我的测试代码,在freertos下跑的,只有这一个任务
[C] 纯文本查看 复制代码
void log_store_init(void)
{
  FRESULT ret;

  ret = f_mount(NULL, "1:", 1);
  ret = f_mount(&fs, "1:", 1);
  if(ret){
    DEBUG_PRINTF("fs mount err:%d.\r\n", ret);
    if(ret == FR_NO_FILESYSTEM){
      DEBUG_PRINTF("create fatfs..\r\n");
      BYTE *work  = (BYTE *)pvPortMalloc(FF_MAX_SS);
      ret = f_mkfs("1:", 0, work, sizeof(work));
      if(ret){
        DEBUG_PRINTF("creates fatfs err:%d.\r\n", ret);
        return;
      }
      else{
        DEBUG_PRINTF("creates fatfs ok.\r\n");
      }
      ret = f_mount(NULL, "1:", 1);
      ret = f_mount(&fs, "1:", 1);
      if(ret){
        DEBUG_PRINTF("fs mount err:%d.\r\n", ret);
        return;
      }
      else{
        DEBUG_PRINTF("fs mount ok.\r\n");
      }
    }
    else{
      return;
    }
  }
  else{
    DEBUG_PRINTF("fs mount ok.\r\n");
  }
}

char filename[] = "1:/test_data0000.bin";
void write_sd_test(void)
{
  FIL file0;
  FRESULT ret;
  uint32_t len = 0;
  static uint64_t total_len = 0;
  static uint16_t file_count = 0;
  
  if(file_count >= 940)
  {
    file_count = 0;
  }
  
  char *filename = (char *)pvPortMalloc(22);
  sprintf(filename, "1:/test_data%04d.bin", file_count);
  if(filename == NULL)
  {
    DEBUG_PRINTF("firename malloc failed.\r\n");
    return;
  }
  
  ret = f_open(&file0, filename, FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS);
  if(ret){
    DEBUG_PRINTF("open file err:%d.\r\n", ret);
  }
  else{
    DEBUG_PRINTF("open file ok. %s\r\n", filename);
    uint8_t *buf = (uint8_t *)pvPortMalloc(16384);
    if(buf == NULL)
    {
      DEBUG_PRINTF("buf malloc failed.\r\n");
      if(filename != NULL)
        vPortFree(filename);
      f_close(&file0);
      return;
    }
    else
    {
      for(uint32_t i = 0; i < 500; i++)
      {
        for(uint16_t j = 0; j < 16384; j++)
        {
          buf[j] = rand();
        }
        f_lseek(&file0, len);
        ret = f_write(&file0, (uint8_t*)buf, 16384, &bytes_written);
        if(ret){
          DEBUG_PRINTF("write file err:%d.\r\n", ret);
          f_close(&file0);
          ret = f_mount(NULL, "1:", 1);
          ret = f_mount(&fs, "1:", 1);
          if(ret){
            DEBUG_PRINTF("fs mount err:%d.\r\n", ret);
            return;
          }
          else{
            DEBUG_PRINTF("fs mount ok.\r\n");
          }
          break;
        }
        else{
          f_sync(&file0);
          len += bytes_written;
          total_len += bytes_written;
          DEBUG_PRINTF("write file ok, byte:%u, total:%lld\r\n", bytes_written, total_len);
        }
        vTaskDelay(1);
      }
      f_close(&file0);
      file_count++;
    }
    if(buf != NULL)
      vPortFree(buf);
  }
  if(filename != NULL)
    vPortFree(filename);
}

static void log_task(void* parameter)
{
  portBASE_TYPE uxHighWaterMark;
  __IO size_t xFreeStackSpace;

  log_store_init();
  
  while(1)
  {
    xFreeStackSpace = xPortGetFreeHeapSize();
    DEBUG_PRINTF("free heap size: %d\r\n", xFreeStackSpace);
    write_sd_test();
    DEBUG_PRINTF("%s runing\r\n", LOG_TASK_NAME);

    vTaskDelay(1);
  }
}

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106749
QQ
发表于 2023-12-14 14:16:55 | 显示全部楼层
1、是不是开DMA了,要特别注意4字节对齐问题。
2、不建议重复的挂载卸载,推荐fopen后,后面仅调用fwrite和f_sync即可,fclose不需要调用,试试是否好点。
回复

使用道具 举报

7

主题

21

回帖

42

积分

新手上路

积分
42
发表于 2023-12-14 15:54:19 | 显示全部楼层
频率太高了吧
回复

使用道具 举报

5

主题

165

回帖

180

积分

初级会员

积分
180
 楼主| 发表于 2023-12-14 16:11:06 | 显示全部楼层
用的是阻塞读写
开始以为是重新下程序后sd卡内部没复位,想着报错的时候重新挂载初始化一下试试,没有f_close的话文件不会异常吗?
回复

使用道具 举报

5

主题

132

回帖

147

积分

初级会员

积分
147
发表于 2023-12-15 08:37:51 | 显示全部楼层
之前遇到过类似的,原因是SD卡用了DMA, UI任务操作LTDC寄存器时 APB2总线会暂停,导致DMA出错
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106749
QQ
发表于 2023-12-15 08:41:08 | 显示全部楼层
DX3906 发表于 2023-12-14 16:11
用的是阻塞读写
开始以为是重新下程序后sd卡内部没复位,想着报错的时候重新挂载初始化一下试试,没有f_cl ...

不会,f_sync也会将数据实际写入文件。
回复

使用道具 举报

5

主题

165

回帖

180

积分

初级会员

积分
180
 楼主| 发表于 2023-12-15 09:42:19 | 显示全部楼层
eric2013 发表于 2023-12-15 08:41
不会,f_sync也会将数据实际写入文件。

好的,我一会儿试试
回复

使用道具 举报

5

主题

165

回帖

180

积分

初级会员

积分
180
 楼主| 发表于 2023-12-15 09:43:05 | 显示全部楼层
无关风月 发表于 2023-12-15 08:37
之前遇到过类似的,原因是SD卡用了DMA, UI任务操作LTDC寄存器时 APB2总线会暂停,导致DMA出错

老哥用的是什么芯片,dma是sdio里的dma吗?
回复

使用道具 举报

5

主题

132

回帖

147

积分

初级会员

积分
147
发表于 2023-12-15 13:24:37 | 显示全部楼层
DX3906 发表于 2023-12-15 09:43
老哥用的是什么芯片,dma是sdio里的dma吗?

stm32f4
Care must be taken when accessing the LTDC registers since the APB2 bus is stalling when
the following operations are ongoing:
&#8226; Register write access and update for 6 xPCKL2 period + 5x LCD_CLK period (5x
HCLK period for register on AHB clock domain)
&#8226; Register read access for 7xPCKL2 period + 5x LCD_CLK period (5x HCLK period for
register on AHB clock domain).
For registers on PCLK2 clock domain, APB2 bus is stalling during the register write access
for 6 xPCKL2 period and 7xPCKL2 period for read access.
回复

使用道具 举报

5

主题

165

回帖

180

积分

初级会员

积分
180
 楼主| 发表于 2023-12-18 10:34:43 | 显示全部楼层
说下这几天的测试结论,不是驱动和f_close的问题,是卡的写入速度慢了,虽然用的是class10的卡,但是用工具测出来单次小数据量的写入速度非常慢
我分别测了杂牌的c10卡、闪迪的c10卡和移速的u3高速卡,在单次写入16KB这一项的速度差距很大
杂牌卡的16KB写入速度只有4MB/S多点,而我的测试代码是1ms循环写入16KB数据,卡跟不上所以报错了,把循环里的延时调大以后就可以稳定了

大家挑sd卡最好还是挑品牌卡比较好,然后能用高速卡尽量用高速卡


杂牌c10卡
微信截图_20231218100035.png

闪迪c10卡
微信截图_20231218101547.png

移速u3卡
微信截图_20231218100422.png

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-4 04:28 , Processed in 0.288377 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表