#1.前言
什么是IAP:就是能通过我们写入的程序向FLASH里烧录数据,达到断电记录参数的功能。
列如我所使用的这款芯片SC32M15X ,是M0的内核。支持IAP操作,有个IAP操作寄存器,来控制对FLASH的写入。
我放以下截图,供大家参考
解锁寄存器
#2.如何操作IAP
我们先需要解锁IAP,然后确定想写入的FLASH地址,在地址空间表上有直接的说明,我这选用的是0xE800000地址空间。
写入FLASH其实也就是直接在相应的存空间赋值,比如说要写入一个0x1234的数,两个字节。我们可以*((short*)(0xE800000))=0x1234。这样就将这个地址空间写入数据了,由于这个空间对应的是FLASH,所以我们也就将值写入了FLASH。下次读取的时候去读取该地址就行:咱们先定义一个变量short a;然后用这个变量去读取之前写入0x1234的地址,a=*((short*)(0xE800000))。这时候你去读取a的值也就是0x1234。这样也就是做到了可以在程序中断电保存参数。
注意,在FLASH空间里都是按页存放的(512字节)。而且存放数据前要擦除整页数据,擦除数据我这款MCU是往对应的寄存器的BIT位上置1。稍后给大家看看后续代码
#3.代码实例
大家可以看这个示范代码
void IAP_Program_Function(void)
{
uint32_t ReadWord = 0;
uint16_t ReadHalfWord = 0;
uint8_t ReadByte = 0;
uint32_t Array_WriteWord[3]={0x11223344,0x22334455,0x33445566}, Array_ReadWord[3];
uint16_t Array_WriteHalfWord[5]={0x1111,0x2222,0x3333,0x4444,0x5555}, Array_ReadHalfWord[5];
uint8_t Array_WriteByte[5]={0x99,0x88,0x77,0x66,0x55}, Array_ReadByte[5];
uint8_t Flag_ReadWord = 0, Flag_ReadHalfWord = 0, Flag_ReadByte = 0, i;
IAP_Unlock(); //解锁IAP操作
IAP_EraseSector((FLASH_USER_ADDR - FLASH_BASE) / 512); //擦除地址所在扇区,每个扇区大小为512Byte
IAP_WriteCmd(ENABLE); //开启写使能
/* 单个数据依次写入(注意地址对齐) */
IAP_ProgramWord(FLASH_USER_ADDR,0x12345678); //字写入,目标地址FLASH_USER_ADDR
IAP_ProgramHalfWord(FLASH_USER_ADDR+4,0x6666); //半字写入,目标地址(FLASH_USER_ADDR+4)
IAP_ProgramByte(FLASH_USER_ADDR+6,0x99); //字节写入,目标地址((FLASH_USER_ADDR+4)+2)
/* 批量数据写入 */
//写入地址请勿重合!写入数据请勿超出扇区范围!
IAP_ProgramWordArray(FLASH_USER_ADDR+20,Array_WriteWord,3);//批量字写入
IAP_ProgramHalfWordArray(FLASH_USER_ADDR+40,Array_WriteHalfWord,5);//批量半字写入
IAP_ProgramByteArray(FLASH_USER_ADDR+60,Array_WriteByte,5);//批量字节写入
IAP_Lock(); //上锁IAP操作,并且复位IAP操作寄存器
/* 单个数据依次读取 */
ReadWord = IAP_ReadWord(FLASH_USER_ADDR); //字读,目标地址(0x803FE00)
ReadHalfWord = IAP_ReadHalfWord(FLASH_USER_ADDR+4); //半字读,目标地址(0x803FE00+4=0x803FE04)
ReadByte = IAP_ReadByte(FLASH_USER_ADDR+6); //字节读,目标地址(0x803FE04+2=0x803FE06)
/* 批量数据读取 */
Flag_ReadWord = IAP_ReadWordArray(FLASH_USER_ADDR+20,Array_ReadWord,3);//批量字读,返回值为读取成功数据大小
Flag_ReadHalfWord = IAP_ReadHalfWordArray(FLASH_USER_ADDR+40,Array_ReadHalfWord,5);//批量半字读,返回值为读取成功数据大小
Flag_ReadByte = IAP_ReadByteArray(FLASH_USER_ADDR+60,Array_ReadByte,5);//批量字节读,返回值为读取成功数据大小
if(ReadWord == 0x12345678 && ReadHalfWord == 0x6666 && ReadByte == 0x99)//单个数据读写判断
{
if(Flag_ReadWord == 3 && Flag_ReadHalfWord == 5 && Flag_ReadByte == 5)//批量写入成功个数判断
{
IAP_Flag = 1;
}
}
一开始先解锁IAP寄存器,按照不同芯片的说明书去解锁,然后写入单个字节和多个字节,我给大家贴一下源码。
单字节写入
boolType IAP_ProgramWord(uint32_t Address, uint32_t Data)
{
assert_param(IS_IAP_ADDRESS(Address));
*(__IO uint32_t*)Address = Data;
if(Data == *(__IO uint32_t*)Address)
return TRUE;
else
return FALSE;
}
多字节写入
uint8_t IAP_ProgramWordArray(uint32_t Address, uint32_t* ByteArray, uint8_t ArraySize)
{
assert_param(IS_IAP_ADDRESS(Address));
uint8_t tmpCnt = 0;
if((Address&0x03)==0)
{
do
{
*(__IO uint32_t*)Address = ByteArray[tmpCnt];
if(ByteArray[tmpCnt] != *(__IO uint32_t*)Address)
break;
Address = Address + 4;
}while(++tmpCnt < ArraySize);
}
return tmpCnt;
}
大家看完之后应该也能触类旁通,就是用不同类型指针去访问该地址,如果要写入一个数组也就是需要加个for循环去多次写入.
#4.总结
IAP就是让FLASH在内存地址的映射能够直接写访问。让我们的程序也能对FLASH进行烧录,存放需要被记忆的参数。
因此我认为我们还可以围绕这个功能做更多的应用,比如让程序烧录更新程序,实现程序更新,而不需要使用烧录器进行更新。将这个FLASH空间进行划分,一部分是程序入口地址那部分放入主程序,然后划分一部分空间来接收更新程序。然后更新完后让cpu从更新程序那边开始进行,如此实现程序更新迭代。
目前我这个程序内部更新还是一个想法,还没有实现。希望各位前辈同仁能不吝赐教。在此拜谢
标签:主程序,ADDR,FLASH,写入,USER,Array,IAP From: https://blog.csdn.net/xc_mt/article/details/142455042