ESP8266有官方提供的软件开发包。下面是对该开发包ESP8266_NONOS_SDK生成的镜像文件构建步骤分析。

一、Flash布局

首先参考官方提供编号为2A的文档,对于4MB(32Mbit) SPI Flash,其布局如下:

User Data区域:当程序(flash.bin和irom0text.bin)未占满整个空间时,空闲区域均可用于存放用户数据。
上图irom0text.bin默认最大为200KB;ESP8266目前程序最大支持1024 KB,因此对于4096 KB Flash,用户可修改编译,使其最大支持到 1024 - 256 = 768 KB。


ld文件夹的eagle.app.v6.ld文件,其中irom0_0_seg的len为设置irom0text.bin上限值。对于4096 KB Flash,此len最大可修改为0xC0000,irom0text.bin最大支持到 768 KB。

题外话:编译官方的AT固件时,如果出现irom0_0seg的报错信息,可能就是因为irom0_0seg的大小空间不够,增大irom0_0seg的len就好。

二、Makefile

这里简单分析一下主目录里的Makefile内容:

23~27行:

BOOT?=none

APP?=0

SPI_SPEED?=40

SPI_MODE?=QIO

SPI_SIZE_MAP?=0

说明:Makefile已经默认配置好了的选项

131行:

LD_FILE = $(LDDIR)/eagle.app.v6.ld

说明:使用的链接文件是\esp_iot_sdk\ld\eagle.app.v6.ld

238~240行:

@$(RM) -r ../bin/eagle.S ../bin/eagle.dump

@$(OBJDUMP) -x -s $< > ../bin/eagle.dump

@$(OBJDUMP) -S $< > ../bin/eagle.S

说明:sdk编译过程中会先生成eagle.app.v6.out,然后dump出段信息和符号文件。下面用一小节介绍一下生成ELF文件的步骤:

生成ELF文件

从bin\eagle.dump中摘取部分有有用的信息,为了方便阅读,转换为表格格式。
Sections:

Idx

Name

Size

VMA

LMA

File off

Algn

0

.data

00000b34

3ffe8000

3ffe8000

000000e0

2**4

1

.rodata

00000d70

3ffe8b40

3ffe8b40

00000c20

2**4

2

.bss

00006cd0

3ffe98b0

3ffe98b0

00001990

2**4

3

.text

00006d6e

40100000

40100000

00001990

2**2

4

.irom0.text

00033230

40240000

40240000

00008700

2**4

结合ld文件的memory信息(本文第一节有图片)可以看到

.data的LMA(Load Memory Address,装载内存地址)为3ffe8000,正好是dram0_0_seg的org;

.rodata的LMA为3ffe8b40,.bss是3ffe98b0,在dram0_0_seg的大小内;

.text是40100000,正好对应iram1_0_seg;

.irom0.text是40240000,正好对应irom0_0_seg;

因此,data、rodata、bbs段都是放到dram0_0_seg中,text段是放到iram1_0_seg中,.irom0.text段是放到irom0_0_seg中。

由于iram1_0_seg大小为0x8000,即32KB,因此,程序段(.text)不能超过32KB;同理,数据段(.data+.rodata)不能超过0x14000,即80KB

将ELF文件转化为烧写镜像

下面回到对Makefile的分析。

第248到251行:

@$(OBJCOPY) --only-section .text -O binary $< eagle.app.v6.text.bin

@$(OBJCOPY) --only-section .data -O binary $< eagle.app.v6.data.bin

@$(OBJCOPY) --only-section .rodata -O binary $< eagle.app.v6.rodata.bin

@$(OBJCOPY) --only-section .irom0.text -O binary $< eagle.app.v6.irom0text.bin

说明:Makefile将以上各个section copy成单个文件。

257行:

@python ../tools/gen_appbin.py $< 0 $(mode) $(freqdiv) $(size_map) $(app)

说明:使用tools/gen_appbin.py脚本文件将eagle.app.v6.text.bin、eagle.app.v6.data.bin和eagle.app.v6.rodata.bin三个文件打包成一个eagle.app.flash.bin。

打包过程简要

在toos/gen_appbin.py脚本文件中,需要给之各项参数,由

@python ../tools/gen_appbin.py $< 0 $(mode) $(freqdiv) $(size_map) $(app)

这条语句可知给了什么参数,源文件如下(121~126行):

