你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

SDIO设置了硬件流控制发送数据就出现CRC错误,怎么解决?

[复制链接]
kokoromi 提问时间:2017-6-23 13:08 /
本帖最后由 kokoromi 于 2017-6-23 13:10 编辑

SDIO和DMA的配置如下:
uint8_t BSP_SD_Init()
{
  uint8_t sd_state = 1;

  //设置 DMA2的流 3中断优先级并使能中断
  HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 15, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
  //设置 SDIO传输时使用的 DMA流 3
  hDMA_SDIO_Tx.Instance = DMA2_Stream3;                             //设置 DMA2的流 3,用于发送数据到 SDIO
  hDMA_SDIO_Tx.Init.Channel = DMA_CHANNEL_4;                        //使用 通道 4
  hDMA_SDIO_Tx.Init.Direction = DMA_MEMORY_TO_PERIPH;               //传输方向为存储器到外设(SDIO)
  hDMA_SDIO_Tx.Init.PeriphInc = DMA_PINC_DISABLE;                   //外设地址不变
  hDMA_SDIO_Tx.Init.MemInc = DMA_MINC_ENABLE;                       //存储器地址增加
  hDMA_SDIO_Tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;      //外设数据为字(字对齐)
  hDMA_SDIO_Tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;         //存储器数据为字节
  hDMA_SDIO_Tx.Init.Mode = DMA_PFCTRL;                              //流控制器为外设(SDIO)
  hDMA_SDIO_Tx.Init.Priority = DMA_PRIORITY_LOW;                    //传输优先级为低
  hDMA_SDIO_Tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;                 //使能 FIFO
  hDMA_SDIO_Tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;        //FIFO阈值为满
  hDMA_SDIO_Tx.Init.MemBurst = DMA_MBURST_INC16;                    //存储器为 16节拍单次突发传输
  hDMA_SDIO_Tx.Init.PeriphBurst = DMA_PBURST_INC4;                  //外设为 4节拍单次突发传输
  //初始化发送 DMA
  if(HAL_DMA_Init(&hDMA_SDIO_Tx) != HAL_OK) return 1;
  //链接 DMA到 SDIO
  __HAL_LINKDMA(&hSD, hdmatx, hDMA_SDIO_Tx);


  //设置 DMA2的流 6中断优先级并使能中断
  HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 15, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
  //设置 SDIO传输时使用的 DMA流 6
  hDMA_SDIO_Rx.Instance = DMA2_Stream6;                             //设置 DMA2的流 6,用于从 SDIO接收数据
  hDMA_SDIO_Rx.Init.Channel = DMA_CHANNEL_4;                        //使用通道 4
  hDMA_SDIO_Rx.Init.Direction = DMA_PERIPH_TO_MEMORY;               //传输方向为外设(SDIO)到存储器
  hDMA_SDIO_Rx.Init.PeriphInc = DMA_PINC_DISABLE;                   //外设地址不变
  hDMA_SDIO_Rx.Init.MemInc = DMA_MINC_ENABLE;                       //存储器地址增加
  hDMA_SDIO_Rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;      //外设数据为字(字对齐)
  hDMA_SDIO_Rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;         //存储器数据为字节
  hDMA_SDIO_Rx.Init.Mode = DMA_PFCTRL;                              //流控制器为外设(SDIO)
  hDMA_SDIO_Rx.Init.Priority = DMA_PRIORITY_LOW;                    //传输优先级为低
  hDMA_SDIO_Rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;                 //使能 FIFO
  hDMA_SDIO_Rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;        //FIFO阈值为满
  hDMA_SDIO_Rx.Init.MemBurst = DMA_MBURST_INC16;                    //存储器为 16节拍单次突发传输
  hDMA_SDIO_Rx.Init.PeriphBurst = DMA_PBURST_INC4;                  //外设为 4节拍单次突发传输
  //初始化接收 DMA
  if(HAL_DMA_Init(&hDMA_SDIO_Rx) != HAL_OK) return 1;
  //链接 DMA到 SDIO
  __HAL_LINKDMA(&hSD, hdmarx, hDMA_SDIO_Rx);


  //配置 SDIO中断优先级为 14(必须高于 DMA2流 3和流 6,否则无法抢占 DMA2流中断,导致死锁)
  HAL_NVIC_SetPriority(SDIO_IRQn, 14, 0);
  HAL_NVIC_EnableIRQ(SDIO_IRQn);
  //设置 SDIO的初始化参数
  hSD.Instance = SDIO;                                              //指定 SDIO设备
  hSD.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;                      //上升沿有效
  hSD.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;                 //禁止旁路模式,使能时钟分频
  hSD.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_ENABLE;           //使能节能模式
  hSD.Init.BusWide = SDIO_BUS_WIDE_1B;                              //设置 SDIO总线为 1位
  hSD.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE; //使能 SDIO硬件流控制
  hSD.Init.ClockDiv = 0;                                            //时钟分频为 0,即 SDIO_CK = SDIOCLK/(2 + 0)
  //初始化 SD卡
  if(HAL_SD_Init(&hSD, &SDCardInfo) == SD_OK)
  {
    //使能 SD宽总线模式(4线)
    if(HAL_SD_WideBusOperation_Config(&hSD, SDIO_BUS_WIDE_4B) == SD_OK)
      sd_state = 0;
    else
      sd_state = 1;
  }

  return sd_state;
}


数据传输是使用 DMA方式的。现在的问题是,我读取 SD卡数据没问题,但是向 SD卡写入数据每次都提示 CRC错误,奇怪的是如果我关闭了硬件流控制,写入数据就正常了,这是怎么回事?有人遇到过这个问题吗?



收藏 1 评论7 发布时间:2017-6-23 13:08

举报

7个回答
kokoromi 回答时间:2017-6-23 17:00:53
看样子又是石沉大海了......
再加一个现象,时钟分频我原来设置的是 0,也就是说 SDIO_CK = 45M/(2+0) = 22.5M,我把分频设置为 1也是不好使,但是我把分频设置到 2或者大于2,发送数据就不会出CRC错了,一切正常了....
这是为什么?难道要使用硬件流控制 SDIO_CK的频率不能太高?感觉像ST芯片的硬件BUG。
开心/xin男孩 回答时间:2017-8-3 09:32:47
不懂,帮顶,学习一下,以后可能用到
andeyqi 回答时间:2017-8-3 09:35:55
帮顶一下。
Dandjinh 回答时间:2017-8-3 09:43:02
是F7吗?F7的SDIO确实有硬件错误
QQ截图20170803094236.jpg

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

无薪税绵 回答时间:2017-8-3 09:47:28
有可能是时钟频率太高了。
或者是卡的速度跟不上。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

toofree 回答时间:2017-8-3 11:46:49
什么玩意,都不知道你用什么片子
kokoromi 回答时间:2019-5-15 18:32:16
Dandjinh 发表于 2017-8-3 09:43
是F7吗?F7的SDIO确实有硬件错误

不是F7,用的是F439。

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版