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

STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

[复制链接]
chengdf83 提问时间:2011-11-26 21:46 /
我是使用的STM32F103VDT6芯片,TF卡使用的是sandisk class4 4G的。使用的是SDIO+DMA官方例程,单独测试没有发现问题,但是当我开启其他中断时(不管什么中断),比如我开启TIM3定时中断,中断频率为200Hz,中断中执行一个for循环来模拟中断处理,只要for循环的执行时间较长,就会出现TF卡的操作卡死问题,就是TF卡操作一直在等待DMA标志,并且for循环越长出现这种卡死的概率越大,当达到一定程度后TF卡完全不能操作。我大概估算了一下,差不多在中断执行时间达到总时间的20%左右就会明显有卡死现象,达到50%左右就基本上不能正常操作TF卡了。
由于我需要降低功耗,所以将主频降的比较低,4MHz,所以中断处理相对来说就显得执行时间较长,这样我才意识到这个问题,后来直接用官方例程实测,开通一个TIM3中断,执行for循环延时,当达到一定程度后,可以重现这个问题,所以我觉得应该是固件库或者是硬件的原因,不知道你们有没有发现这个问题,可以的话你们也可以这样测试一下,看能否重现这个问题,要是能解决的话,希望帮忙解决一下,要是这个问题得不到解决的话,我们只能放弃使用这个芯片了。
收藏 评论28 发布时间:2011-11-26 21:46

举报

28个回答
Andy-419672 回答时间:2015-2-10 09:58:37
if (errorstatus == SD_OK)
  {
                        /* 最后为了提高读写,开启4bits模式 */
    errorstatus = SD_EnableWideBusOperation(SDIO_BusWide_1b);       
  }  
用官网例程的话采用1bit模式就行了,应该是4bit模式和DMA配置方面的问题,具体的正在研究。
雪花苑 回答时间:2016-1-12 09:01:30
chengdf83 发表于 2011-11-28 13:13
非常感谢火雷达,我遇到的那个问题貌似解决了,呵呵。把流控加上后问题就搞定了,之前别人移植的代码,最近 ...

您好,关于您很久之前遇到的这个问题,我最近也遇到了,并且很纠结。请问您当时是怎么解决的?就是加了硬件流控么?可我加了硬件流控之后就会出现CRC校验错误。
decomen_leo 回答时间:2014-12-18 19:43:48
chengdf83 发表于 2011-11-28 13:13
非常感谢火雷达,我遇到的那个问题貌似解决了,呵呵。把流控加上后问题就搞定了,之前别人移植的代码,最近 ...

你说需要开启流控是啥意思,我也遇到了这个问题,希望您帮忙解决一下。QQ:1075785006
火雷达 回答时间:2011-11-27 10:30:28

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

具体这个问题,我没有遇到过,不过能从你的描述来看,可能是你自己的程序问题:
1、用官方例程来测试没有问题,至少说明硬件和软件出现问题的几率比较小
2、加中断后,出现问题。这就很可能是中断处理的问题。
3、如果你没有加操作系统的话,就是你采用前后台的系统结构。
(1)把定时器的中断处理时间尽量减少(就是在中断响应函数执行时间缩短)
(2)把中断过程处理的for循环移到中断外面来处理,比如main函数里面,在中断函数只要做一个标记就可以了。
从你描述的过程中,应该是中断执行时间太久的原因(for循环越长出现这种卡死的概率越大),这个很可能是系统错过了某个事件。
不知道你的中断的优先级是怎么配置的。也有可能是让DMA中断不能及时响应。
chengdf83 回答时间:2011-11-27 12:20:29

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

首先谢谢楼上的。
首先中断中没有涉及任何事情,只是延时问题。DMA是使用例程的,没有中断,是使用的查询方式,只有SDIO中断,并且SDIO中断的优先级最高,可以嵌套TIM3中断,整个系统就只有这两个中断。我没有使用操作系统,完全使用的是SDIO+DMA官方例程测试的。当然,把中断中的执行代码拿到中断外,这个问题就不会出现了,但是我的主频很低,中断中稍微多一点事务处理就很可能触发这个问题,我现在已经尽量将可以移出的处理移出来了,但是这个并没有找到问题的根源,说不准他就一定不会在什么时候出问题,而且以后系统需要扩展功能的话,这也是一个暗藏的问题。
我的意思是,即使在中断处理时间较长的情况下(条件比较苛刻的情况),也能保证程序不被卡死,因为只有这样才能保证系统的可靠性。
火雷达 回答时间:2011-11-27 13:37:41

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

