Optimizing the cc2531 firmware for OpenHAB and the Zigbee binding

After several issues using the cc2531 with the stock ZNP-Pro-Secure-Standard 1.2.2a firmware as coordinator for the Zigbee binding, I decided to tweak it a little to see if I could make it mare stable and perform better.

No code changes to the firmware: just tweaking :wrench: configuration parameters through the provided defines.

Addressed issues:

  • Mostly locking out after adding ~20 devices
  • Some irresponsiveness that seemed related to routing discovery storms
  • The dongle running out of memory making it unable to send anything after some time (probably part of the issues when adding more devices).

The improvement approach is:

  • Use many-to-one and source routing as much as possible: increase the source routing table as much as memory allows, set route routing expiracy to maximum, and announce concentrator route at very short intervals
  • Free as much memory as possible by reducing all tables that are allocated statically: reduce standard routing table and expiracy (so use mostly source routing), and reduce the amount of allowed neighbours (even if not optimal in terms of Z-Stack network)

So I have compiled a custom firmware that apparently works now quite stable:

  • ~30 IKEA lights
  • ~5 Osram plugs
  • Some FLS-pp led strips
  • Several IKEA remotes

Unfortunately, the z-stack license seems to prevent us from directly sharing the binary firmware, so unless somebody from TI corrects me or allows us to share it, the only way to get this firmware is by compiling it.

I am sharing the config parameters and steps for those willing to recompile it (bootloader version):

  • Download Z-Stack Home 1.2.2a
  • Download the trial version of IAR Embedded Workbench (one month free trial)
  • Change the stack and znp configuration files (see below)
  • Compile the CC2531 - ProdSBL project
  • The compiled firmware will be in Projects/zstack/ZNP/CC253x/dev/CC2531ZNP-Prod.bin
  • Completely wipe the flash of the CC2531 with an empty file (246k of 0xFF out of 256k flash)
  • The wipe will fail to verify as the bootloader does not seem to allow read back of upper flash area
  • Flash now the compiled bin

Similar steps can be followed to build the hex version to be loaded with the CCDebugger. The wipe will be “cleaner”, but I prefer the bootloader version though.


// These need to be commented out where they appear, as will be overriden later:

// To be added at the end of the file:
-DMAXMEMHEAP=3462                         // Maximum free available after the mods below
-DMAX_RTG_ENTRIES=8                       // Reduce the amount of routing table entries. We will be using Source Routing & Many to One ot avoid routing discovery storms
-DROUTE_EXPIRY_TIME=30                    // Routes to expire fast to use source routing
-DAPSC_ACK_WAIT_DURATION_POLLED=500       // Retry after 1s if no ACK received (only for RxOnIdle devices)
-DAPSC_MAX_FRAME_RETRIES=5                // Retry 5 times, so 5s total retries
-DMAX_RREQ_ENTRIES=4                      // Maximum simultanious routing discoveries.
-DCONCENTRATOR_RADIUS=31                  // Increase radius to reach longer paths (not exactly an "optimization")
-DNWK_MAX_DEVICE_LIST=5                   // Max devices associated directly to the coordinator. Reduced to allow for more memory, but not imposing a limit, as new devices may still associate through a router
-DCONCENTRATOR_ENABLE=1                   // Enable concentrator (many-to-one routing)
-DCONCENTRATOR_DISCOVERY_TIME=30          // This may be a bit chatty, but allows for source routing discoveries happening before the standard discovered routes are refreshed
-DMAX_RTG_SRC_ENTRIES=64                  // Will be able to talk to this amount of devices through source routing (plus standard routing, plus the neighbours)
-DSRC_RTG_EXPIRY_TIME=250                 // Allows for 8 source routing discoveries before a source route expires
-DCONCENTRATOR_ROUTE_CACHE=1              // Force source routing data to be sent from the devices when talking to the coordinator
-DMTO_RREQ_LIMIT_TIME=5000                // Delay 5sec a route request if another one is already running
-DLINK_DOWN_TRIGGER=5                     // Retries before deciding a link is down
-DNWK_ROUTE_AGE_LIMIT=5                   // Route update failures before route is removed
-DBCAST_DELIVERY_TIME=100                 // Increased to let broadcasts live longer on a network (needed for large networks)
-DDEF_NWK_RADIUS=31                       // Increase radius to reach longer paths (not exactly an "optimization")
-DDEFAULT_ROUTE_REQUEST_RADIUS=31         // Increase radius to reach longer paths (not exactly an "optimization")
-DROUTE_DISCOVERY_TIME=13                 // Not exactly an optimization (default 5) but needed for larger networks
-DNWK_LINK_STATUS_PERIOD=15               // Reduce network traffic (default 30) by sending less link status messages
-DMAX_NEIGHBOR_ENTRIES=10                 // Reduced from default. Needed to free Heap memory. Devices in excess to this amount will be addressed by routing instead of single-hop even if reachable


// Add these to the end (not all of them may be necessary, but added to have a more "generic" ZNP device):

Worth reading: TI AN123 – Breaking the 400-Node ZigBee® Network Barrier With TI’s ZigBee SoC and Z-Stack™ Software

This is mostly taken from my understanding of the AN mentioned above, and some trial and error. But working for me :slight_smile:

Just note that if you install the ZStack somewhere other than “C:”, compilation will hang forever without any error unless you modify the file Projects/zstack/ZNP/CC253x/tools/znp.bat from:

chdir %1
start znp.js %2
exit /b

to :

rem Change D: to whatever drive you have installed the z-stack in
chdir %1
start znp.js %2
exit /b

Happy to discuss / change / adjust before my IAR workbench trial license expires :slight_smile:



That is it,

thanks for pointing the right direction.

I followed your suggestions and some others from the TI AN123 reference.

I was stuck at 18 devices and now have more than 30 working smooth.

That is the right way.

About sharing, I do not understand this way. You can share since the final destination is a TI device. You can not use, or, share it if intended to be used at another non TI component.

Otávio Ribeiro

Does you try to connect xiaomi cube using this firmware? I tried many times but stick can not recognize cube. But cube work with znp-prod firmware…

Never tried: I do not have this device.

@puzzle-star Where is this located Compile the CC2531 - ProdSBL project ?

I get an error when I try to load the CC2531.ewp file into the IDE

Can you help?

Necroposting, but for a good reason.

@puzzle-star 's settings greatly helped with my setup. I’ve had issues when pairing more than 30 devices, now with these settings + a bunch of others coming from zigbee2mqtt I managed to pair 40 devices without issues - except for one cc2531 flashed as router that doesn’t want to join the network.

I’m planning to publish my changes as soon as I can verify that everything runs smoothly for a few days.

1 Like