测试CC2652R协调器模块的发送速度,采用如下方法:向串口发送一条命令,程序调用zcl_SendCommand(最终是执行的Zstackapi_AfDataReq),执行完后,串口返回ACK。测试发现从串口发出命令,到ACK回复,中间最长耗时20ms多。
仔细推敲,第一个耗时大户是CC2652R的原厂开发板,TI的XDS110仿真器模拟UART,在SSCOM4.2上居然有10ms的延迟。其次就是出在执行Zstackapi_AfDataReq。TI的实时操作系统TI-RTOS中的应用程序调用Zstackapi_AfDataReq,应用程序会进入IDLE状态,然后在协议栈的task开始运行。但是因为协议栈的task的优先级比应用程序高,协议栈会先执行AF_DataRequest,这个时候要发送的消息已经被压进了发送队列。前面说过协议栈的优先级比应用程序高,因此AF_DataRequest虽然return了,但是协议栈的发送队列里面有要发送的无线数据帧,会切换到nwk_event_loop的NWK_DATABUF_SEND事件,然后再退回到应用程序的任务优先级。
但是在nwk_event_loop执行发送无线数据任务时,出现了很大的延迟。于是在nwk_event_loop的接口处理NWK_DATABUF_SEND事件时打断点,在NV-read的时候,发现执行NWK发送时NV-Read连续读了两次ZCD_NV_NWK_ACTIVE_KEY_INFO,而且每次延时都是5ms。而无线数据从压入TX-FIFO寄存器到从天线出来,耗时不到1ms。ZCD_NV_NWK_ACTIVE_KEY_INFO是用于无线收发时的AES加密解密,硬件AES也是很快的。这样一来就造成一个搞笑的现象:每次无线收发,5%的时钟周期是无线传输,5%的时钟周期是AES加密解密,剩下90%是在查表。
然后参考了CC2530/CC2538最后一版协议栈(z-stack 3.0.2),里面的NV程序里新增了一个叫“hot item”的机制。ZCD_NV_NWKKEY,ZCD_NV_NWK_ACTIVE_KEY_INFO和ZCD_NV_NWK_ALTERN_KEY_INFO共三个item被设置成hot item。在zstack中,普通的NV-item都是在Flash中采用循环的方式一条一条的查找,当然很慢。但是Hot item就是把NV-item对应的flash地址记在RAM变量中,因为对NV-item进行“写”操作并不是真正写flash,flash是不可能被修改的,只是改变NV-item对应的地址。那么每次修改NV-item的时候RAM变量记录NV-item的flash地址也会被刷新。
但是由于CC2652是汇集了蓝牙,zigbee,thread好几种协议栈,因此NV-RAM中又取消了hot item机制,需要手动重新加上。在nvocmp.c中的函数接口NVOCMP_findItem和NVOCMP_writeItem,加入对ZCD_NV_NWKKEY,ZCD_NV_NWK_ACTIVE_KEY_INFO和ZCD_NV_NWK_ALTERN_KEY_INFO的特殊处理即可。
优化后,Zstackapi_AfDataReq的return时间,从12ms降到1ms。