你说的也是,这是个定时炸弹。
你可以详细描述下什么是卡死?
1、你确认一下,SDIO包括STM32的驱动中是否有循环等待某个标志位
2、你的应用程序中(SDIO相关的)是否有循环等待某个标志位。
3、错误处理:
关于DMA,如果有需要的话,每次使用前,全部重新初始化下。我以前看到过一个帖子,说ADC+DMA出现问题,这个建议仅供参考,不负责任的。
chengdf83 回答时间:2011-11-27 15:26:10

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

主要卡死在两个地方:
1、就是在初始化SD卡的时候,有一个FindSCR()函数中:
while (!(SDIO->STA & (SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR)))
  {
    if (SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET)
    {
      *(tempscr + index) = SDIO_ReadData();
      index++;
    }
  }
卡死在这个while循环中,不过这个可以使用index来判断,当大于1时就跳出,不会影响操作。这个姑且算是解决了吧。呵呵。
2、另一个就卡死在SD_ReadBlock()或者SD_WriteBlock()函数的DMA查询那里,比如SD_ReadBlock()中的:
SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_STBITERR, ENABLE);
    SDIO_DMACmd(ENABLE);
    DMA_RxConfiguration(readbuff, BlockSize);
    while (DMA_GetFlagStatus(DMA2_FLAG_TC4) == RESET)
    {}
这个就不好解决了,呵呵。通过观察SDIO中断标志,可以看出大多时候是出现了SDIO_IT_RXOVERR错误,但是极个别时候是数据正常。
另外,应用程序中是没有循环等待的。
测试程序是使用的官方例程,里面的DMA是每次使用前都重新配置了的。
很谢谢你的关注,呵呵。
chengdf83 回答时间:2011-11-27 15:37:55

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

另外,我弱弱的问一下,SDIO发送和接受都是硬件操作吧?那我的中断操作应该不会影响SDIO硬件的发送、响应以及数据接收啊。也就是说前面的SDIO初始化配置都是命令发送以及响应,我查看了,命令发送和响应都是硬件一气呵成的,只要命令一旦装载到命令寄存器,硬件就开始运作,直到接收响应并且置标志位,中断在这些操作中是不会起到干扰的。
当我的中断延时加长后,在SDIO还没有正式传数据的时候就开始出现异常了(就是上面的第一个卡死的地方),这个好像是在读取SCR寄存器,用来确认SD卡是否支持4bits模式,但是这里读取的也是SDIO硬件的FIFO寄存器,也是硬件完成接收操作的。也就是说在出现异常前,所有的通信都是硬件完成,中断也只是间隔在每个操作进程之间的,按照常理来想,中断的长短应该不能引起这种异常啊。所以怎么想都想不通。  呵呵   还望指点迷津啊。
chengdf83 回答时间:2011-11-27 15:42:14

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

还有一个比较重要的信息,好像卡死的基本上都是读数据的时候,包括第一种卡死的那个while其实也是读数据,写数据好像还没有发现卡死过,虽然也有while循环。是不是跟FIFO有关啊?
火雷达 回答时间:2011-11-27 18:33:22

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

while (DMA_GetFlagStatus(DMA2_FLAG_TC4) == RESET)
{}
这个就不好解决了,呵呵。通过观察SDIO中断标志,可以看出大多时候是出现了SDIO_IT_RXOVERR错误,

SDIO_IT_RXOVERR这种错误是怎么解决的?
如果出现了这种错误,你所等待的标志位还是正常的吗?
如果出现错误标志位的话,你所等待的标志位没有置位的话,那你就是在一直等。就是死循环了。
等待的时候,还有做出错处理。
是不是这种情况?
火雷达 回答时间:2011-11-27 18:39:23

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

你要防止硬件错误,这就是很多程序要做的工作,同时还要做正确的出错处理。
chengdf83 回答时间:2011-11-28 11:29:37

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

