【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
对于f407这样的mcu来说,有的时候我们需要对mcu内部的flash进行编程处理。有两种情况需要对flash进行编程,一种情况是可能一部分参数需要放在了flash上面;还有一种情况,就是我们需要对mcu的固件进行升级,同时又不太希望暴露swd接口。这种状况下,一般就是先启动bootloader,然后利用bootloader对固件进行升级处理。
1、flash编程的注意事项
需要注意的地方,主要就是flash的起始地址和范围,其他的按部就班去做就好了。
2、测试代码
我们测试的时候,把flash当成是一般的nor flash就可以了。也就是说,如果需要对这部分flash进行编程的话,首先需要erase处理,然后进行编程,最后下读取相关区域的数据,确认下是否正确。
int InternalFlash_Test(void)
{
uint32_t uwStartSector = 0;
uint32_t uwEndSector = 0;
uint32_t uwAddress = 0;
uint32_t uwSectorCounter = 0;
__IO uint32_t uwData32 = 0;
__IO uint32_t uwMemoryProgramStatus = 0;
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
uwStartSector = GetSector(FLASH_USER_START_ADDR);
uwEndSector = GetSector(FLASH_USER_END_ADDR);
uwSectorCounter = uwStartSector;
while (uwSectorCounter <= uwEndSector)
{
if (FLASH_EraseSector(uwSectorCounter, VoltageRange_3) != FLASH_COMPLETE)
{
return -1;
}
if (uwSectorCounter == FLASH_Sector_11)
{
uwSectorCounter += 40;
}
else
{
uwSectorCounter += 8;
}
}
uwAddress = FLASH_USER_START_ADDR;
while (uwAddress < FLASH_USER_END_ADDR)
{
if (FLASH_ProgramWord(uwAddress, DATA_32) == FLASH_COMPLETE)
{
uwAddress = uwAddress + 4;
}
else
{
return -1;
}
}
FLASH_Lock();
uwAddress = FLASH_USER_START_ADDR;
uwMemoryProgramStatus = 0;
while (uwAddress < FLASH_USER_END_ADDR)
{
uwData32 = *(__IO uint32_t*)uwAddress;
if (uwData32 != DATA_32)
{
uwMemoryProgramStatus++;
}
uwAddress = uwAddress + 4;
}
if(uwMemoryProgramStatus)
{
return -1;
}
else
{
return 0;
}
}
这中间比较奇怪的地方,就是uwSectorCounter递增的方法,看上去很奇怪。也就是说sector的number不是按照1来递增处理的,而是其他方式。从代码上看,sector11和sector12之间的间距是40,在这之前、之后都是8。另外,大家还需要记住这几个函数,
FLASH_Unlock
FLASH_ClearFlag
FLASH_EraseSector
FLASH_ProgramWord
FLASH_Lock
读取数据的话,就直接地址访问即可,不需要函数的操作。
3、地址到sector的转化
我们编写代码的时候,还需要实现一个函数,那就是地址到sector number的转换。这边基本上直接用的映射的办法来完成的。
static uint32_t GetSector(uint32_t Address)
{
uint32_t sector = 0;
if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
{
sector = FLASH_Sector_0;
}
else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
{
sector = FLASH_Sector_1;
}
else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
{
sector = FLASH_Sector_2;
}
else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
{
sector = FLASH_Sector_3;
}
else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
{
sector = FLASH_Sector_4;
}
else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
{
sector = FLASH_Sector_5;
}
else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
{
sector = FLASH_Sector_6;
}
else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
{
sector = FLASH_Sector_7;
}
else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
{
sector = FLASH_Sector_8;
}
else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
{
sector = FLASH_Sector_9;
}
else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
{
sector = FLASH_Sector_10;
}
else /*if((Address < ADDR_FLASH_SECTOR_12) && (Address >= ADDR_FLASH_SECTOR_11))*/
{
sector = FLASH_Sector_11;
}
return sector;
}
从代码上也可以看出来,这里只是考虑了 sector11之前的情况。
4、测试和实验
测试相对而言,测试还是比较简单的。不管测试结果如何,直接通过串口打印出来就可以了。