ESP8266入门学习(一)

在得到一份代码后我们最先应当了解一下它的目录结构,这里用ESP8266_RTOS_SDK_V1.5.0为例:

app:用户代码主目录,用户代码都将放在这里
bin :编译生成和SDK提供的bin文件,用于下载到Flash中
driver_lib : RTOS驱动示例代码
examples:示例代码
extra_include:Xtensa编译器头文件(使用XCC编译时使用,一般用GCC)
include:SDK头文件(包含可用的 API函数和相关的宏定义)
ld:链接时所需的脚本文件,如无特殊需求无需修改
lib:SDK的库文件
third_party:第三方开源库(源码),编译后会放到lib目录
tools:编译bin文件所需的工具,无需修改
Makefile:编译入口脚本(执行make时所执行的文件)
bin文件
文件列表 是否必选 说明 Non-FOTA FOTA
master_device_key.bin 可选 乐鑫云服务,在Espressif Cloud申请 ☑ ☑
esp_init_data_default.bin 必选 初始化射频参数,SDK提供 ☑ ☑
blank.bin 必选 初始化系统参数,SDK提供 ☑ ☑
eagle.flash.bin 必选 主程序,编译生成(app=0) ☑ ❌
eagle.irom0text.bin 必选 主程序,编译生成(app=0) ☑ ❌
user1.bin 初次必选 主程序,编译生成(app=1) ❌ ☑
user2.bin FOTA升级 主程序,编译生成(app=2) ❌ ☑
(文件名不一定相同)
注:user1.bin和user2.bin实际上除了烧录位置不同其它是几乎是一样的,因为在线升级时没有数据缓存位置,所以下载的数据是直接写入flash的,但又不能覆盖当前程序(否则升级一半掉电就无法开机了),所以user1.bin程序FOTA升级使用user2.bin,user2.bin程序FOTA升级使用user1.bin。第一次烧录使用user1.bin。

Flash布局
以下为Flash使用布局,可以根据需要进行修改,这里大致了解一下就可以。

Flash布局
系统程序:程序固件
用户数据:未使用的Flash部分可以给用户自行存储用户数据
用户参数:地址可自定义,IOT_Demo设置为0x3C000开始的4个扇区(master_device_key.bin放在第三个扇区)
系统参数:固定为Flash最后的4个扇区(blank.bin放在倒数第2、1扇区,esp_init_data_default.bin放在倒数第4、3扇区)
Boot信息:FOTA升级相关信息
预留:与Boot信息区对应的预留部分
注:一个扇区为4kb(Byte)
编译过程
如果要了解一个工程的结构,那么从工程的编译来看是最为深刻的,那么了解这个编译过程有什么用?老实说,并没有什么卵用。那为什么还要写这部分?因为我就想把文章写的长一点,啊哈哈哈哈。。。

入口脚本
看过官方的文档都知道,我们编译项目是要进入app这个目录然后执行gen_misc.bat这个文件(Linux下是gen_misc.sh)来编译的,那么我们就从这个文件下刀吧:

@echo off

Rem NOTICE
Rem MUST set SDK_PATH & BIN_PATH firstly!!!
Rem example:
Rem set SDK_PATH=/c/esp_iot_sdk_freertos
Rem set BIN_PATH=/c/esp8266_bin

set SDK_PATH=/c/ESP8266_RTOS_SDK
set BIN_PATH=/c/ESP8266_BIN

echo gen_misc.bat version 20150911
echo .

if not %SDK_PATH% == “” (
echo SDK_PATH: %SDK_PATH%
) else (
echo ERROR: Please set SDK_PATH in gen_misc.bat firstly, exit!!!
goto end
)

if not %BIN_PATH% == “” (
echo BIN_PATH: %BIN_PATH%
) else (
echo ERROR: Please set BIN_PATH in gen_misc.bat firstly, exit!!!
goto end
)

echo .
echo Please check SDK_PATH/BIN_PATH, enter (Y/y) to continue:
set input=default
set /p input=

if not %input% == Y (
if not %input% == y (
goto end
)
)
文件开头这部分,很简单,这里设置SDK_PATH和BIN_PATH两个变量(官方文档也会叫你先改这两个值后在编译),如果没设置就报错,结束编译。什么?你问我Rem是什么意思?那只是注释啦(好学的孩子可以出门左拐看看windows批处理,这里就简单带过了)。

echo .
echo Please follow below steps(1-5) to generate specific bin(s):
echo STEP 1: use boot_v1.2+ by default
set boot=new

echo boot mode: %boot%
echo.

echo STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin, 2=user2.bin)
set input=default
set /p input=enter (0/1/2, default 0):

-----------------------------------这里省略部分代码---------------------------------------

echo.
echo start…
echo.
这部分有点长,中间略写了,就是分5步用选择的方式定义了boot、app、spi_speed、spi_mode和spi_size_map这五个变量。