我跟进去看了,之前认为和写数据没有关系是错误的,读写都有可能错误,就是卡在while (DMA_GetFlagStatus(DMA2_FLAG_TC4) == RESET)处,我将中断延时去掉,开启硬件流控后,也会卡死在这里,反而不开流控还没有卡死,真是郁闷。
chengdf83 回答时间:2011-11-28 11:31:32

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

出现错误标志后,是按照例程中的处理方式处理的,处理函数是SD_ProcessIRQSrc():
---------------------------------------------------
/*******************************************************************************
* Function Name  : SD_ProcessIRQSrc
* Description    : Allows to process all the interrupts that are high.
* Input          : None
* Output         : None
* Return         : SD_Error: SD Card Error code.
*******************************************************************************/
SD_Error SD_ProcessIRQSrc(void)
{
  uint32_t count = 0, restwords = 0;
  if (DeviceMode == SD_INTERRUPT_MODE)
  {
#ifdef DISPSDINFO
    printf("\t\tSD_INTERRUPT_MODE\n");
#endif
    if (SDIO_GetITStatus(SDIO_IT_RXFIFOHF) != RESET)
    {
      for (count = 0; count < SD_HALFFIFO; count++)
      {
        *(DestBuffer + count) = SDIO_ReadData();
      }
      DestBuffer += SD_HALFFIFO;
      NumberOfBytes += SD_HALFFIFOBYTES;
    }
    else if (SDIO_GetITStatus(SDIO_IT_TXFIFOHE) != RESET)
    {
      if ((TotalNumberOfBytes - NumberOfBytes) < SD_HALFFIFOBYTES)
      {
        restwords = ((TotalNumberOfBytes - NumberOfBytes) %  4 == 0) ?
                    ((TotalNumberOfBytes - NumberOfBytes) / 4) :
                    ((TotalNumberOfBytes - NumberOfBytes) / 4 + 1);
        for (count = 0; count < restwords;  count++, SrcBuffer++, NumberOfBytes += 4)
        {
          SDIO_WriteData(*SrcBuffer);
        }
      }
      else
      {
        for (count = 0; count < SD_HALFFIFO; count++)
        {
          SDIO_WriteData(*(SrcBuffer + count));
        }
        SrcBuffer += SD_HALFFIFO;
        NumberOfBytes += SD_HALFFIFOBYTES;
      }
    }
  }
  if (SDIO_GetITStatus(SDIO_IT_DATAEND) != RESET)
  {
#ifdef DISPSDINFO
    printf("\t\tSDIO_IT_DATAEND\n");
#endif
    if (DeviceMode != SD_DMA_MODE)
    {
      while ((SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET)  &&  (NumberOfBytes < TotalNumberOfBytes))
      {
        *DestBuffer = SDIO_ReadData();
        DestBuffer++;
        NumberOfBytes += 4;
      }
    }
    if (StopCondition == 1)
    {
      TransferError = SD_StopTransfer();
    }
    else
    {
      TransferError = SD_OK;
    }
    SDIO_ClearITPendingBit(SDIO_IT_DATAEND);
    SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND |
                  SDIO_IT_TXFIFOHE | SDIO_IT_RXFIFOHF | SDIO_IT_TXUNDERR |
                  SDIO_IT_RXOVERR | SDIO_IT_STBITERR, DISABLE);
    TransferEnd = 1;
    NumberOfBytes = 0;
    return(TransferError);
  }
  if (SDIO_GetITStatus(SDIO_IT_DCRCFAIL) != RESET)
  {
#ifdef DISPSDINFO
    printf("\t\tSDIO_IT_DCRCFAIL\n");
#endif
    SDIO_ClearITPendingBit(SDIO_IT_DCRCFAIL);
    SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND |
                  SDIO_IT_TXFIFOHE | SDIO_IT_RXFIFOHF | SDIO_IT_TXUNDERR |
                  SDIO_IT_RXOVERR | SDIO_IT_STBITERR, DISABLE);
    NumberOfBytes = 0;
    TransferError = SD_DATA_CRC_FAIL;
    return(SD_DATA_CRC_FAIL);
  }
  if (SDIO_GetITStatus(SDIO_IT_DTIMEOUT) != RESET)
  {
#ifdef DISPSDINFO
    printf("\t\tSDIO_IT_DTIMEOUT\n");
#endif
    SDIO_ClearITPendingBit(SDIO_IT_DTIMEOUT);
    SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND |
                  SDIO_IT_TXFIFOHE | SDIO_IT_RXFIFOHF | SDIO_IT_TXUNDERR |
                  SDIO_IT_RXOVERR | SDIO_IT_STBITERR, DISABLE);
    NumberOfBytes = 0;
    TransferError = SD_DATA_TIMEOUT;
    return(SD_DATA_TIMEOUT);
  }
  if (SDIO_GetITStatus(SDIO_IT_RXOVERR) != RESET)
  {
#ifdef DISPSDINFO
    printf("\t\tSDIO_IT_RXOVERR\n");
#endif
    SDIO_ClearITPendingBit(SDIO_IT_RXOVERR);
    SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND |
                  SDIO_IT_TXFIFOHE | SDIO_IT_RXFIFOHF | SDIO_IT_TXUNDERR |
                  SDIO_IT_RXOVERR | SDIO_IT_STBITERR, DISABLE);
    NumberOfBytes = 0;
    TransferError = SD_RX_OVERRUN;
    return(SD_RX_OVERRUN);
  }
  if (SDIO_GetITStatus(SDIO_IT_TXUNDERR) != RESET)
  {
#ifdef DISPSDINFO
    printf("\t\tSDIO_IT_TXUNDERR\n");
#endif
    SDIO_ClearITPendingBit(SDIO_IT_TXUNDERR);
    SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND |
                  SDIO_IT_TXFIFOHE | SDIO_IT_RXFIFOHF | SDIO_IT_TXUNDERR |
                  SDIO_IT_RXOVERR | SDIO_IT_STBITERR, DISABLE);
    NumberOfBytes = 0;
    TransferError = SD_TX_UNDERRUN;
    return(SD_TX_UNDERRUN);
  }
  if (SDIO_GetITStatus(SDIO_IT_STBITERR) != RESET)
  {
#ifdef DISPSDINFO
    printf("\t\tSDIO_IT_STBITERR\n");
#endif
    SDIO_ClearITPendingBit(SDIO_IT_STBITERR);
    SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND |
                  SDIO_IT_TXFIFOHE | SDIO_IT_RXFIFOHF | SDIO_IT_TXUNDERR |
                  SDIO_IT_RXOVERR | SDIO_IT_STBITERR, DISABLE);
    NumberOfBytes = 0;
    TransferError = SD_START_BIT_ERR;
    return(SD_START_BIT_ERR);
  }
  return(SD_OK);
}
---------------------------------------------------
chengdf83 回答时间:2011-11-28 11:54:58

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

