博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
STM32 对内部FLASH读写接口函数(转)
阅读量:6826 次
发布时间:2019-06-26

本文共 7576 字,大约阅读时间需要 25 分钟。

源:

因为要用内部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;   }   }     } }

 

转载地址:http://lhezl.baihongyu.com/

你可能感兴趣的文章
CNNIC第31次中国互联网报告,网民规模达5.64亿
查看>>
55. C# -- 不安全代码(Unsafe)
查看>>
CAS 配置(基于tomcat 6)
查看>>
RobotFramework基础总结(一)
查看>>
平面的空间转换
查看>>
我的友情链接
查看>>
Spring MVC 前后台传值
查看>>
我的友情链接
查看>>
使用node-webkit开发exe窗口程序
查看>>
图解:双IP地址引起的网络故障
查看>>
C语言第三天(文件)
查看>>
MongoDB: couldn't connect to server 127.0.0.1:27017 src/mongo/shell/mongo.js:91
查看>>
第二章 数据,变量和计算
查看>>
openwrt无线连接互联网的实现原理【2】
查看>>
禁止用户使用ctrl+alt+Fn进行tty1-ttyn切换的设置
查看>>
nginx+keepalived+proxy_cache 配置高可用nginx群集和高速缓存
查看>>
Spring cloud 熔断器Hystrix
查看>>
postfix 邮件集群方案(02)
查看>>
内建控制结构之不再使用break和continue
查看>>
自己写的一个JavaScrpt输入验证
查看>>