高级会员
- 积分
- 542
- 金钱
- 542
- 注册时间
- 2017-10-17
- 在线时间
- 118 小时
|
楼主 |
发表于 2023-7-14 17:08:05
|
显示全部楼层
由于stm32l152系列的单片机是在擦除的时候是整页擦除的,而写的时候是半页半页写的
所以需要改动的代码有:
步骤1:
uint32_t iapbuf[256];
//appxaddr:应用程序的起始地址
//appbuf:应用程序CODE.
//appsize:应用程序大小(字节).
void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)
{
uint16_t t;
uint16_t i=0;
uint32_t temp;
u32 fwaddr=appxaddr;//当前写入的地址
u8 *dfu=appbuf;
for(t=0;t<appsize;t+=4)
{
temp=(uint32_t)dfu[3]<<24;
temp|=(uint32_t)dfu[2]<<16;
temp|=(uint32_t)dfu[1]<<8;
temp|=(uint32_t)dfu[0];
dfu+=4;//偏移4个字节
iapbuf[i++]=temp;
if(i == 32 )
{
i=0;
STMFLASH_Write(fwaddr,iapbuf,32);
fwaddr+=128;//偏移2048 16=2*8.所以要乘以2.
}
}
if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去.
// FLASH_WritePage(pack_num,appbuf);
// pack_num++;
}
步骤2:
#include "stmflash.h"
#include "delay.h"
#include "usb_data_process.h"
#include "stm32l1xx_flash.h"
//读取指定地址的半字(16位数据)
//faddr:读地址(此地址必须为2的倍数!!)
//返回值:对应数据.
u32 STMFLASH_ReadHalfWord(u32 faddr)
{
return *(vu32*)faddr;
}
#if STM32_FLASH_WREN //如果使能了写
//不检查的写入
//WriteAddr:起始地址
//pBuffer:数据指针
//NumToWrite:半字(16位)数
__IO FLASH_Status FLASHStatus = FLASH_COMPLETE;
void STMFLASH_Write_NoCheck(u32 WriteAddr, uint32_t* pBuffer, u16 NumToWrite)
{
u16 i;
for(i = 0; i < NumToWrite; i++)
{
FLASH_FastProgramWord(WriteAddr, pBuffer[i]);
WriteAddr += 4; //地址增加2.
}
}
//从指定地址开始写入指定长度的数据
//WriteAddr:起始地址(此地址必须为2的倍数!!)
//pBuffer:数据指针
//NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)
#if STM32_FLASH_SIZE<256
#define STM_SECTOR_SIZE 128 //字节
#else
#define STM_SECTOR_SIZE 2048
#endif
uint32_t STMFLASH_BUF[STM_SECTOR_SIZE / 4]; //最多是2K字节
u32 data_addr = 0;
char CLEAN_STM_SECTOR_SIZE = (256 / STM_SECTOR_SIZE);
void STMFLASH_Write(u32 WriteAddr, uint32_t* pBuffer, u16 NumToWrite)
{
u32 secpos; //扇区地址
u32 secoff; //扇区内偏移地址(16位字计算)
u32 secremain; //扇区内剩余地址(16位字计算)
u32 i;
u32 offaddr; //去掉0X08000000后的地址
if(WriteAddr < STM32_FLASH_BASE || WriteAddr % 4)return; //非法地址
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR\
| FLASH_FLAG_SIZERR | FLASH_FLAG_OPTVERR | FLASH_FLAG_OPTVERRUSR | FLASH_FLAG_RDERR);
// FLASH_ErasePage(WriteAddr);
offaddr = WriteAddr - STM32_FLASH_BASE; //实际偏移地址.
secpos = offaddr / STM_SECTOR_SIZE; //扇区地址 0~127 for STM32F103RBT6
secoff = (offaddr % STM_SECTOR_SIZE) / 4; //在扇区内的偏移(2个字节为基本单位.)
secremain = STM_SECTOR_SIZE / 4 - secoff; //扇区剩余空间大小
if(NumToWrite <= secremain)secremain = NumToWrite; //不大于该扇区范围
FLASH_Unlock(); //解锁
while(1)
{
STMFLASH_Read(secpos * STM_SECTOR_SIZE + STM32_FLASH_BASE, (uint32_t*)STMFLASH_BUF, STM_SECTOR_SIZE / 4); //读出整个扇区的内容
for(i = 0; i < secremain * 4; i++) //校验数据
{
if(STMFLASH_BUF[(secoff * 4) + i] != 0XFFFFFFFF)break; //需要擦除
}
// if(CLEAN_STM_SECTOR_SIZE == 0 )//需要擦除
if(offaddr % 256 == 0) //需要擦除
{
FLASH_ErasePage(secpos * (STM_SECTOR_SIZE) + STM32_FLASH_BASE); //擦除这个扇区
for(u16 i = 0; i < (secremain); i++)
{
(STMFLASH_BUF)[i + (secoff * 4)] = (pBuffer)[i];
}
STMFLASH_Write_NoCheck(secpos * STM_SECTOR_SIZE + STM32_FLASH_BASE, STMFLASH_BUF, STM_SECTOR_SIZE / 4);
data_addr = secpos * STM_SECTOR_SIZE + STM32_FLASH_BASE;
CLEAN_STM_SECTOR_SIZE = 256 / STM_SECTOR_SIZE;
}
else
{
STMFLASH_Write_NoCheck(WriteAddr, pBuffer, secremain); //写已经擦除了的,直接写入扇区剩余区间.
}
if(NumToWrite == secremain)break; //写入结束了
else//写入未结束
{
secpos++; //扇区地址增1
secoff = 0; //偏移位置为0
pBuffer += secremain; //指针偏移
WriteAddr += (secremain * 4); //写地址偏移
NumToWrite -= secremain; //字节(16位)数递减
if(NumToWrite > (STM_SECTOR_SIZE / 4))secremain = STM_SECTOR_SIZE / 4; //下一个扇区还是写不完
else secremain = NumToWrite; //下一个扇区可以写完了
}
}
CLEAN_STM_SECTOR_SIZE -= 1;
FLASH_Lock();//上锁
}
#endif
//从指定地址开始读出指定长度的数据
//ReadAddr:起始地址
//pBuffer:数据指针
//NumToWrite:半字(16位)数
void STMFLASH_Read(u32 ReadAddr, u32* pBuffer, u16 NumToRead)
{
u16 i;
for(i = 0; i < NumToRead; i++)
{
pBuffer[i] = STMFLASH_ReadHalfWord(ReadAddr); //读取2个字节.
ReadAddr += 4; //偏移2个字节.
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//WriteAddr:起始地址
//WriteData:要写入的数据
void Test_Write(u32 WriteAddr, uint32_t WriteData)
{
STMFLASH_Write(WriteAddr, &WriteData, 1); //写入一个字
}
|
|