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

STM32L151RDT6 SDIO读写SD卡 FIFO下溢错误,不知是什么原因

[复制链接]
wanghailong1314 提问时间:2018-10-23 10:01 /
系统介绍:
1.MCU :STM32L151RDT6
2.时钟配置: 外部晶振12M ,PLL分频得到48M给SDIO适配器使用,PLL分频得到系统主时钟32M SDIO外设 PCLK2时钟32M
3.SD_CK上电初始化时400KHz,初始化完成后分频改成24MHz。
SD原理图:

问题:
SD卡上电初始化没有问题,能够读取卡的CID,块的大小等信息。在测试块写入数据时提示SD_TX_UNDERRUN 错误,也就是FIFO下溢错误。
我尝试减小时钟频率的话出现SD_DATA_CRC_FAIL错误,也就是数据块CRC错误。不知什么原因造成的。我是按照原子STM32F407SD卡的例子改的。
  1. SD_Error SD_WriteBlock(u8 *buf,long long addr,  u16 blksize)
  2. {
  3.         SD_Error errorstatus = SD_OK;
  4.         
  5.         u8  power=0,cardstate=0;
  6.         
  7.         u32 timeout=0,bytestransferred=0;
  8.         
  9.         u32 cardstatus=0,count=0,restwords=0;
  10.         
  11.         u32        tlen=blksize;   //总长度
  12.         
  13.         u32*tempbuff=(u32*)buf;                                       
  14.         
  15.          if(buf==NULL)return SD_INVALID_PARAMETER;//参数错误
  16.         
  17.   SDIO->DCTRL=0x0;                                                        //数据寄存器清零关DMA
  18.         
  19.         SDIO_DataInitStructure.SDIO_DataBlockSize= 0;//清除DPSM状态机配置
  20.         SDIO_DataInitStructure.SDIO_DataLength= 0 ;
  21.         SDIO_DataInitStructure.SDIO_DataTimeOut=SD_DATATIMEOUT ;
  22.         SDIO_DataInitStructure.SDIO_DPSM=SDIO_DPSM_Enable;
  23.         SDIO_DataInitStructure.SDIO_TransferDir=SDIO_TransferDir_ToCard;
  24.         SDIO_DataInitStructure.SDIO_TransferMode=SDIO_TransferMode_Block;
  25.   SDIO_DataConfig(&SDIO_DataInitStructure);
  26.         
  27.         
  28.         if(SDIO->RESP1&SD_CARD_LOCKED)return SD_LOCK_UNLOCK_FAILED;//卡锁了
  29.          if(CardType==SDIO_HIGH_CAPACITY_SD_CARD)        //大容量卡
  30.         {
  31.                 blksize=512;
  32.                 addr/=512;
  33.         }   
  34.         if((blksize>0)&&(blksize<=2048)&&((blksize&(blksize-1))==0))
  35.         {
  36.                 power=convert_from_bytes_to_power_of_two(blksize);        
  37.                
  38.                 SDIO_CmdInitStructure.SDIO_Argument = blksize;//发送CMD16+设置数据长度 blksize,短响应
  39.                 SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
  40.                 SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  41.                 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  42.                 SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  43.                 SDIO_SendCommand(&SDIO_CmdInitStructure);        
  44.                
  45.                 errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN);        //等待R1响应
  46.                
  47.                 if(errorstatus!=SD_OK)return errorstatus;           //这里返回SD_OK
  48.                
  49.         }else return SD_INVALID_PARAMETER;        
  50.         
  51.                         SDIO_CmdInitStructure.SDIO_Argument = (u32)RCA<<16;//发送CMD13,查询卡的状态,短响应
  52.                   SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_STATUS;
  53.                         SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  54.                         SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  55.                         SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  56.                         SDIO_SendCommand(&SDIO_CmdInitStructure);        

  57.           errorstatus=CmdResp1Error(SD_CMD_SEND_STATUS);                //等待R1响应
  58.         
  59.         if(errorstatus!=SD_OK)return errorstatus;            //这里返回SD_OK
  60.         cardstatus=SDIO->RESP1;                                                                                                         
  61.         timeout=SD_DATATIMEOUT;
  62.            while(((cardstatus&0x00000100)==0)&&(timeout>0))         //¼ì²éREADY_FOR_DATAλÊÇ·ñÖÃλ
  63.         {
  64. timeout--;  
  65.                
  66.                 SDIO_CmdInitStructure.SDIO_Argument = (u32)RCA<<16;//发送CMD13,查询卡的状态,短响应
  67.                 SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_STATUS;
  68.                 SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  69.                 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  70.                 SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  71.                 SDIO_SendCommand(&SDIO_CmdInitStructure);        
  72.                
  73.                 errorstatus=CmdResp1Error(SD_CMD_SEND_STATUS);        //等待R1响应
  74.                
  75.                 if(errorstatus!=SD_OK)return errorstatus;               
  76.                
  77.                 cardstatus=SDIO->RESP1;                                                                                                         
  78.         }
  79.         if(timeout==0)return SD_ERROR;

  80.                         SDIO_CmdInitStructure.SDIO_Argument = addr;//发送CMD24,写单块指令,短响应
  81.                         SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_SINGLE_BLOCK;
  82.                         SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  83.                         SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  84.                         SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  85.                         SDIO_SendCommand(&SDIO_CmdInitStructure);        
  86.         
  87.         errorstatus=CmdResp1Error(SD_CMD_WRITE_SINGLE_BLOCK);//等待R1响应
  88.         
  89.         if(errorstatus!=SD_OK)return errorstatus;//这里反会SD_OK
  90.         
  91.         StopCondition=0;                                                                        //单块写不需要发送停止传输指令

  92.         SDIO_DataInitStructure.SDIO_DataBlockSize= power<<4; ;        //blksize, 控制器到卡
  93.         SDIO_DataInitStructure.SDIO_DataLength= blksize ;
  94.         SDIO_DataInitStructure.SDIO_DataTimeOut=SD_DATATIMEOUT ;
  95.         SDIO_DataInitStructure.SDIO_DPSM=SDIO_DPSM_Enable;
  96.         SDIO_DataInitStructure.SDIO_TransferDir=SDIO_TransferDir_ToCard;
  97.         SDIO_DataInitStructure.SDIO_TransferMode=SDIO_TransferMode_Block;
  98.   SDIO_DataConfig(&SDIO_DataInitStructure);

  99.         timeout=SDIO_DATATIMEOUT;
  100.                
  101.   if(errorstatus!=SD_OK)return errorstatus;           //这里返回OK
