硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1043|回复: 5
收起左侧

[Flash] H7内部flash操作容易出现死机的情况???

[复制链接]

4

主题

17

回帖

29

积分

新手上路

积分
29
发表于 2023-3-23 13:54:00 | 显示全部楼层 |阅读模式

H7B0内部flash操作会出现死机的情况????????


//读取指定地址的字(32位数据)
//faddr:读地址
//返回值:对应数据.
uint32_t STMFLASH_ReadWord(uint32_t faddr)
{
        return *(__IO uint32_t *)faddr;
}

//获取某个地址所在的flash扇区,仅用于BANK1!!
//addr:flash地址
//返回值:0~11,即addr所在的扇区
uint16_t STMFLASH_GetFlashSector(uint32_t addr)
{
        if(addr<ADDR_FLASH_SECTOR_1_BANK1)return FLASH_SECTOR_0;
        else if(addr<ADDR_FLASH_SECTOR_2_BANK1)return FLASH_SECTOR_1;
        else if(addr<ADDR_FLASH_SECTOR_3_BANK1)return FLASH_SECTOR_2;
        else if(addr<ADDR_FLASH_SECTOR_4_BANK1)return FLASH_SECTOR_3;
        else if(addr<ADDR_FLASH_SECTOR_5_BANK1)return FLASH_SECTOR_4;
        else if(addr<ADDR_FLASH_SECTOR_6_BANK1)return FLASH_SECTOR_5;
        else if(addr<ADDR_FLASH_SECTOR_7_BANK1)return FLASH_SECTOR_6;
        else if(addr<ADDR_FLASH_SECTOR_8_BANK1)return FLASH_SECTOR_7;
        else if(addr<ADDR_FLASH_SECTOR_9_BANK1)return FLASH_SECTOR_8;
        else if(addr<ADDR_FLASH_SECTOR_10_BANK1)return FLASH_SECTOR_9;
        else if(addr<ADDR_FLASH_SECTOR_11_BANK1)return FLASH_SECTOR_10;
        else if(addr<ADDR_FLASH_SECTOR_12_BANK1)return FLASH_SECTOR_11;
        else if(addr<ADDR_FLASH_SECTOR_13_BANK1)return FLASH_SECTOR_12;
        else if(addr<ADDR_FLASH_SECTOR_14_BANK1)return FLASH_SECTOR_13;
        else if(addr<ADDR_FLASH_SECTOR_15_BANK1)return FLASH_SECTOR_14;
       
        return FLASH_SECTOR_15;       
}



/** ****************************************************************************
* @remarks      
* @brief         
* @param[in]     
* @param[out]   
* @return        
* @attention
//从指定地址开始写入指定长度的数据
//特别注意:因为STM32H7的扇区实在太大,没办法本地保存扇区数据,所以本函数
//         写地址如果非0XFF,那么会先擦除整个扇区且不保存扇区数据.所以
//         写非0XFF的地址,将导致整个扇区数据丢失.建议写之前确保扇区里
//         没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写.
//该函数对OTP区域也有效!可以用来写OTP区!
//OTP区域地址范围:0X1FF0F000~0X1FF0F41F
//WriteAddr:起始地址(此地址必须为4的倍数!!)FLASH_TYPEPROGRAM_FLASHWORD
//pBuffer:数据指针
//NumToWrite:字(32位)数(就是要写入的32位数据的个数.)     
*******************************************************************************/
uint32_t write_fmc_flash(uint32_t WriteAddr,uint32_t *pBuffer,uint32_t NumToWrite)
{
        FLASH_EraseInitTypeDef FlashEraseInit;
        HAL_StatusTypeDef FlashStatus=HAL_OK;
        uint32_t SectorError=0;
        uint32_t addrx=0;
        uint32_t endaddr=0;       
        if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return 1;        //非法地址

        HAL_FLASH_Unlock();             //解锁       
        addrx=WriteAddr;                                //写入的起始地址
        endaddr=WriteAddr+NumToWrite*4;        //写入的结束地址

        if(addrx<0X1FF00000)
        {
                while(addrx<endaddr)                //扫清一切障碍.(对非FFFFFFFF的地方,先擦除)
                {
                        if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区
                        {   
                                FlashEraseInit.TypeErase=FLASH_TYPEERASE_SECTORS;       //擦除类型,扇区擦除
                                FlashEraseInit.Sector=STMFLASH_GetFlashSector(addrx);   //要擦除的扇区
                                FlashEraseInit.Banks=FLASH_BANK_1;                                                //操作BANK1
                                FlashEraseInit.NbSectors=1;                             //一次只擦除一个扇区
                                //FlashEraseInit.VoltageRange=VOLTAGE_RANGE_3;      //电压范围,VCC=2.7~3.6V之间!!
                                if(HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError)!=HAL_OK)
                                {
                                        break;//发生错误了       
                                }
                                SCB_CleanInvalidateDCache();                            //清除无效的D-Cache
                        }else addrx+=4;
                        FLASH_WaitForLastOperation(FLASH_WAITETIME,FLASH_BANK_1);    //等待上次操作完成
                }
        }
        FlashStatus=FLASH_WaitForLastOperation(FLASH_WAITETIME,FLASH_BANK_1);       //等待上次操作完成
        if(FlashStatus==HAL_OK)
        {
                while(WriteAddr<endaddr)//写数据
                {
                        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD,WriteAddr,(uint32_t)pBuffer)!=HAL_OK)//写入数据
                        {
                                break;        //写入异常
                        }
                        WriteAddr+=16; //
                        pBuffer+=4;   //
                }
        }
        HAL_FLASH_Lock();           //上锁

        return 0;
}

