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

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

[复制链接]
kokoro 提问时间: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个回答
kokoro 回答时间:2017-6-23 17:00:53
看样子又是石沉大海了......
再加一个现象,时钟分频我原来设置的是 0,也就是说 SDIO_CK = 45M/(2+0) = 22.5M,我把分频设置为 1也是不好使,但是我把分频设置到 2或者大于2,发送数据就不会出CRC错了,一切正常了....
这是为什么?难道要使用硬件流控制 SDIO_CK的频率不能太高?感觉像ST芯片的硬件BUG。
JeffJiang 回答时间:2017-8-3 09:32:47
不懂,帮顶,学习一下,以后可能用到
andey 回答时间: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

查看全部评分

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

不是F7,用的是F439。

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版