Flash基础入门之STM系列 Flash操作
小标 2018-08-06 来源 : 阅读 1182 评论 0

摘要:本文主要向大家介绍了Flash基础入门之STM系列 Flash操作,通过具体的内容向大家展现,希望对大家学习Flash基础入门有所帮助。

本文主要向大家介绍了Flash基础入门之STM系列 Flash操作,通过具体的内容向大家展现,希望对大家学习Flash基础入门有所帮助。

1、flash操作方法

 

1.1 对stm8的flash操作

#define BaseCfgaddr (uint32*)0x4000

/*
 * 函数名称    :   WriteAddrToFlash
 * 函数功能    :   数据写入Flash
 * 输入参数    :
 * 输出参数    :   无
 * 返 回 值    :   0或1
 * 其它说明    :   无
 * */
uint8 SYS_WriteDataToFlash(uint8* Data,uint32* addr,uint16Len)  
{      
    if(!Data)  
    return 0;           
    /*操作EEPROM,先进行解锁*/  
    FLASH_DUKR = 0xAE; /* 注意这里不能断点调试,否则会造成内部不同步,FLASH解锁失败*/
    FLASH_DUKR = 0x56;  
    FLASH_CR2 = 0x00;  
    FLASH_NCR2 = 0xFF;  
    if(!(FLASH_IAPSR & 0x08)) /* 检测对应的位是否解锁  */
    return 0;      
    memcpy(addr,Data,Len);  
    FLASH_IAPSR = (ST_UINT8)(~0x08); /* 重新上锁  */ 
    return 1;  

按字节操作即每次写入一位

 SYS_WriteDataToFlash(Buf,BaseCfgaddr,WriteCfgSize);

 

1.2 stm32f的flash操作。

使用stm32f0k4

/*
 * 函数名称    :   WriteAddrToFlash
 * 函数功能    :   数据写入Flash
 * 输入参数    :
 * 输出参数    :   无
 * 返 回 值    :   0或1
 * 其它说明    :   
                              写入一个配置,每次写只用某一页开始写,不可一页中从起始地址写之后又从中间地址写入。
                              写第二个模块配置时,空间配置从下一页开始写。否则会擦除之前的页,写之前会先擦除该页。
 * */
uint8 Sys_WriteDataToFlash(uint8* pData,uint32 Address,uint32 Len)  
{      
    if(!pData)  
    return 0;  
    uint32_t SLen = 0;
    uint32_t Wdata; 
    FLASH_Unlock();

    FLASH_ErasePage(Address); // 写之前擦除要写入的整页
    FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR); 
    /* Clear pending flags (if any) */  
    do
    {
        memcpy(&Wdata, pData, 4);// 
        FLASH_ProgramWord(Address,Wdata);
        Address += 4; 
        pData += 4;
        SLen += 4;
    }while(SLen<Len);
    FLASH_Lock();
    return 1;
}

 

/*
 * 函数名称    :   Sys_ReadFlashToBuf
 * 函数功能    :   从flash中读出数据到buf查看
 * 输入参数    :
 * 输出参数    :   无
* 返 回 值    :
 * 其它说明    :   
 * */
void Sys_ReadFlashToBuf(uint8* buf,uint32 addr,uint16 len)
{
    while(len--)
    {
        *buf = *(uint8*)addr;
         addr++;
         buf++;
    }
}

 

32位机一个字为4个字节,库函数提供两种形式,一种是半字写入另一种是一个字写入,以上使用的是一个字写入的方式

实际操作过程中是将一个结构体内容写入flash,先将该结构体以字节对其,将该结构体指向buf存储,再将该buf按字节写入flash。

读取时将内容读到buf,在将该buf转为结构体,即可准确提取出结构体中定义的值

 

2、操作中所犯错误及注意点

 

1、内存地址

      错误:从0x08000000基地址开始操作flash,一执行读写flash,程序就卡死。

      要操作flash的地址,如果程序是存储在main flash memory中开始执行,进入用户程序,我们操作flash就不能从flash基地址开始操作,这部分已经被应用程序占用。

      其操作flash地址值要大于本代码所占用FLASH的大小+0x08000000 

      用户程序代码占用flash大小可从编译时候看出来

        8 394 bytes of readonly  code memory 

       84 bytes of readonly  data memory 

       2 828 bytes of readwrite data memory 

        #define FLASH_BASE_ADDR                       (uint32_t)(0x08000000u)
        #define FLASH_STARTADDR_PAGE11    (FLASH_BASE_ADDR + 1024 * 11)

计算可写在第几页,最好的方法是从最后一页开始写,根据手册了解flash大小,页数,勿超出flash大小,否则易出现HardFault_Handler错误

2、将字转换为按字节写入

       错误: 写入的数据与实际的数据值不同

       从cotex-m0的库函数来看,对flash的操作时以字或者半字来操作。实际使用操作多按1个字节操作,造成不对齐。

        uint32_t Wdata; 

        memcpy(&Wdata, pData, 4);// 
        FLASH_ProgramWord(Address,Wdata);
        Address += 4; 
        pData += 4;
        固按以上操作,将4个字节转换为按字写入,统一了使用的所有工程,再将地址按四个字节偏移。

 

