一本精品热在线视频,久久免费视频分类,精品婷婷乱码久久久久久蜜桃,在线可以免费观看的Av

<mark id="vd61v"><dl id="vd61v"></dl></mark>
    <sub id="vd61v"><ol id="vd61v"></ol></sub>

  • <sub id="vd61v"><ol id="vd61v"></ol></sub>

    新聞中心

    EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 「STM32 Flash 操作全解析」擦除、寫(xiě)入、讀取一網(wǎng)打盡!附完整源碼

    「STM32 Flash 操作全解析」擦除、寫(xiě)入、讀取一網(wǎng)打盡!附完整源碼

    作者:嵌入式芯視野 時(shí)間:2025-07-15 來(lái)源:今日頭條 收藏

    在嵌入式開(kāi)發(fā)中,MCU 內(nèi)部的 常用于存儲(chǔ)配置信息、日志數(shù)據(jù)或用于 OTA 升級(jí)。F4 系列 MCU 提供了對(duì) 的靈活操作能力,包括按扇區(qū)擦除、字節(jié)或半字寫(xiě)入等。本文將圍繞一段實(shí)際使用的 操作代碼進(jìn)行講解,主要涉及 Flash 的擦除、寫(xiě)入與讀取功能。

    一、Flash 結(jié)構(gòu)及操作基本原理

    F4 MCU 的 Flash 存儲(chǔ)器按照扇區(qū)(Sector)劃分,每個(gè)扇區(qū)大小不一,例如在 F407 中,前四個(gè)扇區(qū)大小為 16KB,第五個(gè)為 64KB,之后為若干個(gè) 128KB 的大扇區(qū)。片上 Flash 支持:

    • 扇區(qū)級(jí)擦除(Sector Erase)

    • 多種對(duì)齊方式的編程(如 Byte、Halfword、Word、Double Word)

    • 擦寫(xiě)需先解鎖并清除相關(guān)標(biāo)志位

    操作前需解鎖 Flash 控制器,完成后應(yīng)及時(shí)鎖定以防意外寫(xiě)入。

    二、Flash 扇區(qū)映射及擦除操作

    代碼中的扇區(qū)映射表 sec_map[] 采用結(jié)構(gòu)體 sec_info_t 維護(hù)每個(gè)扇區(qū)的起始地址、大小及編號(hào):

    typedef struct {
        unsigned int start;    unsigned int size;    unsigned int secnum;
    } sec_info_t;

    這是一個(gè)結(jié)構(gòu)體類(lèi)型,表示每個(gè)扇區(qū)的起始地址、扇區(qū)大小和扇區(qū)編號(hào)。接著通過(guò)一個(gè)常量數(shù)組 sec_map[] 列出 Flash 不同扇區(qū)的信息:

    const sec_info_t sec_map[] = {
        {0x08000000, 16*1024, FLASH_Sector_0},
        {0x08004000, 16*1024, FLASH_Sector_1},
        {0x08008000, 16*1024, FLASH_Sector_2},
        {0x0800C000, 16*1024, FLASH_Sector_3},
        {0x08010000, 64*1024, FLASH_Sector_4},
        {0x08020000, 128*1024, FLASH_Sector_5},
        {0x08040000, 128*1024, FLASH_Sector_6},
        {0x08040000, 128*1024, FLASH_Sector_7}};

    該映射表根據(jù) STM32F4 的 Flash 布局列出了常用的 8 個(gè)扇區(qū)。


    二、Flash 擦除函數(shù)講解

    函數(shù) mcu_flash_erase() 實(shí)現(xiàn)對(duì) Flash 指定地址范圍的擦除。

    int mcu_flash_erase(unsigned int addr, size_t size)
    • addr: 要擦除的起始地址

    • size: 要擦除的范圍(單位為字節(jié))

    函數(shù)先計(jì)算扇區(qū)數(shù)量:

    int len = sizeof(sec_map) / sizeof(sec_info_t);

    然后依次遍歷扇區(qū),找出與 addr 和 size 匹配的扇區(qū)范圍,并執(zhí)行擦除:

    status = FLASH_EraseSector(sec->secnum, VoltageRange_2);

    在執(zhí)行擦除之前必須解鎖 Flash:

    FLASH_Unlock();

    擦除完成后鎖定 Flash:

    FLASH_Lock();

    最后返回 1 表示成功,返回 0 表示擦除失敗。

    三、Flash 寫(xiě)入函數(shù)講解

    寫(xiě)入函數(shù)為:

    int mcu_flash_write(unsigned int addr ,const void *buf, size_t size)
    • addr: 寫(xiě)入的起始地址

    • buf: 待寫(xiě)入的數(shù)據(jù)緩沖區(qū)

    • size: 寫(xiě)入數(shù)據(jù)的字節(jié)數(shù)

    寫(xiě)入之前,同樣要進(jìn)行 Flash 解鎖,并清除標(biāo)志位:

    FLASH_Unlock();              
    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_OPERR | 
                    FLASH_FLAG_PGAERR);

    然后進(jìn)入一個(gè)循環(huán),按字節(jié)或半字方式逐步寫(xiě)入 Flash:

    if ((addr & 1) == 0 && size > 2) {    status = FLASH_ProgramHalfWord(addr, *((uint16_t *)p));    wrlen = 2;
    } else {    status = FLASH_ProgramByte(addr, *((uint8_t *)p));    wrlen = 1;
    }

    寫(xiě)入完成后更新地址和緩沖區(qū)指針:

    size -= wrlen;addr += wrlen;p    += wrlen;

    如果寫(xiě)入中某次操作返回錯(cuò)誤,則提前跳出,最后執(zhí)行鎖定操作并返回是否寫(xiě)入成功:

    FLASH_Lock();return ret;

    四、Flash 讀取函數(shù)講解

    讀取函數(shù)的接口為:

    int mcu_flash_read(unsigned int addr ,void *buf, size_t size)

    該函數(shù)直接通過(guò)內(nèi)存拷貝讀取 Flash 數(shù)據(jù):

    memcpy(buf, (void *)addr, size);  
    return 0;

    其中 addr 是 Flash 的起始地址,buf 是目標(biāo)緩存區(qū),size 是讀取字節(jié)數(shù)。由于 STM32 的 Flash 可以直接映射為內(nèi)存讀取,因此可以像訪問(wèn)普通內(nèi)存一樣操作。

    五、總結(jié)

    本篇文章介紹了 STM32F4 MCU 內(nèi)部 Flash 的基礎(chǔ)操作實(shí)現(xiàn),包括:

    • 使用結(jié)構(gòu)體映射 Flash 扇區(qū)信息

    • 實(shí)現(xiàn) Flash 擦除函數(shù),通過(guò)匹配地址范圍擦除對(duì)應(yīng)扇區(qū)

    • 實(shí)現(xiàn) Flash 寫(xiě)入函數(shù),按字節(jié)或半字逐步寫(xiě)入 Flash

    • 實(shí)現(xiàn) Flash 讀取函數(shù),通過(guò) memcpy 方式直接讀取 Flash 內(nèi)容

    以上代碼適用于裸機(jī)開(kāi)發(fā),也可作為 STM32 Flash 操作的基礎(chǔ)模板,配合上層協(xié)議或文件系統(tǒng)進(jìn)行擴(kuò)展應(yīng)用,如參數(shù)存儲(chǔ)、數(shù)據(jù)記錄、Bootloader 固件升級(jí)等功能。

    開(kāi)源源碼供參考:

    #include "mcu_flash.h"#include "stm32f4xx.h"#include <string.h>typedef struct {
        unsigned int start;    unsigned int size;    unsigned int secnum;
    }sec_info_t;/*扇區(qū)地址映射 ---------------------------------------------------------------*/const sec_info_t sec_map[] = 
    {
        {0x08000000, 16*1024, FLASH_Sector_0},
        {0x08004000, 16*1024, FLASH_Sector_1},
        {0x08008000, 16*1024, FLASH_Sector_2},
        {0x0800C000, 16*1024, FLASH_Sector_3},
        {0x08010000, 64*1024, FLASH_Sector_4},
        {0x08020000, 128*1024, FLASH_Sector_5},
        {0x08040000, 128*1024, FLASH_Sector_6},
        {0x08040000, 128*1024, FLASH_Sector_7}
    };/*
     * @brief       stm32 mcu 內(nèi)部flash擦除操作
     * @param[in]   addr        - 地址
     * @param[in]   探險(xiǎn)大小    - size
     * @return      0 - 失敗, 非0 - 成功
     */int mcu_flash_erase(unsigned int addr, size_t size){ 
        int i;    int len = sizeof(sec_map) / sizeof(sec_info_t);    const sec_info_t *sec = &sec_map[len - 1];
        
        FLASH_Status status;    
        /*越界處理*/
        if (addr > sec->start + sec->size)        return 0;
        
        FLASH_Unlock();    for (i = 0; i < len; i++)
        {
            sec = &sec_map[i];        if ( (sec->start >= addr && sec->start < addr + size) || 
                 (sec->start + sec->size > addr && sec->start + sec->size <= addr + size))
            {            //FLASH_OB_WRPConfig();
                status = FLASH_EraseSector(sec->secnum, VoltageRange_2);            if (status != FLASH_COMPLETE)
                {
                    FLASH_Lock(); 
                    return 0;  
                }
                              
            }
        }
        FLASH_Lock(); 
        return 1;
    }/*
     * @brief       stm32 mcu 內(nèi)部flash寫(xiě)操作
     * @param[in]   addr        - 地址
     * @param[in]   buf         - 數(shù)據(jù)緩沖區(qū)
     * @param[in]   寫(xiě)入大小    - size
     * @return      0 - 失敗, 非0 - 成功
     */int mcu_flash_write(unsigned int addr ,const void *buf, size_t size){    unsigned char *p = (uint8_t *)buf;//    unsigned int base = addr;//    size_t tlen = size;
        int wrlen;
        FLASH_Status status = FLASH_COMPLETE;    int ret = 0;
        FLASH_Unlock();              
        FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_OPERR | 
                        FLASH_FLAG_PGAERR);     
        while (size) {#if 0
            /*根據(jù)對(duì)齊方式優(yōu)化寫(xiě)入長(zhǎng)度*/
            if ((addr & 7) == 0 && size > 8)             /*8字節(jié)對(duì)齊,按雙字寫(xiě)入*/  
            {
                status = FLASH_ProgramDoubleWord(addr, *((uint64_t *)p));            if (status != FLASH_COMPLETE)                goto _quit;
                wrlen = 8;
            }        else if ((addr & 3) == 0 && size > 4)        /*4字節(jié)對(duì)齊,按字寫(xiě)入*/
            {
                status = FLASH_ProgramWord(addr, *((uint32_t *)p));            if (status != FLASH_COMPLETE)                goto _quit;
                wrlen = 4;
            }        else if ((addr & 1) == 0 && size > 2)        /*2字節(jié)對(duì)齊,按半字寫(xiě)入*/
            {
                status = FLASH_ProgramHalfWord(addr, *((uint16_t *)p));            if (status != FLASH_COMPLETE)                goto _quit;
                wrlen = 2;
            }        else                                         /*按字節(jié)寫(xiě)入 --------*/
            {
                status = FLASH_ProgramByte(addr, *((uint8_t *)p));            if (status != FLASH_COMPLETE)                goto _quit;
                wrlen = 1;
            }#endif
            if ((addr & 1) == 0 && size > 2)        /*2字節(jié)對(duì)齊,按半字寫(xiě)入*/
            {
                status = FLASH_ProgramHalfWord(addr, *((uint16_t *)p));            if (status != FLASH_COMPLETE)                goto _quit;
                wrlen = 2;
            }        else                                         /*按字節(jié)寫(xiě)入 --------*/
            {
                status = FLASH_ProgramByte(addr, *((uint8_t *)p));            if (status != FLASH_COMPLETE)                goto _quit;
                wrlen = 1;
            }        
            /*地址偏移 -------------------------------------------------------*/
            size -= wrlen;
            addr += wrlen;
            p    += wrlen;        
        }
    _quit:

         ret = status == FLASH_COMPLETE;// && memcmp(buf, (void *)base, tlen) ? 1 : 0;     
     FLASH_Lock();     return ret;
    }/*
     * @brief       stm32 mcu 內(nèi)部flash讀操作
     * @param[in]   addr        - 地址
     * @param[in]   buf         - 數(shù)據(jù)緩沖區(qū)
     * @param[in]   讀出長(zhǎng)度    - size
     * @return      0 - 失敗, 非0 - 成功
     */int mcu_flash_read(unsigned int addr ,void *buf, size_t size){    memcpy(buf, (void *)addr, size);  
        return 0;
    }



    關(guān)鍵詞: STM32 Flash

    評(píng)論


    相關(guān)推薦

    技術(shù)專(zhuān)區(qū)

    關(guān)閉