qjp1988113 发表于 2020-6-6 12:48

【MM32 eMiniBoard测评报告】+内部FLASH读写操作(参考原子STM32)

本帖最后由 qjp1988113 于 2020-6-6 12:47 编辑

我看了下官方的FLASH读写程序感觉很单一,是对一个固定地址写数据读数据,不是很通用。
想起以前学STM32时,原子开发板FLASH例程不错,就拿来修修用。
由于不确定,MM32与STM32在FLASH这块到底有什么不同。
查看了中小容量的MM32L073的规格书,最大128页,每页1K字节:

查看了大容量的MM32F103XE的规格书,最大512页,每页同样1K字节:

而我记得ST的好像不一样,页数256以下的为1K,以上的为2K。MM32仅看了这2款,
不敢妄断就是1K,具体用的时候需要查看规格书。
单次读写操作都是2字节(16位),即半字,这点与ST的一致。


知道这个,下面就直接修改代码了:
#include "flash.h"
#include "led.h"
#include "uart.h"
#include "HAL_conf.h"


////每页大小为1024即1K字节共128页
//#define FLASH_PAGE_SIZE    ((uint16_t)0x400)

//#define BANK1_WRITE_START_ADDR((uint32_t)0x08002800)
//#define BANK1_WRITE_END_ADDR    ((uint32_t)0x08003200)
//uint32_t EraseCounter = 0x00, Address = 0x00;
//uint32_t Data = 0x12345679;
//uint32_t NbrOfPage = 0x00;
//volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;


//读取指定地址的半字(16位数据)
//faddr:读地址(此地址必须为2的倍数!!)
//返回值:对应数据.
u16 FLASH_ReadHalfWord(u32 faddr)
{
      return *(vu16*)faddr;
}

#if MM32_FLASH_WREN      //如果使能了写   
//不检查的写入
//WriteAddr:起始地址
//pBuffer:数据指针
//NumToWrite:半字(16位)数   
void FLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)   
{                                          
      u16 i;
      for(i=0;i<NumToWrite;i++)
      {
                FLASH_ProgramHalfWord(WriteAddr,pBuffer);
            WriteAddr+=2;//地址增加2.
      }
}
//从指定地址开始写入指定长度的数据
//WriteAddr:起始地址(此地址必须为2的倍数!!)
//pBuffer:数据指针
//NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)

//经查看,目前MM32的每页字节数好像没有大小页之分 固定在1K字节(不完全确定)
#if MM32_FLASH_SIZE<256
#define MM32_SECTOR_SIZE 1024 //字节//MM32L073 128个页每页1K字节
#else
//#define MM32_SECTOR_SIZE      2048//
#define MM32_SECTOR_SIZE 1024 //MM32的超过256的也是1K字节每页 这里仅查看了MM32F103XE的规格书
#endif

u16 MM32_FLASH_BUF;//最多是1K字节
void FLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)      
{
      u32 secpos;         //扇区地址
      u16 secoff;         //扇区内偏移地址(16位字计算)
      u16 secremain; //扇区内剩余地址(16位字计算)         
         u16 i;   
      u32 offaddr;   //去掉0X08000000后的地址
      if(WriteAddr<MM32_FLASH_BASE||(WriteAddr>=(MM32_FLASH_BASE+1024*MM32_FLASH_SIZE)))return;//非法地址
      FLASH_Unlock();                                                //解锁
      offaddr=WriteAddr-MM32_FLASH_BASE;                //实际偏移地址.
      secpos=offaddr/MM32_SECTOR_SIZE;                        //扇区地址0~127 for STM32F103RBT6
      secoff=(offaddr%MM32_SECTOR_SIZE)/2;                //在扇区内的偏移(2个字节为基本单位.)
      secremain=MM32_SECTOR_SIZE/2-secoff;                //扇区剩余空间大小   
      if(NumToWrite<=secremain)secremain=NumToWrite;//不大于该扇区范围
      while(1)
      {      
                FLASH_Read(secpos*MM32_SECTOR_SIZE+MM32_FLASH_BASE,MM32_FLASH_BUF,MM32_SECTOR_SIZE/2);//读出整个扇区的内容
                for(i=0;i<secremain;i++)//校验数据
                {
                        if(MM32_FLASH_BUF!=0XFFFF)break;//需要擦除            
                }
                if(i<secremain)//需要擦除
                {
                        FLASH_ErasePage(secpos*MM32_SECTOR_SIZE+MM32_FLASH_BASE);//擦除这个扇区
                        for(i=0;i<secremain;i++)//复制
                        {
                              MM32_FLASH_BUF=pBuffer;         
                        }
                        FLASH_Write_NoCheck(secpos*MM32_SECTOR_SIZE+MM32_FLASH_BASE,MM32_FLASH_BUF,MM32_SECTOR_SIZE/2);//写入整个扇区
                }else FLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//写已经擦除了的,直接写入扇区剩余区间.                                    
                if(NumToWrite==secremain)break;//写入结束了
                else//写入未结束
                {
                        secpos++;                              //扇区地址增1
                        secoff=0;                              //偏移位置为0         
                           pBuffer+=secremain;          //指针偏移
                        WriteAddr+=secremain;      //写地址偏移         
                           NumToWrite-=secremain;      //字节(16位)数递减
                        if(NumToWrite>(MM32_SECTOR_SIZE/2))secremain=MM32_SECTOR_SIZE/2;//下一个扇区还是写不完
                        else secremain=NumToWrite;//下一个扇区可以写完了
                }         
      };      
      FLASH_Lock();//上锁
}
#endif

