源:STM32 对内部FLASH读写接口函数

因为要用内部FLASH代替外部EEPROM,把参数放在STM32的0x08000000+320K处,其中20K是bootloader,300K是应用程序。

原理:先要把整页FLASH的内容搬到RAM中,然后在RAM中改动,然后擦除整页FLASH,再把改动后的内容写入原Flash页。下面程序调试通过。

/*******************************************************************************
* Function Name : I2C_EE_BufferRead
* Description : Reads a block of data from the EEPROM.
* Input :
* -RomAddr
* -NumByteToRead
* -pRomData
* Output : None
* Return : None
*******************************************************************************/ void I2C_EE_BufferRead(u16 RomAddr,u16 NumByteToRead,u8 *pRomData)
{ u32 param_flashbase;
u8* ptr; param_flashbase = 0x8000000+(300+20)*1024;
ptr = (u8*)(param_flashbase + RomAddr); while( NumByteToRead-- >0)
{
*pRomData = *ptr; //直接赋值即可
printf("0x%x ",*pRomData);
pRomData++;
ptr++;
}
return;
} /*******************************************************************************
* Function Name : I2C_EE_BufferWrite * Description : Write a block of data to the EEPROM.
* Input :
* -RomAddr
* -NumByteToRead
* -pRomData
* Output : None
* Return : None
*******************************************************************************/ void I2C_EE_BufferWrite(u8 DeviceType,u8 SlaveAddr,u16 RomAddr,u16 NumByteToWrite,u8 *pRomData)
{ uint32_t param_flashbase;
uint32_t tempaddress;
uint32_t startaddress;
uint32_t FlashAddress;
uint32_t datasource;
u8 buf1[PAGE_SIZE];
u8 buf2[PAGE_SIZE];
u32 pagenumber = 0x0;
u32 EraseCounter = 0x0;
u32 i = 0;
FLASH_Status FLASHStatus = FLASH_COMPLETE; param_flashbase = 0x8000000+(300+20)*1024;
startaddress=tempaddress = param_flashbase+RomAddr; /*********************起始指针不在Flash页的开始端*********************/
if( (tempaddress%PAGE_SIZE) != 0)
{ printf("startptr not in Page head \r\n");
if( ((startaddress%PAGE_SIZE)+NumByteToWrite) > PAGE_SIZE ) /*超出一页范围
{
I2C_EE_BufferRead(0,0,(tempaddress-(tempaddress % PAGE_SIZE)),PAGE_SIZE,buf1); /*把起始地址所在页的内容读到内存buf1中
memcpy(buf1+(tempaddress % PAGE_SIZE),pRomData,PAGE_SIZE-(tempaddress % PAGE_SIZE)); /*把需要写入的数据覆盖到buf1中 while( FLASHStatus == FLASH_ErasePage(tempaddress) ) /*buf1写入到Flash
{
i=PAGE_SIZE/4;
datasource = (uint32_t)buf1; FlashAddress = tempaddress-(tempaddress % PAGE_SIZE);
while(i-- >0)
{
FLASH_ProgramWord(FlashAddress,*(uint32_t*)datasource);
if (*(uint32_t*)FlashAddress != *(uint32_t*)datasource)
{
printf("I2C_EE_BufferWrite error!\r\n");
return ;
}
datasource += 4;
FlashAddress += 4;
}
break;
} NumByteToWrite -= PAGE_SIZE-(startaddress % PAGE_SIZE); 需要写入字节数减去,上面覆盖上去的数据的字节数
tempaddress += PAGE_SIZE-(tempaddress % PAGE_SIZE); /*把ptr指针指向下一个页起始位置 if((NumByteToWrite % PAGE_SIZE) != 0) /*末指针不在Flash页的开始端
{
//读取1 PAGE 数据到内存,修改,然后写进去
I2C_EE_BufferRead(0,0,tempaddress,PAGE_SIZE,buf2);
memcpy(buf2,pRomData+PAGE_SIZE-startaddress%PAGE_SIZE+NumByteToWrite-NumByteToWrite%PAGE_SIZE,(NumByteToWrite%PAGE_SIZE)); while( FLASHStatus == FLASH_ErasePage( tempaddress+NumByteToWrite) ) /*把buf2写入到Flash中*
{
i=PAGE_SIZE/4;
datasource = (uint32_t)buf2;
FlashAddress = (tempaddress+NumByteToWrite-(NumByteToWrite % PAGE_SIZE)); /*末地址指针的页首
while(i-- >0)
{
FLASH_ProgramWord(FlashAddress,*(uint32_t*)datasource);
if (*(uint32_t*)FlashAddress != *(uint32_t*)datasource)
{
printf("I2C_EE_BufferWrite error!\r\n");
return ;
}
datasource += 4;
FlashAddress += 4; }
break;
}
} NumByteToWrite -= NumByteToWrite % PAGE_SIZE; //擦除Flash
pagenumber = NumByteToWrite/PAGE_SIZE; for (EraseCounter = 0; (EraseCounter < pagenumber) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
{
FLASHStatus = FLASH_ErasePage( tempaddress + PAGE_SIZE*EraseCounter );
}
//写Flash
datasource = *(uint32_t *)(pRomData+ PAGE_SIZE-(startaddress % PAGE_SIZE) );
FlashAddress = tempaddress; while( pagenumber-- > 0 )
{
i=PAGE_SIZE/4;
while(i -- >0)
{
FLASH_ProgramWord(FlashAddress,*(uint32_t*)datasource);
if (*(uint32_t*)FlashAddress != *(uint32_t*)datasource)
{
printf("I2C_EE_BufferWrite error!\r\n");
return ;
}
datasource += 4;
FlashAddress += 4;
}
}
}
else /*写的内容没有超出一页范围
{
printf("FlashWrire --in one page \r\n");
I2C_EE_BufferRead(0,0,(startaddress-(startaddress % PAGE_SIZE)),PAGE_SIZE,buf1); /*把起始地址所在页的内容读到内存buf1中
memcpy( (buf1+(tempaddress % PAGE_SIZE)),pRomData, NumByteToWrite ); /*把需要写入的数据覆盖到buf1中
while( FLASHStatus == FLASH_ErasePage(tempaddress) )
{
i=PAGE_SIZE/4;
datasource = (uint32_t)buf1;
FlashAddress = tempaddress-(tempaddress % PAGE_SIZE);
while(i-- >0)
{
FLASH_ProgramWord(FlashAddress,*(uint32_t*)datasource);
if (*(uint32_t *)FlashAddress != *(uint32_t *)datasource) /*读取Flash中的数据,看是否写入正确
{
printf("I2C_EE_BufferWrite error!\r\n");
return ;
}
datasource += 4;
FlashAddress += 4;
}
break;
}
}
}
/*******************起始指针在Flash页的开始端****************************/
else
{ printf("startptr in Page head \r\n");
if((NumByteToWrite % PAGE_SIZE) != 0)
{
//读取1 PAGE 数据到内存,修改,然后写进去
I2C_EE_BufferRead(0,0,(u16)(tempaddress+NumByteToWrite-(NumByteToWrite % PAGE_SIZE)),PAGE_SIZE,buf1);
printf("already copy to bug1 \r\n");
memcpy(buf1,pRomData+NumByteToWrite-(NumByteToWrite % PAGE_SIZE),(NumByteToWrite % PAGE_SIZE)); //end of debug
}
//擦除Flash
if( (NumByteToWrite%PAGE_SIZE) == 0 )
{
pagenumber = NumByteToWrite/PAGE_SIZE;
}
else
{
pagenumber = NumByteToWrite/PAGE_SIZE + 1;
}
for (EraseCounter = 0; (EraseCounter < pagenumber) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
{
FLASHStatus = FLASH_ErasePage(startaddress + (PAGE_SIZE * EraseCounter));
} //写Flash
if( pagenumber == 1) /*只有一页
{ i=PAGE_SIZE/4;
datasource = (uint32_t)buf1;
FlashAddress = startaddress;
while(i-- >0)
{
FLASH_ProgramWord(FlashAddress,*(uint32_t *)datasource);
if (*(uint32_t *)FlashAddress != *(uint32_t *)datasource)
{
printf("I2C_EE_BufferWrite error!\r\n");
return ;
}
datasource +=4;
FlashAddress +=4;
}
}
else /*很多页时,先写前面页,最后写buf1
{
while( pagenumber-- > 1 )
{
datasource = (u32)pRomData;
FlashAddress = startaddress;
i=PAGE_SIZE/4;
while(i -- >0)
{
FLASH_ProgramWord( FlashAddress, *(uint32_t *)datasource );
if (*(uint32_t *)FlashAddress != *(uint32_t *)datasource)
{
printf("I2C_EE_BufferWrite error!\r\n");
return ;
}
datasource += 4;
FlashAddress += 4;
}
}
//写后面的页
datasource = (uint32_t)buf1;
FlashAddress = startaddress+(pagenumber-1)*PAGE_SIZE;
i=PAGE_SIZE/4;
while(i -- >0)
{
FLASH_ProgramWord( FlashAddress, *(uint32_t *)datasource );
if (*(uint32_t *)FlashAddress != *(uint32_t *)datasource)
{
printf("I2C_EE_BufferWrite error!\r\n");
return ;
}
datasource += 4;
FlashAddress += 4;
}
}
}
}

STM32 对内部FLASH读写接口函数(转)的更多相关文章

  1. STM32 对内部FLASH读写接口函数

    因为要用内部FLASH代替外部EEPROM,把参数放在STM32的0x08000000+320K处,其中20K是bootloader,300K是应用程序. 原理:先要把整页FLASH的内容搬到RAM中 ...

  2. 【转】STM32擦除内部FLASH时间过长导致IWDG复位分析

    @20119-01-29 [小记] STM32擦除内部FLASH时间过长导致IWDG复位分析

  3. stm32 Flash读写独立函数[库函数]

    一. stm32的FLASH分为 1.主存储块:用于保存具体的程序代码和用户数据,主存储块是以页为单位划分的, 一页大小为1KB.范围为从地址0x08000000开始的128KB内. 2.信息块   ...

  4. [nRF51822] 11、基础实验代码解析大全 · 实验16 - 内部FLASH读写

     一.实验内容: 通过串口发送单个字符到NRF51822,NRF51822 接收到字符后将其写入到FLASH 的最后一页,之后将其读出并通过串口打印出数据. 二.nRF51822芯片内部flash知识 ...

  5. STM32 实现内部Flash的读写(HAL库版)

    Flash 中文名字叫闪存,是一种长寿命的非易失性(断电数据不丢失)的存储器.可以对称为块的存储器单元块进行擦写和再编程,在进行写入操作之前必须先执行擦除.一个Nand Flash由多个块(Block ...

  6. 第50章 读写内部FLASH—零死角玩转STM32-F429系列

    第50章     读写内部FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...

  7. STM32学习笔记:读写内部Flash(介绍+附代码)

    一.介绍 首先我们需要了解一个内存映射: stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯片实际的flash大小,不同的芯片flash大小不同. RAM起 ...

  8. STM32 内部flash的读写程序

    ​ /* Base address of the Flash sectors */ #define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base ...

  9. stm32——Flash读写

    stm32——Flash读写 一.Flash简介 通过对stm32内部的flash的读写可以实现对stm32的编程操作. stm32的内置可编程Flash在许多场合具有十分重要的意义.如其支持ICP( ...

随机推荐

  1. Net Protocol Related

    Data used to deliver through net should be encapsulated. General encapsulation include 4 layer of he ...

  2. ueditor 文本编辑器

    百度编辑器       压缩包在文件里 百度UEditor编辑器使用教程与使用方法 发布时间:2014-08-23 14:23:34.0 作者:青岛做网站 我们在做网站的时候,网站后台系统一般都会用到 ...

  3. mysql 初始化时root无密码

    修改密码 update user set password=PASSWORD('123456') where User='root'; 添加用户设置权限 grant select,insert,upd ...

  4. UIViewContentMode 图文解说

    在iOS应用开发中我们常常要对视图的contentMode属性进行设置,尤其在使用UIImageView视图时设置这个属性的概率很高.我们知道contentMode的类型是UIViewContentM ...

  5. 转:LoadRunner获取毫秒及字符串替换实现

    今天做一个性能测试,参数化要求创建用户名不可以重复,想来想不没有什么好的办法来避免用户名字的重复.所以就想用时间+随机数来实现,但是实现中遇到一个问题. 名字中不可以包含.这个特殊的字符的.所以要处理 ...

  6. MySQL架构优化:定时计划任务与表分区

    转自: MySQL架构优化实战系列3:定时计划任务与表分区 - 今日头条(TouTiao.com)http://toutiao.com/a6304736482361049345/?tt_from=mo ...

  7. 不停止MySQL服务增加从库的两种方式【转载】

    现在生产环境MySQL数据库是一主一从,由于业务量访问不断增大,故再增加一台从库.前提是不能影响线上业务使用,也就是说不能重启MySQL服务,为了避免出现其他情况,选择在网站访问量低峰期时间段操作. ...

  8. C#排列组合类

    //----------------------------------------------------------------------------- // // 算法:排列组合类 // // ...

  9. 使用compass更高效的编辑css --- 图片精灵

    compass是sass的一个库,关系相当于js中的jq.比较可惜的是compass的文档比较混乱 看的不太舒服,下面是compass的文档地址,有兴趣的可以去看看 http://compass-st ...

  10. iptables-过滤61开头的ip数据包

    iptables -F root@android:/system/bin # iptables -L -n iptables -L -n Chain INPUT (policy ACCEPT) tar ...