乐鑫Esp32学习之旅 20 一篇好文,开发过程中编译esp32固件太大,无法正常启动?教你如何自定义分区表partitions.csv。


  • 本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。

1、 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 “Hellow World”。
2、 巧用eclipes编辑器,官方教程在在Windows下搭建esp32开发环境,打印 “Hellow World”。
3、 认识基本esp32的GPIO接口,开始点亮您的第一盏 LED和中断回调实现按键功能 。
4、体会esp32的强大的定时器功能, 实现定时2s闪烁一盏LED灯。
5、接触实践esp32的pwm宽度脉冲功能, 实现呼吸效果闪烁一盏LED灯。
6、smartConfig和微信airKiss在esp32的实现,一键配网轻松快捷连接路由器。
7、利用GPIO中断做一个按键的短按和长按的回调事件,再也无须担心触发源。
8、esp32上实现本地 UDP 客户端和服务端角色,在局域网内实现通讯。
9、esp32上实现本地 TCP 客户端和服务端角色,可断线重连原路返回数据。
10、乐鑫esp32 SDK编程利用rmt驱动ws2812七彩灯,实现彩虹渐变效果。
11、入门 乐鑫esp-adf 音频框架开发,esp32造一个蓝牙耳机,实现切换歌曲,获取歌曲信息等功能。
12、开源一个微信公众号airkiss配网esp32以及局域网发现功能的工程,分享一个airkiss配网小工具。
13、esp32 内置 dns 服务器,无需外网访问域名返回指定网页。
14、esp32 sdk编程实现门户强制认证,连接esp32热点之后,自动强制弹出指定的登录界面。
15、认识本地离线语音唤醒识别框架 esp-skainet ,实现较低成本的硬件语音本地识别控制。
16、学习本地语音唤醒离线识别框架 esp-skainet ,如何修改唤醒词? 如何自定义命令词?如何做意图动作?
17、全网首发,乐鑫esp32 sdk直连京东微联·小京鱼 · IoT开放平台,实现叮咚音响语音智能控制。
18、入门京东微联·小京鱼的控制面板H5开发,读懂vue语法,做自己的控制页面。
19、重磅开源,如何在微信小程序上ble蓝牙配网esp32,blufi的那些事!
20、一篇好文,开发过程中编译esp32固件太大,无法正常启动?教你如何自定义分区表partitions.csv。


一、前言


      这年可真是互联网公司的寒冬,在群里询问问题的群友明显减少了。最近的网易裁员、华为维权事件,不难看出,普遍说法“青春饭”的程序员,30岁应该何去何从? 有得去送外卖,有的转管理,有的创业,有的奋斗在架构师前言技术。不管怎么样,一定要对自己的职业生涯有所规划!别混混沌沌过日子,别以为一直专研技术未来就会一片光明! 社会在变,人也要一直适应在“变”!

      对于程序员的职业发展,我推荐阅读下面文章:


二、认识乐鑫idf框架定义的分区表


      在群里,我又看到一个群友发出这样的疑问,程序大致报错如下:

esp_image: Image length 1053648 doesn't fit in partition length 1048576
boot: Factory app partition is not bootable
boot: No bootable app partitions in the partition table
ets Jun 8 2016 00:22:57

      对话内容如下,群昵称已马赛克处理!

