單片機-FLASH軟件模擬EEPROM,提升flash保存重要參數的使用壽命

目錄

??1. FLASH和EEPROM讀寫數據的對比
??2. FLASH模擬EEPROM的原理
??3. FLASH模擬EEPROM的優點
??4. 實戰項目工程代碼

1. FLASH和EEPROM讀寫數據的對比

1.1 擦除操作

  • EEPROM通常支持按單字節擦除和寫入,這一特性使其非常適合需要頻繁更新小量數據的應用場景。
  • Flash存儲器通常是按塊、扇區、頁擦除的,這意味著即使只更改一個字節的數據,也需要擦除整個扇區或頁。

1.2 寫入速度

  • EEPROM的寫入速度通常比Flash快,尤其是在擦除和重新編程單個字節時。
  • Flash的寫入速度較慢,特別是在擦除操作期間,因為它涉及到更大的存儲區域。

1.3 寫入次數限制

  • EEPROM和Flash都有寫入次數限制,但EEPROM通常設計為能夠承受更多的擦寫循環,通常達到百萬次級別。
  • Flash存儲器的擦寫次數限制較低,通常在10,000到100,000次之間;對于頻繁擦寫數據的操作,易造成flash損壞。

1.4 數據保持能力

  • EEPROM 的數據保持時間通常較長,一般可達到 20 年以上,這使得它非常適合長期保存關鍵數據的應用場景。
  • FLASH 的數據保持時間通常在 10 年左右,雖然也能滿足大多數應用的需求,但相較于 EEPROM 仍略遜一籌。

基本特性對比

特性FLASHEEPROM
存儲單元結構NAND(共享位線,高密度)/ NOR(獨立位線,高速)雙晶體管結構(控制柵 + 存儲柵,支持字節操作)
擦除單位Block(塊擦除)Byte(字節級擦除)
寫入速度0.2-10ms/page1-10ms/byte
擦除時間1-300ms/block (NOR Flash)字節擦除與寫入同時完成(無需單獨擦除步驟)
擦寫次數10K-100K次100K-1M次
存儲密度高(適合大容量存儲)低(適合小數據存儲)
功耗較高(需要高壓擦除)較低
典型應用場景操作系統存儲、文件系統、代碼 / 數據批量存儲配置參數存儲、少量數據頻繁讀寫

2. FLASH模擬EEPROM的原理

2.1 劃分區域

  • 單片機的 FLASH 通常由多個頁或扇區組成,在寫入數據前,必須按頁或扇區進行擦除操作;
  • 可將 FLASH 按頁或扇區劃分為多個區域,其中一個區域用于存儲程序代碼,其他區域則可用于數據存儲,從而實現模擬 EEPROM 的功能;

2.2 擦除和寫數據

  1. 在首次使用或存儲空間不足時,對模擬 EEPROM 的 FLASH 區域進行整體擦除,并記錄 FLASH 剩余空間大小,其初始值等于分配給模擬 EEPROM 的總空間大小;
  2. 通過偏移寫地址寫入新的數據,每次寫入后,FLASH 剩余空間大小相應減去寫入數據的長度;
  3. 當 FLASH 空間即將寫滿或剩余空間不足時,重復執行步驟 1 和步驟 2,即先擦除整個區域,再重新寫入數據;

2.3 磨損均衡技術

  • 為了延長 FLASH 的使用壽命,通常會采用磨損均衡技術,將擦寫操作均勻分布到各個塊或扇區,避免某些區域過早損壞。
  • 常見的磨損均衡算法有簡單的順序循環、基于計數的動態分配以及更復雜的基于使用頻率的智能分配等。

2.4 數據結構設計

  • 為了實現高效的數據管理,通常會設計特定的數據結構,如使用索引表記錄每個數據項的存儲位置和狀態。
  • 在寫入新數據時,可以采用追加寫入的方式,而不是直接覆蓋原有數據,從而提高寫入效率并減少擦除次數。

2.5 FLASH讀寫操作示意圖

在這里插入圖片描述


在這里插入圖片描述


