相关系列文章

基于芯科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     0X541Bstruct 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 callbackEMBER_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 1extern 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 DEFINETOKENSstatic 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 filebool 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"//------------------------------------------------------------------------------
// GLOBALSconst 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 -1static 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 Declarationsstatic 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);//------------------------------------------------------------------------------
// APIEmberStatus 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 := 1ifdef INCLUDE_MAKEFILEinclude $(INCLUDE_MAKEFILE)
endif  .SUFFIXES:COMPILER ?= xtensa-esp32-elf-gcc
LINKER   ?= xtensa-esp32-elf-gcc
ARCHIVE  ?= ar
STD      ?= gnu99ARCHIVE_EXTENSION ?= .aCC = $(COMPILER)
LD = $(LINKER)
SHELL = /bin/shifneq ($(CURDIR),$(shell dirname '$(abspath $(lastword $(MAKEFILE_LIST)))'))
$(error This makefile should only be invoked under its current directory ($(shell dirname '$(abspath $(lastword $(MAKEFILE_LIST)))')))
endifCOMPILER_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.hPLATFORM_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_READLINECPPFLAGS += -DNO_READLINE
elseLINKER_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
endifARCHIVE_FLAGS ?= rus# Rules.PHONY: all
all: $(TARGET_FILE)ifneq ($(MAKECMDGOALS),clean)
-include $(APPLICATION_OBJECTS:.o=.d)
endififdef 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移植过程写完,但是写得太长了,看着也累。还是分开几篇吧,这里先写到这,怎么使用静态库,下一篇再写。

基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(三)-移植到ESP32平台(1)相关推荐

  1. 基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(-)-Z3GatewayHost应用

    相关系列文章 基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(-)-Z3GatewayHost应用搭建 基于芯科Host-NCP解决方案的Zigbee 3.0 Gate ...

  2. 基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(二)-使用gateway-management-ui

    相关系列文章 基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(-)-Z3GatewayHost应用搭建 基于芯科Host-NCP解决方案的Zigbee 3.0 Gate ...

  3. ZigBee 3.0实战教程-Silicon Labs EFR32+EmberZnet-2-02:芯科的软件解决方案Gecko SDK

    [ 源码. 文档. 软件. 硬件. 技术交流. 技术支持, 入口见 文末] [所有相关 IDE. SDK和 例程源码均可从群文件 免费获取, 免安装, 解压即用] 持续更新中,欢迎关注! 虽然Sili ...

  4. 2018FME博客大赛-基于FME的不同比例尺线面要素 一致性检测关键技术研究

    编  写:曹 文 涛 武汉市测绘研究院 二○一八年三月 概述 随着地理信息系统技术的不断发展和广泛应用,各省市国土测绘部门都纷纷建立起了各种比例尺的基础地理信息数据库,其提供的矢量地理数据为社会各行业 ...

  5. 国科金:共融机器人基础理论与关键技术研究重大研究计划

    来源:学术头条 国家自然科学基金委员会现发布共融机器人基础理论与关键技术研究重大研究计划 2022 年度项目指南,请申请人及依托单位按项目指南中所述的要求和注意事项申请. 国家自然科学基金委员会 20 ...

  6. ZigBee 3.0实战教程-Silicon Labs EFR32+EmberZnet-2-01:芯科的硬件解决方案EFR32

    [源码.文档.软件.硬件.技术交流.技术支持,入口见文末] [所有相关IDE.SDK和例程源码均可从群文件免费获取,免安装,解压即用] 持续更新中,欢迎关注! Silicon Labs提供可用作Zig ...

  7. 国内android应用商城中程序隐私泄露分析,基于数据生命周期的Android应用程序隐私泄露分析技术研究...

    摘要: 目前,随着智能手机应用市场的发展与成熟,用户在方便地使用各类型应用的过程中亦会产生大量隐私数据,隐私泄露已成为智能手机平台的一个严重安全问题.由于Android平台的开放性,该问题更为突出,不 ...

  8. 【无标题】(论文阅读)基于蚁群算法的现代藏文字符轮廓提取技术研究-孙淑娟

    一.摘要 由于对字符提取骨架往往会失去受污损部位的重要信息,因此本文提出了一种基于蚁群算法的现代藏文字符轮廓提取 算法‚旨在用字符的轮廓线代替骨架线来表征字符.本算法用于印刷体藏文轮廓提取‚取得了良好 ...

  9. 文献拜读小记:7.基于深度学习的图像与无线信号的融合定位关键技术研究

    基于无线信号的室内定位技术 具有计算复杂度低.可实现性强的优点,但存在多径.非视距干扰.特征空间区分度不够等缺点; 基于计算机视觉的室内定位技术 具有能获得大量稳定的环境信息的优点,但存在计算复杂度高 ...

最新文章

  1. 一份整理 | PyTorch是什么,为何选择它
  2. 操作像素(一)--存取像素值
  3. FPGA从Xilinx的7系列学起(7)
  4. 将 a.txt 文件中的单词与 b.txt 文件中的单词交替合并到 c.txt 文件 中
  5. MySQL5.7.17的简单配置文件
  6. 网络协议:HTTPS
  7. Linux环境通过java虚拟机定位程序问题位置的方法
  8. 开源风云 20 年!
  9. 【iOS开发】理解 IBOutlet 和 IBAction
  10. Flutter: MobX和flutter_mobx状态管理器
  11. 为什么要有handler机制
  12. 事实表和维度表(重点)
  13. 智能营销获客引流-入门-宁波慧客科技有限公司
  14. iOS开发调试技巧之模拟定位国外位置
  15. 基于OpenCASCADE自制三维建模软件(五)鼠标模式
  16. pr学习心得(入门篇)
  17. C语言-广度优先遍历
  18. js引用类型之RegExp类型-new RegExp()
  19. 题解:luogu P2634 [国家集训队]聪聪可可
  20. C++学习15:C++模板的参数

热门文章

  1. C++软件开发岗位要求
  2. java word设置纸张a3,Word中进行设置A3文档纸张大小的操作技巧
  3. SHOUG线上活动 Maclean Liu分享《学习甲骨文数据库的自由之翼-与Oracle的世界相连接》...
  4. cordova 图标设置
  5. 蓝叠模拟器查看Android版本,BlueStacks蓝叠版本信息在哪看蓝叠模拟器版本信息查看方法...
  6. MySQL数据库的锁 --- 六种分类 - 14种锁详细介绍
  7. 进阶项目(6)LCD12864液晶屏幕设计讲解
  8. 页面动态时间php,HTML制作网页动态时钟教程
  9. numpy如何对txt文件读取_NumPy——文件读取与写入
  10. apache php 整合,【原创】Apache整合PHP