复制代码


Snipaste_2018-10-23_09-17-35.png
收藏 评论3 发布时间:2018-10-23 10:01

举报

3个回答
STM1024 回答时间:2018-10-23 10:57:03
Underrun(underflow)
      In computing, buffer underrun or buffer underflow is a state occurring when a buffer used to communicate between two devices or processes is fed with data at a lower speed than the data is being read from it. This requires the program or device reading from the buffer to pause its processing while the buffer refills. This can cause undesired and sometimes serious side effects, since the data being buffered is generally not suited to stop-start access of this kind.

既然是TX Underrun,你把发送的频率提高一些试试?

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

wanghailong1314 回答时间:2018-10-23 11:43:30
stm1024 发表于 2018-10-23 10:57
Underrun(underflow)
      In computing, buffer underrun or buffer underflow is a state occurring whe ...

24Mhz已经是SD_CK的最大时钟了 我用407的板子调试是没问题的  是不是这块芯片的SDIO硬件有问题
wanghailong1314 回答时间:2018-10-24 09:14:11
wanghailong1314 发表于 2018-10-23 11:43
24Mhz已经是SD_CK的最大时钟了 我用407的板子调试是没问题的  是不是这块芯片的SDIO硬件有问题 ...

对于SD卡FIFO下溢错误 解决办法1.降低SD_CK的频率 2.开启硬件流控制。
对于SD_DATA_CRC_FAIL错误,我调试的时候先让板子用1线模式调试能够正确写进数据,改成4线模式就出现SD_DATA_CRC_FAIL错误,那问题就是配置4线的程序有问题。后来我使用了官网例程的配置4线模式函数,降低时钟频率,运行SD_OK了。
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版