elf_file = sys.argv[1]# < eagle.app.v6.out
boot_mode = sys.argv[2] # < 0
flash_mode = sys.argv[3] # < mode=0
flash_clk_div = sys.argv[4] # < freqdiv=0
flash_size_map = sys.argv[5] # < size_map=0
user_bin = sys.argv[6] # < app=0

之后使用nm -g eagle.app.v6.out产生eagle.app.sym文件,并在sym文件中找出section地址和入口地址。

(cmd = 'xt-nm -g ' + elf_file + ' > eagle.app.sym')

最后按照如下格式打包成eagle.app.flash.bin。(代码略)

HEAD0 = BIN_MAGIC_FLASH
HEAD1 = 3
HEAD2 = flash_mode
HEAD3 = flash_size_map<<4 | flash_clk_div
ENTRY = entry_addr 入口地址

TEXTADDR = TEXT_ADDRESS
TEXTLEN = eagle.app.v6.text.bin的文件长度4字节对齐
TEXT = eagle.app.v6.text.bin 的数据,4字节对齐,最后不对齐的补0

DATAADDR = data_start_addr
DATALEN = eagle.app.v6.data.bin的文件长度4字节对齐
DATA = eagle.app.v6.data.bin 的数据,4字节对齐,最后不对齐的补0

RODATAADDR = data_start_addr
RODATALEN = eagle.app.v6.rodata.bin的文件长度4字节对齐
RODATA = eagle.app.v6.rodata.bin 的数据,4字节对齐,最后不对齐的补0

ALIGMENT = 对齐数据,保证sum前的数据16字节对齐,不对齐这里补0

CHKSUM = eagle.app.flash.bin的校验和

其他

回到Makefile,258~259行:

@mv eagle.app.flash.bin ../bin/eagle.flash.bin

@mv eagle.app.v6.irom0text.bin ../bin/eagle.irom0text.bin

说明:最后两个mv指令是把生成的两个bin文件,改成相应的名字并移动到esp_iot_sdk/bin/目录下。

自此,整个Makefile执行结束,生成eagle.flash.bin和eagle.irom0text.bin文件。

三、启动运行过程

1、芯片上电后会先运行片上的ROM,完成必要初始化;
2、片上ROM读取SPI Flash 0x00000处的flash.bin,并解析出text、data、rodata在内存中的位置,并将这3部分加载到片上内存中
- text会加载到iram1上,因此text最大不能超过32KB(0x8000);(解决方法参见注意事项和建议的第一条)
- data和rodata加载到dram0上,因此这二者和不能大于80KB(0x14000);
- 在dram0上还有bbs、stack、heap,要注意使用量。以IoT_Demo固件来看:data+rodata+bbs = 0xb34+0xd70+0x6cd0 = 0x8574,因此stack和heap能用的内存只有46K左右(0x14000-0x8574),如果是空白的固件,则大约有50KB左右;

3、片上固化rom加载flash.bin完毕后跳到入口地址entry_addr处执行;
4、当执行到irom1上的代码时(通过ICACHE_FLASH_ATTR定义的函数),会将它们从SPI Flash上加载到cache中运行;

四、注意事项和建议

1、标注「ICACHE_FLASH_ATTR」宏的函数存储在irom0里面(Flash里面),表示将其存放在Flash中,仅调用时才加载到cache 运行;

没有标注的会放在iram1里面,iram1大小只有32KB,IoT_Demo固件使用了大约27KB,还剩下5KB,而irom0最大支持768KB。所以如果自己用SDK开发,请尽量给函数都标注该宏,不然会出现内存不够用的错误信息:「.output/eagle/debug/image/eagle.app.v6.out section `.text' will not fit in region `iram1_0_seg'」

2、不要在GPIO或UART中断处理函数中调用带有「ICACHE_FLASH_ATTR」宏的函数,否则可能会进入异常导致重启。

3、上电时会以串口波特率76800bps(和晶振有关)打印「ets Jan 8 2013,rst cause:2, boot mode:(1,7)」等信息,这一上电信息是保存在片上固化ROM的,无法屏蔽。