3. FLASH模擬EEPROM的優點

  • 降低設計成本:EEPROM通常提供較小的存儲容量,但單位容量的成本可能較高。Flash存儲器通常提供更大的存儲容量,且單位容量的成本較低;
  • 提升寫數據速度:FLASH模擬EEPROM,寫數據前是先整體擦除區域,再對同一個扇區或頁分段寫入數據,寫入過程中不再涉及擦除FLASH操作,提升了寫數據的速度;
  • 提高寫數據次數:FLASH擦寫數據是有次數限制的,單個扇區或頁通過偏移地址可多次寫數據后再擦除 FLASH,極大減少了FLASH擦除次數,提高了可寫數據的次數;
  • 提高集成度:使用單片機的內置Flash減少了外部組件的數量,簡化了電路設計和布局;

核心優勢對比

優勢維度傳統EEPROMFLASH模擬方案
硬件成本需要獨立芯片復用現有FLASH
存儲容量通常<512KB可擴展至MB級別
系統集成度需要額外接口電路片上集成
可移植性依賴特定硬件純軟件實現
功耗表現靜態功耗較高靜態功耗趨近于零

4. 實戰項目工程代碼

可使用的flash 軟件模擬EEPROM lib功能庫 :https://download.csdn.net/download/weixin_43176196/90797265

flash 軟件模擬EEPROM 項目工程程序 :https://download.csdn.net/download/weixin_43176196/90789413


需將功能模塊 eepromSoft 添加到工程下,并實現 flash讀寫操作.具體應用如下

4.1 通用接口定義