2.1 那么问题来了,这个报错是什么原因?

      上面抛转引玉之后,这还得从乐鑫这个idf框架说起!

       一般的乐鑫老粉丝都知道,2.0sdk之前的程序烧录都是固定在flash芯片的某个位置的,但 3.0 sdk 也即是 idf 框架之后,完全可以自定义 固件的烧录位置,那么既然可以自定义 固件的烧录位置,那就避免不了位置的选择,一旦用户自己乱搞,那就经常报一些问题出来,下面整理最常见的三个原因导致,包括:

  1. 位置不对,没按照现有的硬件的flash大小来定义,比如2M的flash,你却定义在2M以外的位置。
  2. 定义固件长度过小,比如你分区表定义的固件大小尺寸是1M,但是你编译之后的固件1.5M,这也会报错;
  3. 定义启动程序的起位置,没有和64K对齐,也会报无法编译错误!

      上面群友提出的问题,明显就是第二个原因导致!


      不管怎么样,还是要对 flash 有所了解,才可以玩透这个分区表!

      首先啰嗦一下,esp8266或esp32都只是一个芯片,不带flash芯片,而常见的外挂flash芯片有 25q16、25q32 等华邦出产芯片,查看,比较详细地说到了里面地分布,大概地:我也总结如下:

  • ①、w25q系列生产的加工的商家很多,但是里面的分布和命名规则都是一样的。比如华邦的w25q64spi通讯接口,64就是指64Mbit也就是8M的容量。而我们平时的8266-12f32Mbit就是4M容量。

  • ②、w25q64为例,我分析下里面的存储分布。w25q648M容量分为了128块,每一块又分为16个扇区,而每个扇区占4K大小。由此可计算到,w25q6464Mbit / 8 * 1024 / 16 / 4 = 128 块 ,有128 * 16 = 2048 个扇区,此计算原理后面我会提到。

  • ③、w25q64为例,我们在擦除数据时候,最少擦除单位为一个扇区,也就是每次必须擦除 4K 字节。写数据也是一样,必须一个扇区一个扇区去写,所以有我们的esp8266文档提到为什么要4的倍数去写读一个数据。

  • ④、w25q64为例,我们在往某个地址写之前必须确保这个地址上的值是0xFF,否则说明这个地址以前被写过数据,还没有被擦除。w25q64擦除的最小单位是Sector也就是4k个字节,也就是说如果要想往某个地址写一个值,如果这个地址上的值不是0xFF,那么就要把整个扇区都擦除,然后在写。

  • ⑤、w25q64为例,给w25q64开辟一个4k的缓存,比如定义一个4k的数组,然后在写数据之前先判断如果这个地址上的数据不是0xFF,就先把这个地址所在的Sector里的数据全部保存在4k缓存中,再擦除这个扇区,再把缓存中对应的地址上的数据更新,再把这个4k缓存区的所有数据一次性的写入到这个Sector中。因此我们在esp8266操作存储时候,要注意先擦除再写数据。

  • ⑥、w25q64为例,一共是8M字节=810241024=8388608(Byte),分为128块(64K),每一块有分为16个扇区(4K),所以扇区的个数是:12816=2048(个),那么我们选择扇区的范围就是0-2047,假如要擦除第1000个的扇区,那么这个扇区的字节起始就是10004096=4096000,然后W25Q64就从4096000开始往下擦除4K大小的数据空间,计算地址的时候是使用字节来计算的。


  • 下面是我用心画的一个示意图,方便大家去了解下:

    • 这个多少块的计算公式的得来主要后面推导过来的,我们仔细发现,后面都是一个4K为一个扇区,16个扇区为一块,所以我们先将我们的64Mbit换算为64/8*1024= 8192k的容量去除于每个扇区的大小就是一共有多少块了!

这里写图片描述


2.2 如何读懂自定义的分区表


       首先,先从支持和不支持ota说起,我们可以从make menuconfig配置选择一个简单的预定义分区表:

  • “Single factory app, no OTA”
  • “Factory app, two OTA definitions”
系统默认的不支持 ota 的分区表:
# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x6000,
phy_init, data, phy,     0xf000,  0x1000,
factory,  app,  factory, 0x10000, 1M,
  • flash 芯片中的 0x10000(64KB) 偏移量被标记为 factory 应用程序. 默认情况下,引导加载程序将运行此应用程序.,定义的长度是1M。
  • 在分区表中还定义了两个用于存储 NVS 库分区和 PHY 初始化数据的数据区域.
