STM32 对内部FLASH读写接口函数

摘要:
0){*pRomData=*ptr;*pRomData);ptr++;u8buf2[PAGE_SIZE];FLASH_StatusFLASHStatus=FLASH_COMPLETE;param_flashbase=0x8000000+(300+20)*1024;

因为要用内部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 ");
  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! ");
          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! ");
                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! ");
               return ;
           }
           datasource += 4;
           FlashAddress += 4;
    }
   }
  }
  else /*写的内容没有超出一页范围
  {
   printf("FlashWrire --in one page ");
   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! ");
               return ;
        }
        datasource += 4;
        FlashAddress += 4;    
    }
    break;
   }
  }
 }
/*******************起始指针在Flash页的开始端****************************
 else
 { printf("startptr  in Page head ");
  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 ");
   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! ");
            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! ");
                  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! ");
             return ;
       }
       datasource += 4;
       FlashAddress += 4;
   } 
  }    
 } 
}

免责声明:文章转载自《STM32 对内部FLASH读写接口函数》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇VIM操作指南aws术语-小结下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Docker中的Cgroup Driver:Cgroupfs 与 Systemd

在安装kubernetes的过程中,会出现 failed to create kubelet: misconfiguration: kubelet cgroup driver: "cgroupfs" is different from docker cgroup driver: "systemd" 文件驱动默认由systemd改成cgroupfs, 而我们...

WPF利用动画实现圆形进度条

  这是我的第一篇随笔,最近因为工作需要,开始学习WPF相关技术,自己想实现以下圆形进度条的效果,逛了园子发现基本都是很久以前的文章,实现方式一般都是GDI实现的,想到WPF中动画效果不错,于是自己研究了一下,还真让我做出来了,废话不多说了,先上效果。   这个效果是不是还不错?这里面实现了数字实时显示以及根据进度进行自动渐变的效果。实现原理其实很简单,...

ElementUI中的el-table实现递增的序号列

场景 ElementUI中的el-table中实现动态添加一行、删除一行、清空所有行: https://mp.csdn.net/console/editor/html/107815187 在上面中能实现动态添加一行并实现序号递增的效果。 这里记录下递增序号是怎样实现的。 注: 博客: https://blog.csdn.net/badao_liumang_...

基于WPF系统框架设计(3)-Fluent Ribbon界面布局

一个系统框架除了功能菜单导航,有系统内容显示区域,系统状态栏。 Silver: Blue: Black: 系统界面设计,就不进行技术细节介绍了,主题以框架设计为主,Xaml源码参考: <Fluent:RibbonWindow x:Class="TLAgent.SecurityManager.WPF.MainWindow" xml...

angularJS 调用摄像头扫描二维码,输出结果

背景:在一个angularJS的项目中,需要添加点击某个按钮之后调用手机的照相机,扫描二维码输出所扫描二维码的结果,利用这个结果来处理其他的事情。 效果如下 扫描玩二维码把结果alert出来如下图 扫描二维码   1.在本地需要安装下面的包文件 在现有的angularJS项目中,执行下面的命令 npm install npm i @zxing/bro...

(翻译)Entity Framework技巧系列之九 Tip 35 36

提示35. 怎样实现OfTypeOnly<TEntity>()这样的写法 如果你编写这样LINQ to Entities查询: 1 var results = from c in ctx.Vehicles.OfType<Car>() 2 select c; 这会返回,Cars包括那些派生自Car类型,如...