Arduino ESP8266 使用LittleFS存储配置文件实践

首先引用前辈的文章,了解一下esp8266 的flash 布局layout:

http://idarc.cn/index.php/archives/1156/
ESP8266 flash布局(layout)
支持flash为512KB, 1M, 2M, 4M.
4KB为1个扇区,也就是16进制的0x1000. 4096

非OTA布局
a) 前64个扇区256KB烧写主程序+用户数据+用户参数, 主程序文件名eagle.flash.bin, 最大64KB, 用户参数占用最后4个扇区, 共16KB
b) 后面的部分, 烧写主程序+用户数据+系统参数, 主程序文件名 eagle.irom0text.bin, 最大768KB, 默认200KB. 系统参数占用最后4个扇区, 共16KB.sdk提供. 依次为:
b1) 初始化射频参数,1个扇区, esp_init_data_default.bin
b2) 初始化系统参数,2个扇区, blnk.bin
b3) bootloader, 1个扇区.
64KB主程序+(用户数据)+16KB用户参数

OTA布局
a) 可选前段是256KB, 512KB, 1MB, 后段至少要大于等于前段的大小.
b) 前段包括启动程序+主程序+用户数据+用户参数(后两个扇区为云端KEY). 启动程序boot.bin为4KB, 主程序user1.bin, 用户参数4个扇区16KB的后两个扇区存储乐鑫云端KEY master_device_key.bin
c) 后段包括预留区+主程序+用户数据+系统参数. 预留区4KB, 与启动程序的4KB对应, 主程序user2.bin,实际上是云端下载的缓存区, 事实上也不需要烧录. 系统参数与非OTA布局的相同.

布局文件的位置
在ESP8266_NONOS_SDK/ld/eagle.app.v6.ld中的MEMORY字段.

eagle.flash.bin和eagle.irom0text.bin的构成
eagle.flash.bin是用于存储直接读取到程序内存运行的程序段和数据内存的数据段的.
eagle.irom0text.bin是用于存储放在flash上, 不直接读取到内存中的程序段的.

程序内存:iram, internal ram, 通过ibus访问, 共32KB, 存放编译后的elf的TEXT字段
数据内存:dram, data ram, 通过 dbus访问, 可能是80kb或者96kb. 存放编译后的elf的data, rodata字段, 这部分字段可用约50kB. 其他的空间用于存放BBS, stack, heap.
FLASH存储: irom, 最大768KB, 存放编译后的elf的irom0.text字段, C源码函数前面有ICACHE_FLASH_ATTR前缀的就是说这个函数是放在irom中的. 另, 最大768KB的原因是, irom起始于256KB处, esp8266最大访问1MB程序段, 故1MB - 256KB = 768KB.
具体需要看(sdk中的eagle.app.v6.ld文件)[https://github.com/espressif/ESP8266_RTOS_SDK/blob/master/ld/eagle.app.v6.ld]对这几个存储的地址和大小的分配, 例如:

MEMORY
{dport0_0_seg :                        org = 0x3FF00000, len = 0x10dram0_0_seg :                         org = 0x3FFE8000, len = 0x18000iram1_0_seg :                         org = 0x40100000, len = 0x8000irom0_0_seg :                         org = 0x40220000, len = 0x5C000
}

编译术语
BBS block started By Symbol. 存放未初始化的全局变量, 静态分配
data 已经初始化的全局变量, 静态分配
text 程序执行代码
rodata 字符串与#define常量
heap 堆,动态分配的内存段(malloc, free)
stack 栈, 临时局部变量, 函数调用栈
常量段, 编译器产生的数据

使用 littlefs 保存的地址在何处?
Aduino环境下翻看相关源码,管中窥一下豹:

LittleFS.cpp

FS LittleFS = FS(FSImplPtr(new littlefs_impl::LittleFSImpl(FS_PHYS_ADDR, FS_PHYS_SIZE, FS_PHYS_PAGE, FS_PHYS_BLOCK, FS_MAX_OPEN_FILES)));

参数
FS_PHYS_ADDR, 
FS_PHYS_SIZE, 
FS_PHYS_PAGE,
FS_PHYS_BLOCK, 
FS_MAX_OPEN_FILES


#include <Arduino.h>
#include <stdlib.h>
#include <algorithm>
#include "LittleFS.h"
#include "debug.h"
#include "flash_hal.h"extern "C" {
#include "c_types.h"
#include "spi_flash.h"
}

D:\Mixly_WIN\arduino\portable\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266
文件flash_hal.h