make clean

make COMPILE=xcc BOOT=%boot% APP=%app% SPI_SPEED=%spi_speed% SPI_MODE=%spi_mode% SPI_SIZE_MAP=%spi_size_map%

:end
看结尾这部分,首先先执行了make clean清除构建,然后进行make编译,把上面五个变量传递进去,make执行的即当前目录下的Makefile文件。
啥?你说:end又是啥?这还是一个注释啦,啊哈哈哈哈哈哈哈哈
最后这一小部分则是这个文件最关键的,给后面make操作提供了参数(COMPILE、BOOT、APP、SPI_SPEED、SPI_MODE和SPI_SIZE_MAP)。gen_misc.sh类似区别在于使用的脚本语音不同,最后参数就COMPILE不一样(用于选择编译器的)。

入口Makefile
看Makefile可以对照《跟我一起写Makefile》或者我的一起来看神奇的Makefile

TARGET = eagle
#FLAVOR = release
FLAVOR = debug

#EXTRA_CCFLAGS += -u
parent_dir:=$(abspath ( s h e l l p w d ) / (shell pwd)/ (shellpwd)/(lastword ( M A K E F I L E L I S T ) ) ) p a r e n t d i r : = (MAKEFILE_LIST))) parent_dir:= (MAKEFILELIST)))parentdir:=(shell dirname ( p a r e n t d i r ) ) p a r e n t d i r : = (parent_dir)) parent_dir:= (parentdir))parentdir:=(shell dirname $(parent_dir))

SDK_PATH= ( p a r e n t d i r ) B I N P A T H = (parent_dir) BIN_PATH= (parentdir)BINPATH=(SDK_PATH)/bin
开头定义了两个变量TARGET和FLAVOR表示编译的目标和版本,接下来的parent_dir比较有意思,从字面上看是父路径的意思,猜测就是当前的上一级也就是工程根目录,但这里采用了一个很复杂的方式取得:先从MAKEFILE_LIST取最后一个词(也就是当前Makefile的文件名),加上pwd取得当前路径,然后再取绝对路径。而后又连续取两次目录名(去掉两级路径)也就是当前目录的上一级,可绕脑了,这是想让看Makefile的小朋友望而怯步吗。。。
接下来主要的还是定义SDK_PATH和BIN_PATH两个目录(工程根目录和bin目录)

ifndef PDIR # {
GEN_IMAGES= eagle.app.v6.out
GEN_BINS= eagle.app.v6.bin
SPECIAL_MKTARGETS=$(APP_MKTARGETS)
SUBDIRS=
user
driver

endif # } PDIR
这里PDIR没有定义,为什么?因为我们一路看下来并没有发现哪里有定义啊!
这里定义了SUBDIRS变量,记住它。

LDDIR = $(SDK_PATH)/ld

CCFLAGS += -Os

TARGET_LDFLAGS =
-nostdlib
-Wl,-EL
–longcalls
–text-section-literals

ifeq ($(FLAVOR),debug)
TARGET_LDFLAGS += -g -O2
endif

ifeq ($(FLAVOR),release)
TARGET_LDFLAGS += -g -O0
endif
定义了几个变量LDDIR(ld文件目录)、CCFLAGS(编译参数)和TARGET_LDFLAGS(链接参数),这里上面定义的FLAVOR变量已经使用上了。

COMPONENTS_eagle.app.v6 =
user/libuser.a
driver/libdriver.a

LINKFLAGS_eagle.app.v6 =
-LKaTeX parse error: Expected 'EOF', got '#' at position 24: …H)/lib \ #̲ 定义链接库的搜索路径是 SD…(LD_FILE) \ # 读取链接描述脚本,以确定符号等的定位地址
-Wl,–no-check-sections \ # Do not check section addresses for overlaps 不检查重叠地址
-u call_user_start \ # 取消定义的宏(call_user_start)
-Wl,-static \ # 使用静态链接
-Wl,–start-group \ #库列表开始
-lcirom
-lcrypto
-lespconn
-lespnow
-lfreertos
-lgcc
-lhal
-ljson
-llwip
-lmain
-lmesh
-lmirom
-lnet80211
-lnopoll
-lphy
-lpp
-lpwm
-lsmartconfig
-lspiffs
-lssl
-lwpa
-lwps
$(DEP_LIBS_eagle.app.v6)
-Wl,–end-group # 库列表结束

DEPENDS_eagle.app.v6 =
$(LD_FILE)
$(LDDIR)/eagle.rom.addr.v6.ld
定义三个变量COMPONENTS_eagle.app.v6(需要生成的目标)、LINKFLAGS_eagle.app.v6(链接库)和DEPENDS_eagle.app.v6(ld文件)。LINKFLAGS_eagle.app.v6中-Wl,–start-group前面的为链接参数和-Wl,–end-group间为链接库,可以根据需要进行删减。