/** ****************************************************************************
* @remarks      
* @brief         
* @param[in]     
* @param[out]   
* @return        
* @attention   
*******************************************************************************/
uint32_t read_fmc_flash(uint32_t ReadAddr,uint32_t *pBuffer,uint32_t NumToRead)
{
        uint32_t i;
        for(i=0;i<NumToRead;i++)
        {
                pBuffer=STMFLASH_ReadWord(ReadAddr);//读取4个字节.
                ReadAddr+=4;//偏移4个字节.       
        }
        return 0;
}


#define ADDR_FLASH_SECTOR_0_BANK1     ((uint32_t)0x08000000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_1_BANK1     ((uint32_t)0x08002000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_2_BANK1     ((uint32_t)0x08004000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_3_BANK1     ((uint32_t)0x08006000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_4_BANK1     ((uint32_t)0x08008000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_5_BANK1     ((uint32_t)0x0800A000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_6_BANK1     ((uint32_t)0x0800C000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_7_BANK1     ((uint32_t)0x0800E000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_8_BANK1     ((uint32_t)0x08010000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_9_BANK1     ((uint32_t)0x08012000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_10_BANK1     ((uint32_t)0x08014000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_11_BANK1     ((uint32_t)0x08016000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_12_BANK1     ((uint32_t)0x08018000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_13_BANK1     ((uint32_t)0x0801A000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_14_BANK1     ((uint32_t)0x0801C000) //扇区0起始地址, 8 Kbytes  
#define ADDR_FLASH_SECTOR_15_BANK1     ((uint32_t)0x0801E000) //扇区0起始地址, 8 Kbytes


回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
发表于 2023-3-24 10:15:08 | 显示全部楼层
直接调用最新版的HAL库Flash操作API即可,注意这个系列默认只有128KB的内部Flash。而且只有一个扇区。如果你的程序在内部Flash运行,别自己把自己擦除了。
回复

使用道具 举报

4

主题

17

回帖

29

积分

新手上路

积分
29
 楼主| 发表于 2023-3-24 14:25:45 | 显示全部楼层
eric2013 发表于 2023-3-24 10:15
直接调用最新版的HAL库Flash操作API即可,注意这个系列默认只有128KB的内部Flash。而且只有一个扇区。如果 ...

汉哥,这个128K,最小擦除块8K;偶尔出现写入失败情况,之后死机,断电重启都恢复不了;需要重新刷写才行;
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
发表于 2023-3-24 15:40:32 | 显示全部楼层
1021256354 发表于 2023-3-24 14:25
汉哥,这个128K,最小擦除块8K;偶尔出现写入失败情况,之后死机,断电重启都恢复不了;需要重新刷写才行 ...


想起来了,我曾经还改写过一次这个H7B的算法文件。


倒腾一晚上给H7-TOOL的脱机烧录制作了个好使的STM32H7Ax,STM32H7Bx下载算法文件,MDK自带的用在TOOL上不好用
https://www.armbbs.cn/forum.php? ... 0101&fromuid=58
(出处: 硬汉嵌入式论坛)



回复

使用道具 举报

1

主题

11

回帖

14

积分

新手上路

积分
14
发表于 2023-4-10 22:42:52 | 显示全部楼层
eric2013 发表于 2023-3-24 15:40
1021256354 发表于 2023-3-24 14:25
汉哥,这个128K,最小擦除块8K;偶尔出现写入失败情况,之后死机,断 ...

可能是出现了ECC错误 ,需要清楚掉,不然上电还是会出发错误
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
发表于 2023-4-11 09:09:21 | 显示全部楼层
antzhan 发表于 2023-4-10 22:42
可能是出现了ECC错误 ,需要清楚掉,不然上电还是会出发错误

对,有这种情况,开启ECC后,对应的Flash中断处理也要开了。
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-3 06:11 , Processed in 0.204393 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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