OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2145|回复: 4

移植fatfs发现了一个SD卡底层操作的问题

[复制链接]

21

主题

66

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
273
金钱
273
注册时间
2017-7-19
在线时间
89 小时
发表于 2019-2-13 13:43:14 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 飛饵 于 2019-2-13 18:29 编辑

SD卡操作是用ST官方的SDIO例程。用fatfs时发现 f_open()老返回no_filesystem错误,debug到最后发现SD卡的那个单块读函数 SD_ReadBlock()读的数据是错的,单独测试这个函数也是错的,没仔细研究过这个函数原理,所以不懂怎么解决。
不过那个多块读函数就没问题,虽然fatfs接口里可以用多块读代替,但有没有人知道 SD_ReadBlock()的bug怎么解决?


还有个现象,单独测试 SD_ReadBlock()时,如果在前面先执行一遍 SD_ReadMultiBlocks(),接下来 SD_ReadBlock()读出来的数据又对了。但是单独执行的数据就一直错的


贴上代码
[mw_shl_code=c,true]SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize)
{
  SD_Error errorstatus = SD_OK;
#if defined (SD_POLLING_MODE)
  uint32_t count = 0, *tempbuff = (uint32_t *)readbuff;
#endif

  TransferError = SD_OK;
  TransferEnd = 0;
  StopCondition = 0;
  
  SDIO->DCTRL = 0x0;

  
  if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  {
    BlockSize = 512;
    ReadAddr /= 512;
  }

  SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
  SDIO_DataInitStructure.SDIO_DataLength = BlockSize;
  SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) 9 << 4;
  SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;
  SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
  SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
  SDIO_DataConfig(&SDIO_DataInitStructure);

  /*!< Send CMD17 READ_SINGLE_BLOCK */
  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)ReadAddr;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_READ_SINGLE_BLOCK;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SD_CMD_READ_SINGLE_BLOCK);

  if (errorstatus != SD_OK)
  {
    return(errorstatus);
  }

#if defined (SD_POLLING_MODE)  
  /*!< In case of single block transfer, no need of stop transfer at all.*/
  /*!< Polling mode */
  while (!(SDIO->STA &(SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR)))
  {
    if (SDIO_GetFlagStatus(SDIO_FLAG_RXFIFOHF) != RESET)
    {
      for (count = 0; count < 8; count++)
      {
        *(tempbuff + count) = SDIO_ReadData();
      }
      tempbuff += 8;
    }
  }

  if (SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) != RESET)
  {
    SDIO_ClearFlag(SDIO_FLAG_DTIMEOUT);
    errorstatus = SD_DATA_TIMEOUT;
    return(errorstatus);
  }
  else if (SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL) != RESET)
  {
    SDIO_ClearFlag(SDIO_FLAG_DCRCFAIL);
    errorstatus = SD_DATA_CRC_FAIL;
    return(errorstatus);
  }
  else if (SDIO_GetFlagStatus(SDIO_FLAG_RXOVERR) != RESET)
  {
    SDIO_ClearFlag(SDIO_FLAG_RXOVERR);
    errorstatus = SD_RX_OVERRUN;
    return(errorstatus);
  }
  else if (SDIO_GetFlagStatus(SDIO_FLAG_STBITERR) != RESET)
  {
    SDIO_ClearFlag(SDIO_FLAG_STBITERR);
    errorstatus = SD_START_BIT_ERR;
    return(errorstatus);
  }
  while (SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET)
  {
    *tempbuff = SDIO_ReadData();
    tempbuff++;
  }
  
  /*!< Clear all the static flags */
  SDIO_ClearFlag(SDIO_STATIC_FLAGS);

#elif defined (SD_DMA_MODE)
//    SDIO_ITConfig(SDIO_IT_DATAEND, ENABLE);
          SDIO_ITConfig(SDIO_IT_RXOVERR|SDIO_IT_DTIMEOUT|SDIO_IT_DCRCFAIL|SDIO_IT_DATAEND, ENABLE);//使用这句,防止传输错误造成卡死
    SDIO_DMACmd(ENABLE);
    SD_LowLevel_DMA_RxConfig((uint32_t *)readbuff, BlockSize);
#endif

  return(errorstatus);
}[/mw_shl_code]

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

6

主题

107

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
374
金钱
374
注册时间
2012-12-30
在线时间
48 小时
发表于 2019-2-13 15:18:33 | 显示全部楼层
回复

使用道具 举报

1

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1183
金钱
1183
注册时间
2015-5-28
在线时间
149 小时
发表于 2019-2-13 17:33:25 | 显示全部楼层
有条件的话用逻辑分析仪抓一下波形,看看SD总线上是具体是怎样的,感觉像是你代码的逻辑问题
回复

使用道具 举报

21

主题

66

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
273
金钱
273
注册时间
2017-7-19
在线时间
89 小时
 楼主| 发表于 2019-2-13 18:26:52 | 显示全部楼层
BG4RFF 发表于 2019-2-13 15:18
设置block大小不一样吧

单块读和多块读都一样的block大小
回复

使用道具 举报

21

主题

66

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
273
金钱
273
注册时间
2017-7-19
在线时间
89 小时
 楼主| 发表于 2019-2-13 18:27:31 | 显示全部楼层
小陀螺爱炒蛋 发表于 2019-2-13 17:33
有条件的话用逻辑分析仪抓一下波形,看看SD总线上是具体是怎样的,感觉像是你代码的逻辑问题

那没办法了。代码是官方例程没修改过的。
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-23 13:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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