Silicon lab的EFR32MG系列芯片可以同時支持BLE,zigbee,thread等2.4GHZ的無線通信協議。但是網上關於這款芯片的資料卻不多。前段時間將該芯片的zigbee功能移植到了openwrt系統上,現在將其中的一些需要注意的細節記錄下來,方便自己查閱也方便跟大家一起討論。
這里采用的是NCP(Network Coprocessor)即協處理器的模式,silicon lab的芯片作為一個獨立工作的單獨模塊實現zigbee的功能,HOST端程序運行與主機上,通過串口或者SPI的方式來與芯片通信。主機和模塊的通信被封裝成EZSP的一個通信協議,用戶可以通過HOST端操作從網絡建立,設備加入,消息發送,安全設置等等功能,這些操作及參數指令被封裝成特定的幀通過串口或者SPI發送給模塊。NCP模塊上的firmware通過silicon lab的開發sdk生成出來,注意選擇好對應的芯片以及通信方式即可。這里需要注意的一點是不同的通信方式要選好對應的bootloader。 這里當使用串口通信的時候選擇"UART XMODE Bootloader", 當使用SPI通信的時候選擇"EZSP SPI Bootloader"。在模塊的Applacation固件里要確認好相關的配置參數,如串口的默認針腳,波特率,流控方式等等。
HOST端的程序其實也是在SDK里生成出來的,但是該HOST程序只能在Linux下編譯運行,在其他的操作系統下會編譯出錯。我們的任務就是排查出這些錯誤,然后讓這個HOST端在openwrt系統下也能正確的編譯運行。
首先第一步是在SDK下生成出HOST端程序,選擇ZCL Application Framwork V2->EmberZNetPro GA HOST->Z3GateWay, 然后Generate出代碼。下一步把整個V2.2文件夾拷貝到Linux虛擬機下,注意要拷貝整個文件目錄,因為編譯過程依賴這個文件夾下的目錄樹,破壞目錄結構編譯就會出錯。這個文件夾看起來比較大,其實里面有很多不需要的東西,可以把藍牙,thread的文件夾刪除,然后zigbee文件夾下也有很多不需要的芯片配置表之類的東西,可以都刪除掉,最后必要的源文件大概就幾十MB大小。
第二步創建openwrt的package包。將V2.2的文件夾直接改名src,按照openwrt的ipk包的組織形式創建package包的目錄結構。這時候HOST端的主Makefile文件是在src目錄深處的,而且不能移動出來,否則破壞了相對目錄結構。在src里的package主Makefile里引導到實際的HOST端Makefile上。
all: make -C app/builder/Z3GatewayHost clean: make -C app/builder/Z3GatewayHost clean
在package的Makefile里要添加依賴庫“+libncurses +libreadline”。 app/builder/Z3GatewayHost下的Makefile不需要做太多改動,只要將鏈接語句里的$(LD)改成$(CC),這里與openwrt的編譯方式有關,openwrt會將這里的CC替換成他的編譯工具,比如ARM或者MIPS的編譯工具。如果這里的LD沒有被替換,結果就會在鏈接的時候使用X86平台的GCC鏈接器,導致鏈接錯誤。
如果編譯的時候出現CSTOP和CSTART未定義的錯誤,去staging_dir目錄下,找到使用的交叉編譯工具鏈,然后在include/termios.h里加一句“#include<sys/ttydefaults.h>”。這個錯誤的原因是tty端口初始化的時候在Linux下有一個默認配置表,但是在openwrt下沒有包含這個表,在端口初始化頭文件“termios.h”里包含上這個表即可。
另一個需要改動的地方是在源代碼里,在HOST端源碼protocol/zigbee/app/ezsp-host/ezsp-host-io.c里,這是串口初始化的一段代碼,這里找到這兩句代碼:
tcsetattr(*serialPortFdReturn, TCSAFLUSH, &tios); // set EZSP serial port options tcgetattr(*serialPortFdReturn, &checkTios); // and read back the result
在這兩段代碼前面加上一句"memset(checkTios.c_cc, _POSIX_VDISABLE, NCCS); " 這里是一個奇怪的問題,代碼在設置TTY端口參數之后會讀取設置后的參數,與原來要設置的參數對比,確認端口已經被正確的設置。但這里的一個問題是,用來讀取設置后參數的結構體checkTios.c_cc,本身在聲明之后未被清零處理。本來也沒什么問題,因為在讀取TTY端口參數的過程中會被填充上讀取到的數值,但是這個結構體里有32BIT,從17開始后面都是保留位,讀取過程中保留位不會被設置,所以若申明之后未清零,保留位上隨機的數值可能會保留下來,下一步檢查是否設置正確的時候就會出錯。這里應該是源碼里的一個小bug,在Linux下可能不會出錯,但是移植到其他平台的時候這個錯誤就會顯現出來。最簡單的方法就是在檢查之前先做清零處理。
最后編譯出來的程序會包含一個Z3GateWay的ipk包,以及libreadline,libncureses,terminfo的ipk包,這三個包是依賴庫,如果openwrt上原本沒安裝這三個庫,那就需要先裝上這三個庫。安裝上Z3GateWay的IPK之后,連接好模塊的串口線,找到該目錄下運行./Z3GateWay就可以運行zigbee HOST端的程序了。
SPI的設置跟這個大同小異,只有一些小地方需要修改一下,下回再接着寫。