系统默认的支持 ota 的分区表:
# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x4000,
otadata,  data, ota,     0xd000,  0x2000,
phy_init, data, phy,     0xf000,  0x1000,
factory,  0,    0,       0x10000, 1M,
ota_0,    0,    ota_0,  0x110000, 1M,
ota_1,    0,    ota_1,  0x210000, 1M,
  • 现在有三个应用程序分区定义,factory、ota_0 和 ota_1;
  • 这三种 Type 都设置为 app,但在 0x10000 位置的 factory 应用程序和后面的两个 OTA 应用程序的子类型有所不同,但是长度大小都是1M;
  • 还有一个新的 ota data 区域,用于保存 OTA 更新的数据. 引导加载程序会查询此数据,以便了解要执行的应用程序. 如果 ota data 为空,它将执行 factory 应用程序。
在分区表定义私有数据的存储位置

       什么叫私有数据,类似阿里云三元组的数据信息,一机一密,每个设备都有其唯一凭证,这个数据,我们完全是可以自己烧进去flash中,然后通过代码读取出去的,如果你要为每个设备写好代码编译再烧录进去,那么功夫是有多费劲?

     下面以支持ota为例,同时定义私有数据,所以我们必须重新自定义分区表,比如我这样:

nvs,      data, nvs,     0x9000,  0x4000
otadata,  data, ota,     0xd000,  0x2000
phy_init, data, phy,     0xf000,  0x1000
ota_0,    0,    ota_0,   0x10000, 0xF0000
fctry,    data, nvs,     0x100000,0x4000
ota_1,    0,    ota_1,   0x110000,0xF0000

     自定义分区表特别要注意和你的硬件相对应,没有那么大的头就别戴那么大的帽子,这里说的意思是:flash芯片的大小决定这个分区是否有效,否则有意想不到的事情发现。

     上面的分区表把 25q16 系列的 512个扇区全部用完了,怎么看?我教你一招,直接看最后一个文件存储位置 0x110000 ,这个数值除于 1000 就是第几个扇区了, 0x110000 / 1000 = 0x110 换成十进制就是272,而 0xF0000 / 1000 = 0xF0 十进制就是 240 , 您看,第272个扇区加上240恰好是 512

     你还会问为什么 25q16 是一共512个扇区?请看文章上面的总结;

     温馨提示:这个分区仅适合 25q16 flash芯片或更大容量,而 25q8是不适合的,平时的 esp8266-01s 就是典型的 25q8 flash;当然了,esp32都基本是 25q32 的flash了!

     我再一步为大家写来了图,详细说明用这个分区文件编译之后的程序存储位置:


三、群友的问题,如何分析解决;


     我当时就立刻给了个分区表他,是可行的,下面说说我的解决思路:

     我当时看到那个报错,就一口咬定他的固件大小大概是 1053648 也就是 1M多一点,因为esp32模块市面上基本都是 4M 的flash 了,把我之前的定义的分区表给他;

nvs,      data, nvs,     0x9000,  0x4000
otadata,  data, ota,     0xd000,  0x2000
phy_init, data, phy,     0xf000,  0x1000
ota_0,    0,    ota_0,   0x10000,  0x1a9000
ota_1,    0,    ota_1,   0x210000, 0x1a9000

     那么上面定义的固件1位置是 0x10000,尺寸是 0x1a9000 ,是多大呢? 0x1a9000 除于 0x1000 等于 0x1a9 , 换为十进制就是 425 个扇区 ,一个扇区4k,那么 425*4 =1700k ,足够大了!


另外,不要把我的博客作为学习标准,我的只是笔记,难有疏忽之处,如果有,请指出来,欢迎留言哈!也欢迎加群讨论!

  • 玩转esp8266带你飞、付费QQ群,不喜的朋友勿喷勿加:434878850
  • esp8266源代码学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp8266
  • esp32源代码学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp32
  • 关注下面微信公众号二维码,干货多多,第一时间推送!
    在这里插入图片描述
发布了152 篇原创文章 · 获赞 785 · 访问量 79万+

猜你喜欢

转载自blog.csdn.net/xh870189248/article/details/103417052