Z-Stack 中ZigBee 设备的 IEEE 地址 的初始化,读取,设置
来源:互联网 发布:mac可以玩使命召唤吗 编辑:程序博客网 时间:2024/06/06 02:26
Zstack协议的阅读:首先从主函数ZMain.c着手,其中Zmain.c:
- int main( void )
- {
- // Turn off interrupts
- osal_int_disable( INTS_ALL );
- // Initialization for board related stuff such as LEDs
- HAL_BOARD_INIT();
- // Make sure supply voltage is high enough to run
- zmain_vdd_check();
- // Initialize board I/O
- InitBoard( OB_COLD );
- // Initialze HAL drivers
- HalDriverInit();
- // Initialize NV System
- osal_nv_init( NULL );
- // Initialize the MAC
- ZMacInit();
- // Determine the extended address
- zmain_ext_addr();
- #if defined ZCL_KEY_ESTABLISH
- // Initialize the Certicom certificate information.
- zmain_cert_init();
- #endif
- // Initialize basic NV items
- zgInit();
- #ifndef NONWK
- // Since the AF isn't a task, call it's initialization routine
- afInit();
- #endif
- // Initialize the operating system
- osal_init_system();
- // Allow interrupts
- osal_int_enable( INTS_ALL );
- // Final board initialization
- InitBoard( OB_READY );
- // Display information about this device
- zmain_dev_info();
- /* Display the device info on the LCD */
- #ifdef LCD_SUPPORTED
- zmain_lcd_init();
- #endif
- #ifdef WDT_IN_PM1
- /* If WDT is used, this is a good place to enable it. */
- WatchDogEnable( WDTIMX );
- #endif
- osal_start_system(); // No Return from here
- return 0; // Shouldn't get here.
- } // main()
从zmain.c里可以知道这个函数一共做了两件事,系统初始化(由启动代码初始化硬件和软件架构需要的各个模块)和开始执行操作系统实体。里面的具体工作有:关闭中断---板级初始化(设置了PA)---电压检测 ---初始化板载IO--- 初始化HAL驱动 ---初始化NV系统 ---确定扩展地址(64位IEEE/物理地址)---初始化基本NV条目--- 初始化MAC ---操作系统---- 允许中断-----最终板初始化 ---显示设备信息 液晶支持显示。启动代码为操作系统做好准备工作后,就开始执行操作系统入口程序,并将控制权彻底交给操作系统。
.4大致说了:CC2530芯片在TI出厂时已经预先烧写了 Primary IEEE address,这个64位地址是全球唯一的。这个地址在CC2530的FLASH信息页中,是只读的。但是用户貌似可以重新写这个预先烧写的Primary IEEE address。具体再来看看 Section 7.2
7.2中说Z-STACK通过4个步骤来确定设备的IEEE地址:
1.从Z-stack的NV中读取
2.从Second IEEE 的位置中寻找
3.在Primary IEEE 的位置寻找
4.由随机数产生器产生一个临时IEEE地址。
也就是说,ZigBee设备在上电后,首先会从NV中读取IEEE地址,如果读取失败,则从FLASH的Second IEEE 的存放位置读取IEEE地址,如果读取失败,则再从Primary IEEE 的存放位置读取IEEE,如果还是失败,则由随机数发生器产生一个临时IEEE地址。步骤2或者步骤3一旦有效并且使能了“NV_RESTORE”,就会把这个IEEE地址写入到NV中去。这样下次上电的时候,就可以通过步骤1从NV中直接读取 IEEE地址。
接下来我们再来看看每一个步骤具体是怎么实现的:
Step1 从Z-stack的NV中读取 IEEE地址: 源代码见 Z-stack 2.5.1.a --> ZMain.c --> main( ) --> zmain_ext_addr()
我将源代码拿上来,自己添加了注释。
如果 NV 读取IEEE成功,则直接跳到最后,执行
(void)ZMacSetReq(MAC_EXTENDED_ADDRESS, aExtendedAddress); //将读取成功的 IEEE地址 写到MAC层的PIB属性中
如果 NV 读取失败,或者读取出来的值全为0xFF,则说明 NV中 ZCD_NV_EXTADDR 这个元素并没有被配置过,视为无效,那就从Step2 中读取 IEEE 地址
Step2 从Second IEEE 的位置中找到 IEEE 地址
这个Second IEEE 到底在哪里呢,Z-Stack User's Guide - CC2530DB.pdf 的 7.2 中已经提到,这个位置是在 FLASH 地址最后置偏移 0x0018个地址的地方。拿CC2530F256来说,256K的FLASH,那偏移0x18地址的位置应该是:0x3FFE8,IEEE 地址长度是8个字节,所以 Second IEEE 地址的存放地址应该是 0x3FFE8 ~ 3FFEF。
有人可能会疑惑,为什么是偏移0x18个地址呢,这里我个人的理解是:0x18=24=16+8. 这里的8就是IEEE地址的长度,这个16应该是FLASH最后的加密位。
再从代码来看,第一个 if 满足之后便是下面这句:
HalFlashRead(HAL_FLASH_IEEE_PAGE, HAL_FLASH_IEEE_OSET, aExtendedAddress, Z_EXTADDR_LEN);
这是直接读FLASH 的函数,从 HAL_FLASH_IEEE_PAGE 这一页的 HAL_FLASH_IEEE_OSET 位置来读取 Second IEEE
在来看看 HAL_FLASH_IEEE_PAGE 和 HAL_FLASH_IEEE_OSET 分别是什么从宏定义来看,HAL_FLASH_IEEE_PAGE 是NV最后一页再加1,也就是127页,是FLASH的最后一页(1也是2048 byte),地址是 HAL_FLASH_PAGE_SIZE - HAL_FLASH_LOCK_BITS - HAL_FLASH_IEEE_SIZE,也就是地址最后减去16 字节的加密位和8字节的IEEE地址,即2048-24 = 2024, 这也验证了我之前step1 中的猜想。
第二个 if 是判断这个 Second IEEE 地址是否有效,如果有效,则到代码的最后将有效的 IEEE 地址写入 PIB 中,若无效则进入Step3
Step3 从Primary IEEE 的位置中找到 IEEE 地址
这个 Primary IEEE 地址到底又在什么地方呢,Z-Stack User's Guide - CC2530DB.pdf 的 7.2 中已经提到,Primary IEEE 位于 FLASH 信息页偏移 0x0c ~ 0x13 个地址的地方。那么这个 FLASH 信息页到底又在哪里呢,参照 CC2530 user's guide 的 2.2.2 CPU memery space ,可以知道, 这个 FLASH information page 是映射到 XDADA的 0x7800 ~ 0x7FFF 上的,那么偏移0x0c个地址,应该就是XData 的 0x780c ~ 0x7813 地址上。
再来看看源代码[/code]
源代码中第三个if直接用osal_memcmp 将 Xdata 中 (P_INFORFAGE + HAL_INFOP_IEEE_OSET) 与 8个 0xFF作比较。这个(P_INFORFAGE + HAL_INFOP_IEEE_OSET) 到底又是什么呢,请看它的宏定义:很明显,这个地址便是 0x7800 + 0xc = 0x780c,正确。如果这个地址有效,就作为 IEEE地址 使用,若无效则需要进入Step4
Step4 随机得到这个 IEEE 地址
文档中说到,如果前面的step1 ~ step3 都失效,则只能随机产生这个 IEEE地址,随机产生的这个 IEEE 地址 是以 0XF8 开头的。并且这个 IEEE地址不会被保存到 NV 中,因此如果说这个 IEEE 地址时随机产生的,那么这个值 每次上电后都是随机产生的,即使你使能了“NV_RESTORN”也不会存到 NV 中。这样的话如果用于实际应用其实是很危险的,所以尽量不要这种情况发生。
接下来看看是怎么产生这个随机 IEEE 地址的:这个 else 之后便是产生随机 IEEE 地址的过程。
首先代码禁止了 NV的存储。然后通过一个 for 循环 产生了 6byte的随机地址。注意这里为什么只有6byte,我们的IEEE地址不是8byte的嘛。不要忘记,文档中说过,这个随机 IEEE 地址是要以 0xf8 开头, 那还有一个字节干嘛去了呢,代码中应该能看到,这个字节用于表示不同的设备类型了,协调器是0x10 , 路由器是 0x20 ,终端节点则是 0x30
所以最后这个随机 IEEE 地址的格式是: 0xF8 + (设备类型) + 6byte 随机值。
通过以上的讲述,应该把 Z-STACK 中 IEEE 地址的由来说清楚了,我已经经过仿真验证,但是今天太晚了不能再写下去了。
最后还有几个疑问:希望高手看到了能够帮我解答一下:
1. FLASH 的信息页 映射到 Xdata的地址是 0x7800 ~ 0x7FFF, 它实际的地址在哪里
2. 在对CC2530 仿真时,怎么查看 0x3FFE8 ~ 0x3FFEF 的地址。因为51内核 CODE的最大寻址空间是64k,即0x0000~0xFFFF, CC2530通过映射的方法将FLASH分成了8个bank,每个bank 32kb,我通过仿真查看 Logic Code 区域 bank7 的flash,但是好像不对。我有空再验证一下。
4. 到底能不能修改 Primary IEEE 地址,这个问题和问题1类似,需要只要 FALSH的信息页对应地址才能修改,但是这个信息页是只读的,又需要怎么修改。
- Z-Stack 中ZigBee 设备的 IEEE 地址 的初始化,读取,设置
- 研究 Z-Stack 中ZigBee 设备的 IEEE 地址
- ZigBee读取IEEE地址
- zigbee z-stack 地址类型
- Zigbee协议栈--Z-Stack的使用
- 揭开ZigBee 2006协议栈Z-Stack的”开源“面纱
- ZigBee协议栈Z-Stack开发指南的一些翻译
- 揭开ZigBee 协议栈Z-Stack的”开源“面纱
- zigbee z-stack实现按键的长按
- [Zigbee]Z-stack Zed 失去节点之后的流程
- ZigBee IEEE地址说明
- Zigbee之Z-Stack
- 物联网|无线传感器网络|IEEE 802.15.4|ZigBee|CC2530|Z-Stack
- ZigBee协议栈Z-Stack开发指南(翻译的TI的手册Z-Stack Developer's Guide.pdf)
- CC2530的IEEE地址
- Zigbee 设置信道,PANID,发射功率现对z-stack里几个网络参数的设置以及如何获取总结一下。
- Z-stack中对按键的处理
- 揭开ZigBee 2006协议栈Z-Stack的”开源“面纱 以及其它的开源协议
- 查找一个字符串中各个字符出现的次数,用TreeMap实现
- tar压缩文件
- mapreduce作业reduce被大量kill掉
- oc NSString和NSMutableString基本用法
- 用Python解压缩文件
- Z-Stack 中ZigBee 设备的 IEEE 地址 的初始化,读取,设置
- 黑马程序员——JAVA反射机制基础
- PowerShell清空IIS日志
- python压缩与读取.tar.bz2压缩包
- 原型模式(ProtoType) - Java里的对象复制
- mac10.10配置apache环境
- Eclipse 建立自己的Library
- 12/15/2014-读书笔记-《站在发展的前沿——新一代互联网思维》
- ZOJ3623:Battle Ships(完全背包)