STM32F407.FLASH 读写经验

现象:
如下代码:
//从指定地址开始写入指定长度的数据

//该函数对OTP区域也有效!可以用来写OTP区!
//OTP区域地址范围:0X1FFF7800~0X1FFF7A0F
//WriteAddr:起始地址(此地址必须为4的倍数!!)
//pBuffer:数据指针
//NumToWrite:字(32位)数(就是要写入的32位数据的个数.) 
void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)        
{ 
        u8 status=0;
        u32 addrx=0;
        u32 endaddr=0;        
          if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return;        //非法地址
        STMFLASH_Unlock();                                                                        //解锁  
        addrx=WriteAddr;                                //写入的起始地址
        endaddr=WriteAddr+NumToWrite*4;        //写入的结束地址
        if(addrx<0X1FFF0000)                        //只有主存储区,才需要执行擦除操作!!
        {
                while(addrx<endaddr)                //扫清一切障碍.(对非FFFFFFFF的地方,先擦除)
                {
                        if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区
                        {   
                                printf("S");

                                status=STMFLASH_EraseSector(STMFLASH_GetFlashSector(addrx));
                                if(status)break;        //发生错误了
                        }else addrx+=4;
                } 
        }
        if(status==0)
        {
                while(WriteAddr<endaddr)//写数据
                {
                        if(STMFLASH_WriteWord(WriteAddr,*pBuffer))//写入数据
                        { 
                                break;        //写入异常
                        }
                        WriteAddr+=4;
                        pBuffer++;
                } 
        } 
        STMFLASH_Lock();//上锁

红色的printf,加上,程序运行正常.
红色的printf去掉,程序随即进入死循环,死在等待FLASH空闲里面,一旦JTAG仿真,并设置断点在这里,则可以不要printf,也可以正常运行.
非常诡异.

试过的方法:
1,找官方代码替换掉我的代码,结果,失败.
2,把printf,换成延时,失败.
3,把代码结构改了,失败.
4,把printf,换成直接写DR的方式发送,失败.
5,清FLASH->SR标记位,失败.
6,将系统的delay_us,换成i--之类的延时,失败.
7,加多等待FLASH操作结束,失败.
...

总之,2个晚上,就在不停的尝试各种可能的解决方案.不停的刷代码,估计这板子上的F4,都快要被我刷爆了...


最后,眼看着今晚又要3点了,万念俱灰之际,找来stm32f4的编程手册(其实一直在看,寄存器看了N遍了...),发现

这感情十分吻合啊,bus stall...
shit,才想起来,在系统时钟初始化的时候,默认是设置了DATA FETCHES的,仿真看下FLASH->ACR的DCEN位,果然是1.

立即修改代码如下:
//从指定地址开始写入指定长度的数据
//该函数对OTP区域也有效!可以用来写OTP区!
//OTP区域地址范围:0X1FFF7800~0X1FFF7A0F
//WriteAddr:起始地址(此地址必须为4的倍数!!)
//pBuffer:数据指针
//NumToWrite:字(32位)数(就是要写入的32位数据的个数.) 
void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)        
{ 
        u8 status=0;
        u32 addrx=0;
        u32 endaddr=0;        
          if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return;        //非法地址
        STMFLASH_Unlock();                                                                        //解锁 
        FLASH->ACR&=~(1<<10);                        //FLASH擦除期间,必须禁止数据fetch!!!搞了我两晚上才发现这个问题!
        addrx=WriteAddr;                                //写入的起始地址
        endaddr=WriteAddr+NumToWrite*4;        //写入的结束地址
        if(addrx<0X1FFF0000)                        //只有主存储区,才需要执行擦除操作!!
        {
                while(addrx<endaddr)                //扫清一切障碍.(对非FFFFFFFF的地方,先擦除)
                {
                        if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区
                        {   
                                status=STMFLASH_EraseSector(STMFLASH_GetFlashSector(addrx));
                                if(status)break;        //发生错误了
                        }else addrx+=4;
                } 
        }
        if(status==0)
        {
                while(WriteAddr<endaddr)//写数据
                {
                        if(STMFLASH_WriteWord(WriteAddr,*pBuffer))//写入数据
                        { 
                                break;        //写入异常
                        }
                        WriteAddr+=4;
                        pBuffer++;
                } 
        }
        FLASH->ACR|=1<<10;                //FLASH擦除结束,开启数据fetch
        STMFLASH_Lock();//上锁


下载,测试....

奇迹出现了...运行正常了.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值