找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2558|回复: 2
打印 上一主题 下一主题
收起左侧

MCU不定时死机-移植STM32标准例程惹的祸

[复制链接]
跳转到指定楼层
楼主
ID:965255 发表于 2021-9-14 13:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在开发一款智能化仪器时,需定时采集数据,并同时进行数据分析、储存和远距离光纤传送。因此选用了带有浮点运算功能的STM32F407高性能 MCU。也移植了许多STM32F4的标准例程。程序编译仿真等一切顺利。但试运行时不定时死机,多则几天,少则几小时,毫无规律。
死机的原因很多,如环境干扰;电路板设计不合理产生自激;中断冲突;中断程序中没有清除中断标志位;地址溢出;堆栈溢出;无条件的死循环等等。
因是试机时死机,所以首先考虑环境干扰问题,经屏蔽隔离,消除环境干扰后,故障依旧,机外因素排除。
认真检查了各中断优先等级,设置的中断时刻,中断服务函数等均无任何冲突。仿真检查也无异常。折腾了一天,程序梳理了几遍,也没发现蛛丝马迹,但故障依旧。
无奈之际,利用逐一停用程序模块的方法发现了问题,当停用sd卡模块后不再死机。可以断定问题出在SD卡模块上,但是SD卡模块程序是移植的标准例程,不会是标准例程有问题吧!
于是对sdio_sdcard.c文件逐句分析。在SD_Error SD_SelectDeselect(u32 addr)函数中发现如下加黑的语句:
while(SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET)     
        {
               *tempbuff=SDIO->FIFO;
               tempbuff++;
        }
        INTX_ENABLE();
        SDIO_ClearFlag(SDIO_STATIC_FLAGS);           
}else if(DeviceMode==SD_DMA_MODE)
{
              TransferError=SD_OK;
        StopCondition=0;              
        TransferEnd=0;                        
        SDIO->MASK|=(1<<1)|(1<<3)|(1<<8)|(1<<5)|(1<<9);
      SDIO->DCTRL|=1<<3;                 
           SD_DMA_Config((u32*)buf,blksize,DMA_DIR_PeripheralToMemory);
            while(((DMA2->LISR&(1<<27))==RESET)&&(TransferEnd==0)&&(TransferError==SD_OK)&&timeout)timeout--;
        if(timeout==0)return SD_DATA_TIMEOUT;
        if(TransferError!=SD_OK)errorstatus=TransferError;
    }  
       return errorstatus;
}
汇编语言中
CPSID     I      PRIMASK=1  是关闭中断
CPSIE     I      PRIMASK=0   是开启中断
INTX_ENABLE()是在sys.h中用汇编语言定义的开启所有中断函数;
即:
_asm void INTX_ENABLE(void)
{
CPSIE   I
BX      LR
}
INTX_DISABLE()是在sys.h中用汇编语言定义的关闭所有中断函数;
即:
__asm void INTX_DISABLE(void)
{
CPSID   I
BX      LR  
}
指令“CPSID   I和CPSIE   I”都是对状态寄存器CPSR中中断标志位进行操作,只是简单的不让CPU响应中断,并没有阻止中断的发生,也没有清除中断标志。
SDIO_ClearFlag(SDIO_STATIC_FLAGS)是在STM32f4xx_sdio.c 中定义的,是清除SDIO 挂起标志库函数。
至此不定时死机的机理就真相真相大白了:由于采集的数据各不相同,处理这些数据的耗时也不相同,处理数据后产生的中断时间也就不固定。虽然在程序编制时精心安排了各中断的优先等级,某些外设中断还会提前或延时到CF卡的读写时间段内。因在sdio_sdcard.c函数中,多次使用了INTX_DISABLE()与INTX_ENABLE()函数关闭和开启中断。由于这些函数没有阻止中断的发生,中断发生时同样会产生中断标志,只是暂时停止中断的执行。当开启所有中断时,就有可能出现多个中断标志,使中断发生冲突,这必定会引起死机。
解决办法是注销掉sdio_sdcard.c文件所有INTX_DISABLE()和INTX_ENABLE()函数,把cf卡的读写操作放入一个中断服务函数中,并把该中断设为最高等级,退出中断服务函数前,先清除所有中断标志。经此处理后再也没出现过死机。

评分

参与人数 2黑币 +56 收起 理由
6789364 + 6 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
ID:939553 发表于 2021-9-15 18:53 | 只看该作者
分析透彻,学习了
回复

使用道具 举报

板凳
ID:298123 发表于 2021-10-8 16:54 | 只看该作者
这种处理方式,好像是不对的吧!即使不死机,那也是有问题的
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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