CONFIGURATION_DEFINES = -DICACHE_FLASH

DEFINES +=
$(UNIVERSAL_TARGET_DEFINES)
$(CONFIGURATION_DEFINES)

DDEFINES +=
$(UNIVERSAL_TARGET_DEFINES)
$(CONFIGURATION_DEFINES)
定义DEFINES和DDEFINES,给编译用。两个值都是"-DICACHE_FLASH"具体做啥用我也不清楚,字面上看应该是Flash的cache缓存相关的。

INCLUDES := $(INCLUDES) -I $(PDIR)include
sinclude $(SDK_PATH)/Makefile

.PHONY: FORCE
FORCE:
最后给INCLUDES添加了"include"目录然后调用根目录的Makefile文件(这里只是展开文件并没有切换目录,还是在app目录下执行),最后两行是定义了一个FORCE的伪目标,啥都没做。
这里只要记住这个Makefile文件定义了SUBDIRS、COMPONENTS_eagle.app.v6、LINKFLAGS_eagle.app.v6和DEPENDS_eagle.app.v6这几个变量即可。

主Makefile
这个文件是主要的编译文件,主要是具体的编译,比较长,这里只取较为关键的部分。

ifeq ($(COMPILE), xcc)
AR = xt-ar
CC = xt-xcc
NM = xt-nm
CPP = xt-xt++
OBJCOPY = xt-objcopy
OBJDUMP = xt-objdump
else
AR = xtensa-lx106-elf-ar
CC = xtensa-lx106-elf-gcc
NM = xtensa-lx106-elf-nm
CPP = xtensa-lx106-elf-g++
OBJCOPY = xtensa-lx106-elf-objcopy
OBJDUMP = xtensa-lx106-elf-objdump
endif
根据COMPILE选择编译器,从开头的脚本克制Windows使用xcc,Linux使用gcc。实际测试在windows下使用gcc也似乎并没有问题。

BOOT?=new
APP?=1
SPI_SPEED?=40
SPI_MODE?=QIO
SPI_SIZE_MAP?=2
设置参数的默认值,这里说一下上一节我们编译机智云的工程为啥使用不一样的方式,原因就是机智云的工程里这里的默认值是不一样的,我们直接使用了make而没有传入参数,所以会导致编辑结果不一样,事实上也无需关心这部分,我们只要给它传参就可以了,开篇只是作为验证编译器是否正常而已。
后续一百多行的脚本根据这几个变量定义了boot、app、freqdiv、mode、addr、size_map、flash、LD_FILE以及BIN_NAME,比较简单这里不赘述。

CSRCS ?= $(wildcard *.c) # $(wildcard xxx)这个意思是在当前目录下使用通配符列出所有文件
CPPSRCS ?= $(wildcard *.cpp)
ASRCs ?= $(wildcard *.s)
ASRCS ?= $(wildcard *.S)
SUBDIRS ?= ( p a t s u b s t (patsubst %/,%, (patsubst(dir $(wildcard */Makefile)))

ODIR := .output
OBJODIR := ( O D I R ) / (ODIR)/ (ODIR)/(TARGET)/$(FLAVOR)/obj

OBJS := ( C S R C S : (CSRCS:%.c= (CSRCS:(OBJODIR)/%.o)
( C P P S R C S : (CPPSRCS:%.cpp= (CPPSRCS:(OBJODIR)/%.o)
( A S R C s : (ASRCs:%.s= (ASRCs:(OBJODIR)/%.o)
( A S R C S : (ASRCS:%.S= (ASRCS:(OBJODIR)/%.o)

DEPS := ( C S R C S : (CSRCS:%.c= (CSRCS:(OBJODIR)/%.d)
( C P P S R C S : (CPPSRCS:%.cpp= (CPPSRCS:(OBJODIR)/%.d)
( A S R C s : (ASRCs:%.s= (ASRCs:(OBJODIR)/%.d)
( A S R C S : (ASRCS:%.S= (ASRCS:(OBJODIR)/%.d)

LIBODIR := ( O D I R ) / (ODIR)/ (ODIR)/(TARGET)/$(FLAVOR)/lib
OLIBS := ( G E N L I B S : (GEN_LIBS:%= (GENLIBS:(LIBODIR)/%)

IMAGEODIR := ( O D I R ) / (ODIR)/ (ODIR)/(TARGET)/$(FLAVOR)/image
OIMAGES := ( G E N I M A G E S : (GEN_IMAGES:%= (GENIMAGES:(IMAGEODIR)/%)

BINODIR := ( O D I R ) / (ODIR)/ (ODIR)/(TARGET)/$(FLAVOR)/bin
OBINS := ( G E N B I N S : (GEN_BINS:%= (GENBINS:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值