#ifdef ARDUINO
extern "C" uint32_t _FS_start;
extern "C" uint32_t _FS_end;
extern "C" uint32_t _FS_page;
extern "C" uint32_t _FS_block;#define FS_PHYS_ADDR ((uint32_t) (&_FS_start) - 0x40200000)
#define FS_PHYS_SIZE ((uint32_t) (&_FS_end) - (uint32_t) (&_FS_start))
#define FS_PHYS_PAGE ((uint32_t) &_FS_page)
#define FS_PHYS_BLOCK ((uint32_t) &_FS_block)
#endif

arduino IDE 开发板配置
flash size: "4MB (FS:1MB OTA:~1019KB)"
4M1M.build.flash_ld=eagle.flash.4m1m.ld

D:\Mixly_WIN\arduino\portable\packages\esp8266\hardware\esp8266\2.7.4

boards.txt

d1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB)
d1.menu.eesz.4M1M.build.flash_size=4M
d1.menu.eesz.4M1M.build.flash_size_bytes=0x400000
d1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld
d1.menu.eesz.4M1M.build.spiffs_pagesize=256
d1.menu.eesz.4M1M.upload.maximum_size=1044464
d1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
d1.menu.eesz.4M1M.build.spiffs_start=0x300000
d1.menu.eesz.4M1M.build.spiffs_end=0x3FA000
d1.menu.eesz.4M1M.build.spiffs_blocksize=8192
d1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB)
d1.menu.eesz.4M2M.build.flash_size=4M
d1.menu.eesz.4M2M.build.flash_size_bytes=0x400000
d1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld
d1.menu.eesz.4M2M.build.spiffs_pagesize=256
d1.menu.eesz.4M2M.upload.maximum_size=1044464
d1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000
d1.menu.eesz.4M2M.build.spiffs_start=0x200000
d1.menu.eesz.4M2M.build.spiffs_end=0x3FA000
d1.menu.eesz.4M2M.build.spiffs_blocksize=8192
d1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB)
d1.menu.eesz.4M3M.build.flash_size=4M
d1.menu.eesz.4M3M.build.flash_size_bytes=0x400000
d1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld
d1.menu.eesz.4M3M.build.spiffs_pagesize=256
d1.menu.eesz.4M3M.upload.maximum_size=1044464
d1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000
d1.menu.eesz.4M3M.build.spiffs_start=0x100000
d1.menu.eesz.4M3M.build.spiffs_end=0x3FA000
d1.menu.eesz.4M3M.build.spiffs_blocksize=8192
d1.menu.eesz.4M=4MB (FS:none OTA:~1019KB)
d1.menu.eesz.4M.build.flash_size=4M
d1.menu.eesz.4M.build.flash_size_bytes=0x400000
d1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld
d1.menu.eesz.4M.build.spiffs_pagesize=256
d1.menu.eesz.4M.upload.maximum_size=1044464
d1.menu.eesz.4M.build.rfcal_addr=0x3FC000
d1.menu.ip.lm2f=v2 Lower Memory
d1.menu.ip.lm2f.build.lwip_include=lwip2/include
d1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat
d1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0

4M1M其中的配置:
d1.menu.eesz.4M1M.build.flash_size=4M
d1.menu.eesz.4M1M.build.flash_size_bytes=0x400000-----------------4,194,304  (4MB)
d1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld-------------------------
d1.menu.eesz.4M1M.build.spiffs_pagesize=256
d1.menu.eesz.4M1M.upload.maximum_size=1044464-----------------FEFF0==(1MB-4KB)(1,048,576)
d1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000
d1.menu.eesz.4M1M.build.spiffs_start=0x300000
d1.menu.eesz.4M1M.build.spiffs_end=0x3FA000
d1.menu.eesz.4M1M.build.spiffs_blocksize=8192

D:\Mixly_WIN\arduino\portable\packages\esp8266\hardware\esp8266\2.7.4\tools\sdk\ld

eagle.flash.4m1m.ld


/* Flash Split for 4M chips */
/* sketch @0x40200000 (~1019KB) (1044464B) */
/* empty  @0x402FEFF0 (~2052KB) (2101264B) */
/* spiffs @0x40500000 (~1000KB) (1024000B) */
/* eeprom @0x405FB000 (4KB) */
/* rfcal  @0x405FC000 (4KB) */
/* wifi   @0x405FD000 (12KB) */MEMORY
{dport0_0_seg :                        org = 0x3FF00000, len = 0x10dram0_0_seg :                         org = 0x3FFE8000, len = 0x14000iram1_0_seg :                         org = 0x40100000, len = 0x8000irom0_0_seg :                         org = 0x40201010, len = 0xfeff0
}PROVIDE ( _FS_start = 0x40500000 );
PROVIDE ( _FS_end = 0x405FA000 );//-------------------FA000=1000 KB
PROVIDE ( _FS_page = 0x100 );//-------------------256
PROVIDE ( _FS_block = 0x2000 );//-----------------------8192
PROVIDE ( _EEPROM_start = 0x405fb000 );
/* The following symbols are DEPRECATED and will be REMOVED in a future release */
PROVIDE ( _SPIFFS_start = 0x40500000 );
PROVIDE ( _SPIFFS_end = 0x405FA000 );
PROVIDE ( _SPIFFS_page = 0x100 );
PROVIDE ( _SPIFFS_block = 0x2000 );INCLUDE "local.eagle.app.v6.common.ld"

