My set-top box for my TV has a remote that works with RF instead of infrared light. I read somewhere that it could be Zigbee, which made me interested in sniffing Zigbee communication. I bought a development board without thinking how to get it working. Also, I don’t have much experience with hardware. In this article I describe what I learned along the way.

Texas Instruments CC2530

I searched on DealExtreme for Zigbee interfaces and bought the cheapest one available, for €5. This board is basically a Texas Instruments CC2530 chip with some pins and an antenna attached to it. After receiving it, I looked up the datasheet. It says a couple of things:

The CC2530 is a true system-on-chip (SoC) solution for IEEE 802.15.4, Zigbee and RF4CE applications.

System-on-chip means that this is a whole computer in one chip. So it has a CPU, memory, flash, timers, clock, UART, all the things.

High-Performance and Low-Power 8051 Microcontroller Core With Code Prefetch.

It has a 8051 CPU, as in compatible with Intel 8051 from the 1980’s.

The CC2530 pinout is shown in Figure 7 and a short description of the pins follows.

The datasheet also provides information about all the pins. This is particularly helpful since the development board doesn’t have any documentation at all. I had to trace the lines on the PCB to figure out what all the pins do.

CC2530 board

Blinking LED

The first step is to run some program on this, and a blinking LED is an obvious first choice.

Like many microcontrollers, the CC2530 has memory mapped I/O. That means that some memory addresses perform hardware functions, instead of storing data in memory. Writing 0xFF to memory address 0x80 will put 5 volts on all pins of port 0. Writing 0x00 will turn them off. We can create a “variable” that points to this address using __sfr, which stands for special function register:

__sfr __at(0x80) P0;        // port 0
__sfr __at(0xfd) P0DIR;     // port 0 direction (1 = output)

Then, we can write to these addresses by simple assignment. This will turn all pins on port 0 high:

P0DIR = 0xff;
P0 = 0xff

This way, I created a blink program which turns some pins on and off. After some searching I found a compiler that can compile for 8051: SDCC. Compiling the C file creates an Intel HEX file, which contains HEX data and offsets where to put it in flash.

Uploading the program

Normally you would have a development board or a programmer with a chip, but I didn’t have that. From the user guide I gathered that the typical way to upload a program to the CC2530 is using the debug interface. If I could get an Arduino to talk that protocol, I figured I could get the CC2530 to do something. As it turns out, someone else already had that idea and implemented CCLib, an Arduino implementation for the CC2530 debug protocol.

I had some trouble getting this working, because of how flash works. Flash memory can only be erased in page chunks (2048 bytes). When a flash page is erased, all bits are set to 1. After that, it is possible to set bits to 0, but it is not possible to set them to 1 anymore without erasing the whole page. I tried to overwrite the flash without erasing it first, which won’t work. I solved this by always passing --erase to the cc_write_flash.py script.

Even then, HEX files wouldn’t always write correctly. HEX files contain data and offsets. The data should be written to the corresponding offset. On the CC2530, you can only write 4-byte words to locations that are divisible by 4. So if the offset in the HEX file is not divisible by 4, it will get written incorrectly. I created a pull request which partially solves this.

After some trial and error I successfully uploaded the program and had a blinking LED on the CC2530.

Getting Zigbee firmware

The next step was to upload some code that could talk Zigbee. There are two programs that Texas Instruments provide:

  • Z-Stack ZNP (Zigbee Network Processor)
  • SmartRF Protocol Packet Sniffer

The ZNP is basically a conversion layer from serial to Zigbee. You implement all business logic in another processor, and just ask the ZNP software on the CC2530 to send and receive Zigbee. Texas Instruments also provides ZTool (part of Z-Stack), which can talk with a microcontroller with ZNP on it. I decided to try this first.

The Z-Stack kit comes with a couple of binaries with firmware. I tried to write one of these CC2530ZNP-SB.hex to the CC2530. I spent way too long to get this working, until someone on the TI forum pointed out that this was only a bootloader, and doesn’t contain the ZNP at all. No wonder I couldn’t get it working.

Since apparently there was no binary available I tried to get it to work with the firmware compiled myself. I opened Projects/zstack/ZNP/CC253x/znp.eww in IAR Embedded Workbench, which has a 30-day trial license. I set the output format to “intel-extended” in the project options under linker output,and build the CC2530 - Debug project.

This worked correctly after I also connected CFG1 to ground, so that UART instead of SPI interface is used. I used the “Alternate pin configuration” as described in the docs (Z-Stack ZNP Interface Specification.pdf). The latest version of this document, shipped with Z-Stack 3.0.0, doesn’t mention what CFG1 does at all, which I think is a pretty big omission. It controls whether SPI (high) or UART (low) communication is used.

I also changed the firmware a bit so that it flashes a LED on a particular place. This way, I could determine what the firmware was actually doing.

After uploading this to the CC2530 I could connect using the ZTool and perform some operations. It works!

Trying the sniffer

The ZNP exposes a pretty low-level API to Zigbee. It would still take some effort to get Zigbee communication working, because you have to call the right functions on the API. An alternative is the SmartRF Protocol Packet Sniffer. The sniffer just listens in on Zigbee traffic and can display messages on your computer. I uploaded the sniffer firmware to the CC2530, but I couldn’t get it working. I also couldn’t really find the right configuration for the serial port that this firmware uses. Normally you would use it on a CC2531, which has an USB port.

Conclusion

I made it pretty hard on myself by just buying one chip without any development kit or even proper documentation. I got stuck a few times where things just didn’t work and I had no idea how to debug the problem. In the end I didn’t succeed in sending or receiving any Zigbee messages, but I learned a lot about embedded programming.

Read more