eepromSoft.h
//  eeprom 可分配使用的個數, 最大不超過 5
#define  EPROM_SOFT_NUM   (5 )// 分配頁緩沖區大小, 該數值必須為使用 pageSize 最大的一個 EEPROM_SOFT_INDEX 的 pageSize
#define EPROM_BUF_DATA_SIZE  (128 * 2)typedef int32_t EEPROM_SOFT_INDEX; // 索引類型// eeprom 錯誤碼
typedef enum{EPROM_ERR_NORMAL     = 0, // 正常EPROM_ERR_UNDEFINE,       // 未知錯誤,可能為傳入的參數無效EPROM_ERR_MEMBUF,         // 數據緩沖區設置出錯EPROM_ERR_READ,           // 讀失敗EPROM_ERR_WRITE,          // 寫錯誤EPROM_ERR_ERASE,          // 擦除扇區錯誤EPROM_ERR_OVER_DATA,      // 數據過大,會超出頁大小EPROM_ERR_PAGE_SIZE,      // 分配的頁大小不正確EPROM_ERR_ADDR,           // 分配的 falsh 的 adrrStart 或 adrrEnd 不正確EPROM_ERR_FUNC,           // 設置的函數指針無效EPROM_ERR_SOFT_NUM,       // 分配的個數不足,需設大 EPROM_SOFT_NUMEPROM_ERR_NUM_SET,        // EPROM_SOFT_NUM 設置不符合要求EPROM_ERR_LOCK,           // 加鎖失敗EPROM_ERR_INDEX,          // 未知索引號EPROM_ERR_NUM
}EPROM_ERR;/* eeprom 基準信息數據結構 */
typedef struct{uint32_t adrrStart; // 分配的 flash 扇區起始地址(此地址必須為4的倍數,且不能為0)uint32_t adrrEnd;   // 分配的 flash 扇區結束地址(此地址必須為4的倍數)// 設置的頁大小(該數值必須是 128 的倍數),進行 falsh 的頁分配,單位:Byte // 頁大小并不代碼實際存放數據的最大長度,每頁里面會保存基準信息uint32_t pageSize;  /* flash 讀函數指針,// flashAddr,要讀取數據的flash地址;// buf, 讀取數據緩沖的指針// readLen, 要讀取數據的長度(單位:字節)// 返回, 實際讀取到的數據長度  */uint32_t (*fRead)(uint32_t flashAddr, uint8_t *buf, uint32_t readLen);/* flash 寫函數指針(不帶擦除扇區寫入數據),// flashAddr,開始寫入數據的flash地址;// data, 要寫入的數據指針// len, 要寫入的數據長度(單位:字節)// 返回, 0, 寫入成功//       1, 寫入失敗*/uint8_t (*fWrite)(uint32_t flashAddr,const uint8_t *data, uint32_t len);/* flash 擦除函數指針,// flashAddr,要擦除flash數據的起始地址;// len, 要擦除數據的數據長度(單位:字節)// 返回, 0, 成功//       1, 失敗*/uint8_t (*fErase)(uint32_t flashAddr, uint32_t len);}EPROM_SOFT_INFO;// 聲明外部其他文件定義的 crc32校驗函數; 若只模擬一個eeprom 可進行簡單求和校驗 .
extern uint32_t AlgorithCrc32(const uint8_t* data, uint32_t len); /*!* * @param[in]  timeOutMs :毫秒超時時間* @param[out] none* @return 1 :加鎖成功* @return 0 :加鎖失敗* * @brief  聲明外部其他文件定義的 加鎖保護機制.* @note  . 主要用于 EPROM_BUF_DATA_SIZE 分配的數據緩沖區資源保護;*        */
extern uint8_t EepromSoftLock(uint32_t timeOutMs);extern void EepromSoftUnLock(void); // 釋放鎖/*!* * @param[in]  num : eeprom 可模擬的個數,取值 1 - 10;* @param[in]  pageBuf : 要分配的頁緩沖區指針;* @param[in]  pageSize : 頁緩沖區的大小(必須為 128的倍數,單位:字節);* @param[out] none* @return EPROM_ERR 錯誤碼* * @brief  模擬eeprom 公共資源分配設置* @note   . 必須在 EepromSoftInit() 函數使用前,調用該函數執行一次;*        */
EPROM_ERR EepromSoftSet(uint8_t num, uint8_t* pageBuf, uint32_t pageSize);/*!* * @param[in]  info : 要配置的基準信息結構指針* @param[out] errCode :EPROM_ERR 返回指針,存放返回的錯誤碼* @return >=0的數值 : eeprom 索引號* @return 其他值: 出錯* * @brief  初始化基準信息,若成功,就返回對應 eeprom 的索引號.* @note   . 該操作會檢測分配的地址是否正確,并獲取上次寫入有效數據的基準信息;*         . 若未獲取到有效基準信息,就擦除扇區,從起始地址開始讀/寫數據;*        */
EEPROM_SOFT_INDEX EepromSoftInit(EPROM_SOFT_INFO* info, EPROM_ERR* errCode);/*!* * @param[in]  index :eeprom索引號* @param[in]  buf :數據緩沖區,存放讀取到的數據* @param[in]  readLen :要讀取的數據長度* @param[out] errCode :EPROM_ERR 返回指針,存放返回的錯誤碼* @return 實際讀取到的數據長度* * @brief  讀數據* @note   . 從上次成功寫入數據的地址讀取數據;*        */
uint32_t EepromSoftRead(EEPROM_SOFT_INDEX index, uint8_t *buf, uint32_t readLen, EPROM_ERR* errCode);/*!* * @param[in]  index :eeprom索引號* @param[in]  data: 要寫入的數據指針* @param[in]  len:要寫入的數據長度* @param[out] none* @return PROM_ERR 錯誤碼* * @brief  寫入數據* @note   . 寫數據之前會將上次成功寫入的地址進行偏移,若數據成功寫入數據,就記錄該地址;*        */
EPROM_ERR EepromSoftWrite(EEPROM_SOFT_INDEX index, uint8_t *data, uint32_t len);

使用方法:

    1. 在其他文件,實現函數 AlgorithCrc32()、 EepromSoftLock() 、 EepromSoftUnLock() ;
    1. EepromSoftSet() 分配模擬 eeprom的個數,頁緩沖區(多個eeprom的公共緩沖區);
      該函數必須在 EepromSoftInit() 使用之前調用一次;
    1. EepromSoftInit() 初始化 eeprom 的基準信息,初始化成功會返回 EEPROM_SOFT_INDEX 索引號 ;
    1. EepromSoftRead()、 EepromSoftWrite() 進行數據讀、寫操作;

4.2 接口應用

/* USER CODE BEGIN 4 */// 定義 crc32校驗
uint32_t AlgorithCrc32(const uint8_t* data, uint32_t len)
{uint32_t val = 0;for(int i = 0; i < len; i++){val += data[i];}return val;
}// 定義保護鎖機制
uint8_t s_LockStatus = 0;
uint8_t EepromSoftLock(uint32_t timeOutMs)
{s_LockStatus = 1;return s_LockStatus;
}// 釋放鎖
void EepromSoftUnLock(void)
{s_LockStatus = 0;
}// 定義模擬 eeprom 緩沖區
static uint8_t s_EepromBuf[EPROM_BUF_DATA_SIZE];EEPROM_SOFT_INDEX s_EepronIndex1 = -1, s_EepronIndex2 = -1; // 定義索引變量void TestFlashHandle(void)
{unsigned char buf[20 + 8] = {0x11, 0x22, 0x33, 0x44, 0x55};EPROM_ERR errCode = 0;uint32_t len = 0;EPROM_SOFT_INFO eepromInfo;// 設置 eeprom 公共資源分配errCode =  EepromSoftSet(EPROM_SOFT_NUM, s_EepromBuf, EPROM_BUF_DATA_SIZE);// 模擬 第一個 eepromeepromInfo.adrrStart = FLASH_ADDR_SECTOR_9;   // 設置模擬eeprom 的扇區起始地址eepromInfo.adrrEnd   = FLASH_ADDR_SECTOR_10; // 設置模擬eeprom 的扇區結束地址eepromInfo.pageSize  = 128; // 每次寫數據操作的flash大小(最小128)eepromInfo.fErase    = FlashHardErase;eepromInfo.fRead     = FlashHardRead;eepromInfo.fWrite    = FlashWriteNoErase;s_EepronIndex1 = EepromSoftInit(&eepromInfo, &errCode); // 初始化基準信息if(s_EepronIndex1 < 0) {return ;}// 寫數據buf[16] = 0xAA;buf[17] = 0xBB;buf[18] = 0xCC;buf[19] = 0xDD;errCode = EepromSoftWrite(s_EepronIndex1, buf, 20);// 讀數據memset(buf, 0, 20);len = EepromSoftRead(s_EepronIndex1, buf, 20, &errCode);// 模擬 第二個 eepromeepromInfo.adrrStart = FLASH_ADDR_SECTOR_10;   // 設置模擬eeprom 的扇區起始地址eepromInfo.adrrEnd   = FLASH_ADDR_SECTOR_11; // 設置模擬eeprom 的扇區結束地址eepromInfo.pageSize  = EPROM_BUF_DATA_SIZE; // 每次寫數據操作的flash大小(最小128)eepromInfo.fErase    = FlashHardErase;eepromInfo.fRead     = FlashHardRead;eepromInfo.fWrite    = FlashWriteNoErase;s_EepronIndex2 = EepromSoftInit(&eepromInfo, &errCode); // 初始化基準信息if(s_EepronIndex2 < 0) {return ;}// 寫數據buf[16] = 0xA1;buf[17] = 0xB1;buf[18] = 0xC1;buf[19] = 0xD1;errCode = EepromSoftWrite(s_EepronIndex2, buf, 20);// 讀數據memset(buf, 0, 20);len = EepromSoftRead(s_EepronIndex2, buf, 20, &errCode);// 再讀取 s_EepronIndex1 ,觀察是否有變化memset(buf, 0, 20);len = EepromSoftRead(s_EepronIndex1, buf, 20, &errCode);}




本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/904793.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/904793.shtml
英文地址,請注明出處:http://en.pswp.cn/news/904793.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

探索Stream流:高效數據處理的秘密武器

不可變集合 stream流 Stream流的使用步驟&#xff1a; 先得到一條Stream流&#xff08;流水線&#xff09;&#xff0c;并把數據放上去 使用中間方法對流水線上的數據進行操作 使用終結方法對流水線上的數據進行操作 Stream流的中間方法 注意1&#xff1a;中間方法&#xff0…

vue3筆記(自存)

1. Vue3簡介 2020年9月18日&#xff0c;Vue.js發布版3.0版本&#xff0c;代號&#xff1a;One Piece&#xff08;n 經歷了&#xff1a;4800次提交、40個RFC、600次PR、300貢獻者 官方發版地址&#xff1a;Release v3.0.0 One Piece vuejs/core 截止2023年10月&#xff0c;最…

實驗4 mySQL查詢和視圖

一、實驗目的 掌握SELECT語句的基本語法多表連接查詢GROUP BY的使用方法。ORDER BY的使用方法。 二、實驗步驟、內容、結果 實驗內容&#xff1a; 實驗4.1數據庫的查詢 目的與要求 (1)掌握SELECT語句的基本語法。 (2)掌握子查詢的表示。 (3)掌握連接查詢的表示。 (4)掌…

【bug】fused_bias_act_kernel.cu卡住沒反應

簡述 在推理人臉修復face restoration算法 GPEN的時候&#xff0c;發現有時候fused_bias_act_kernel.cu卡住沒反應。 解決 清理下緩存&#xff0c;讓程序自己再編譯下

.net/C#進程間通信技術方案總結

C# 應用進程間通信(IPC)技術方案 進程間通信(Inter-Process Communication, IPC)是不同進程之間交換數據和消息的機制。以下是C#中常用的IPC技術方案&#xff1a; 1. 命名管道(Named Pipes) 適用于本地機器上的進程通信&#xff0c;支持雙向通信。 ??服務端示例??&…

阿里云服務器數據庫故障排查指南?

阿里云服務器數據庫故障排查指南? 以下是針對阿里云服務器&#xff08;如ECS自建數據庫或阿里云RDS等托管數據庫&#xff09;的故障排查指南&#xff0c;涵蓋常見問題的定位與解決方案&#xff1a; 一、數據庫連接失敗 檢查網絡連通性 ECS自建數據庫 確認安全組規則放行數據庫…

深度學習 ———— 遷移學習

遷移學習原理 什么是遷移學習&#xff1f; 遷移學習利用在大規模數據集&#xff08;如ImageNet&#xff09;上預訓練的模型&#xff0c;改裝小數據集&#xff08;如CIFAR-10&#xff09;。優勢&#xff1a; 減少訓練時間&#xff1a;預訓練模型已學習通用特征&#xff08;如邊…

單調棧模版型題目(3)

單調棧型題目貢獻法 基本模版 這是數組a中的 首先我們要明白什么叫做貢獻&#xff0c;在一個數組b{1,3,5}中&#xff0c;連續包含1的連續子數組為{1}&#xff0c;{1,3}&#xff0c;{1,3,5}&#xff0c;一共有三個&#xff0c;這三個數一共能組成6個連續子數組&#xff0c;而其…

日常知識點之隨手問題整理(思考單播,組播,廣播哪個更省帶寬)

新入職的公司在某些場景下無腦使用組播技術&#xff0c;自己突然就意識到一個問題&#xff1a;單播&#xff0c;組播&#xff0c;廣播&#xff0c;哪個更省帶寬&#xff1f; 有所收獲&#xff0c;做點筆記&#xff0c;僅僅是個人理解~ 1&#xff1a;簡單理解 單播&#xff1…

R1-Omni

一、Omni概述 Omni 文本視頻音頻&#xff0c;全模態。 R1Omni 強化學習全模態。 二、Omni舉例-humanOmni humanOmni&#xff1a;以人體姿態和人物交互為中心的全模態模型。 visual projector有3個&#xff0c;分別負責人臉標簽、姿態檢測、人和物交互。有點像moe。text enc…

linux中的日志分割

1.問題背景&#xff0c;nginx日志過大不好刪除 [rootlocalhost cron.daily]# cd /lk/nginx/log/ [rootlocalhost log]# ll 總用量 2386188 -rw-r--r--. 1 root root 2078699697 5月 9 13:02 access.log -rw-r--r--. 1 root root 11138 5月 6 10:28 error.log [rootloc…

華為云Flexus+DeepSeek征文|從開通到應用:華為云DeepSeek-V3/R1商用服務深度體驗

前言 本文章主要講述在華為云ModelArts Studio上 開通DeepSeek-V3/R1商用服務的流程&#xff0c;以及開通過程中的經驗分享和使用感受幫我更多開發者&#xff0c;在華為云平臺快速完成 DeepSeek-V3/R1商用服務的開通以及使用入門注意&#xff1a;避免測試過程中出現部署失敗等問…

【機器學習-線性回歸-5】多元線性回歸:概念、原理與實現詳解

線性回歸是機器學習中最基礎且廣泛應用的算法之一&#xff0c;而多元線性回歸則是其重要擴展。本文將全面介紹多元線性回歸的核心概念、數學原理及多種實現方式&#xff0c;幫助讀者深入理解這一強大的預測工具。 1. 多元線性回歸概述 1.1 什么是多元線性回歸 多元線性回歸(…

GOC指令

網絡版GoC常見繪圖命令說明 &#xff08;V3.8&#xff09; 目錄 l 基本畫圖命令 fd, bk, lt, rt l 設置筆狀態命令 c, rgb, size, up, down l 狀態命令 show, hide, speed, showXY, wait, pause, cls, clsRec l 增強畫圖命令 o, oo, e, ee, r, rr l 坐標命令 moveTo, lineTo, g…

Qt獲取CPU使用率及內存占用大小

Qt 獲取 CPU 使用率及內存占用大小 文章目錄 Qt 獲取 CPU 使用率及內存占用大小一、簡介二、關鍵函數2.1 獲取當前運行程序pid2.2 通過pid獲取運行時間2.3 通過pid獲取內存大小 三、具體實現五、寫在最后 ? 一、簡介 近期在使用軟件的過程中發現一個有意思的東西。如下所示&a…

期刊論文寫作注意點

下面給出關于期刊寫作的幾個關鍵注意點 一、摘要突出創新點 最重要的是論文的摘要&#xff0c;因為在論文送審的時候&#xff0c;編輯如果沒有時間&#xff0c;最先看的就是摘要。摘要要寫好。如果投的是頂刊&#xff0c;在摘要里面盡量不要寫是在什么方法的基礎上進行改進之類…

Swagger 3.0 中注解詳細示例

Swagger 3.0 提供了豐富的注解來詳細描述 API 的請求和響應。以下是一個使用 Operation、Parameter、RequestBody 和 ApiResponse 注解的示例&#xff0c;展示了如何設置請求頭、請求參數、路徑變量、請求體和響應體。代碼中未使用 DTO 對象&#xff0c;而是使用 Map 來傳遞參數…

切比雪夫不等式專題習題解析

切比雪夫不等式專題習題解析 前言 本文為概率論習題集專欄的切比雪夫不等式專題習題解析,針對習題篇中的10道題目提供詳細解答。希望通過這些解析幫助大家深入理解切比雪夫不等式的應用和意義。 一、基礎概念題解析 習題1解析: 錯誤。切比雪夫不等式適用于任何具有有限方…

軟件測試的概念

需求的概念 開發模型 測試模型 1. 什么是需求 在多數軟件公司&#xff0c;會有兩部分需求&#xff0c;?部分是??需求&#xff0c;?部分是軟件需求。 1.1 ??需求 ??需求&#xff1a;可以簡單理解為甲?提出的需求&#xff0c;如果沒有甲?&#xff0c;那么就是終端??…

前端面試每日三題 - Day 29

這是我為準備前端/全棧開發工程師面試整理的第29天每日三題練習&#xff1a; ? 題目1&#xff1a;Web Components技術全景解析 核心三要素 Custom Elements&#xff08;自定義元素&#xff09; class MyButton extends HTMLElement {constructor() {super();this.attachShado…