相关系列文章
基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(-)-Z3GatewayHost应用搭建
基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(二)-使用gateway-management-ui
基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(三)-移植到ESP32平台(1)
基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(三)-移植到ESP32平台(2)
基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(四)-移植到STM32平台
概要
前两章节已经简单介绍了芯科的Host-NCP解决方案,对一些相关概念有了初步认识,接下来这个章节将记录一下将Host应用从Ubuntu移植到乐鑫ESP32上的过程和注意事项。在芯科官方的视频教学中,也有关于LCGW网关(低成本网关?)的介绍,可以看出芯科官方也希望Host-NCP解决方案能在更广的范围进行推广,教学视频地址如下(感谢相关文章作者的分享,在此借以引用参考,如有涉及版权问题,请及时联系我):
《Zigbee 3.0 RTOS网关介绍》,如下图所示:https://www.bilibili.com/video/BV1L54y1z7aZ
所以,如果有条件的话,应当尽量使用芯科官方提供的RTOS SDK进行移植。
如果想体验一下将Host移植到不同MCU平台的过程,那下面的内容也许可以给你帮助。
整个移植工作主要分为以下几步:
1.软硬件环境准备工作:ESP32选型、相关的SDK、交叉编译工具链等
2.生成ESP32调用的静态库:Host需要调整的相关文件、交叉编译参数
3.在ESP32工程中使用静态库:在ESP32开发环境中导入和使用静态库,结合ESP32自身的uart、wifi、mqtt、spiffs等实现相关功能的移植
4.移植后的功能验证:zigbee主要功能的验证工作
软硬件环境准备工作
1.硬件环境
Host:ESP32-WROOM-32D Flash:8MB SRAM :536KB (备注:采用Flash 4MB的版本也是可以的)
NCP:EFR32MG21A020F768IM32
因为,Host-NCP间是通过uart进行数据传输的,所以对串口稳定性要求想对较高;一开始,我是用杜邦线连接ESP32核心板和EFR32模组进行开发的,但经常会出现各种莫名其妙的通讯问题,所以后来打样了一块ESP32-EFR32开发板,方便测试。
这块开发板主要包括了:esp32模组、efr32模组、ch340、2个功能按键、2个功能指示灯、oled屏接口、大彩触摸屏接口;可以通过usb线进行esp32固件下载。
当然,你也可以用esp32开发板+efr32模组的方式进行开发,如下图所示:
2.软件环境
编译环境:Ubuntu 18.04(建议使用乐鑫的开发虚拟机镜像,里面已经安装交叉编译工具链)
编译工具链:xtensa-esp32-elf-gcc gcc version 8.2.0 (crosstool-NG esp-2019r2)
软件:Simplicity Studio V4、Eclipse IDE for C/C++ Developers、ESP-IDF Tools(以插件方式在Eclipse中安装)
芯科SDK:EmberZNet SDK 6.7.5.0
备注:如果对ESP32开发不熟悉,请先查看乐鑫ESP-IDF 编程指南文档;和 ESP32 & ESP32S2 平台官方工具链的设置和下载
生成ESP32调用的静态库
将前面章节中在Ubuntu下编译的工程项目,直接复制一份,然后将文件夹修改为esp32,如下图所示:
需要修改的文件主要分为以下几类:
- 基础配置文件
- 涉及串口相关操作的
- 涉及文件操作相关的
具体修改文件列表(为了不影响SDK,所有需要修改的文件,都是原地复制一份;然后在文件名增加"-esp32"后缀,例如“gcc-esp32.h”即代表对原来的“gcc.h”文件)
编号 | 文件名 | 所在路径 | 分类 | 调整 | 备注 |
1 | gcc-esp32.h | v2.7/platform/base/hal/micro/unix/compiler/ | gcc配置文件 | 微调 | |
2 | linux-serial-esp32.c | v2.7/protocol/zigbee/app/util/serial/ | 串口相关操作 | 调整较多 | |
3 | ezsp-host-io-esp32.c | v2.7/protocol/zigbee/app/ezsp-host/ | |||
4 | ezsp-esp32.c | v2.7/protocol/zigbee/app/util/ezsp/ | ezsp协议实现 | 微调 | 有不确定的内存泄露问题 |
5 | gateway-relay-mqtt-esp32.c | v2.7/protocol/zigbee/app/framework/plugin-host/gateway-relay-mqtt/ | mqtt插件相关实现 | 微调 | |
6 | gateway-support-esp32.c | v2.7/protocol/zigbee/app/framework/plugin-host/gateway/ | 感觉很重要,但暂时没弄清楚它的作用 | 微调 | 后续考虑移除 |
7 | command-relay-esp32.c | v2.7/protocol/zigbee/app/framework/plugin/command-relay/ | 命令行插件相关实现 | 微调 | |
8 | device-table-esp32.c | v2.7/protocol/zigbee/app/framework/plugin/device-table/ | device-table插件 | 微调 | |
9 | device-table-discovery-esp32.c | v2.7/protocol/zigbee/app/framework/plugin/device-table/ | 微调 | 有可能引发异常,具体原因还没找到 | |
10 | ota-storage-linux-esp32.c | v2.7/protocol/zigbee/app/framework/plugin/ota-storage-posix-filesystem/ | ota插件 | 微调 | |
11 | token-esp32.c | v2.7/platform/base/hal/micro/unix/host/ | 不清楚要来干嘛 | 基本把功能都屏蔽了 | |
12 | backchannel-support-esp32.c | v2.7/protocol/zigbee/app/framework/plugin-host/gateway/ | 不清楚要来干嘛 | 基本把功能都屏蔽了 | |
13 | Makefile | 项目根目录 | 编译配置文件 | 调整较多 | 配置esp32编译器、编译文件、编译参数等 |
移植文件修改:
1)gcc-esp32.h
107行,将原来的“#error endianess not defined”修改为“#define BIGENDIAN_CPU false”
备注:此处用于指定运行平台CPU为大端模式(big endian)还是小端(little endian)模式;MCU一般都为小端模式
2)linux-serial-esp32.c
改动实在太多,不一一列举,基本上是把各linux串口操作方法具体内容删掉,直接返回success,如下图所示
备注:这个文件的方法主要是用于linux串口的操作,移植到MCU,大部分方法都不适用(更好的做法应该是直接去掉)。但emberSerialPrintfVarArg方法比较重要,用于通过串口打印各种调试信息,是各种调试信息(ezsp、ash、af等)最后调用的底层,所以修改如下;将原来的backchannel打印去掉了:
// Main printing routine.
// Calls into normal C 'vprintf()'
EmberStatus emberSerialPrintfVarArg(uint8_t port, const char * formatString, va_list ap)
{
EmberStatus stat = EMBER_SERIAL_INVALID_PORT;
char* newFormatString = transformEmberPrintfToStandardPrintf(formatString,
true);
vprintf(newFormatString, ap);
free(newFormatString);
return EMBER_SUCCESS;
}
3)ezsp-host-io-esp32.c
替换头文件termios.h的引用
termios.h是用于定义串口操作的一些常量,例如波特率等。因为在esp32的编译链中是没有,所以可以直接在网上找一个,放到目录中引用。如下图所示;
网上找到的termios.h定义
#ifndef _TERMIOS_H
#define _TERMIOS_H
#define TTY_BUF_SIZE 1024 //tty缓冲区长度
/*
*0x54只是一个魔数,目的是位来使这些常数唯一
*tty设备的ioctl调用命令集合,iosctl将命令编码在低位字中
*下面TC的含义是tty控制命令
*/
//取相应终端termios结构中的信息
#define TCGETS 0x5401
//设置应终端termios结构中的信息
#define TCSETS 0x5402
//在设置终端termios的信息前,需要先等待输出队列中所有处理完,对于修改参数回影响输出的情况
//就绪要使用这种形式
#define TCSETSW 0x5403
//在设置termios信息前,需要先等待输出队列中所有数据处理完,并且刷新输入队列
#define TCSETSF 0x5404
//取相应终端termios对应的信息
#define TCGETA 0x5405
//设置相应终端termios对应的信息
#define TCSETA 0x5406
//在设置终端termios的信息前,需要先等待输出队列中所有处理完,对于修改参数回影响输出的情况
//就绪要使用这种形式(参见tcsetattr TCSADRAIN选项)
#define TCSETAW 0x5407
//在设置termios信息前,需要先等待输出队列中所有数据处理完,并且刷新输入队列
//(参见tcsetattr TCSAFLUSH)
#define TCSETAF 0x5408
//等待输出队列处理完毕(空),如果参数值是0,则发送一个brank
#define TCSBRK 0x5409
//开始/停止控制,参数为0则挂起,为1,则重新开启挂起出处,是2则挂起,为3则重新开启挂起的输入
#define TCXONC 0x540A
//刷新已写输出但还没有发送或已收但换没有读数据。参数为0,则刷新输入队列;为1,刷新输出队列
//为2,刷新输入输出队列
#define TCFLSH 0x540B
//下面TIO含义是tty输入输出控制命令
//设置终端串行线路专用模式
#define TIOCEXCL 0x540C
//复位终端串行线路专用模式
#define TIONXCL 0x540D
//设置tty为控制终端
#define TIOCSCTTY 0x540E
//读取指定终端设备进程的组id
#define TIOCGPGRP 0x540F
//设置指定终端设备进程的组id
#define TIOCSPGRP 0x5410
//返回输出队列中还未送出的字符数
#define TIOCOUTQ 0x5411
//模拟终端输入,该命令以一个指向字符的指针作为参数,并假装该字符是在终端上键入的,用户必须
//在该控制终端上具有超级用户权限或具有读权限
#define TIOCSTI 0x5412
//读取终端设备窗口大小信息
#define TIOCGWINSZ 0x5413
//设置终端设备窗口大小信息
#define TIOCSWINSZ 0x5414
//返回modem状态控制引线的当前状态比特位标志集
#define TIOCMGET 0x5415
//设置单个modem状态控制引线的状态
#define TIOCMBIS 0x5416
//复位单个modem状态控制引线的状态
#define TIOCMBIX 0x5417
//设置modem状态引线的状态。如果某一比特位置位,则modem对应的状态引线将置位有效
#define TIOCMSET 0x5418
/*读取软件载波检测标志(0-关闭,1-开启)。对于本地连接的终端或其他设备,软件载波标志是开启的
*对于使用modem线路的终端或设备则是关闭的。为了能使用这两个ioctl调用,tty线路应该是以
*O_NDELRY方式打开的,这样open就不回等待载波
*/
#define TIOCGSOFTCAR 0x5419
//设置软件载波检测标志
#define TIOCSSOFTCAR 0x541A
//返回输入队列还位取走字符的数目
#define TIOCINQ 0X541B
struct winsize
{
unsigned short ws_row; //窗口字符行数
unsigned short ws_col; //窗口字符列数
unsigned short ws_xpixel;//窗口宽度,像素值
unsigned short ws_ypixel;//窗口高度,像素值
};
#define NCC 8 //termios结构中控制字符数组的长度
struct termio
{
unsigned short c_iflag; //输入模式标志
unsigned short c_oflag; //输出模式标志
unsigned short c_cflag; //控制模式标志
unsigned short c_lflag; //本地模式标志
unsigned char c_line ; //线路规程(速率)
}; unsigned char c_cc[NCC]; //控制字符数组
#define NCCS 17 //termios结构中控制字符数组的长度
struct termios
{
unsigned long c_iflag; //输入模式标志
unsigned long c_oflag; //输出模式标志
unsigned long c_cflag; //控制模式标志
unsigned long c_lflag; //本地模式标志
unsigned char c_line; //线路规程(速率)
unsigned char c_cc[NCCS];//控制字符数组
};
//c_cc数组对应字符索引值
#define VINTR 0 //c_cc[VINTR]=INTR (^C) \003 中断字符
#define VQUIT 1 //c_cc[VQUIT]=QUIT (^\) \034 退出字符
#define VERASE 2 //c_cc[VERASE]=ERASE (^H) \0177 擦除字符
#define VKILL 3 //c_cc[VKILL]=KILL (^U) \025 终止字符
#define VEOF 4 //c_cc[VEOF]=EOF (^D) \004 文件结束字符
#define VTIME 5 //c_cc[VTIME]=TIME (\0) \0 定时器值
#define VMIN 6 //c_cc[VMIN]= MIN (\1) \1 定时器值
#define VSWTC 7 //c_cc[VSWTC]= SWTC (\0) \0 交换字符
#define VSTART 8 //c_cc[VSTART]=START (^Q) \021 开始字符
#define VSTOP 9 //c_cc[VSTOP]=STOP (^S) \023 停止字符
#define VSUSP 10 //c_cc[VSUSP]=SUSP (^Z) \032 挂起字符
#define VEOL 11 //c_cc[VEOL]=EOL (\0) \0 行结束字符
#define VREPRINT 12 //c_cc[VREPRINT]=REPRINT (^R) \022 重显示字符
#define VDISCARD 13 //c_cc[VDISCARD]=DISCARD (^O) \017 丢弃字符
#define VWERASE 14 //c_cc[VWERASE]=WERASE (^W) \027 单词擦除字符
#define VLNEXT 15 //c_cc[VLNEXT]=LNEXT (^V) \026 下一行字符
#define VEOL2 16 //c_cc[VEOL2]=EOL2 (\0) \0 行结束2
//termios结构输入模式字段c_iflag标志符号常数
#define IGNBRK 0000001 //输入时回略break条件
#define BRKINT 0000002 //在break时产生sigint信号
#define IGNPAR 0000004 //胡恶劣奇哦校验出错的字符
#define PARMRK 0000010 //标记奇哦校验错
#define INPCK 0000020 //允许输入奇哦校验
#define ISTRIP 0000040 //屏蔽字符第8位
#define INLCR 0000100 //输入时将换行符NL映射成回车符CR
#define IGNCR 0000200 //忽略回车符CR
#define ICRNL 0000400 //在输入时将回车符CR映射成换行符NL
#define ICULC 0001000 //在输入时将大写字符转换成小写字符
#define IXON 0002000 //允许开始/停止输出控制
#define IXANY 0004000 //允许任何字符重启输出
#define IXOFF 0010000 //允许开始/停止输入控制
#define IMAXBEL 0020000 //输入队列满时响铃
//termios结构中输出模式字段c_oflag何种标志
#define OPOST 0000001 //执行输出处理
#define OLCUC 0000002 //在输出时将小写字符转换成大写字符
#define ONLCR 0000004 //在输出时将换行符NL映射成回车换行符CR-NL
#define OCRNL 0000010 //子输出时将回车符CR映射成换行符NL
#define ONOCR 0000020 //在0列不输出回车符CR
#define ONLRET 0000040 //换行符NL在执行回车符的功能
#define OFILL 0000100 //延迟时使用填充字符而不使用时间延迟
#define OFDEL 0000200 //填充字符是ASCII码DEL,如果未设置,使用ASCII NULL
#define NLDLY 0000400 //选择换行延迟
#define NL0 0000000 //换行延迟类型0
#define NL1 0000400 //换行延迟类型1
#define CRDLY 0003000 //选择回车延迟
#define CR0 0000000 //回车延迟类型0
#define CR1 0001000 //回车延迟类型1
#define CR2 0002000 //回车延迟类型2
#define CR3 0003000 //回车延迟类型3
#define TABDLY 0014000 //选择水平制表延迟
#define TAB0 0000000 //水平制表延迟类型0
#define TAB1 0004000 //水平制表延迟类型1
#define TAB2 0010000 //水平制表延迟类型2
#define TAB3 0014000 //水平制表延迟类型3
#define XTABS 0014000 //将制表符TAB换成空格,该值表示空格数
#define BSDLY 0020000 //选择退格延迟
#define BS0 0000000 //退格延迟类型0
#define BS1 0020000 //退格延迟类型1
#define VTDLY 0040000 //纵向制表延迟
#define VT0 0000000 //纵向制表延迟类型0
#define VT1 0040000 //纵向制表延迟类型1
#define FFDLY 0040000 //选择换页延迟
#define FF0 0000000 //换页延迟类型0
#define FF1 0040000 //换页延迟类型1
//termios结构中控制模式字段c_cfag符号
#define CBAUD 0000000 //传输速率屏蔽码
#define B0 0000000 //挂断线路
#define B50 0000000 //波特率50
#define B75 0000000 //波特率75
#define B110 0000000 //波特率110
#define B134 0000000 //波特率134
#define B150 0000000 //波特率150
#define B200 0000000 //波特率200
#define B300 0000000 //波特率300
#define B600 0000000 //波特率600
#define B1200 0000000 //波特率1200
#define B1800 0000000 //波特率1800
#define B2400 0000000 //波特率2400
#define B4800 0000000 //波特率4800
#define B9600 0000000 //波特率9600
#define B19200 0000000 //波特率1920
#define B38400 0000000 //波特率38400
#define B57600 0000000 //波特率38400
#define B115200 0000000 //波特率38400
#define B230400 0000000 //波特率38400
#define EXTA B19200 //扩展波特率A
#define EXTB B38400 //扩展波特率B
#define _POSIX_VDISABLE 0
#define CSTART 0
#define CSTOP 0
#define CSIZE 0000060 //字符位宽度屏蔽码
#define CS5 0000000 //每字符5比特位
#define CS6 0000020 //每字符6比特位
#define CS7 0000040 //每字符7比特位
#define CS8 0000060 //每字符8比特位
#define CSTOPB 0000100 //设置两个停止位
#define CREAD 0000200 //允许接收
#define CPARENB 0000400 //开始输出时产生奇哦位,输入时进行奇哦校验
#define CPARODD 0001000 //输入/输入校验是奇校验
#define HUPCL 0002000 //最后进程关闭后挂断
#define CLOCAL 0004000 //忽略调制解调器
#define CLBAUD 0360000 //输入波特率被
#define CRTSCTS 02000000000 //流控制
#define PARENB CPARENB
#define PARODD CPARODD
//termios结构是哦那个本地模式标志字段c_lflag
#define ISIG 0000001 //当接收到字符INTR,QUIT,SUSP,DSUSP产生相应信号
#define ICANON 0000002 //开始规范模式
#define XCASE 0000004 //若设置来ICANON,终端是大写字符
#define ECHO 0000010 //回显输入字符
#define ECHOE 0000020 //若设置了ICANON,则erase/werase将擦除前一字符/单词
#define ECHOK 0000040 //若设置了ICANON,则kill字符旧爱那个擦除当前行
#define ECHONL 0000100 //若设置了ICANON,则即使咩有ECHO也回显NL字符
#define NOFLSH 0000200 //当生成SIGINT忽然SIGQUIT信号时不刷新输入输出队列,当
//生成SIGSUSP信号后,刷新输入队列
#define TOSTOP 0000400 //发送SIGTOU信号到后台进程的进程组,该后台进程试图写自己
//自己的控制终端
#define ECHOCTL 0001000 //若设置了ECHO,则除来TAB,NL,START,STOP以外的ASCII
//控制信号将被回显成象‘^X’样子,X是控制符+0x40
#define ECHORPT 0002000 //若设置来IECHO,ICANON则字符在擦除时将显示
#define ECHOKE 0004000 //若设置了ICANON,则kill通过擦除行上所有字符被回显
#define FLUSHO 0010000 //输出被刷新,通过键入DISCARD字符,该标志被反转
#define PENDIN 0040000 //当下一个字符是读时,输入队列中的所有字符将被重显
#define IEXTEN 0100000 //开启实现时定义的输入处理
//modem线路信号符号常数
#define TIOCM_LE 0x001 //线路允许
#define TIOCM_DTR 0x002 //数据终端就绪
#define TIOCM_RTS 0x004 //请求发送
#define TIOCM_ST 0x008 //串行数据发送
#define TIOCM_SR 0x010 //串行数据接收
#define TIOCM_CTS 0x020 //清除发送
#define TIOCM_CAR 0x040 //载波检测
#define TIOCM_RNG 0x080 //响玲指示
#define TIOCM_DSR 0x100 //数据设备就绪
#define TIOCM_CD TIOCM_CAR//
#define TIOCM_R1 TIOCM_RNG//
//tcfow()和TCXONCSHIYONG
#define TCOOFF 0 //挂起输出
#define TCOON 1 //重启被挂起的输出
#define TCIOFF 2 //系统传输一个stop字符,使设备停止向系统传输数据
#define TCION 3 //系统传输一个start字符,使设备开始向系统传输数据
//tcflush()和TCFLSH使用
#define TCIFLUSH 0 //请接收到的数据但不读
#define TCOFLUSH 1 //清已写的数据但不传送
#define TCIOFLUSH 2 //清接收到的数据但不读,清已写的数据但不传送
//tcsetattr()使用
#define TCSANOW 0 //改变立即发生
#define TCSADRAIN 1 //改变在所有已写的输出被传输之后发生
#define TCSAFLUSH 2 //改变在所有已写的输出被传输之后并且在所有接收到
//还没有读取的数据被丢弃之后发生
typedef int speed_t; //波特率数值类型
//返回termios_p所指termios结构中的接收波特率
extern speed_t cfgetispeed(struct termios *termios_p);
//返回termios_p所指termios结构中的发送波特率
extern speed_t cfgetospeed(struct termios *termios_p);
//将termios_p所指termios结构中的接收波特率设置为speed
extern int cfsetispeed(struct termios*termios_p,speed_t speed);
//将termios_p所指termios结构中的发送波特率设置为speed
extern int cfsetospeed(struct termios *termios_p,speed_t speed);
//等待fildes所指对象已写输出数据被传送出去
extern int tcdrain(int fildes);
//挂起/重启fildes所指对象数据的接收和发送
extern int tcflow(int fildes,int action);
//丢弃fildes指定对象 所有已写但还没传送以及所有已收到但还没有读取的数据
extern int tcflush(int fildes,int queue_selector);
//获取与句柄fildes对应对象的参数,并将其保存在termios_p所指的地方
extern int tcgetattr(int fildes,struct termios *termios_p);
//如果终端使用异步串行数据传输,则在一定时间内连续传输一系列0值比特位
extern int tcsendbreak(int fildes,int duration);
//使用termios结构指针termios_p所指的数据,设置与终相关的参数
extern int tcsetattr(int fildes,int optional_actions,struct termios *termios_p);
#endif
修改ezspSetupSerialPort方法实现;
EzspStatus ezspSetupSerialPort(int* serialPortFdReturn,
char* errorStringLocation,
int maxErrorLength,
bool bootloaderMode)
{
//TODO 使用esp32 串口2;在应用启动时完成串口初始化
return EZSP_SUCCESS;
}
增加外部方法声明(这两个方法,将在esp32中实现):
//串口写入数据
extern int esp32_uart_SerialWriteByte(const char* src, size_t size);
//串口读取数据
extern int16_t esp32_uart_SerialReadByte(uint8_t* buf, uint16_t length);
然后将此文件中(有多处),
bytesRead = read(serialFd, inBuffer, inBlockLen); 替换为 bytesRead = esp32_uart_SerialReadByte( inBuffer, inBlockLen);
count = write(serialFd, outBufRd, outBufWr - outBufRd); 替换为 count = esp32_uart_SerialWriteByte( (const char*) outBufRd, outBufWr - outBufRd);
如下图所示
备注:ezspSerialReadAvailable、ezspSerialWriteFlush这两个方法非常重要,是host和ncp在通讯时,串口的写入和读取;对性能要求很高,不能出现阻塞的情况。特别是ezspSerialReadAvailable,在主程序中每隔20ms会调用一次,用于不断检测ncp是否有数据送到host。
4)ezsp-esp32.c
EzspStatus sendCommand(void)方法、void ezspTick(void)方法中的assert改成打印错误信息(assert在esp32中会引发MCU重启,或者重新定义assert在esp32中的实现,会是更好的解决方案)
备注:ezsp协议的主要实现方法都在这里,尽量不要改动里面内容。
5)gateway-relay-mqtt-esp32.c
static void publishMqttZclCommand(uint8_t commandId,
boolean clusterSpecific,
uint16_t clusterId,
boolean mfgSpecific,
uint16_t mfgCode,
uint8_t* buffer,
uint8_t bufLen,
uint8_t payloadStartIndex)
备注:publishMqttZclCommand方法好像会产生内存泄露问题,特别是在OTA的时候,需要向mqtt大量上报OTA状态的时候。每次调用会泄露52字节;因为mqtt是采用esp32自己的api;不是使用芯科的插件,所以可能导致某些资源(例如json对象)没有释放;暂时的解决办法是直接返回,好像功能也正常,相当奇怪;后面再仔细研究。
这个方法的调用链如下:
emAfPreCommandReceived -> emberAfPluginGatewayRelayMqttPreCommandReceivedCallback -> publishMqttZclCommand
emAfPreCommandReceived 位于“znet-bookkeeping.c”文件中;(难道是host收到命令后,如果是zcl命令,又将命令发送到mqtt?这么奇怪)
6)gateway-support-esp32.c
先把assert后面的代码先屏蔽了。
static void ezspSerialPortCallback(EzspSerialPortEvent event, int fileDescriptor)
{
printf("=================ezspSerialPortCallback=================");
if (event == EZSP_SERIAL_PORT_CLOSED) {
printf("EZSP serial port closed. FD=%d \r\n", fileDescriptor);
} else if (event == EZSP_SERIAL_PORT_OPENED) {
printf("Registered EZSP FD %d \r\n", fileDescriptor);
}
/**
assert(fileDescriptor != NULL_FILE_DESCRIPTOR);
if (event == EZSP_SERIAL_PORT_CLOSED) {
debugPrint("EZSP serial port closed. FD=%d", fileDescriptor);
emberAfPluginFileDescriptorDispatchRemove(fileDescriptor);
} else if (event == EZSP_SERIAL_PORT_OPENED) {
EmberAfFileDescriptorDispatchStruct dispatchStruct = {
ezspFileDescriptorReadyCallback, // callback
(void *) fileDescriptor, // data passed to callback
EMBER_AF_FILE_DESCRIPTOR_OPERATION_READ,
fileDescriptor,
};
debugPrint("Registered EZSP FD %d", fileDescriptor);
if (EMBER_SUCCESS != emberAfPluginFileDescriptorDispatchAdd(&dispatchStruct)) {
emberAfCorePrintln("Error: Gateway Plugin failed to register EZSP FD %d", fileDescriptor);
}
}
**/
}
备注:如果ezsp出现通讯异常,会打印异常错误码,都定义在“ezsp-enum.h”的EzspStatus结构体中;如下图所示。
下面是出现频率最多的错误,先记录一下
// Operation not yet complete.
EZSP_ASH_IN_PROGRESS = 0x20,
// Fatal error detected by host.
EZSP_HOST_FATAL_ERROR = 0x21,
// Fatal error detected by NCP.
EZSP_ASH_NCP_FATAL_ERROR = 0x22,
// Tried to send DATA frame too long.
EZSP_DATA_FRAME_TOO_LONG = 0x23,
// Tried to send DATA frame too short.
EZSP_DATA_FRAME_TOO_SHORT = 0x24,
// No space for tx'ed DATA frame.
EZSP_NO_TX_SPACE = 0x25,
// No space for rec'd DATA frame.
EZSP_NO_RX_SPACE = 0x26,
// No receive data available.
EZSP_NO_RX_DATA = 0x27,
// Not in Connected state.
EZSP_NOT_CONNECTED = 0x28,
// The NCP received a command before the EZSP version had been set.
EZSP_ERROR_VERSION_NOT_SET = 0x30,
// The NCP received a command containing an unsupported frame ID.
EZSP_ERROR_INVALID_FRAME_ID = 0x31,
7)command-relay-esp32.c
将emberAfPluginCommandRelaySave、emberAfPluginCommandRelayLoad方法调整如下;将原来的文件操作部分先删除,后面有需要再调整为esp32的文件操作方式。如下图所示
void emberAfPluginCommandRelaySave(void)
{
//TODO esp32暂时不将配置保存到本地文件
emberAfPluginCommandRelayChangedCallback();
}
void emberAfPluginCommandRelayLoad(void)
{
initRelayTable();
//TODO esp32暂时不将配置保存到本地文件
emberAfPluginCommandRelayChangedCallback();
}
备注:此文件是命令行处理插件,相关的文件还包括command-interpreter2.h等文件;在command-interpreter2.h有详细的命令行使用方法(类似其他MCU的AT指令操作),可以重点关注,特别是其中的bool emberProcessCommandString(uint8_t *input, uint8_t sizeOrPort) 方法。
8)device-table-esp32.c
和上面类似,将emAfDeviceTableSave、emAfDeviceTableLoad关于文件操作部分先删除。
// Save/Load the devices
void emAfDeviceTableSave(void)
{
//TODO esp32 不保存device table 文件
return;
}
void emAfDeviceTableLoad(void)
{
//TODO esp32 不保存device table 文件
return;
}
9)device-table-discovery-esp32.c
emAfPluginDeviceTablePreZDOMessageReceived方法最后,调整为return true;如下图所示。
如果是return false;可能引发esp32重启(可能是内存访问越界),具体原因还没找到,先记录一下。
10)ota-storage-linux-esp32.c
修改ota文件保存目录(与后续esp32中的分区表保持一致)、修改相关的存储初始化方法、关闭方法(后续在esp32中做相应处理)。
static char* storageDevice = "/ota-files/";
static bool storageDeviceIsDirectory = true;
EmberAfOtaStorageStatus emAfOtaSetStorageDevice(const void* device)
{
if (initDone) {
return EMBER_AF_OTA_STORAGE_ERROR;
}
}
EmberAfOtaStorageStatus emberAfOtaStorageInitCallback(void)
{
if (initDone) {
return EMBER_AF_OTA_STORAGE_SUCCESS;
}
EmberAfOtaStorageStatus status;
status = initImageDirectory();
iterator = NULL; // Must be initialized via
// otaStorageIteratorReset()
if (status == EMBER_AF_OTA_STORAGE_SUCCESS) {
initDone = true;
}
return status;
}
void emAfOtaStorageClose(void)
{
OtaImage* ptr = imageListLast;
while (ptr != NULL) {
OtaImage* current = ptr;
ptr = (OtaImage*)ptr->prev;
freeOtaImage(current);
}
imageListLast = NULL;
imageListFirst = NULL;
initDone = false;
imageCount = 0;
}
11)token-esp32.c
不清楚要来干嘛,暂时调整如下:
#define _XOPEN_SOURCE 500
#include PLATFORM_HEADER
#include CONFIGURATION_HEADER
#include EMBER_AF_API_HAL
#ifdef EMBER_AF_API_TOKEN
#define VERSION 1
extern const uint16_t tokenCreators[];
extern const bool tokenIsCnt[];
extern const uint8_t tokenSize[];
extern const uint8_t tokenArraySize[];
extern const void * const tokenDefaults[];
// TODO: Don't include stack tokens on the host.
#define DEFINETOKENS
#define TOKEN_MFG TOKEN_DEF
#define TOKEN_DEF(name, creator, iscnt, isidx, type, arraysize, ...) \
TOKEN_##name##_ADDRESS,
static const uint16_t addresses[] = {
#include "stack/config/token-stack.h"
};
#undef TOKEN_DEF
#undef TOKEN_MFG
#undef DEFINETOKENS
static void initializeTokenSystem(void);
static void resetTokenData(void);
static size_t getNvmOffset(uint16_t token, uint8_t index, uint8_t len);
#ifndef EMBER_AF_TOKEN_FILENAME
#if defined(EMBER_AF_DEVICE_NAME)
#define EMBER_AF_TOKEN_FILENAME EMBER_AF_DEVICE_NAME ".nvm"
#elif defined(ZA_PROMPT)
#define EMBER_AF_TOKEN_FILENAME ZA_PROMPT ".nvm"
#else
#error EMBER_AF_TOKEN_FILENAME must be defined.
#endif
#endif
// #define EMBER_AF_HOST_TOKEN_DEBUG
#ifdef EMBER_AF_HOST_TOKEN_DEBUG
#define hostTokenDebugPrintf(...) fprintf(stdout, __VA_ARGS__)
#else
#define hostTokenDebugPrintf(...)
#endif
// mmap(2) returns MAP_FAILED on failure, which is not necessarily defined the
// same as NULL.
static uint8_t *nvm = MAP_FAILED;
#define isInitialized() (nvm != MAP_FAILED)
#define PER_TOKEN_OVERHEAD \
(sizeof(tokenCreators[0]) \
+ sizeof(tokenIsCnt[0]) \
+ sizeof(tokenSize[0]) \
+ sizeof(tokenArraySize[0]))
#define TOTAL_SIZE \
(1 /* version overhead */ \
+ TOKEN_COUNT * PER_TOKEN_OVERHEAD \
+ TOKEN_MAXIMUM_SIZE)
typedef struct {
size_t offset; // offset from start of nvm file
bool present; // true if entry is present in nvm file
} nvmCreatorOffsetType;
// keeps track of token offsets in nvm file (helps with rearranged tokens)
// when populating, each index is maintained to be the same as the creator's
// index in tokenCreators[], tokenIsCnt[] etc.
static nvmCreatorOffsetType nvmCreatorOffset[TOKEN_COUNT];
void halInternalGetTokenData(void *data, uint16_t token, uint8_t index, uint8_t len)
{
}
void halInternalSetTokenData(uint16_t token, uint8_t index, void *data, uint8_t len)
{
}
void halInternalSetMfgTokenData(uint16_t token, void *data, uint8_t len)
{
}
// check if token in nvm file is still present in stack/app
// if present, return new index in tokenCreators, else return false
static bool isOldToken(uint16_t tokCreator, size_t* index)
{
return false;
}
// should we copy nvm values?
// if index is present (was populated) and token structure is same, return true
// else return false, so that we reset values
static bool copyNvm(uint8_t* nvmData,
size_t index,
size_t* tokOffset)
{
return false;
}
static void initializeTokenSystem(void)
{
}
static void resetTokenData(void)
{
}
static size_t getNvmOffset(uint16_t token, uint8_t index, uint8_t len)
{
return 1;
}
#endif // EMBER_AF_API_TOKEN
12)backchannel-support-esp32.c
不清楚要来干嘛,暂时调整如下:
#include PLATFORM_HEADER //compiler/micro specifics, types
#include "stack/include/ember-types.h"
#include "stack/include/error.h"
#include "hal/hal.h"
#include <sys/types.h>
#include "app/framework/plugin-host/gateway/gateway-support.h"
//------------------------------------------------------------------------------
// GLOBALS
const bool backchannelSupported = true;
// The serial port number (0 or 1) plus this offset gives the port that the
// socket server will listen on. By default (to match the InSight Adapter
// behavior):
// * serial port 0 -> server port 4900
// * serial port 1 -> server port 4901
int backchannelSerialPortOffset = EMBER_AF_PLUGIN_GATEWAY_TCP_PORT_OFFSET;
#define SERVER_PORT_OFFSET (backchannelSerialPortOffset)
#define INVALID_FD -1
static int socketFd[] = { INVALID_FD, INVALID_FD };
static int clientFd[] = { INVALID_FD, INVALID_FD };
//struct sockaddr_in clientConnections[2];
static bool debugOn = false;
static const char debugString[] = "backchannel";
// These will change
static int LOCAL_STDIN = 0;
static int LOCAL_STDOUT = 1;
static int LOCAL_STDERR = 2;
#define REMOTE_STDIN 0
#define REMOTE_STDOUT 1
#define REMOTE_STDERR 2
#define MAX_STRING_LENGTH 250
// Turned on via command-line options
bool backchannelEnable = false;
static FILE* clientOut[] = { NULL, NULL };
//------------------------------------------------------------------------------
// Forward Declarations
static int willConnectionBlock(bool server, uint8_t port, bool read);
#define willClientConnectionBlock(port) \
willConnectionBlock(false, (port), false)
#define willServerConnectionBlock(port) \
willConnectionBlock(true, (port), true)
static bool getNewConnection(uint8_t port);
static void unixError(const char* format, ...);
static void debugPrint(const char* formatString, ...);
static void infoPrint(const char* formatString, ...);
static int myPrintf(int fd, const char* formatString, ...);
static int myVprintf(int fd, const char* formatString, va_list ap);
//------------------------------------------------------------------------------
// API
EmberStatus backchannelStartServer(uint8_t port)
{
return EMBER_SUCCESS;
}
EmberStatus backchannelClientConnectionCleanup(uint8_t port)
{
return EMBER_SUCCESS;
}
EmberStatus backchannelStopServer(uint8_t port)
{
return EMBER_SUCCESS;
}
// Retrieves a single byte from the client connection. Returns the number
// of bytes read, or -1 on error. If no client connection currently exists,
// then it will block until one is established. If an error is returned then
// it means an attempt was made to establish one but it failed.
EmberStatus backchannelReceive(uint8_t port, char* data)
{
return EMBER_ERR_FATAL;
}
EmberStatus backchannelSend(uint8_t port, uint8_t * data, uint8_t length)
{
return EMBER_INVALID_CALL;
}
// Checks on the state of the current backchannel connection.
// If one doesn't exist, it can wait for a new connection and return
// the result.
BackchannelState backchannelCheckConnection(uint8_t port,
bool waitForConnection)
{
return NO_CONNECTION;
}
EmberStatus backchannelServerPrintf(const char* formatString, ...)
{
return EMBER_SUCCESS ;
}
EmberStatus backchannelClientPrintf(uint8_t port, const char* formatString, ...)
{
return EMBER_SUCCESS ;
}
EmberStatus backchannelClientVprintf(uint8_t port,
const char* formatString,
va_list ap)
{
return EMBER_SUCCESS ;
}
// Re-map STDIN, STDOUT, and STDERR to the client connection.
// This allows the software to use normal read() and write() calls to
// to receive and send data to the remote client.
EmberStatus backchannelMapStandardInputOutputToRemoteConnection(int port)
{
return EMBER_SUCCESS;
}
EmberStatus backchannelCloseConnection(uint8_t port)
{
return EMBER_SUCCESS ;
}
//------------------------------------------------------------------------------
// Internal Functions
// Returns 0 if a read/write will not block, 1 if it will, and -1 on error.
static int willConnectionBlock(bool server, uint8_t port, bool read)
{
return 0 ;
}
// Accepts a new TCP connection. Returns the state of the connection.
static bool getNewConnection(uint8_t port)
{
return false;
}
//------------------------------------------------------------------------------
// Internal Printing routines
// Print an error message plus the associated 'errno' string
static void unixError(const char* format, ...)
{
}
static void debugPrint(const char* formatString, ...)
{
}
static void infoPrint(const char* formatString, ...)
{
}
// Because we mess around with FDs, we need our own printing routine
// for handling where messages are printed to.
static int myPrintf(int fd, const char* formatString, ...)
{
return 0;
}
// Returns 0 on success, 1 on error
static int myVprintf(int fd, const char* formatString, va_list ap)
{
return 0;
}
13)Makefile
指定以生成静态库方式编译,指定esp32交叉编译命令
将前面12个修改的esp32文件名,替换到对应的位置
在编译参数中增加 mlongcalls参数
如果不增加此参数,可以正常编译为静态库;但在esp32中使用时,会出现“call8: call target out of range: malloc”异常,如下图所示
具体异常描述,可查看此贴子:https://www.esp32.com/viewtopic.php?t=1612
最后,将修改后的Makefile内容贴上,仅供参考
# This file was generated by Simplicity Studio from the following template:
# protocol/zigbee/tool/appbuilder/host-unix-Makefile-afv2
# Please do not edit it directly.
# This Makefile defines how to build a unix host application connected to an
# Ember NCP EZSP device. This also works for Windows machines running
# Cygwin.
# Variables
# If using a different compiler than GCC, you can create a makefile
# that overrides the following variables.
# COMPILER - Compiler binary path
# LINKER - Linker binary path
# ARCHIVE - Optional archive tool, only necessary for building a library.
# Must also set GENERATE_LIBRARY := 1 in your makefile.
# COMPILER_INCLUDES - Any additional compiler includes each prefixed with -I
# COMPILER_DEFINES - Any additional compiler defines each prefixed with -D
# COMPILER_FLAGS - The set of compiler flags (not including dependencies)
# LINKER_FLAGS - The set of linker flags
# ARCHIVE_FLAGS - The set of archive tool flags.
# DEPENDENCY_FLAGS - The set of dependency generation flags used to generate
# dependencies at the same time compilation is executed.
# DEPENDENCY_POST_PROCESS - An optional post processing step for massaging
# generated dependencies. Only necessary when using a compiler on the
# non-native platform (e.g. Windows compiler on Linux)
# PLATFORM_HEADER_FILE - The header file defining the basic int8u, int32u,
# and other typedefs and platform elements.
# ARCHIVE_EXTENSION - The file extension for archives if not using the standard
# .a file extension.
#
# Then pass the makefile to this one on the command line with:
# "make -C app/builder/Z3GatewayHost_ESP32 INCLUDE_MAKEFILE=my-custom.mak"
# or
# "cd app/builder/Z3GatewayHost_ESP32; make INCLUDE_MAKEFILE=my-custom.mak"
#
NO_READLINE ?= 1
GENERATE_LIBRARY := 1
ifdef INCLUDE_MAKEFILE
include $(INCLUDE_MAKEFILE)
endif
.SUFFIXES:
COMPILER ?= xtensa-esp32-elf-gcc
LINKER ?= xtensa-esp32-elf-gcc
ARCHIVE ?= ar
STD ?= gnu99
ARCHIVE_EXTENSION ?= .a
CC = $(COMPILER)
LD = $(LINKER)
SHELL = /bin/sh
ifneq ($(CURDIR),$(shell dirname '$(abspath $(lastword $(MAKEFILE_LIST)))'))
$(error This makefile should only be invoked under its current directory ($(shell dirname '$(abspath $(lastword $(MAKEFILE_LIST)))')))
endif
COMPILER_INCLUDES ?=
INCLUDES= -I./ \
$(COMPILER_INCLUDES) \
-I./../../../v2.7 \
-I./../../../v2.7/protocol/zigbee/app/framework \
-I./../../../v2.7/protocol/zigbee/app/framework/../.. \
-I./../../../v2.7/protocol/zigbee/app/framework/../../stack \
-I./../../../v2.7/protocol/zigbee/app/framework/../util \
-I./../../../v2.7/protocol/zigbee/app/framework/../util/common \
-I./../../../v2.7/protocol/zigbee/app/framework/../util/ezsp \
-I./../../../v2.7/protocol/zigbee/app/framework/../util/serial \
-I./../../../v2.7/protocol/zigbee/app/framework/../util/zigbee-framework \
-I./../../../v2.7/protocol/zigbee/app/framework/cli \
-I./../../../v2.7/protocol/zigbee/app/framework/include \
-I./../../../v2.7/protocol/zigbee/app/framework/security \
-I./../../../v2.7/protocol/zigbee/app/framework/util \
-I./Z3GatewayHost_ESP32 \
-I./../../../v2.7/platform/base/hal \
-I./../../../v2.7/platform/base/hal/plugin \
-I./../../../v2.7/platform/base/hal/.. \
-I./../../../v2.7/platform/base/hal/micro/generic \
-I./../../../v2.7/platform/base/hal/micro/unix/host \
-I../../../v2.7/platform/base/hal/micro/unix/host/board \
-I../../../v2.7/util/plugin/plugin-common/mbedtls \
-I../../../v2.7/util/third_party/mbedtls \
-I../../../v2.7/util/third_party/mbedtls/include \
-I../../../v2.7/util/third_party/mbedtls/include/mbedtls \
-I../../../v2.7/util/third_party/mbedtls/sl_crypto/include \
\
APP_BUILDER_OUTPUT_DIRECTORY=.
APP_BUILDER_CONFIG_HEADER=$(APP_BUILDER_OUTPUT_DIRECTORY)/Z3GatewayHost_ESP32.h
APP_BUILDER_STORAGE_FILE=$(APP_BUILDER_OUTPUT_DIRECTORY)/Z3GatewayHost_ESP32_endpoint_config.h
PLATFORM_HEADER_FILE ?= \"../../../v2.7/platform/base/hal/micro/unix/compiler/gcc-esp32.h\"
DEFINES = \
$(COMPILER_DEFINES) \
-DUNIX \
-DUNIX_HOST \
-DPHY_NULL \
-DCONFIGURATION_HEADER=\"../../../v2.7/protocol/zigbee/app/framework/util/config.h\" \
-DEZSP_HOST \
-DGATEWAY_APP \
-DZA_GENERATED_HEADER=\"$(APP_BUILDER_CONFIG_HEADER)\" \
-DATTRIBUTE_STORAGE_CONFIGURATION=\"$(APP_BUILDER_STORAGE_FILE)\" \
-DPLATFORM_HEADER=$(PLATFORM_HEADER_FILE) \
-DBOARD_HOST \
-DBOARD_HEADER=\"Z3GatewayHost_ESP32_board.h\" \
-DEM_AF_TEST_HARNESS_CODE \
-DEM_AF_LINK_M \
-DEM_AF_LINK_PTHREAD \
-DEMBER_AF_API_EMBER_TYPES=\"stack/include/ember-types.h\" \
-DEMBER_AF_API_DEBUG_PRINT=\"app/framework/util/print.h\" \
-DEMBER_AF_API_AF_HEADER=\"app/framework/include/af.h\" \
-DEMBER_AF_API_AF_SECURITY_HEADER=\"app/framework/security/af-security.h\" \
-DEMBER_AF_API_NEIGHBOR_HEADER=\"stack/include/stack-info.h\" \
-DEMBER_STACK_ZIGBEE \
-DEZSP_ASH \
-DMBEDTLS_CONFIG_FILE=\"mbedtls-config-generated.h\" \
-DWITH_POSIX \
-D_GNU_SOURCE \
COMPILER_FLAGS ?= \
-Wall \
-ggdb \
-O0 \
-mlongcalls \
-std=$(STD)
APPLICATION_FILES= \
./znet-bookkeeping.c \
./call-command-handler.c \
./callback-stub.c \
./stack-handler-stub.c \
./znet-cli.c \
./Z3GatewayHost_ESP32_callbacks.c \
../../../v2.7/protocol/zigbee/app/framework/../util/common/library.c \
../../../v2.7/protocol/zigbee/app/framework/../util/serial/command-interpreter2.c \
../../../v2.7/protocol/zigbee/app/framework/../util/zigbee-framework/zigbee-device-common.c \
../../../v2.7/protocol/zigbee/app/framework/../util/zigbee-framework/zigbee-device-host.c \
../../../v2.7/protocol/zigbee/app/framework/../../stack/framework/event-control.c \
../../../v2.7/platform/base/hal/micro/generic/led-stub.c \
../../../v2.7/platform/base/hal/micro/generic/mem-util.c \
../../../v2.7/platform/base/hal/plugin/antenna-stub/antenna-stub.c \
../../../v2.7/platform/base/hal/plugin/buzzer-stub/buzzer-stub.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/address-table/address-table.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/address-table/address-table-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/basic/basic.c \
../../../v2.7/util/third_party/cjson/cJSON.c \
../../../v2.7/util/third_party/cjson/cJSON_Utils.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/color-control-server/color-control-server.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/command-relay/command-relay-esp32.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/command-relay/command-relay-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/concentrator/concentrator-support.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/concentrator/concentrator-support-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/counters/counters-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/counters/counters-ota-host.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/counters/counters-host.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/device-table/device-table-esp32.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/device-table/device-table-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/device-table/device-table-discovery-esp32.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/device-table/device-table-tracking.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ezmode-commissioning/ez-mode.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ezmode-commissioning/ez-mode-cli.c \
../../../v2.7/protocol/zigbee/app/util/ezsp/ezsp-callbacks.c \
../../../v2.7/protocol/zigbee/app/util/ezsp/ezsp-enum-decode.c \
../../../v2.7/protocol/zigbee/app/util/ezsp/ezsp-frame-utilities.c \
../../../v2.7/protocol/zigbee/app/util/ezsp/ezsp-esp32.c \
../../../v2.7/protocol/zigbee/app/ezsp-host/ezsp-host-io-esp32.c \
../../../v2.7/protocol/zigbee/app/ezsp-host/ezsp-host-queues.c \
../../../v2.7/protocol/zigbee/app/ezsp-host/ezsp-host-ui.c \
../../../v2.7/protocol/zigbee/app/util/ezsp/serial-interface-uart.c \
../../../v2.7/protocol/zigbee/app/ezsp-host/ash/ash-host-ui.c \
../../../v2.7/protocol/zigbee/app/ezsp-host/ash/ash-host.c \
../../../v2.7/platform/base/hal/micro/generic/ash-common.c \
../../../v2.7/protocol/zigbee/app/framework/plugin-host/file-descriptor-dispatch/file-descriptor-dispatch.c \
../../../v2.7/protocol/zigbee/app/framework/plugin-host/gateway/gateway-support-esp32.c \
../../../v2.7/protocol/zigbee/app/framework/plugin-host/gateway/backchannel-support-esp32.c \
../../../v2.7/protocol/zigbee/app/framework/plugin-host/gateway/gateway-support-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin-host/gateway-relay-mqtt/gateway-relay-mqtt-esp32.c \
../../../v2.7/protocol/zigbee/app/framework/plugin-host/gateway-relay-mqtt/gateway-relay-mqtt-commands.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/green-power-client/green-power-client.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/green-power-client/green-power-client-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/green-power-common/green-power-common.c \
../../../v2.7/protocol/zigbee/stack/gp/gp-util.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/heartbeat/heartbeat.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ias-zone-client/ias-zone-client.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ias-zone-client/ias-zone-client-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/identify/identify.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/identify/identify-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/identify-feedback/identify-feedback.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/level-control/level-control.c \
../../../v2.7/util/plugin/plugin-common/linked-list/linked-list.c \
../../../v2.7/util/third_party/mbedtls/library/aes.c \
../../../v2.7/util/third_party/mbedtls/library/aesni.c \
../../../v2.7/util/third_party/mbedtls/library/arc4.c \
../../../v2.7/util/third_party/mbedtls/library/asn1parse.c \
../../../v2.7/util/third_party/mbedtls/library/asn1write.c \
../../../v2.7/util/third_party/mbedtls/library/base64.c \
../../../v2.7/util/third_party/mbedtls/library/bignum.c \
../../../v2.7/util/third_party/mbedtls/library/blowfish.c \
../../../v2.7/util/third_party/mbedtls/library/camellia.c \
../../../v2.7/util/third_party/mbedtls/library/ccm.c \
../../../v2.7/util/third_party/mbedtls/library/certs.c \
../../../v2.7/util/third_party/mbedtls/library/cipher.c \
../../../v2.7/util/third_party/mbedtls/library/cipher_wrap.c \
../../../v2.7/util/third_party/mbedtls/library/cmac.c \
../../../v2.7/util/third_party/mbedtls/library/ctr_drbg.c \
../../../v2.7/util/third_party/mbedtls/library/debug.c \
../../../v2.7/util/third_party/mbedtls/library/des.c \
../../../v2.7/util/third_party/mbedtls/library/dhm.c \
../../../v2.7/util/third_party/mbedtls/library/ecdh.c \
../../../v2.7/util/third_party/mbedtls/library/ecdsa.c \
../../../v2.7/util/third_party/mbedtls/library/ecjpake.c \
../../../v2.7/util/third_party/mbedtls/library/ecp.c \
../../../v2.7/util/third_party/mbedtls/library/ecp_curves.c \
../../../v2.7/util/third_party/mbedtls/library/entropy.c \
../../../v2.7/util/third_party/mbedtls/library/entropy_poll.c \
../../../v2.7/util/third_party/mbedtls/library/error.c \
../../../v2.7/util/third_party/mbedtls/library/gcm.c \
../../../v2.7/util/third_party/mbedtls/library/havege.c \
../../../v2.7/util/third_party/mbedtls/library/hmac_drbg.c \
../../../v2.7/util/third_party/mbedtls/library/md.c \
../../../v2.7/util/third_party/mbedtls/library/md2.c \
../../../v2.7/util/third_party/mbedtls/library/md4.c \
../../../v2.7/util/third_party/mbedtls/library/md5.c \
../../../v2.7/util/third_party/mbedtls/library/md_wrap.c \
../../../v2.7/util/third_party/mbedtls/library/memory_buffer_alloc.c \
../../../v2.7/util/third_party/mbedtls/library/net_sockets.c \
../../../v2.7/util/third_party/mbedtls/library/oid.c \
../../../v2.7/util/third_party/mbedtls/library/padlock.c \
../../../v2.7/util/third_party/mbedtls/library/pem.c \
../../../v2.7/util/third_party/mbedtls/library/pk.c \
../../../v2.7/util/third_party/mbedtls/library/pk_wrap.c \
../../../v2.7/util/third_party/mbedtls/library/pkcs11.c \
../../../v2.7/util/third_party/mbedtls/library/pkcs12.c \
../../../v2.7/util/third_party/mbedtls/library/pkcs5.c \
../../../v2.7/util/third_party/mbedtls/library/pkparse.c \
../../../v2.7/util/third_party/mbedtls/library/pkwrite.c \
../../../v2.7/util/third_party/mbedtls/library/ripemd160.c \
../../../v2.7/util/third_party/mbedtls/library/rsa.c \
../../../v2.7/util/third_party/mbedtls/library/rsa_internal.c \
../../../v2.7/util/third_party/mbedtls/library/sha1.c \
../../../v2.7/util/third_party/mbedtls/library/sha256.c \
../../../v2.7/util/third_party/mbedtls/library/sha512.c \
../../../v2.7/util/third_party/mbedtls/library/ssl_cache.c \
../../../v2.7/util/third_party/mbedtls/library/ssl_ciphersuites.c \
../../../v2.7/util/third_party/mbedtls/library/ssl_cli.c \
../../../v2.7/util/third_party/mbedtls/library/ssl_cookie.c \
../../../v2.7/util/third_party/mbedtls/library/ssl_srv.c \
../../../v2.7/util/third_party/mbedtls/library/ssl_ticket.c \
../../../v2.7/util/third_party/mbedtls/library/ssl_tls.c \
../../../v2.7/util/third_party/mbedtls/library/threading.c \
../../../v2.7/util/third_party/mbedtls/library/timing.c \
../../../v2.7/util/third_party/mbedtls/library/version.c \
../../../v2.7/util/third_party/mbedtls/library/version_features.c \
../../../v2.7/util/third_party/mbedtls/library/x509.c \
../../../v2.7/util/third_party/mbedtls/library/x509_create.c \
../../../v2.7/util/third_party/mbedtls/library/x509_crl.c \
../../../v2.7/util/third_party/mbedtls/library/x509_crt.c \
../../../v2.7/util/third_party/mbedtls/library/x509_csr.c \
../../../v2.7/util/third_party/mbedtls/library/x509write_crt.c \
../../../v2.7/util/third_party/mbedtls/library/x509write_csr.c \
../../../v2.7/util/third_party/mbedtls/library/xtea.c \
../../../v2.7/protocol/zigbee/app/framework/plugin-host/ncp-configuration/ncp-configuration.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/network-creator/network-creator.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/network-creator/network-creator-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/network-creator-security/network-creator-security.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/network-creator-security/network-creator-security-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/network-steering/network-steering.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/network-steering/network-steering-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/network-steering/network-steering-v2.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/network-steering/network-steering-host.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/on-off/on-off.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ota-common/ota-common.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ota-server/ota-server.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ota-server/ota-server-page-request.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ota-server/ota-server-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ota-server/ota-server-dynamic-block-period.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ota-server-policy/ota-server-policy.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ota-storage-common/ota-storage-common.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ota-storage-common/ota-storage-common-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/ota-storage-posix-filesystem/ota-storage-linux-esp32.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/poll-control-client/poll-control-client.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/poll-control-client/poll-control-client-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/reporting/reporting.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/reporting/reporting-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/reporting/reporting-default-configuration.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/scan-dispatch/scan-dispatch.c \
../../../v2.7/protocol/zigbee/app/util/ezsp/secure-ezsp-stub.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/simple-main/simple-main.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/simple-metering-client/simple-metering-client.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/simple-metering-client/simple-metering-client-cli.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/stack-diagnostics/stack-diagnostics.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/test-harness/test-harness.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/test-harness/read-write-attributes.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/test-harness/test-harness-host.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/time-server/time-server.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/trust-center-nwk-key-update-broadcast/trust-center-nwk-key-update-broadcast.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/trust-center-nwk-key-update-periodic/trust-center-nwk-key-update-periodic.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/trust-center-nwk-key-update-unicast/trust-center-nwk-key-update-unicast.c \
../../../v2.7/platform/base/hal/micro/generic/crc.c \
../../../v2.7/platform/base/hal/micro/generic/endian.c \
../../../v2.7/platform/base/hal/micro/generic/random.c \
../../../v2.7/platform/base/hal/micro/generic/system-timer.c \
../../../v2.7/platform/base/hal/micro/unix/host/micro.c \
../../../v2.7/platform/base/hal/micro/unix/host/token-def-unix.c \
../../../v2.7/platform/base/hal/micro/unix/host/token-esp32.c \
../../../v2.7/protocol/zigbee/app/util/serial/linux-serial-esp32.c \
../../../v2.7/platform/base/hal/plugin/serial/ember-printf-convert.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/update-tc-link-key/update-tc-link-key.c \
../../../v2.7/protocol/zigbee/app/framework/plugin/update-tc-link-key/update-tc-link-key-cli.c \
../../../v2.7/protocol/zigbee/app/framework/cli/core-cli.c \
../../../v2.7/protocol/zigbee/app/framework/cli/network-cli.c \
../../../v2.7/protocol/zigbee/app/framework/cli/option-cli.c \
../../../v2.7/protocol/zigbee/app/framework/cli/plugin-cli.c \
../../../v2.7/protocol/zigbee/app/framework/cli/security-cli.c \
../../../v2.7/protocol/zigbee/app/framework/cli/zcl-cli.c \
../../../v2.7/protocol/zigbee/app/framework/cli/zdo-cli.c \
../../../v2.7/protocol/zigbee/app/framework/security/af-node.c \
../../../v2.7/protocol/zigbee/app/framework/security/af-security-common.c \
../../../v2.7/protocol/zigbee/app/framework/security/af-trust-center.c \
../../../v2.7/protocol/zigbee/app/framework/security/crypto-state.c \
../../../v2.7/protocol/zigbee/app/framework/util/af-event.c \
../../../v2.7/protocol/zigbee/app/framework/util/af-main-common.c \
../../../v2.7/protocol/zigbee/app/framework/util/attribute-size.c \
../../../v2.7/protocol/zigbee/app/framework/util/attribute-storage.c \
../../../v2.7/protocol/zigbee/app/framework/util/attribute-table.c \
../../../v2.7/protocol/zigbee/app/framework/util/client-api.c \
../../../v2.7/protocol/zigbee/app/framework/util/message.c \
../../../v2.7/protocol/zigbee/app/framework/util/multi-network.c \
../../../v2.7/protocol/zigbee/app/framework/util/print.c \
../../../v2.7/protocol/zigbee/app/framework/util/print-formatter.c \
../../../v2.7/protocol/zigbee/app/framework/util/process-cluster-message.c \
../../../v2.7/protocol/zigbee/app/framework/util/process-global-message.c \
../../../v2.7/protocol/zigbee/app/framework/util/service-discovery-common.c \
../../../v2.7/protocol/zigbee/app/framework/util/time-util.c \
../../../v2.7/protocol/zigbee/app/framework/util/util.c \
../../../v2.7/protocol/zigbee/app/framework/util/af-main-host.c \
../../../v2.7/protocol/zigbee/app/framework/util/service-discovery-host.c \
LIBRARIES = \
\
OUTPUT_DIR=$(APP_BUILDER_OUTPUT_DIRECTORY)/build
OUTPUT_DIR_CREATED= $(OUTPUT_DIR)/created
EXE_DIR=$(OUTPUT_DIR)/exe
# Build a list of object files from the source file list, but all objects
# live in the $(OUTPUT_DIR) above. The list of object files
# created assumes that the file part of the filepath is unique
# (i.e. the bar.c of foo/bar.c is unique across all sub-directories included).
APPLICATION_OBJECTS= $(addprefix $(OUTPUT_DIR)/, $(notdir $(APPLICATION_FILES:.c=.o)))
ifdef GENERATE_LIBRARY
TARGET_FILE= $(EXE_DIR)/Z3GatewayHost_ESP32$(ARCHIVE_EXTENSION)
else
TARGET_FILE= $(EXE_DIR)/Z3GatewayHost_ESP32
endif
# -MMD and -MF generates Makefile dependencies while at the same time compiling.
# -MP notes to add a dummy 'build' rule for each header file. This
# prevent a problem where a removed header file will generate an error because a
# dependency references it but it can't be found anymore.
DEPENDENCY_FLAGS ?= -MMD -MP -MF $(@D)/$(@F:.o=.d)
# Dependency post process is a way to massage generated dependencies.
# This is necessary for example when using Make under Cygwin but compiling
# using a native Windows compiler that generates native Windows paths
# that Cygwin will choke on. Or if compiling on Linux using Wine to run a
# Windows compiler, a similar problem can occur.
DEPENDENCY_POST_PROCESS ?=
CPPFLAGS= $(INCLUDES) $(DEFINES) $(COMPILER_FLAGS) $(DEPENDENCY_FLAGS)
LINKER_FLAGS ?=
ifdef NO_READLINE
CPPFLAGS += -DNO_READLINE
else
LINKER_FLAGS += \
-lreadline \
-lncurses
endif
# Conditionally include the math library if EM_AF_LINK_M is defined.
ifeq ($(findstring -DEM_AF_LINK_M,$(DEFINES)),-DEM_AF_LINK_M)
LINKER_FLAGS += \
-lm
endif
# Conditionally include the POSIX threads library if EM_AF_LINK_PTHREAD is
# defined.
ifeq ($(findstring -DEM_AF_LINK_PTHREAD,$(DEFINES)),-DEM_AF_LINK_PTHREAD)
LINKER_FLAGS += \
-lpthread
endif
ARCHIVE_FLAGS ?= rus
# Rules
.PHONY: all
all: $(TARGET_FILE)
ifneq ($(MAKECMDGOALS),clean)
-include $(APPLICATION_OBJECTS:.o=.d)
endif
ifdef GENERATE_LIBRARY
$(TARGET_FILE): $(APPLICATION_OBJECTS) $(LIBRARIES)
$(ARCHIVE) $(ARCHIVE_FLAGS) $(TARGET_FILE) $^
@echo -e '\n$@ build success'
else
$(TARGET_FILE): $(APPLICATION_OBJECTS) $(LIBRARIES)
$(LD) $^ $(LINKER_FLAGS) -o $(TARGET_FILE)
@echo -e '\n$@ build success'
endif
.PHONY: clean
clean:
rm -rf $(OUTPUT_DIR)
$(OUTPUT_DIR_CREATED):
mkdir -p $(OUTPUT_DIR)
mkdir -p $(EXE_DIR)
touch $(OUTPUT_DIR_CREATED)
# To facilitate generating all output files in a single output directory, we
# must create separate .o and .d rules for all the different sub-directories
# used by the source files.
# If additional directories are added that are not already in the
# $(APPLICATION_FILES) above, new rules will have to be created below.
# Object File rules
# NOTE: We escape the commands in this rule because we don't want
# them to be interpreted when the function executes. We don't escape
# the dependency rule itself (1st line) because we want this to be
# explicit for each target.
define create-build-rules
$(OUTPUT_DIR)/$(notdir $(1:%.c=%.o)): $1 | $(OUTPUT_DIR_CREATED)
$$(CC) $$(CPPFLAGS) -c $$< -o $$@
$$(DEPENDENCY_POST_PROCESS)
endef
$(foreach d, $(APPLICATION_FILES), $(eval $(call create-build-rules,$d)))
# Dependency rules
# No explicit rules. Dependencies are generated as part of the compile step.
编译生成静态库
进入esp32工程项目,先用make clean清除编译环境,然后用make命令编译生成静态库,如下图所示。
成功编译后,会在build/exe目录生成Z3GatewayHost_ESP32.a静态库文件
用readelf -h Z3GatewayHost_ESP32.a命令,可以看到静态库信息如下:
至此,为esp32调用的准备工作结束,接下来将转到esp32的开发环境进行后续的集成工作。
本来想一篇文章把整个esp32移植过程写完,但是写得太长了,看着也累。还是分开几篇吧,这里先写到这,怎么使用静态库,下一篇再写。