ESP32學習與快速總結——5.系統存儲

1.ESP32分區表

  • 為什么ESP32要分區? ? 00:34--
    • 簡述:其他單片機生成文件少,功能少,而ESP32功能多,文件多? ? ? ?
  • 分區表各個文件簡介? ?--7:31
  • vscode查看分區表? --9:33
  • ota通過idf.py menuconfig配置命令調出配置菜單? --12.35
  • 創建自己的分區? --17.41
  • 寫.c文件
    • #include <stdio.h>
      #include "esp_partition.h"
      #include "esp_log.h"
      #include <string.h>static const char* TAG = "partition";   //TAG 區分日志#define USER_PARTITION_TYPE 0x40
      #define USER_PARTITION_SUBTYPE 0x00     //定義分區類型static const esp_partition_t* partition_user = NULL;    //定義分區指針操作分區的void app_main(void)
      {//找到自定義的分區,找得到之后會返回分區指針/*知識點1find與find_first的區別 --21.10find_first: 找到第一個符合條件的分區find: 找到符合條件的所有分區*/partition_user = esp_partition_find_first(USER_PARTITION_TYPE, USER_PARTITION_SUBTYPE, NULL); if (partition_user == NULL) {ESP_LOGE(TAG, "Failed to find user partition");return;}esp_partition_erase_range(partition_user, 0, 0x1000);    //擦除分區const char *data = "Hello, ESP32!";esp_partition_write(partition_user, 0, data, strlen(data));    //寫入分區 char buffer[100];memset(buffer, 0, sizeof(buffer));esp_partition_read(partition_user, 0, buffer,strlen(data));     //讀取分區ESP_LOGI(TAG, "Read from user partition: %s", buffer);return;}
      

補充1:分區表

# Name, ? Type, SubType, Offset, ?Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, ? ? ?data, nvs, ? ? , ? ? ? ?0x6000,
phy_init, data, phy, ? ? , ? ? ? ?0x1000,
factory, ?app, ?factory, , ? ? ? ?1M,
user, ? ? 0x40, 0x01, ? ?, ? ? ? ?0x1000, ?

列含義
  • Name:分區的名稱,方便識別和引用。
  • Type:分區的類型,常見有?app(應用程序)、data(數據),也可以用十六進制表示自定義類型。
  • SubType:分區類型的子類型,進一步細分分區用途。
  • Offset:分區在存儲設備上的起始偏移地址。
  • Size:分區的大小,可以用十六進制(如?0x1000)或單位(如?1M)表示。
  • Flags:分區的額外標志,可選字段。

每行解釋

  • nvs:非易失性存儲分區,用于存儲系統和應用的配置信息。Type?為?dataSubType?為?nvs,大小是?0x6000
  • phy_init:物理層初始化數據分區,存儲與硬件物理層初始化相關的數據。Type?為?dataSubType?為?phy,大小是?0x1000
  • factory:工廠應用分區,用于存儲出廠默認的應用程序。Type?為?appSubType?為?factory,大小是?1M
  • user:自定義分區,Type?是十六進制?0x40SubType?是?0x01,大小是?0x1000,可用于用戶自定義的數據或應用。

補充2 OTA

OTA 分區作用

設備軟件更新時,新固件先下載到 OTA 分區,驗證通過后,系統從該分區加載新固件,避免直接覆蓋運行中的程序,提升更新安全性與可靠性。

OTA 分區常見配置示例及解釋
# Name,   Type, SubType, Offset,  Size, Flags
ota_0,    app,  ota_0,   ,        1M,
ota_1,    app,  ota_1,   ,        1M,
  • Name:常見的 OTA 分區名稱有 ota_0 和 ota_1,系統會在這兩個分區間切換來實現固件更新。
  • Type:分區類型為 app,用于存儲應用程序固件。
  • SubType:ota_0 和 ota_1 是 OTA 分區的子類型,可區分不同 OTA 槽位,讓系統確定當前使用的分區。
  • Offset:即分區在存儲設備上的起始偏移地址,留空由系統自動分配。
  • Size:每個 OTA 分區大小設為 1M,最多能存儲 1MB 的應用程序固件。

設備實際使用時,通過 ota_0 和 ota_1 分區交替實現更新。若當前運行 ota_0 固件,新固件下載至 ota_1,驗證通過后,下次啟動便從 ota_1 加載新固件 。

本章脈絡?

2.ESP中的NVS?

如何更方便的管理NVS存儲操作

  • 背景? ---3.20
  • 操作??
    • 新建nvs測試程序
      • 創建項目文件夾
        • esp32下idf.py create-project nvs_test
        • nvs_test下idf.py build
        • VScode下打開文件夾
      • 代碼
        • 定義兩個命名空間,兩個空間中有相同的鍵,向這兩個鍵寫入不同的值,觀察他們會不會受到影響
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_err.h"#define NAME_SPACE_WIFI1 "wifi1"
#define NAME_SPACE_WIFI2 "wifi2"#define KEY_SSID_KEY "ssid"
#define KEY_PASSWORE_KEY "password"void nvs_blob_read(const char *name_space, const char *key, void *buffer, int maxlen)
{nvs_handle_t nvs_handle; //用于存儲NVS分區的句柄size_t length = 0;nvs_open(name_space, NVS_READONLY, &nvs_handle);nvs_get_blob(nvs_handle, key, (void*)&length, &length); //讀取鍵數據,并獲取鍵數據的長度(主要是這個)if (length && length <= maxlen) //如果鍵數據存在且長度不超過maxlen{nvs_get_blob(nvs_handle, key, buffer, &length); //讀取鍵數據}else{printf("nvs_blob_read: %s is not exist or too long\n", key); //打印錯誤信息}nvs_close(nvs_handle); //關閉NVS分區
}void app_main(void)
{nvs_handle_t nvs_handle1;esp_err_t ret = nvs_flash_init();   //初始化NVS分區if (ret != ESP_OK) {                 //如果初始化失敗,擦除NVS分區,再初始化NVS分區nvs_flash_erase();               //擦除NVS分區ESP_ERROR_CHECK(nvs_flash_init()); //ESP_ERROR_CHECK()是一個宏定義,用于檢查函數的返回值,如果返回值不為ESP_OK,則打印錯誤信息并終止程序}/*命名空間1 NVS寫入*/nvs_open(NAME_SPACE_WIFI1, NVS_READWRITE, &nvs_handle1); //打開NVS分區,讀寫模式nvs_set_blob(nvs_handle1, KEY_SSID_KEY, "wifi_esp32", strlen("wifi_esp32")); //寫入鍵數據nvs_set_blob(nvs_handle1, KEY_PASSWORE_KEY, "12345678", strlen("12345678")); //寫入密碼數據// strlen()函數是一個C語言庫函數,用于計算字符串的長度。nvs_commit(nvs_handle1); //提交數據/*如果不調用nvs_commit()函數,那么數據將不會被寫入到NVS分區中(flash)。寫入的時機要跟隨系統走如果調用nvs_commit()函數,那么數據將立即被寫入到NVS分區中(flash)。不許推遲寫入*/nvs_close(nvs_handle1); //關閉NVS分區/*命名空間2 NVS寫入*/ nvs_open(NAME_SPACE_WIFI2, NVS_READWRITE, &nvs_handle1); //打開NVS分區,讀寫模式nvs_set_blob(nvs_handle1, KEY_SSID_KEY, "hello,world", strlen("hello,world")); //寫入鍵數據nvs_set_blob(nvs_handle1, KEY_PASSWORE_KEY, "654321", strlen("654321")); //寫入密碼數據nvs_commit(nvs_handle1); //提交數據nvs_close(nvs_handle1); //關閉NVS分區vTaskDelay(1000 / portTICK_PERIOD_MS); //延時1秒char read_buffer[64];//用于存儲鍵數據//命名空間WIFI1 SSID的值memset(read_buffer, 0, sizeof(read_buffer)); //清空read_buffer數組nvs_blob_read(NAME_SPACE_WIFI1, KEY_SSID_KEY, read_buffer, sizeof(read_buffer)); //讀取鍵數據ESP_LOGI("NVS", "namespace: %s , key:%s -> value:%s", NAME_SPACE_WIFI1,KEY_SSID_KEY,read_buffer); //打印鍵數據
//命名空間WIFI1 PASSWORD的值memset(read_buffer, 0, sizeof(read_buffer)); nvs_blob_read(NAME_SPACE_WIFI1, KEY_SSID_KEY, read_buffer, sizeof(read_buffer)); ESP_LOGI("NVS", "namespace: %s , key:%s -> value:%s", NAME_SPACE_WIFI1,KEY_PASSWORE_KEY,read_buffer); 
//命名空間WIFI2 SSID的值memset(read_buffer, 0, sizeof(read_buffer)); nvs_blob_read(NAME_SPACE_WIFI2, KEY_SSID_KEY, read_buffer, sizeof(read_buffer)); ESP_LOGI("NVS", "namespace: %s , key:%s -> value:%s", NAME_SPACE_WIFI2,KEY_SSID_KEY,read_buffer); 
//命名空間WIFI2 PASSWORD的值memset(read_buffer, 0, sizeof(read_buffer)); nvs_blob_read(NAME_SPACE_WIFI2, KEY_SSID_KEY, read_buffer, sizeof(read_buffer)); ESP_LOGI("NVS", "namespace: %s , key:%s -> value:%s", NAME_SPACE_WIFI2,KEY_PASSWORE_KEY,read_buffer); 
}

3.ESP32中的SPIFFS文件系統

  • 新建SPIFFS測試程序
    • 創建項目文件夾----4.00
      • esp32下idf.py create-project spiffs_test
      • spiffs_test下 cp ../esp-idf/components/partition_table/partitions_singleapp.csv .
        • 注意這個partitions,這里后面的s不要拉下
        • 不要忘了后面有個點
      • 通過idf.py menuconfig指定分區表
      • spiffs_test下idf.py build
      • VScode下打開文件夾
      • 改分區表? 5.48--6.30
        • 記得改成512k而不是1M,后面會改
    • 代碼
      • 配置spiffs文件系統
        • esp_vfs_spiffs_register具體實現邏輯? 9.10

      • 文件操作

        • 文件打開
          • f = fopen("/spiffs/hello.txt","r");?嘗試以只讀模式打開位于 SPIFFS 文件系統下的?hello.txt?文件。如果打開失敗(f?為?NULL),則通過?ESP_LOGE?輸出錯誤日志并返回,結束當前函數執行。
        • 文件讀取
          • fgets(line,sizeof(line),f);?使用?fgets?函數從打開的文件?f?中讀取一行內容,存儲到字符數組?line?中,最多讀取?sizeof(line) - 1?個字符。
          • fclose(f);?讀取完成后關閉文件。
        • 處理換行符
          • char *pos = strchr(line,'\n');?查找字符數組?line?中第一次出現換行符?\n?的位置。
          • 如果找到換行符(pos?不為?NULL),則將該位置的字符設置為?'\0',即把換行符替換為字符串結束符,從而去掉換行符。
        • 日志輸出
          • ESP_LOGI("spiffs","read str:%s",line);?使用?ESP_LOGI?輸出讀取到的字符串內容。
        • 文件系統注銷
          • esp_vfs_spiffs_unregister(conf.partition_label);?注銷之前注冊的 SPIFFS 文件系統,這里的?conf?應該是之前定義好的配置結構體,partition_label?是文件系統分區標簽。

????????VFS(虛擬文件系統)是一個抽象層,它讓操作系統能以統一的方式管理不同類型的文件系統,就像一個萬能的 “翻譯官”,讓你不用管具體的文件系統差異,就能方便地操作文件。

????????抽象層是一種編程和系統設計里常用的概念。

????????現實中存在很多不同類型的文件系統,比如 FAT、NTFS、ext4 等,它們存儲和管理文件的方式各不相同。

????????抽象層就像是一個 “翻譯官” 和 “協調者”。VFS 作為抽象層,把不同文件系統的具體操作細節都隱藏起來,給操作系統和用戶程序提供一套統一的接口。無論你用的是哪種底層文件系統,操作系統和程序都可以通過這套統一接口來進行文件的創建、讀取、修改、刪除等操作。

????????這樣一來,操作系統和程序開發者就不用關心具體是哪種文件系統在工作,降低了開發和使用的復雜度。

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_spiffs.h"
#include "esp_err.h"
#include "esp_log.h"
#include <string.h>void app_main(void)
{// 定義 SPIFFS 配置結構體esp_vfs_spiffs_conf_t conf = {.base_path = "/spiffs",         // 掛載基礎路徑.format_if_mount_failed = true, // 掛載失敗時格式化.max_files = 5,                 // 最大可打開文件數.partition_label = NULL         // 分區標簽為 NULL};// 注冊 SPIFFS 文件系統esp_err_t ret = esp_vfs_spiffs_register(&conf);if (ret != ESP_OK) {ESP_LOGE("spiffs", "spiffs mount fail!");return;}// 檢查 SPIFFS 分區完整性ret = esp_spiffs_check(conf.partition_label);if (ret != ESP_OK) {ESP_LOGE("spiffs", "spiffs check fail!");return;}// 獲取 SPIFFS 分區信息size_t total = 0, used = 0;ret = esp_spiffs_info(conf.partition_label, &total, &used);if (ret != ESP_OK) {ESP_LOGE("spiffs", "spiffs info fail!");return;}ESP_LOGI("spiffs", "spiffs total size:%d,used:%d", total, used);// 若使用空間大于總空間,再次檢查分區完整性if (used > total) {ret = esp_spiffs_check(conf.partition_label);if (ret != ESP_OK) {ESP_LOGE("spiffs", "used > total & spiffs check fail!");return;}}// 以寫入模式打開文件FILE *f = fopen("/spiffs/helloworld.txt", "w");if (f == NULL) {ESP_LOGE("spiffs", "Failed to open file");return;}// 寫入內容fprintf(f, "Hello, World!\n");// 關閉寫入的文件fclose(f);// 延時 1 秒vTaskDelay(pdMS_TO_TICKS(1000));// 以讀取模式打開文件f = fopen("/spiffs/helloworld.txt", "r");if (f == NULL) {ESP_LOGE("spiffs", "Failed to open file for read");return;}// 讀取文件一行內容char line[64];fgets(line, sizeof(line), f);// 關閉讀取的文件fclose(f);// 去除換行符char *pos = strchr(line, '\n');if (pos) {*pos = 0;}// 打印讀取的內容ESP_LOGI("spiffs", "read str:%s", line);// 注銷 SPIFFS 文件系統esp_vfs_spiffs_unregister(conf.partition_label);
}

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

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

相關文章

Linux 進程控制(自用)

非阻塞調用waitpid 這樣父進程就不會阻塞&#xff0c;此時循環使用我們可以讓父進程執行其他任務而不是阻塞等待 進程程序替換 進程PCB加載到內存中的代碼和數據 替換就是完全替換當前進程的代碼段、數據段、堆和棧&#xff0c;保存當前的PCB 代碼指的是二進制代碼不是源碼&a…

Spring 微服務解決了單體架構的哪些痛點?

1. 部署困難 (Deployment Difficulty & Risk) 單體痛點: 整體部署: 對單體應用的任何微小修改&#xff08;哪怕只是一行代碼&#xff09;&#xff0c;都需要重新構建、測試和部署整個龐大的應用程序。部署頻率低: 由于部署過程復雜且風險高&#xff0c;發布周期通常很長&a…

面試題之高頻面試題

最近開始面試了&#xff0c;410面試了一家公司 針對自己薄弱的面試題庫&#xff0c;深入了解下&#xff0c;也應付下面試。在這里先祝愿大家在現有公司好好沉淀&#xff0c;定位好自己的目標&#xff0c;在自己的領域上發光發熱&#xff0c;在自己想要的領域上&#xff08;技術…

【MySQL】Read view存儲的機制,記錄可見分析

read view核心組成 1.1 事務id相關 creator_trx_id: 創建該read view的事務id 每開啟一個事務都會生成一個 ReadView&#xff0c;而 creator_trx_id 就是這個開啟的事務的 id。 m_ids: 創建read view時系統的活躍事務&#xff08;未提交的事務&#xff09;id集合 當前有哪些事…

【刷題Day20】TCP和UDP(淺)

TCP 和 UDP 有什么區別&#xff1f; TCP提供了可靠、面向連接的傳輸&#xff0c;適用于需要數據完整性和順序的場景。 UDP提供了更輕量、面向報文的傳輸&#xff0c;適用于實時性要求高的場景。 特性TCPUDP連接方式面向連接無連接可靠性提供可靠性&#xff0c;保證數據按順序…

Flink 內部通信底層原理

Flink 集群內部節點之間的通信是用 Akka 實現,比如 JobManager 和 TaskManager 之間的通信。而 operator 之間的數據傳輸是用 Netty 實現。 RPC 框架是 Flink 任務運行的基礎,Flink 整個 RPC 框架基于 Akka 實現。 一、相關概念 RPC(Remote Procedure Call) 概念 定義:…

企業級Kubernetes 1.28高可用集群離線部署全指南(含全組件配置)

企業級Kubernetes 1.28高可用集群離線部署全指南(含全組件配置) 摘要:本文手把手教學在無外網環境下部署生產級Kubernetes 1.28高可用集群,涵蓋ETCD集群、HAProxy+Keepalived負載均衡、Containerd運行時、Calico網絡插件及Kuboard可視化管理全流程。提供100年有效證書配置…

【中間件】redis使用

一、redis介紹 redis是一種NoSQL類型的數據庫&#xff0c;其數據存儲在內存中&#xff0c;因此其數據查詢效率很高&#xff0c;很快。常被用作數據緩存&#xff0c;分布式鎖 等。SpringBoot集成了Redis&#xff0c;可查看開發文檔Redis開發文檔。Redis有自己的可視化工具Redis …

C語言——函數遞歸與迭代

各位CSDN的uu們大家好呀&#xff0c;今天將會給大家帶來關于C語言的函數遞歸的知識&#xff0c;這一塊知識理解起來稍微會比較難&#xff0c;需要多花點時間。 話不多說&#xff0c;讓我們開始今天的內容吧&#xff01; 目錄 1.函數遞歸 1.1 什么是遞歸&#xff1f; 1.2 遞歸…

藏品館管理系統

藏品館管理系統 項目簡介 這是一個基于 PHP 開發的藏品館管理系統&#xff0c;實現了藏品管理、用戶管理等功能。 藏品館管理系統 系統架構 開發語言&#xff1a;PHP數據庫&#xff1a;MySQL前端框架&#xff1a;BootstrapJavaScript 庫&#xff1a;jQuery 目錄結構 book/…

centos停服 遷移centos7.3系統到新搭建的openEuler

背景 最近在做的事&#xff0c;簡單來講&#xff0c;就是一套系統差不多有10多臺虛擬機&#xff0c;都是centos系統&#xff0c;版本主要是7.3、7.6、7.9&#xff0c;現在centos停止維護了&#xff0c;轉為了centos stream&#xff0c;而centos stream的定位是&#xff1a;Red …

什么是 IDE?集成開發環境的功能與優勢

原文&#xff1a;什么是 IDE&#xff1f;集成開發環境的功能與優勢 | w3cschool筆記 &#xff08;注意&#xff1a;此為科普文章&#xff0c;請勿標記為付費文章&#xff01;且此文章并非我原創&#xff0c;不要標記為付費&#xff01;&#xff09; IDE 是什么&#xff1f; …

jenkins批量復制Job項目的shell腳本實現

背景 現在需要將“測試” 目錄中的所有job全部復制到 一個新目錄中 test2。可以結合jenkins提供的apilinux shell 進行實現。 測試目錄的實際文件夾名稱是 test。 腳本運行效果如下&#xff1a; [qdevsom5f-dev-hhyl shekk]$ ./copy_jenkins_job.sh 創建文件夾 test2 獲取源…

VisualSVN過期后的解決方法

作為一款不錯的源代碼管理軟件&#xff0c;svn還是有很多公司使用的。在vs中使用svn&#xff0c;大家一般用的都是VisualSVN插件。在30天試用期過后&#xff0c;它就不能被免費使用了。下面給大家講如何免費延長過期時間&#xff08;自定義天數&#xff0c;可以設定一個很大的值…

硬件工程師筆記——電子器件匯總大全

目錄 1、電阻 工作原理 歐姆定律 電阻的物理本質 一、限制電流 二、分壓作用 三、消耗電能&#xff08;將電能轉化為熱能&#xff09; 2、壓敏電阻 伏安特性 1. 過壓保護 2. 電壓調節 3. 浪涌吸收 4. 消噪與消火花 5. 高頻應用 3、電容 工作原理 &#xff08;…

[圖論]Kruskal

Kruskal 本質&#xff1a;貪心&#xff0c;對邊進行操作。存儲結構&#xff1a;邊集數組。適用對象&#xff1a;可為負權圖&#xff0c;可求最大生成樹。核心思想&#xff1a;最短的邊一定在最小生成樹(MST)上&#xff0c;對最短的邊進行貪心。算法流程&#xff1a;對全體邊集…

vulnhub five86系列靶機合集

five86 ~ VulnHubhttps://www.vulnhub.com/series/five86,272/ five86-1滲透過程 信息收集 # 主機發現 nmap 192.168.56.0/24 -Pn ? # 靶機全面掃描 nmap 192.168.56.131 -A -T4 目錄掃描 dirsearch -u http://192.168.56.131/ /robots.txt提示/ona。 /ona二層目錄掃描。 …

如何高效利用呼叫中心系統和AI語音機器人

要更好地使用呼叫中心系統和語音機器人&#xff0c;需要結合兩者的優勢&#xff0c;實現自動化、智能化、高效率的客戶服務與業務運營。以下是優化策略和具體實踐方法&#xff1a; 一、呼叫中心系統優化 1. 智能路由與IVR優化 智能ACD&#xff08;自動呼叫分配&#xff09; …

Nacos安裝及數據持久化

1.Nacos安裝及數據持久化 1.1下載nacos 下載地址&#xff1a;https://nacos.io/download/nacos-server/ 不用安裝&#xff0c;直接解壓縮即可。 1.2配置文件增加jdk環境和修改單機啟動standalone 找到bin目錄下的startup.cmd文件&#xff0c;添加以下語句(jdk路徑根據自己…

【牛客練習賽137 C】題解

比賽鏈接 C. 變化的數組(Easy Version) 題目大意 一個長度為 n n n 的非負數組 a a a&#xff0c;要求執行 k k k 次操作&#xff0c;每次操作如下&#xff1a; 有 1 2 \frac{1}{2} 21? 的概率令 a i ← a i ( a i ? m ) x , ? i ∈ [ 1 , n ] a_i \leftarrow a_…