上文
/* sketch @0x40200000 (~1019KB) (1044464B) */
#define FS_PHYS_ADDR ((uint32_t) (&_FS_start) - 0x40200000)---------------300000
这里计算地址为0x300000

引用arduino-esp8266 的filesystem 的doc文章,实践如何上传文件

https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#filesystem

Filesystem
Flash layout
Even though file system is stored on the same flash chip as the program, programming new sketch will not modify file system contents. This allows to use file system to store sketch data, configuration files, or content for Web server.

The following diagram illustrates flash layout used in Arduino environment:

|--------------|-------|---------------|--|--|--|--|--|
^              ^       ^               ^     ^
Sketch    OTA update   File system   EEPROM  WiFi config (SDK)

.。。。。。。。

They share a compatible API but have incompatible on-flash implementations, so it is important to choose one or the per project as attempting to mount a SPIFFS volume under LittleFS may result in a format operation and definitely will not preserve any files, and vice-versa.

它们共享一个兼容的API,但在flash实现上不兼容,因此每个项目选择一个或多个API是很重要的,因为尝试在LittleFS下装载SPIFFS卷可能会导致格式化操作,并且肯定不会保留任何文件,反之亦然。

Uploading files to file system
-----------------------------------------------------
ESP8266FS is a tool which integrates into the Arduino IDE. It adds a menu item to Tools menu for uploading the contents of sketch data directory into ESP8266 flash file system.

ESP8266FS是一个集成到Arduino IDE中的工具。在工具菜单中增加了一个菜单项,用于将草图数据目录的内容上传到ESP8266 flash文件系统中。

工具能把文件打包成SPIFFS映像,上传到flash的文件系统区

Download the tool: https://github.com/esp8266/arduino-esp8266fs-plugin/releases/download/0.5.0/ESP8266FS-0.5.0.zip

In your Arduino sketchbook directory, create tools directory if it doesn’t exist yet.

Unpack the tool into tools directory (the path will look like <home_dir>/Arduino/tools/ESP8266FS/tool/esp8266fs.jar) If upgrading, overwrite the existing JAR file with the newer version.

Restart Arduino IDE.

Open a sketch (or create a new one and save it).

Go to sketch directory (choose Sketch > Show Sketch Folder).

Create a directory named data and any files you want in the file system there.

Make sure you have selected a board, port, and closed Serial Monitor.

If your board requires you to press a button (or other action) to enter bootload mode for flashing a sketch, do that now.

Select Tools > ESP8266 Sketch Data Upload. This should start uploading the files into ESP8266 flash file system. When done, IDE status bar will display SPIFFS Image Uploaded message.

------------------------------------------------------
ESP8266LittleFS is the equivalent tool for LittleFS.
ESP8266LittleFS为LittleFS的同样工具。工具能把文件打包成LittleFS映像,上传到flash的文件系统区

Download the 2.6.0 or later version of the tool: https://github.com/earlephilhower/arduino-esp8266littlefs-plugin/releases

Install as above

To upload a LittleFS filesystem use Tools > ESP8266 LittleFS Data Upload实践,按说明配置好,上传的提示

[LittleFS] data    : E:\project\8266ap\WiFiAccessPoint\data
[LittleFS] size    : 1000
[LittleFS] page    : 256
[LittleFS] block   : 8192
/a.txt
/b.txt
/hello.txt
[LittleFS] upload  : E:\temp\arduino_build_677886/WiFiAccessPoint.mklittlefs.bin
[LittleFS] address : 0x300000
[LittleFS] reset   : --before default_reset --after hard_reset
[LittleFS] port    : COM3
[LittleFS] speed   : 921600
[LittleFS] python   : D:\Mixly_WIN\arduino\portable\packages\esp8266\tools\python3\3.7.2-post1\python3.exe
[LittleFS] uploader : D:\Mixly_WIN\arduino\portable\packages\esp8266\hardware\esp8266\2.7.4\tools\upload.pyesptool.py v2.8
Serial port COM3
Connecting....
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: a4:cf:12:ef:89:a4
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 1024000 bytes to 1345...
Wrote 1024000 bytes (1345 compressed) at 0x00300000 in 0.0 seconds (effective 200378.7 kbit/s)...
Hash of data verified.Leaving...
Hard resetting via RTS pin...

ok,上传完成。如此这般,开发设备时很多需要初始化的数据、配置参数等等。都可以烧录到flash里,8266内部进行读写就so easy啦。