【ESP8266】ESP8266_NONOS_SDK开发包生成的镜像文件构建步骤分析相关推荐

  1. vs2005生成安装部署文件的步骤

    vs2005生成安装部署文件的步骤 1 新建安装部署项目 打开VS,点击新建项目,选择:其他项目类型->安装与部署->安装向导(安装项目也一样),然后点击确定. 2 安装向导 关闭后打开安 ...

  2. 浏览器打不开Axure生成的html文件

    用chrome浏览器打开Axure生成的html文件,会提示需要安装一个相应的Axure扩展才能正常使用.今天我用Edge浏览器打开也遇到同样的提示,问题是Edge浏览器目前根本无法安装chrome的 ...

  3. vs2008生成安装部署文件的步骤

    1 新建安装部署项目 打开VS,点击新建项目,选择:其他项目类型->安装与部署->安装向导(安装项目也一样),然后点击确定. 2 安装向导 关闭后打开安装向导,点击下一步,或者直接点击完成 ...

  4. 封装win7系统、制作win7GHO镜像、制作一个自定义的镜像文件具体步骤、制作Win10镜像gho

    1. 准备工作 1.1.首先需要下载IT天空的几个工具. 工具1:Easy Sysprep,一个封装部署辅助工具. 工具2:万能驱动 ,可以与EasySysprep配合使用的万能驱动包. 工具3:Ea ...

  5. 封装win7系统、制作win7GHO镜像、制作一个自定义的镜像文件具体步骤、制作Win10镜像gho...

    作者:导演你让灰太狼吃只羊  来源:CSDN  原文:https://blog.csdn.net/qq_35057426/article/details/83015516  版权声明:本文为博主原创文 ...

  6. 用“XML解析开发包Jaxp”对XML文件进行Dom方式的CRUD操作

    IT程序员开发必备-各类资源下载清单,史上最全IT资源,个人收藏总结! package edu.jaxp; import java.io.FileNotFoundException; import j ...

  7. flume案例-文件数据采集-步骤分析

    采集文件到 HDFS 需求 比如业务系统使用log4j生成的日志,日志内容不断增加,需要把追加到日志文件中的数据实时采集到hdfs 分析 根据需求,首先定义以下3大要素 采集源,即source--监控 ...

  8. c语言文件构建步骤,C语言文件的创建与建立

    C语言文件的创建与建立 c语言中对于文件的创建与建立已经有相当经典且应用相当广泛的语法了.下面是小编为大家带来的C语言文件的创建与建立的知识,欢迎阅读. 首先是文件的创建: # include # i ...

  9. 【C++ 语言】Visual Studio 配置 FFMPEG 开发环境 ( VS2019 CMake 环境安装 | 下载 FFMPEG 开发包 | 配置 FFMPEG )

    文章目录 Visual Studio 2019 社区版 CMakeList 开发环境安装 创建 FFMPEG 配置项目 FFMPEG 开发包下载 FFMPEG 头文件 静态链接库 ( .lib ) 动 ...

最新文章

  1. 有了Anaconda如何安装Pycharm以及简单使用和调试
  2. java的函数传值_java 函数形参传值和传引用的区别[转]
  3. 向线程传递数据与线程用回调方法检索数据
  4. os.path.join的妙用
  5. 解决yarn全局安装模块后但仍提示无法找到命令的问题
  6. iPad开发--QQ空间,处理横竖屏布局,实现子控件中的代理
  7. ASP.NET是如何在IIS下工作的
  8. document.ready 与 onload 的区别
  9. xenserver 虚拟机扩容lvm磁盘分区的方法_vm虚拟机中linux Centos7.4硬盘扩容
  10. 第九章 JSP标签——《跟我学Shiro》[张开涛]
  11. Android 启动模拟器是出现 Failed to allocate memory 8 错误提示的原因及解决办法
  12. 论文翻译器:pdf 英文论文一键转换成中英文对照的文档
  13. LFS8.0完全安装搭建制作教程
  14. 微阵列芯片服务器,微阵列(生物芯片)类型详解
  15. 给C盘减减肥,让你电脑飞一般速度
  16. 基于MXNET实现的年龄性别识别
  17. iOS 图片裁剪(用户头像裁剪)
  18. 台媒曝大S女儿小名格格吉祥 汪小菲否认
  19. oracle存储过程初学实例
  20. 最优化理论公式大赏(上)

热门文章

  1. Redis是如何写代码注释的?
  2. 【看图识算法】这是你见过最简单的 “算法说明书”
  3. 操作系统:进程的三种状态
  4. Hibernate一个简单实例的各种坑
  5. 3.JAVA中的多态
  6. IntelliJ IDEA maven库下载依赖包速度慢的问题(包制百病)
  7. php怎么定义索引,PHP未定义的索引/变量
  8. 字节跳动践行节能减排,数据中心能效居行业前列
  9. 刷新你的数据中心冷却词汇
  10. 机房配电系统与配电电缆线径的选择及巡查