加了硬件流控之后,出现SDIO_IT_DCRCFAIL错误了,晕死,搞到最后,和网上别人遇到的问题差不多了。但是没见到一位给出了解决方案的。
去掉流控,今天测试又没有出现SDIO_IT_RXOVERR错误了,程序就一直在while (DMA_GetFlagStatus(DMA2_FLAG_TC4) == RESET)卡起,期间没有进过SDIO中断,DMA2->ISR寄存器一直是0,也就是说SDIO没有出现传输错误,也没有传输完成,甚至都没有超时,DMA的寄存器也没有反应,就是DMA也没有操作完成,好像所有一套硬件机制都冻结了一样。
chengdf83 回答时间:2011-11-28 11:56:32

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

不加流控的话,会不会导致硬件冻结呢?  呵呵   好像也不合常理。哎  我都快疯了。
chengdf83 回答时间:2011-11-28 13:13:07

RE:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

非常感谢火雷达,我遇到的那个问题貌似解决了,呵呵。把流控加上后问题就搞定了,之前别人移植的代码,最近天天看资料才发现流控制没有开启。
弄了这么多天,唉,还好,解决了。呵呵
火雷达 回答时间:2011-11-28 20:56:06

回复:STM32+SDIO+DMA 4bits 出现卡死问题求助!!!

问题解决了,就好了,这个MCU功能太复杂,很多东西忘记配置。
12下一页

所属标签

相似问题

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