https://docs.platformio.org/en/latest/platforms/espressif8266.html#uploading-files-to-filesystem

Arduino ESP8266 使用LittleFS存储配置文件实践相关推荐

  1. Arduino ESP8266 SPI-FFS存储区域

    Arduino ESP8266 SPI-FFS存储区域 首先请原谅我分开来写,文章老是不过审核. 前言 在前面博文关于ESP8266WiFiWebServer的例程中,大家可以发现,博主基本上都是手动 ...

  2. Arduino ESP8266 For EEPROM数据存储示例

    Arduino ESP8266 For EEPROM数据存储示例 本示例所选开发板型号: 所需库:ESP_EEPROM库:https://github.com/jwrw/ESP_EEPROM 管理库页 ...

  3. Arduino ESP8266 MQTT 阿里 腾讯 连接示例

    Arduino ESP8266 MQTT 阿里 腾讯 连接示例 ESP8266基于Arduino IDE 快速搭建IoT还是很方便的,降低了很多门槛.官方的示例丰富的话,中小学生都能搞物联网了.真希望 ...

  4. Arduino ESP32 flash数据存储结构

    Arduino ESP32 flash数据存储结构 分区表官方文档:<分区表> 想了解ESP32 flash数据存储结构需要从分区表开始了解.一点类似一台电脑上挂载的硬盘一样. 分区表保存 ...

  5. mysql配置文件没有spring_spring cloud config使用mysql存储配置文件

    spring cloud config使用mysql存储配置文件 1.结构图 2.pom.xml: 4.0.0 com.didispace config-server-db 1.0.0 jar con ...

  6. javaconfig配置mysql_spring cloud config使用mysql存储配置文件

    spring cloud config使用mysql存储配置文件 1.结构图 2.pom.xml: 4.0.0 com.didispace config-server-db 1.0.0 jar con ...

  7. Arduino ESP8266利用AJAX局部动态更新网页内容

    Arduino ESP8266利用AJAX局部动态更新网页内容

  8. Arduino ESP8266/ESP32读取和改写MAC

    Arduino ESP8266/ESP32读取和改写MAC ESP8266/ESP32读取MAC示例代码 /*读取MAC*/ #ifdef ESP32#include <WiFi.h> # ...

  9. NodeMcu arduino ESP8266 使用Ticker库(多任务处理)

    NodeMcu arduino ESP8266 本文章学习借鉴于太极创客团队,以表感谢.官网http://www.taichi-maker.com/ ESP8266 使用Ticker库(多任务处理) ...

最新文章

  1. HDU4080 Stammering Aliens(二分 + 后缀数组)
  2. 文巾解题 56. 合并区间
  3. matlab怎么给函数自变量赋值_MATLAB的变量及赋值
  4. redhat es4 u5 下安装ORACLE 11G.
  5. 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
  6. C#多线程学习(一) 多线程的相关概念
  7. 【编程导航】这本小书,把常考算法题讲活了!
  8. 识别和追踪主题层次的影响力者(来自2018 Machine Learning 论文学习笔记)
  9. 远程连接linux服务器文件共享,linux mount 远程服务器共享目录
  10. android sdk更新失败 解决方案
  11. HDU 3315 My Brute
  12. LeetCode 119. Pascal’s Triangle II
  13. SQL Server:CASE WHEN OREN ELSE END =不支持OR
  14. usbcamera拔掉设备崩溃
  15. vijos1846 [NOIP2013] 华容道【最短路】
  16. Senparc.Weixin.MP SDK 微信公众平台开发教程(十):多客服接口说明
  17. 超市管理系统连接服务器失败,国内超市管理系统的使用现状
  18. 关于计算机信息技术论文,信息技术论文
  19. tcp 粘包是怎么产生的?
  20. 【有利可图网】PS实战系列:PS制作人像印章效果

热门文章

  1. 用python做通讯录包括姓名地址qq_我是如何用Python获取整个学校女生电话和QQ?技术撩妹...
  2. 17小学计算机课程目录,课程
  3. 完美世界:影视和游戏,二者为何不可兼得?
  4. Ubuntu 11.10与“核高基画饼“
  5. Java如何读取和操作上G文本数据
  6. 杭州建筑工程师职称评审条件
  7. cpufreq: cpufreq_online: Failed to initialize policy for cpu: 0 (-19)
  8. Unity Failed to load ‘Sssets/Plugins/xxx.dll with error 找不到指定的模块
  9. Educational Codeforces Round 95 (Rated for Div. 2)D. Trash Problem(权值线段树+离散化)
  10. html期末作业代码网页设计——简洁日式料理餐饮(4页) HTML+CSS+JavaScript 父亲美食HTM5网页设计作业成品