记录一个STM32H7的FLASH调试

首先我们都知道我们的代码是保存在FLASH里的,FLASH的数据掉电不会消失,所以我们也可以将FLASH当作eeprom来用,这里以H743为例,743有两个1M的bank,每个bank有8个128k的扇区,我们需要注意的是每个扇区写之前都是要先擦除的,这也是为什么750不能用FLASH当做eeprom来用,一般750会额外外挂一个外扩的FLASH芯片,比如w25q之类的,因为750只有一块扇区,首先我们看一下743的扇区:

/* FLASH 扇区的起始地址,分2个bank,每个bank 1MB */
/* BANK1 */
#define BANK1_FLASH_SECTOR_0    ((uint32_t)0x08000000)      /* Bank1扇区0起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_1    ((uint32_t)0x08020000)      /* Bank1扇区1起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_2    ((uint32_t)0x08040000)      /* Bank1扇区2起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_3    ((uint32_t)0x08060000)      /* Bank1扇区3起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_4    ((uint32_t)0x08080000)      /* Bank1扇区4起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_5    ((uint32_t)0x080A0000)      /* Bank1扇区5起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_6    ((uint32_t)0x080C0000)      /* Bank1扇区6起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_7    ((uint32_t)0x080E0000)      /* Bank1扇区7起始地址, 128 Kbytes */

/* BNAK2 */
#define BANK2_FLASH_SECTOR_0    ((uint32_t)0x08100000)      /* Bank2扇区0起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_1    ((uint32_t)0x08120000)      /* Bank2扇区1起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_2    ((uint32_t)0x08140000)      /* Bank2扇区2起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_3    ((uint32_t)0x08160000)      /* Bank2扇区3起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_4    ((uint32_t)0x08180000)      /* Bank2扇区4起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_5    ((uint32_t)0x081A0000)      /* Bank2扇区5起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_6    ((uint32_t)0x081C0000)      /* Bank2扇区6起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_7    ((uint32_t)0x081E0000)      /* Bank2扇区7起始地址, 128 Kbytes */

另外还需要注意一点就是对FLASH的操作地址必须是4字节对齐的,也就是说必须是4的倍数,不然会出问题:

//从指定地址读取一个字
uint32_t flash_read_word(uint32_t pAddr)
{
    return *(uint32_t *)pAddr;
}

//从指定地址读出指定长度的数据
void flash_read(uint32_t pAddr, uint32_t *pBuf, uint32_t pLength)
{
    for (int i = 0; i < pLength; i++)
    {
        pBuf[i] = flash_read_word(pAddr);
        pAddr += 4;
    }
}
//获取某个地址所在的扇区
uint8_t flash_get_flash_sector(uint32_t pAddr)
{
    if (pAddr < BANK1_FLASH_SECTOR_1)return 0;
    else if (pAddr < BANK1_FLASH_SECTOR_2)return 1;
    else if (pAddr < BANK1_FLASH_SECTOR_3)return 2;
    else if (pAddr < BANK1_FLASH_SECTOR_4)return 3;
    else if (pAddr < BANK1_FLASH_SECTOR_5)return 4;
    else if (pAddr < BANK1_FLASH_SECTOR_6)return 5;
    else if (pAddr < BANK1_FLASH_SECTOR_7)return 6;
    else if (pAddr < BANK2_FLASH_SECTOR_0)return 7;
    else if (pAddr < BANK2_FLASH_SECTOR_1)return 8;
    else if (pAddr < BANK2_FLASH_SECTOR_2)return 9;
    else if (pAddr < BANK2_FLASH_SECTOR_3)return 10;
    else if (pAddr < BANK2_FLASH_SECTOR_4)return 11;
    else if (pAddr < BANK2_FLASH_SECTOR_5)return 12;
    else if (pAddr < BANK2_FLASH_SECTOR_6)return 13;
    else if (pAddr < BANK2_FLASH_SECTOR_7)return 14;
    return 15;
}
//从指定地址写入指定长度数据
void flash_write(uint32_t pAddr, uint32_t *pbuf, uint32_t length)
{
    FLASH_EraseInitTypeDef FlashEraseInit;
    HAL_StatusTypeDef FlashStatus = HAL_OK;
    uint32_t SectorError = 0;
    uint32_t  addrx = 0;
    uint32_t  endaddr = 0;

    if (pAddr < 0x08000000 || pAddr % 32 || pAddr > (0x081FFFFF))
    {
        return;
    }

    HAL_FLASH_Unlock();                         
    addrx = pAddr;                          
    endaddr = pAddr + length * 4;     

    if (addrx < 0x081FFFFF)
    {
        while (addrx < endaddr)
        {
            if (flash_read_word(addrx) != 0XFFFFFFFF)
            {
                if (addrx < 0x08100000) {
                    FlashEraseInit.Banks = FLASH_BANK_1;
                    FlashEraseInit.Sector = flash_get_flash_sector(addrx);
                }
                else {
                    FlashEraseInit.Banks = FLASH_BANK_2;
                    FlashEraseInit.Sector = (flash_get_flash_sector(addrx) - 8);
                }
                FlashEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
                FlashEraseInit.NbSectors = 1;
                FlashEraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3;            /* 电压范围,VCC=2.7~3.6V之间!! */
							 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1);
								// __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGSERR | FLASH_FLAG_WRPERR);
                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 (pAddr < endaddr)                 /* 写数据 */
        {
            if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, pAddr, (uint64_t)pbuf) != HAL_OK)    /* 写入数据 */
            {
                break;                          /* 写入异常 */
            }
            pAddr += 32;
            pbuf += 8;
        }
    }
    HAL_FLASH_Lock();                           /* 上锁 */
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值