3、宏定义地址

       错误:flash读取时数据出错,内容指向错误。

       SYS_BASE_CFG_T *pCfg = (SYS_BASE_CFG_T *) FLASH_STARTADDR_PAGE11;

       操作是将flash页11的地址读取出来,指向转为结构体SYS_BASE_CFG_T 形式读取数据

       但在读取就出错,程序运行到该句即出现内存操作错误中断产生

        void HardFault_Handler(void)
        {
             while (1)
             {
             }
        }

        从运行参数上看,当运行到该句,地址指向并不是预先设计好的11页地址

        #define FLASH_STARTADDR_PAGE11    FLASH_BASE_ADDR + 1024 * 11

        由于宏定义加操作没有加括号,导致实际偏移值出现错误。宏定义式子为防错误一定要加括号

         #define FLASH_STARTADDR_PAGE11    (FLASH_BASE_ADDR + 1024 * 11)

4、HardFault_Handler  

        该中断产生的一般条件是内存非法操作,包括数组越界、内存溢出、指针地址错误、野指针存在

        在stm8中当内存非法操作时mcu内部会产生复位,从复位源可查看为非法操作符复位  

5、页大小

        flash操作擦除时可以以页为单位擦除或者以整片flash擦除。

        在使用flash时,如果需要写入两组不同的数据并且在一页以内,建议直接使用一页一组数据,由于内存够大而且防止误操作到其他组数据。

        M3或者M0内核大容量与小容量的flash的页大小有所区别,小容量以1024字节 1k为一页,大容量以2048字节2k 为一页。所以操作具体内存时以

         (FLASH_BASE_ADDR + 1024 * 11)形式,更直观看出数据位置,便于IDE调试查看。

 

对结构体的flash写入写出

 

uint16 ReadToFlash(uint8 *pCfg)
{
    CfgInfo.pBaseCfg = (BASE_CFG_T *)pCfg;
    return sizeof(BASE_CFG_T);
}

void ReadAllCfg(void)
{
    uint8 *pRead = (uint8*)FLASH_STARTADDR_PAGE11; // 转化为unsigned char 按字节操作 32位一次偏移4字节
    uint32 CfgLen = 0;
    
    CfgLen = ReadToFlash(pRead );
    pRead += CfgLen;
    CfgInfo.SysReadCfgSize += CfgLen;
}

uint16 WriteToFlash(uint8 *pCfg)
{
     CfgInfo.pBaseCfg = (BASE_CFG_T *)pCfg;
     CfgInfo.pBaseCfg->WriteFlashFlag = CFG_FLASH_FLAG;
     CfgInfo.pBaseCfg->FeedWatDogTime = 200;
     return sizeof(BASE_CFG_T);
}

static void WriteAllCfg(void)
{
    uint8 *pWrite = CfgInfo.CfgBuf;
    uint32 CfgLen = 0;
    
    CfgLen = WriteToFlash(pWrite );
    pWrite += CfgLen;
    CfgInfo.SysWriteCfgSize += CfgLen;
    Sys_WriteDataToFlash(CfgInfo.CfgBuf,FLASH_STARTADDR_PAGE11,CfgInfo.SysWriteCfgSize);
    Sys_ReadAllCfg();  
}  

void Sys_CfgInit(void)
{
    BASE_CFG_T *pCfg = (BASE_CFG_T *) FLASH_STARTADDR_PAGE11;

 /*在要写入的一个buf的第一位作为写入标志位,程序下次执行到这儿就不再重写,而只是读取这个flash的内容,实现配置的形式操作。*/
    if(pCfg->WriteFlashFlag != CFG_FLASH_FLAG) 

    {
        /* 写配置到FLASH */
        WriteAllCfg();
    }
    else
    {
        ReadAllCfg();
        memcpy(CfgInfo.CfgBuf, (char *)FLASH_STARTADDR_PAGE11, CfgInfo.SysReadCfgSize);
    }
}     

 

typedef __packed  struct 
{
    uint8             WriteFlashFlag;    /* FLASH写标志 */
    uint8             DebugFalg;           /* 调试使用标志 */
    uint32           FeedWatDogTime;       
}BASE_CFG_T;            /* 系统基本配置 */

typedef __packed  struct
{
    BASE_CFG_T  *pBaseCfg;       /* 系统基本配置参数 */
    uint8            SysWriteCfgSize;
    uint8            SysReadCfgSize;    
    uint8          CfgBuf[SYS_CFG_SIZE]; /* 所有人的配置文件 */
}CFG_INFO_T; /* 配置配置参数的 */

 CFG_INFO_T        CfgInfo;

#define  CFG_FLASH_FLAG (0x57)

以上内容为个人使用过程的方法笔记及个人认为的注意点、知识点.

内容不全面,如之后使用有所补充随时更新。

如您发现有所问题,希望给我意见。

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标常用软件Flash频道!


本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程