//从指定地址开始读出指定长度的数据
//ReadAddr:起始地址
//pBuffer:数据指针
//NumToWrite:半字(16位)数
void FLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)         
{
      u16 i;
      for(i=0;i<NumToRead;i++)
      {
                pBuffer=FLASH_ReadHalfWord(ReadAddr);//读取2个字节.
                ReadAddr+=2;//偏移2个字节.      
      }
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
//WriteAddr:起始地址
//WriteData:要写入的数据
void Test_Write(u32 WriteAddr,u16 WriteData)         
{
      FLASH_Write(WriteAddr,&WriteData,1);//写入一个字
}

///////////old code
//u8 FLASH_Program(void)
//{
//   
//    /* Porgram FLASH Bank1 ********************************************************/      
//    /* Unlock the Flash Bank1 Program Erase controller */
//    FLASH_Unlock();
//   
//    /* Clear All pending flags */
//    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);      
//   
//    FLASH_ErasePage(BANK1_WRITE_START_ADDR);
//   
//    FLASH_ClearFlag(FLASH_FLAG_EOP );      
//   
//    FLASHStatus = FLASH_ProgramWord(0x08001FFC, Data);
//   
//    FLASH_ClearFlag(FLASH_FLAG_EOP );      
//   
//    FLASH_Lock();
//   
//    printf("%x\r\n",(*(__IO uint32_t*) 0x08001FFC));
//   
//    if((*(__IO uint32_t*) 0x08001FFC) != Data)
//    {
//      return 1;
//    }
//    return 0;
//}

主程序:
#include "delay.h"
#include "sys.h"
#include "led.h"
#include "uart.h"
#include "flash.h"
#include "stdio.h"
#include "string.h"

//要写入到STM32 FLASH的字符串数组
u8 TEXT_Buffer[]={"MM32 FLASH TEST"};
#define SIZE sizeof(TEXT_Buffer)               //数组长度
#define FLASH_SAVE_ADDR0X08009000         //设置FLASH 保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小+0X08000000)
/********************************************************************************************************
**函数信息 :main(void)                     
**功能描述 :
**输入参数 :无
**输出参数 :无
********************************************************************************************************/
int main(void)   
{
                u8 datatemp;
                u8 FlashOK**=0;
    //下载程序前要选择全擦除
//    u8 t;
    delay_init();
    LED_Init();
    uart_initwBaudRate(115200);
//    t=FLASH_Program();
          FLASH_Write(FLASH_SAVE_ADDR,(u16*)TEXT_Buffer,SIZE);
          delay_ms(200);
    FLASH_Read(FLASH_SAVE_ADDR,(u16*)datatemp,SIZE);
          delay_ms(200);
//          while(1)
//                {
                        printf("%s\r\n",datatemp);
                        delay_ms(2000);
//                }
//               
          if(strstr((char*)datatemp,(char*)TEXT_Buffer)>0) FlashOK**=1;
    else         FlashOK**=0;
//                while(1)
//                {
//                              printf("%x\r\n",(*(__IO uint32_t*) 0x08001FFC));
//                              delay_ms(2000);                        
//                }
    if(FlashOK**>0)
      while(1)            //无限循环
      {
            printf("program ok\r\n");
            LED1_TOGGLE();
            LED2_TOGGLE();
            LED3_TOGGLE();
            LED4_TOGGLE();
            delay_ms(1000);
      }
    else
      while(1)
      {
            printf("program error\r\n");
            delay_ms(1000);
      }
}
调试下载,板上4LED闪烁,串口数据显示正常:

好了。就到这里了。
附上代码:










zeshoufx 发表于 2020-6-6 13:11

谢谢分享

wwppd 发表于 2021-6-13 21:39

资料够全的,多谢分享                                 

mickit 发表于 2021-6-13 21:39

以后多交流交流                  

pl202 发表于 2021-6-13 21:39

谢谢你共享的资料                                 

fengm 发表于 2021-6-13 21:39

资料的确是很全面                                 

everyrobin 发表于 2021-6-13 21:39

应用还是很广泛的                                 

jstgotodo 发表于 2021-6-13 21:39

有时间需要好好看看   不错                                 

geraldbetty 发表于 2021-6-13 21:39

回复查看一下相关的内容。                                 

pixhw 发表于 2021-6-13 21:39

谢谢你共享的资料                                 

xiaoyaozt 发表于 2021-6-13 21:39

资料够全的,多谢分享                                 

xiaoyaodz 发表于 2021-6-13 21:40

应用还是很广泛的                                 

fentianyou 发表于 2021-6-13 21:40

正准备学习的朋友推荐下载。                                 

burgessmaggie 发表于 2021-6-13 21:40

相当全的资料,很适合初学者                                 

louliana 发表于 2021-6-13 21:40

正准备学习的朋友推荐下载。                                 

sesefadou 发表于 2021-6-13 21:40

资料很实用,谢谢楼主!                                 

olivem55arlowe 发表于 2021-6-13 21:40

有时间需要好好看看   不错                                 

albertaabbot 发表于 2021-6-13 21:40

有时间需要好好看看   不错                                 

usysm 发表于 2021-6-13 21:40

内容还是非常丰富的                                 

菜鸟的第一步 发表于 2021-6-15 13:28

访问片内flash,会不会很慢,我记得之前用片内flash时需要遍历,很浪费时间
页: [1]
查看完整版本: 【MM32 eMiniBoard测评报告】+内部FLASH读写操作(参考原子STM32)