扇区号大于FLASH_SECTOR_11时进行加4操作

以下是STM32F4系列HAL库里的flash擦除函数。该函数下有一条语句是如果扇区号大于11,需要加4偏移值。
在这里插入图片描述从字面上理解,意思是如果我要擦除23扇区,则需要加4,就变成了擦除27扇区。其实这样理解是不对的。先看一下STM32F429的2Mbytes的flash空间,它被分成bank1和bank2,各1Mbytes。

/* Base address of the Flash sectors */
 /* STM32F429各个扇区的基地址 */
 #define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000)//16 Kbyte
 #define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000)//16 Kbyte
 #define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000)//16 Kbyte
 #define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000)//16 Kbyte
 #define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000)//64 Kbytes
 #define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000)//128 Kbytes
 #define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000)
 #define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000)
 #define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000)
 #define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000)
 #define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000)
 #define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000)//128 Kbytes
 
 #define ADDR_FLASH_SECTOR_12 ((uint32_t)0x08100000)//16 Kbyte
 #define ADDR_FLASH_SECTOR_13 ((uint32_t)0x08104000)//16 Kbyte
 #define ADDR_FLASH_SECTOR_14 ((uint32_t)0x08108000)//16 Kbyte
 #define ADDR_FLASH_SECTOR_15 ((uint32_t)0x0810C000) //16 Kbyte
 #define ADDR_FLASH_SECTOR_16 ((uint32_t)0x08110000)//64 Kbytes
 #define ADDR_FLASH_SECTOR_17 ((uint32_t)0x08120000)
 #define ADDR_FLASH_SECTOR_18 ((uint32_t)0x08140000)
 #define ADDR_FLASH_SECTOR_19 ((uint32_t)0x08160000)
 #define ADDR_FLASH_SECTOR_20 ((uint32_t)0x08180000)
 #define ADDR_FLASH_SECTOR_21 ((uint32_t)0x081A0000)
 #define ADDR_FLASH_SECTOR_22 ((uint32_t)0x081C0000)
 #define ADDR_FLASH_SECTOR_23 ((uint32_t)0x081E0000) //128 Kbytes

每一个地址对应的扇区可以通过函数STMFLASH_GetFlashSector(addr)获得。

//获取某个地址所在的flash扇区
//addr:flash地址
//返回值:0~23,即addr所在的扇区
uint8_t STMFLASH_GetFlashSector(uint32_t addr)
{
	if(addr<ADDR_FLASH_SECTOR_1)return FLASH_SECTOR_0;
	else if(addr<ADDR_FLASH_SECTOR_2)return FLASH_SECTOR_1;
	else if(addr<ADDR_FLASH_SECTOR_3)return FLASH_SECTOR_2;
	else if(addr<ADDR_FLASH_SECTOR_4)return FLASH_SECTOR_3;
	else if(addr<ADDR_FLASH_SECTOR_5)return FLASH_SECTOR_4;
	else if(addr<ADDR_FLASH_SECTOR_6)return FLASH_SECTOR_5;
	else if(addr<ADDR_FLASH_SECTOR_7)return FLASH_SECTOR_6;
	else if(addr<ADDR_FLASH_SECTOR_8)return FLASH_SECTOR_7;
	else if(addr<ADDR_FLASH_SECTOR_9)return FLASH_SECTOR_8;
	else if(addr<ADDR_FLASH_SECTOR_10)return FLASH_SECTOR_9;
	else if(addr<ADDR_FLASH_SECTOR_11)return FLASH_SECTOR_10;
	else if(addr<ADDR_FLASH_SECTOR_12)return FLASH_SECTOR_11;
	else if(addr<ADDR_FLASH_SECTOR_13)return FLASH_SECTOR_12;
	else if(addr<ADDR_FLASH_SECTOR_14)return FLASH_SECTOR_13;
	else if(addr<ADDR_FLASH_SECTOR_15)return FLASH_SECTOR_14;
	else if(addr<ADDR_FLASH_SECTOR_16)return FLASH_SECTOR_15;
	else if(addr<ADDR_FLASH_SECTOR_17)return FLASH_SECTOR_16;
	else if(addr<ADDR_FLASH_SECTOR_18)return FLASH_SECTOR_17;
	else if(addr<ADDR_FLASH_SECTOR_19)return FLASH_SECTOR_18;
	else if(addr<ADDR_FLASH_SECTOR_20)return FLASH_SECTOR_19;
	else if(addr<ADDR_FLASH_SECTOR_21)return FLASH_SECTOR_20;
	else if(addr<ADDR_FLASH_SECTOR_22)return FLASH_SECTOR_21;  	
	else if(addr<ADDR_FLASH_SECTOR_23)return FLASH_SECTOR_22; 	
	return FLASH_SECTOR_23;	
}

再看看手册上对FLASH_CR寄存器的说明,确实12-15被not allowed了。从12扇区开始,都需要跳过4个扇区号,也就有了前面库函数里的扇区+4操作。
在这里插入图片描述

在这里插入图片描述那为什么要对扇区进行+4操作?猜测原因在于要兼顾到其他产品使用的双BANK应用模式。
如果此处不进行+4操作,则会出现擦除的扇区和写入读出的扇区不一致,导致读出数据不是写入的数据。下面是库函数原型。

/**
  * @brief  Erase the specified FLASH memory sector
  * @param  Sector FLASH sector to erase
  *         The value of this parameter depend on device used within the same series      
  * @param  VoltageRange The device voltage range which defines the erase parallelism.  
  *          This parameter can be one of the following values:
  *            @arg FLASH_VOLTAGE_RANGE_1: when the device voltage range is 1.8V to 2.1V, 
  *                                  the operation will be done by byte (8-bit) 
  *            @arg FLASH_VOLTAGE_RANGE_2: when the device voltage range is 2.1V to 2.7V,
  *                                  the operation will be done by half word (16-bit)
  *            @arg FLASH_VOLTAGE_RANGE_3: when the device voltage range is 2.7V to 3.6V,
  *                                  the operation will be done by word (32-bit)
  *            @arg FLASH_VOLTAGE_RANGE_4: when the device voltage range is 2.7V to 3.6V + External Vpp, 
  *                                  the operation will be done by double word (64-bit)
  * 
  * @retval None
  */
void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)
{
  uint32_t tmp_psize = 0U;

  /* Check the parameters */
  assert_param(IS_FLASH_SECTOR(Sector));
  assert_param(IS_VOLTAGERANGE(VoltageRange));
  
  if(VoltageRange == FLASH_VOLTAGE_RANGE_1)
  {
     tmp_psize = FLASH_PSIZE_BYTE;
  }
  else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)
  {
    tmp_psize = FLASH_PSIZE_HALF_WORD;
  }
  else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)
  {
    tmp_psize = FLASH_PSIZE_WORD;
  }
  else
  {
    tmp_psize = FLASH_PSIZE_DOUBLE_WORD;
  }

  /* Need to add offset of 4 when sector higher than FLASH_SECTOR_11 */
  if(Sector > FLASH_SECTOR_11) 
  {
    Sector += 4U;
  }
  /* If the previous operation is completed, proceed to erase the sector */
  CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
  FLASH->CR |= tmp_psize;
  CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);
  FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos);
  FLASH->CR |= FLASH_CR_STRT;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ydgd118

您的鼓励是我最大的动力!谢赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值