DEBUGPRINT Is Now ZPAL_LOG

The 2025.6 Silicon Labs SSDK Z-Wave release changes the familiar DEBUGPRINT utility to ZPAL_LOG. A brief mention of the change is in the Important Changes for the Z-Wave 7.24.0 release however I’ll give a more detailed description of what has changed and how to use this new utility. If you’re trying to upgrade a project from an earlier SDK, this “breaking change” will make that effort more difficult as you have to switch any DPRINT statements to the new ZPAL_LOG format.

DEBUGPRINT

First a little history. The DEBUGPRINT utility came from the original early 2000s Zensys code running on the 8051 8-bit CPU. From the initial 100 series thru the 500 series, DEBUGPRINT was the ONLY debug utility we had! Even though this was the 2000s thru most of the 2010s, debugging using PRINTF was obsolete by the late 1980s – but not for Z-Wave. PRINTF would print out a short message and maybe a hex value or two and we would try to divine what was going on from these tiny details. There were no breakpoints, no ability to single step the CPU or watch RAM or registers change as the code was executing. Because sending characters out the UART would block the CPU until the UART was empty, you could only send a few characters and maybe a hex value. Sending more characters out the UART would alter the flow of the program and either mask the bug or break something else or often cause a watchdog reset! UGH. While primitive, it was all we had and we made do. DEBUGPRINT was easy to enable or disable – just #define DEBUGPRINT in the file you needed the print statements and recompile. Typically, only a few print statements were enabled at a time or the UART would spew out too much detail or messages would get mixed together making gibberish of the output.

Debugging Today

Debug is much easier with the modern ARM CM33 processor on todays Z-Wave chips. We have Single-Wire-Debug (SWD) and can set breakpoints, watchpoints, single step, view memory and peripherals. There’s even Trace where every instruction executed is logged enabling the precise flow of a program to be viewed after the trigger condition of a bug. We still have DEBUGPRINT which is handy for printing out high level messages like “eReset Reason=3′ each time the chip reboots. These messages are handy during debug and were easy to remove prior to building the final production code simply by commenting out the #define.

ZPAL_LOG

The Z-Wave Log component in a Simplicity Studio project .slcp file is installed by default in all the sample applications starting with the 7.24 release. This is good thing and a bad thing. It’s good since it’s already installed and printing messages before you’ve started modifying the code for your project. It’s bad because when you should remove this code for the final production build, we’ll get into that shortly.

General

When you Configure the Z-Wave Log component you get a lot of radio buttons to switch various features on or off. The first block “General” includes:

  • Size of the buffer (default is 96 bytes) – Leave this as-is
  • Display log level – prints 3 characters identifying Info, Debug, Warnings or Error messages
  • Display log source component – prints a number which identifes which module the print statement is from
  • Display log timestamp – prints a decimal number of ticks since reset

Enabling any of these messages slightly increases the total FLASH usage. The bigger problem is that it increases the number of characters sent out the UART potentially causing the CPU to block and thus changing the program flow. I recommend leaving these at their defaults.

The Display Log Source component would be useful IF SSv5 decoded the numeric value for you and displayed the name in the console window. Unfortunately it just prints a number which you then must manually decode by looking up the value in the enumerated type zpal_log_component in the zpal_log.h file. The trick would be to send just the numeric number out the UART (thus not taking up significant amounts of time or FLASH) and then SSv5 expanding it to the component name. I have suggested this to the SSv5 team in the past but hasn’t yet come to fruition. The source component is useful if there are several similar or even identical PRINT statements in different blocks of code to help identify where it is coming from. Also if you enable a lot of PRINT statements, it can help narrow down which block a specific message is coming from.

If you enable all 3 of these switches you get: “000000023 [I] (1) ApplicationInit eResetReason = 7”. Where the 00000023 is the timestamp; [i] is the Log Level (Info in this case) and (1) is the component which you have to then decode yourself as mentioned above (ZPAL_LOG_APP in this case) .

Output Channels

The next block is the Output Channels which can enable the four levels of messages: Debug, Info, Warning and Error messages. The default has just Info enabled with the word “vcom” entered into the Info box. I recommend enabling all four of these by entering “vcom” into all four of them. This will increase FLASH usage as the strings for all these messages are now stored on-chip.

Component Filtering

The final configuration block in the Z-Wave Log component is the Component Filtering section. This section has a bunch of radio buttons you can enable which will turn on various messages from the respective module. If you enable ALL of these, it’ll add about 10K bytes of FLASH so maybe only enable ones you think you need.

UART Blocking

The EUSART is only running at 115200 baud which makes each character take over 10 microseconds to send out the UART. This might seem fast, but when you’re transmitting long strings of characters this can seriously impact the program flow in real time. If the UART buffer fills, the code will stall and wait for more buffer space to fill (see the “while” loop in eusart_tx in sl_iostream_eusart.c). If you’re spitting out a lot of messages, the UART will fill causing the program flow to change potentially masking the bug or sending you down the wrong rathole. The baud rate is easily increased to 1mbps which will speed up the printing by 10X which helps, but you need to be aware of the amount of messages pouring out the limited speed of the UART.

Disabling ZPAL_LOG

Once debugging is complete, the next step is to compile all of these messages out of the production code. Fortunately this is easy – just remove “vcom” from all four of the Output Channels section of the Z-Wave Log component. While this removes most of the code for debug messages, the Command Line Interface (CLI) is still there and the EUSART is still used by the sample applications. When developing your own application you will typically want to remove ZPAL_LOG and the CLI as it’s not something your application needs – it is only for the Silicon Labs demos.

Conclusion

Why did silabs make this “breaking change”? I don’t have specific insights from Silicon Labs but the new format provides easily configured “levels” of logging. Is that worth a “breaking change”? I wish they’d spend more time testing the code to reduce the bugs than making a lot of file changes tweaking features that don’t really improve the developers experience. If you’re going to change an important feature, it’s also important to document it which is sorely lacking. But I hope this post helps you utilize this new feature and not be quite so frustrated when updating your project to the latest SDK.

Dreaded Flash Memory Overflow Solutions

The EFR32ZG23 Z-Wave 800 series MCU has limited FLASH and RAM available for the application. The 800 series actually has less FLASH than the 700 series which stored the bootloader in a dedicated 16K memory. Worse, the bootloader in the 800 series has grown from 16K to 24K! Features are always being added to the SDK making it ever larger leaving less for the application. Seems like Silicon Labs needs to spend some time squeezing the code instead of constantly adding features.

Here is the typical error message when FLASH overflows:

Description	
FLASH memory overflowed !	
make: *** [makefile:114: all] Error 2
make[1]: *** [makefile:123: SwOnOff_2024120_ZG23B_GeoLoc.axf] Error 1
region `FLASH' overflowed by 92 bytes
SwOnOff_2024120_ZG23B_GeoLoc.axf section `.nvm' will not fit in region `FLASH'

We can’t create more FLASH on the chip, it has what it has. But, there’s always software we can change! By default, the project has ZAF->Z-Wave Release installed which sets the C compiler optimization to -Os which optimizes for size which is probably what we want since we’re out of FLASH. However, deep in the configuration files there is the definition for SL_BOOTLOADER_STORAGE_SIZE which changes from 196K to 180Kbytes when NDEBUG is defined. NDEBUG is defined when the Z-Wave->ZAF->Z-Wave Debug component is installed. The question of why BOOTLOADER size is being reduced by only 16K when debug is enabled is unclear to me. However, in my testing, adding the DEBUG component still results in FLASH overflowing but now by 4344 bytes! Obviously the change in Optimization from -Os to -Og (debugging) blew up the code which is expected. I enabled DEBUGPRINT to get debugging information out the UART which increased the flash usage even more.

Since I am debugging and will not be testing OTA at this stage, I don’t care how big the bootloader storage size is since I am not using it. I need more FLASH space for debugging! Simply edit the sl_storage_config.h file and change SL_BOOTLOADER_STORAGE_SIZE from 0x2C000 to 0x20000 to free up another 48K bytes:

// <o SL_BOOTLOADER_STORAGE_SIZE> Size of the bootloader storage.
// <i> Default: 0x20000
// <i> Note that this value is only being used if BOOTLOADER_STORAGE_USE_DEFAULT
// <i> is set to false. This value will control how much of the flash memory
// <i> is reserved for bootloader storage.
#if defined(NDEBUG)
#define SL_BOOTLOADER_STORAGE_SIZE  0x00030000
#else /* defined(NDEBUG) */
//#define SL_BOOTLOADER_STORAGE_SIZE  0x0002C000    - original value
#define SL_BOOTLOADER_STORAGE_SIZE  0x00020000
#endif /* defined(NDEBUG) */

Now the project fits comfortably in FLASH with plenty of left over space. However, I cannot OTA it and definitely cannot ship it in this way for production. Once I’m done debugging, I’ll have to revert back to RELEASE mode and remove DEBUGPRINT. If FLASH is overflowing that will require some additional effort to squeeze back into the available space. I would first try Link-Time-Optimization (-flto) to the C compiler but that can introduce some instability and require significant amounts of testing time. Next, try looking for code you don’t need and remove it. After that, complain to Silicon Labs they need to shrink their code!

Ram usage       :    65532 /    65532 B (100.00 %)
Flash usage     :   446868 /   491520 B ( 90.92 %)

RAM usage is at 100% is OK because the HEAP is expanded to fill the available space. But there is very little left over for the application as any RAM usage is making the HEAP smaller. The HEAP is used for all sorts of things like temporary variables, buffers and FreeRTOS. I am very concerned that some of the bugs in Z-Wave products are due to heap overflows. Heap overflows are very difficult to reproduce and debug as they typically require several failures to happen at just the right time. Unfortunately these failures seem to happen with regularity in the real world.

Hope this helps you get back to debugging quickly. Leave me a comment below with your helpful hints that I can include in a future post.

Geographic Location Command Class – GPS Coordinates to the Centimeter

Z-Wavre Long Range Heat Map

First Pass is Rarely Perfect

Geographic Location Command Class was introduced around 2014 but it appears no one ever implemented it. How do I know no one implemented it you ask? Because version 1 is not particularly useful. I asked the Z-Wave Certification manager to search the certified database and no product has ever claimed support for it. The problem with V1 is that the 16-bit coordinates limit the resolution to about two kilometers. Two kilometers is sufficient to determine the time for sunrise or sunset, but not to locate a device within a home or yard. With the arrival of Z-Wave Long Range where devices could be placed in an area as large as twelve square miles, we need a way for the device to store and report its location within a few meters or less. Thus, while the first pass (version 1) has some usefulness, with new technology (ZWLR) we have new needs and thus there is a need for a new version of Geographic Location CC. Updating a command class demonstrates the living document nature of the Z-Wave specification and how you and I can add new features to the standard!

Resolution of a Location on the Earth

The circumference of the earth is about 40,075,000 meters. There are 360 degrees of longitude so each degree is 111,319 meters. The earth isn’t a perfect spheroid but for our purposes, a sphere is close enough. In embedded systems with limited resources, we need to represent the latitude/longitude with enough bits for sufficient accuracy to meet our needs. I propose a resolution of approximately one centimeter which is certainly more than enough and currently beyond the resolution of todays (but not tomorrows) low-cost GPS receivers.

The current Z-Wave Geographic Location Command Class V1 uses 1 bit for the sign, 8 bits for the Degrees and 7 bits for the Minutes. Since the 7 bits are in minutes instead of a fraction of a degree, the 7-bit value only ranges from 0-60 which means there are actually less than 6 bits of resolution. Thus, the resolution of the current V1 is 111319m/60=1.855km. Two kilometers of resolution isn’t enough to locate a device within a single Z-Wave network.

How many bits are needed for 1 centimeter resolution?

Degree Fraction BitsResolutionComments
0111,319m1 degree=111km
155,6560m
227,830m
3 … 16Each bit doubles the resolution
170.85m
180.42m
190.21m
200.11m
210.05m
220.03m
230.01mCentimeter resolution
GPS Coordinate Degree Fraction Bits of Resolution

The proposal is to update Geographic Location CC to V2 and make the values 32-bits to achieve roughly 1 centimeter resolution. Using only fractional degrees gives more resolution with fewer bits and is easier to compute. We need 8 bits to represent Longitude from 0 to 180 plus the sign bit for a total of 9 bits. Then another 23 bits for the fraction. Version 1 has the sign bit in the Minutes field which doesn’t make for an easy number to manipulate. We have to bit-swizzle the sign and then divide minutes by 60 to get the fraction. The proposal for V2 is a simple fixed-point fraction as shown below:

Geographic Location SET

76543210
Command Class = COMMAND_CLASS_GEOGRAPHIC_LOCATION (0x8C)
Command = GEOGRAPHIC_LOCATION_SET (0x01)
Lo SignLongitude Degree Integer[7:1]
Lo[0]Long Fraction[22:16]
Longitude Fraction[15:8]
Longitude Fraction[7:0]
La SignLatitude Degree Integer[7:1]
La[0]Lat Fraction[22:16]
Latitude Fraction[15:8]
Latitude Fraction[7:0]
Altitude[23:16] MSB
Altitude[15:8]
Altitude[7:0] LSB
Geographic Location CC V2 proposal

Longitude/Latitude

Longitude and Latitude formats are the same with a sign bit, 8 bits of integer Degree and 23 bits of fraction. The values are signed Degrees which for longitude varies from -180 to +180 and for latitude varies from -90 to +90. The rest of the bits are a fraction of a degree which yields roughly centimeter resolution.

Altitude

Altitude is a twos-complement signed 24 bit integer which yields a maximum of 83km in centimeters (more than enough!) to as much as -6,000km which is the radius of the earth. Note that altitude can be negative as the altitude is relative to sea level. Most GPS receivers will provide altitude so why not include it here in the Z-Wave standard? We need altitude because ZWLR devices could be spaced out vertically as well as horizontally.

Geographic Location GET

Geographic Location GET is the same as the existing V1.

76543210
Command Class = COMMAND_CLASS_GEOGRAPHIC_LOCATION (0x8C)
Command = GEOGRAPHIC_LOCATION_Get (0x02)

Geographic Location REPORT

76543210
Command Class = COMMAND_CLASS_GEOGRAPHIC_LOCATION (0x8C)
Command = GEOGRAPHIC_LOCATION_REPORT (0x03)
Lon SignLongitude Integer[7:1]
Lon Int[0]Long Fraction[22:16]
Longitude Fraction[15:8]
Longitude Fraction[7:0]
Lat SignLatitude Integer[7:1]
Lat Int[0]Lat Fraction[22:16]
Latitude Fraction[15:8]
Latitude Fraction[7:0]
Altitude[23:16] MSB
Altitude[15:8]
Altitude[7:0] LSB
QualROAl ValidLa ValidLo Valid
REPORT is the same as SET with the additional STATUS byte

Status Byte

The additional Status byte provides additional information about the long/lat/alt values:

Qual: From the NMEA GPS Quality Indicator: GPS receivers need a minimum of four satellites to compute the location. Thus, QUAL is the number of satellites used for the most recent computation. If more than 15 satellites are used, then the value is clamped to 15. The values 0-3 are reserved for debugging.

RO: Read Only – Long/Lat/Alt are Read-Only when set to 1. Devices with GPS receivers set this bit to indicate that the values are from an on-board sensor. SET commands are ignored. Devices without a GPS receiver clear this bit to zero and will have their location set at commissioning time typically using a phone to set the GPS coordinates.

Al Valid: The Altitude value is valid when set to 1. When cleared to 0, the Altitude value is unknown and MUST be ignored.

La & Lo Valid: Each bit signifies when the Latitude and Longitude values are valid. When cleared to zero, the Latitude or Longitude MUST be ignored.

If a SET command was sent, the Longitude, Latitude and Altitude is then considered valid and is retained thru a power cycle but will be cleared if excluded or factory reset.

GPS Receiver to Geographic Location Conversion

All GPS receivers use the NMEA 0183 standard for reporting the coordinates. The string of ASCII characters for longitude and latitude is defined to be [D]DDMM.MMM[M] where D is decimal degrees and M are the miutes. The MM.MMMM value must be divided by 60 to convert minutes into fractions of a degree.

A typical NMEA sentence looks like:

$GPGGA,134658.00,5106.9792,N,11402.3003,W,2,09,1.0,1048.47,M,-16.27,M,08,AAAA*60

Text color matches the field: Latitude, Longitude, altitude – see the details via the NMEA link above.

Converting the values in Geographic Location CC to decimal is accomplished using code similar to: const longitude=payload.readInt32BE(0) / (1 << 23);

GitHub Repo

An implementation of the Geographic Location CC V2 is at: https://github.com/drzwave/GeographicLocationCC

The repository implements Geographic Location CC in an end-device such as the Z-Wave Alliance ZRAD project or on a Silicon Labs Devkit using a QWIIC I2C based GPS receiver like the M8Q from Sparkfun.

See the repo for more examples and details. The official Z-Wave Alliance specification update with GeoLocV2 is currently being reviewed and expected to be published in one of the 2025 releases.

Heat Map Examples

One of the drivers to create GeoLocV2 is to generate heat maps of the RF Range for testing Z-Wave Long Range. In previous Unplugfests we use a very subjective measurement of having an LED stop blinking when out of range. Often the LED would pause, but then start blinking again, then stop so it was difficult to determine the exact edge of RF range. With GeoLocV2 we can map the exact locations where the device is when it is able to make 100% error free, encrypted connection.

The Silicon Labs Works With 2024 conference produced a fantastic video (featuring DrZWave! – well, I have a supporting role) demonstrating GeoLocV2 in action on a motorcycle! Skip to minute 43:40 (about 3/4 of the way thru the video) to see the video.

Z-Wave Long Range demonstration video from Silicon Labs Works With 2024 using Geographic Location Version 2

Below is a heat map from a skydiving test that we will be producing a video in the near future. Z-Wave Long Range demonstrated 2.7 mile range – straight UP! A ZRAD was used as the controller running Z-Wave JS and a small Javascript program to extract the GeoLoc data from a commercial Z-Wave device using a PCB antenna stuffed inside a fanny pack of the jumper. This example demonstrates the need for the Altitude in the specification.

Below is a heat map with the color showing the transmit power needed to make an error free connection which ranges from -6dBm to +20dBm. The test took place in a residential neighborhood outside Boston Massachusetts where the ZRAD controller is in a wood frame building on the second floor and a ZRAD End Device was driven around the neighborhood reaching a general 500m and a maximum of over 1.4km. This demonstrates the dynamic power of Z-Wave Long Range where it saves battery power anywhere within 100 meters but can extend the range thru many obstacles to over a kilometer.

Be sure to attend the upcoming Z-Wave Unplugfest and Summit in Barcelona Spain in February 2025 or the one in Carlsbad CA in April to see GeoLocV2 in action.

Team Z-Wave Development Using Git

Silicon Labs Simplicity Studio v5 (SSv5) has a steep learning curve but once you’re up the curve it can accelerate an IoT firmware development. However, sharing the project among several engineers isn’t as straightforward as it should be. Fortunately it is actually quite easy once you know the trick which I explain below.

Step 1 – Create the Repo

Create the repository using Github or your own private server. Typically this is done via a browser which also sets various options up such as the language and the license. Once this has been created, copy the name of the repository to use in the next step.

Step 2 – Clone the Repo locally

Clone the repo onto your computer using the typical “git clone HTTPS://github.com/<gitusername>/<projectName.git>“. Choose a folder on your computer that is convenient. I recommend the folder be under the SSv5 workspace folder which will make finding it later a little easier.

Step 3 – add a .gitignore file

Create a file at the top level of the repo to ignore the files you do not need to put under source code control. Use the lines below and include any other files or folders as needed. You may want to include the .hex, .gbl, .map, and .axf files which are under the GNU* folder or copy them to another folder so you have the binary files in case building the project proves to be difficult. Note that I am NOT checking in the SDK which is huge and Silabs keeps even quite old versions on github and via their website. Thus you don’t need to keep a copy of the SDK on your local servers – but you can if your are that kind of person.

################ Silabs files to ignore #####################
# Ignore the Build Directory entirely
GNU*
# Other SSv5 files to ignore
.trash
.uceditor
.projectlinkstore
*.bak

Step 4 – Create the SSv5 Project

Create the SSv5 project within this folder. Typically this is done using the Project Wizard or selecting one of the sample applications. Be sure to locate the project within the repo folder.

Step 5 – Commit the Files

Commit the files to the repo using:

git add *
git commit -am "Initial checking"
git push

At this point you can either clone the repo into a different folder to see if it works or have a team member clone it onto their computer. Try building the project to see if there are any missing files.

Step 6 – Import the Newly Cloned Repo into SSv5

This is the tricky bit! We’re going to Import the project into SSv5 but the TRICK is to import it into the cloned repo folder. By default, SSv5 will make a COPY of the project when importing. The problem with that is that you then lose the connection to the git repo which is the whole point!

Use “File – Import” then browse to the cloned git repo folder. The project name should show up with a Simplicity Studio .sls file. Select this file by clicking on it then click Next.

Then the next screen pops up. Ensure the proper compiler is selected for the project! GCC10 or GCC12! These settings should come from the .sls so you shouldn’t need to change them.

Click on Next

THIS IS THE MOST IMPORTANT STEP! In the next screen, UNCHECK the “Use Default Location” button! Click on Browse and select the repo folder.

Click on Finish. Then check that the project builds properly.

Team members can now work collaboratively on the project and manage the check in/out and merging using standard git commands.

When the project is complete, be sure everything is checked in and the repo is clean, then in SSv5 right click on the project and select delete. But do not check the “delete project contents on disk” checkbox unless you want to also delete the local repo. This removes the project from the workspace in SSv5 but leaves the files where they are. You can clean up the files later.

The key to using git with SSv5 is to UNCHECK the Default Location button during the import. If you leave that checked, or browse to the wrong folder, SSv5 will make a COPY of all the files and you lose the connection to the git repo.

The Joys of Trace Debugging

Debugging a HardFault is ROUGH, but with trace debugging, it’s a joy! A big problem with debugging firmware on a System-on-Chip (SoC) design is that the CPU and memory are encased in a plastic package severely limiting the visibility of what the CPU is doing. There are tons of interrupts and exceptions and just plain old bugs in your software that can send the CPU off into la-la land and you have no way of tracking down how it got there. Good ‘ol PRINTFs do not help since the CPU has gone off the rails. The most common method of debugging this kind of fault is to keep removing code or disabling interrupts until you magically divine the cause by inspection after a lot of tedious narrowing of possible causes and reverting checkins. In this post I’ll describe the joys of debugging using the Segger J-Trace and the Ozone debugger.

ARM CoreSight Architecture

ARM CPUs are intended to be implemented in SoCs so naturally ARM designed in a set of tools to enable visibility and debugging called the CoreSight architecture. For the embedded Cortex processors, and specifically the CM33 in the EFR32ZG23, the key components are the ARM ETMv4 which then feeds the TPIU. The ETM/TPIU tracks the CPU Program Counter (PC), packetizes changes in the PC and thus the program flow, compresses the data, then sends it out the trace pins to an external Trace Port Analyzer such as the Segger J-Trace. The Segger tools decompress and decode the trace data to match it with the image file of the compiled code to show exactly the path the program followed. ARM has a huge amount of documentation on their web site but the problem is there is too much information. ARM has many CPUs, architectures, versions and the entire ETM is an optional component with many configurable parts. This makes reading the ARM documentation much like reading the dictionary, lots of detailed information but it is tough to follow the story of how the pieces work together. Fortunately, Segger has read the documentation and figured out how to make it work.

ARM CoreSight provides CPU visibility using only 2, 3 or 5 pins

Segger J-Trace and Ozone Debugger

Segger is well known in the embedded industry for their J-Link hardware programmers, the Ozone debugger and lots of other services. They have wide support for virtually every MCU made including all of the Silicon Labs EFR32 chips. Their support for Trace debugging is excellent with reliable hardware and software. The Ozone debugger is able to read in your .AXF file out of Simplicity Studio, find all the source code, connect to the DUT via the J-Trace (which includes a J-Link for programming/debug), download the firmware in seconds and run to Main and then display the path your firmware took to get there. Easy and fast!

The Segger J-Trace Pro Cortex-M is required for Trace Debugging. While not, cheap, it’s also not expensive compared to the cost of an engineer working for days trying to capture how their firmware dropped into the weeds. The J-Trace connects to your PCB via a 20 pin header that is 50mil on centers so it is quite small. However, I’ve come up with a small PCB that lets you use the standard 10 pin MiniSimplicity header for Trace.

etm_zwave Github Repo and J2Mini Adapter

Most Z-Wave IoT products have very small PCBs and no room for another 20 pin header even if it is 50mil. I came up with a simple way to use the existing 10 pin tag-connect/MiniSimplicity header for Trace and placed all the files in a public github called etm_zwave. You do have to connect a couple of extra pins from the ZG23 to the tag-connect/MiniSimplicity header. Replace the PTI pins with the trace clock and a second data pin – the first data pin is the SWO pin already on the header. This header is tiny and you need a way to program the ZG23 anway and this is the way to go. The PTI pins are not that useful as they are only used for radio packet tracing which Z-Wave uses standalone Zniffers instead of wiring multiple nodes to the Network Analyzer. For less than $30 you can build your own JT2Mini adapter boards and then be able to use trace with just the MiniSimplicity header. You will need a extra ground connection as there is a single ground pin on the MiniSimplicity header. I’ll discuss that issue more in the troubleshooting section below.

JT2Mini adapter board plugs directly into the Segger J-Trace and MiniSimplicity cable. It only provides two trace data pins which Segger claims will only occasionally cause the CPU to stall. With 4 pins the CPU will almost never stall. Obviously with only 1 data pin you’ve cut the data rate to get the trace info out of the chip and it will stall (insert wait states) anytime the TPIU fifos will up until they are able to unload the data off-chip.

Setup Trace in Ozone

Now that the hardware is wired up, we have to enable Trace in Ozone.

  1. Open Ozone
  2. Include the *.JlinkScript file in the etm_zwave github repo
    • For the ZG23 use ZG23_Traceconfig.JLinkScript
    • There are comments in the file and more info in the repo ReadMe.md on how to properly insert the script into your Ozone *.jdebug project file.
  3. Click on Tools->Trace Settings
  4. Change the Trace Source to Trace Pins
  5. CPU Frequency=39MHz
  6. Trace Port Width=2 (if using JT2Mini)
  7. Click on Green Power button
  8. Ozone will download the code and run to MAIN()
  9. Open the Timeline and Code Profile windows

The TimeLine should look something like this – maybe “run” for just a fraction of a second:

This window shows how long the CPU has been in each function and the complete program flow in real time. Interrupts and switching RToS tasks are shown and make it much easier to immediately find where the hardfault occurred. Clicking in the timeline brings up the exact line of C code and optionally disassembly at that instant in time. You can quickly follow exactly where your code went wrong and the hardfault occurred.

The Timeline window also allows you to immediately see how long each function is taking. What is most important here is checking your interrupt service routines to ensure they are not busy burning a lot of CPU time doing less important work and starving other time sensitive functions. The obvious waster of time is the memset and memcpy functions which I am working on another post about those specific functions so stay tuned!

Ozone has a Code Coverage window which displays the number of lines of code that have been executed and the number of assembly instructions executed. Using this feature with a product validation suite you can quickly identify untested and potentially dead code.

Segger has plenty of training videos that go into a great deal of detail on how to use these tools. But first you need a J-Trace and get it wired up to your board.

How to get printfs via J-Trace

Unfortunately the Segger J-Trace Pro does not support the VCOM serial interface. Thus, if you want to open a terminal window and see the printfs in your code, you have to jumper the Rx/Tx pins (and ground) to a Serial to USB adapter. Fortunately I put a header on the JT2Mini PCB for exactly this purpose. The J5 header has the Rx (Pin 1 square pad) and Tx pins on it (Pin 2 round pad). J3 has ground on both pins. Use an FTDI serial to USB adapter and PuTTY or other serial terminal program to view the printfs. The DevKit EXP pins should be able to read in the serial data but I was not able to find the right combination of In/Out/MCU and AEM/Bat/USB and get SSv5 to work. Thus I recommend using a simple FTDI interface to watch the printfs when tracing.

Troubleshooting

The number one challenge with getting Trace to work is the signal integrity of the clock and the trace data pins. Once you have a clean connection, it seems to be rock stable and produces really valuable debugging data even with just two data pins. If Ozone if giving strange errors and specifically different errors with each run, odds are you have a signal integrity problem.

Yellow is Trace Data1, Green is TRACECLK – GPIOs are at max bandwidth

The EFR32 Series 2 (including the ZG23) GPIOs have only a 20MHz bandwidth. The Trace clock is a divide by 2 of the 39MHz CPU clock so it is running right at the maximum of the GPIO. Trace data is clocked out on both edges of the clock. Since the MiniSimplicity header has only 1 ground on it and there are at least 3 GPIOs toggling at their maximum rates, the signal integrity is marginal even in the best of circumstances. The JT2Mini has extra ground pins and I highly recommend connecting them with additional jumper wire while using Trace. The cable from your board to the JT2Mini should also be no more than 6 inches long. The .JlinkScript file has code in it for adjusting the slew rate of the GPIOs which can improve or possibly degrade the trace signal integrity. Ozone and J-Trace can also adjust the relative timing of the CLK to the data with sub-nanosecond resolution. You’ll have to experiment on your own if you are having problems.

Conclusion

I can’t live without Trace debugging. I don’t necessarily use it all the time but I will wire it up to every board I design in the future! I have spent weeks debugging hardfaults in the past and then solve the problem in 10 minutes using Trace. Get one for yourself!

See many of you next week at the Z-Wave Summit in Orlando Florida where I will be giving a presentation on The Joys of Trace Debugging and running the UnPlugFest on Monday!

Who is Trident IoT?

Trident IoT is the Host sponsor of the 2023 Z-Wave Members Meeting and UnPlug Fest in Orlando Florida September 18-20. But you may be wondering, who is Trident IoT?

Z-Wave Summit 2023

Trident IoT is a technology and engineering company focused on simplifying RF development for connected device manufacturers.

Trident is a brand new company that has just come out of stealth mode today. Founded by Mariusz Malkowski (CTO), Michael Lamb (President), and Bill Scheffler (VP Sales), three IoT industry pioneers with decades of success who understand the complexity of bringing connected products to market. Mariusz and Bill were integral parts of Zensys, the company that invented Z-Wave back in 2000. Michael is an industry veteran bringing hundreds of IoT devices to market at companies like EcoLink, Ring, Comcast, and Honeywell.

Trident has hired several of the key Z-Wave engineering experts in Copenhagen which Silicon Labs recently closed. This talent and additional Trident engineering resources are focussed on bringing additional silicon sources and software to Z-Wave and eventually other wireless IoT protocols. The goal is to provide a much faster and easier path to bring wireless IoT products to market. They will be providing an alternative protocol stack, new footprint compatible modules, second source silicon, certification testing and engineering expertise to quickly bring your new products to market.

Read more details in the Trident press release or better yet, come to the Z-Wave Summit in Orlando in September and talk with the founders in person. Early Registration ends this week so snap up the registration, book the inexpensive hotel and flights and meet us for a good time in Florida! Bring your new devices and hubs to Summit on Monday during UnPlugFest where we plan to test just how far Z-Wave Long Range can reach with real commercial products. Naturally we’ll be testing interoperability as well – you can read more about the proposed agenda for UnPlugFest via this link (this is a link to an Alliance Members only page so you need a login which you can get for free if your company is an Alliance Member).

To RTOS or Not To RTOS?

To use an RTOS for your embedded project, or Not! That is the question poor Yorick! I digress from my usual focus on Z-Wave to discuss the general topic of using a Real-Time Operation System (RTOS) for simple embedded IoT devices. The question is moot for Z-Wave since the protocol has FreeRTOS built-in starting with the release of the 700 series. For the moment at least, the choice is To RTOS!

What is an RTOS?

My focus in this post is on small IoT devices like sensors, dimmers, window shades, to more complex devices like thermostats and door locks. Using an RTOS for simple devices like these brings different requirements than say a full Operating System like Windows or Linux. The purpose of an Operating System (OS) is to provide common resources to an application – things like memory management and insulating the application from hardware . The term “Real-Time” comes from basic concept of dividing up the resources of an embedded system so that tasks are completed within a certain timeframe. A hard-real-time system is often used in demanding applications like Engine Control. The precise management of firing the spark plugs at exactly the proper microsecond is critical to the efficient operation of an internal combustion engine. But simple IoT devices have much lower demands on the RTOS and instead are attracted to the coding efficiency and standardization of an RTOS – this is often called a soft-RTOS. All this comes at a cost in CPU and memory resources so the question remains – is an RTOS worth it for simple IoT devices?

  • FreeRTOS Features:
    • Trusted Reliable Kernel
    • MultiTasking/MultiThreaded
    • Mailboxes, Mutexes, Queues
    • Modular Libraries
    • Broad Eco-System support – 40+ MCU architectures
    • Small Scalable kernel size with power saving modes
    • Complete online documentation
    • Long Term Stable Support – Active support Community
    • Completely Free Open Source project

Z-Wave History with FreeRTOS

In the beginning Z-Wave ran on an 8-bit MCU with limited FLASH and RAM which meant life without an RTOS due to CPU performance and memory limitations. The Z-Wave protocol was built on “Bare Metal” and thus interrupt driven with a tick-timer and drivers to provide basic services. The 700 series opened the world of a 32-bit RISC MCU and significantly more memory which enabled the use of an RTOS as the foundation of the Z-Wave protocol.

I was a Field Applications Engineer for Silicon Labs for several years and in that time I would guess easily half the bugs I came across were caused by the complexity of the RTOS. I don’t have any hard statistics but it certainly seemed that way to me! The Z-Wave protocol code was ported from a Bare-Metal implementation on an 8-bit CPU to a 32-bit ARM running FreeRTOS – a challenging port to say the least! The developers treated FreeRTOS like a black-box (which is the whole point of an RTOS) and often made small mistakes that turned into really difficult to debug problems. Things like: not checking when a queue is full, not using the *FromISR() version of various calls inside interrupt service routines, hidden stack overflows by not enabling overflow checking, incomplete configuration of the many, many, many options just to name a few. An RTOS adds a LOT of complexity but you get a lot of features. The developers have to be fully trained and understand the best practices for using the complexity of the RTOS to achieve a robust system.

My primary complaint with the current implementation is that it continues to be pre-compiled into the Z-Wave library. More and more of the configuration files and various parts of FreeRTOS have been moved out of the library and into source code with each SDK release. Moving the entire RTOS into source form is not exposing any proprietary code – after all, it’s open source! It would allow developers to more quickly move to newer releases of the RTOS and related libraries. Perhaps this will come as part of the Open Source Work Group (OSWG) in the Z-Wave Alliance. We’ll have to wait and see…

The Case FOR an RTOS – Pros

I want to again note that I am talking about using an RTOS for small IoT devices. There are many other applications and environments for an RTOS which have different Pros/Cons. A few of the main features of an RTOS for IoT are:

  • MultiTasking, MultiThreading, Mutexes, Mailboxes, Queues
  • Priority Based Resource Scheduling
  • Standardized Resource Drivers
  • Modularity & Code Reuse
  • Security Features

The Case AGAINST an RTOS – Cons

Measuring the complexity and bug rate introduced by an RTOS unfortunately can’t be quantitatively measured. I contend that in the case of Z-Wave the complexity has outweighed the benefits. The “features” of an RTOS lead to its complexity. For one task to communicate with another, you need to setup queues in both directions. That’s a lot of code and RAM where a simple handshake would most likely do the job as was done in the Bare Metal days.

  • Complexity
  • Resource Usage – CPU, FLASH, RAM
  • Development Tools
  • Training of developers

Final Thoughts

Simple devices like light switches, sensors, window shades, and the like barely need an RTOS. These simple devices rarely need multiple tasks or the other features compared to the complexity added. More complex devices like thermostats and door locks often have a high performance application CPU where even more resources are available for things like OLED screen drivers and fingerprint readers. In this case, the Z-Wave chip is relegated to a minor role of just providing wireless connectivity which again does not need an RTOS. All that being said, the current Z-Wave protocol is fundamentally based on FreeRTOS so the To RTOS or Not To RTOS question has already been settled – To RTOS we go!

One final point on code reuse – I find Code Reuse to be a double edge sword. One the one hand, the name sounds very attractive – code once, use many times. The reality is that most code is not reusable and in the effort to make it modular, more bugs are introduced than are saved. In many cases I can write a function in a fraction of the lines of code compared to the “driver” that does it all for every flavor of chip. There’s many research papers that discuss that bugs/line of code is fairly constant. So the fewer lines of code, the fewer bugs. The fewer lines of code the easier to read and to test. Not to say that all reusable code is bad and certainly code that has been extensively tested in many ways is super valuable, but every engineer needs to make that judgement for their specific application. That’s why you get paid the big bucks!

Make Your Own Z-Wave Device

Have you always wanted your very own Z-Wave widget-thing-a-ma-bob-doohickey? Silicon Labs recently released the Thunderboard Z-Wave (TBZ) which is an ideal platform for building your own Z-Wave device. Officially known as the ZGM230-DK2603A, the TBZ has sensors galore, expansion headers to connect even more stuff, comes with a built-in debugger via USB-C and can be powered with a single coin cell. Totally cool! I am working on a github repo for the TBZ but right now there are three simple sample apps in Simplicity Studio to get started.

ThunderBoard Z-Wave

Thunderboard Z-Wave

Features

  1. ZGM230 Z-Wave Long Range Module – +14dBm radio – 1mi LOS RF range
    1. ARM Cortex-M33, 512/64K FLASH/RAM, UARTs, I2C, SPI, Timers, DAC/ADC and more
  2. Built-in Segger J-Link debugger
  3. USB-C connectivity for SerialAPI and/or debugging
  4. RGB LED, 2 yellow LEDs, 2 pushbuttons
  5. Temperature/Humidity sensor
  6. Hall Effect sensor
  7. Ambient Light sensor
  8. 6-Axis Inertial sensor
  9. Metal sensor
  10. 1Mbyte SPI FLASH
  11. Qwiic I2C connector
  12. Break-out holes
  13. SMA connector for antenna
  14. Coin cell, USB or external power
  15. Firmware development support via Simplicity Studio

Sample Applications

There are three sample applications in Simplicity Studio at the time of this writing (Aug 2022 – SDK 7.18.1);

  1. SerialAPI,
  2. SwitchOnOff
  3. SensorMultilevel

The TBZ ships with the SerialAPI pre-programmed into it so you can use it as a Z-Wave controller right out of the box. Connect the TBZ to a Raspberry Pi or other computer to build a Z-Wave network. Use the Unify SDK to get a host controller up and running quickly or use the PC-Controller tool within Simplicity Studio for development and testing. The SwitchOnOff sample app as the name implies simply turns an LED on/off on the board via Z-Wave. This is the best application to get started as the ZGM230 chip is always awake and is easy to debug and try out. The SensorMultilevel sounds like a great app as it returns a temperature and humidity but at the moment it does not use the sensor on the TBZ and simply always returns a fixed value. SensorMultilevel shows how to develop a coin-cell powered device. Additional sample apps are expected to be available in future SDK releases but I am working on a github repo with a lot of sensor support.

Naturally a single Z-Wave Node doesn’t do much without a network. You’ll need some sort of a hub to connect to. Most of the common hubs (SmartThings, Hubitat, Home Assistant, etc) will at least let you join your widget to the network and do some basic control or status reporting. You need either a pair of TBZs or perhaps purchase the even cheaper UZB7 for the controller side and then the TBZ for the end-device. Then you have a network and can build your doohickey and talk to it over the Z-Wave radio.

Getting Started

Plug in the TBZ to your computer and open Simplicity Studio which will give you a list of applicable documents including the TBZ User Guide. Writing code for the TBZ definitely requires strong C programming skills. This is not a kit for an average Z-Wave user without strong programming skills. There is a steep learning curve to learn how to use the Z-Wave Application Firmware (ZAF) so only experienced programmers should take this on. I would recommend watching the Unboxing the 800 series video on the silabs web site to get started using Simplicity Studio. I hope to make a new video on the TBZ and publish the github repo so stay tuned.

Have you created a Thing-a-ma-bob using the TBZ? Let me know in the comments below!

Z-Wave 800 GPIO Decoder Ring

The two Z-Wave 800 series chips from Silicon Labs have flexible GPIOs but figuring out which one is the best for which function can be challenging. There are a number of restrictions based on the function and the energy (sleep) mode you need the GPIO to operate in. Similar to my posting on the 700 series, this post will guide you to make wise decisions on which pin to use for which function.

The tables below are a compilation of several reference documents but all of the data here was manually copied out of the documents and I could have made a mistake or two. Please post a comment if you see something wrong and I’ll fix it right away.

Reference Documents

  • EFR32xG23 Z-Wave 800 SoC Family Datasheet
  • ZGM230 Z-Wave 800 Module Datasheet
  • EFR32xG23 Reference Manual
  • WSTK2 Schematic (available via Simplicity Studio)
  • BRD4210 EFR32ZG23 Radio Board +20dBm Schematic
  • Thunderboard Z-Wave UG532 and Schematic

Pin Definitions

The table below lists the pins from the most flexible to the most fixed function. There are more alternate functions than the ones listed in this table. The most commonly used alternate functions are listed here to keep the table readable. Refer to the schematics and datasheets for more details.

Port A and B are operational down to EM2, other GPIOs will retain their state but will not switch or pass inputs. Thus, use port A and B for anything special and use C and D for simple things not needed when sleeping (LEDs, enables, etc).

WSTK GPIO Probe Points

Only the ZG23 QFN48 pin numbers are listed in the table. The QFN48 is expected to be pin compatible with future version of the ZG23 with additional Flash/RAM so I recommend using it over the QFN40. The WSTK2 is the Pro DevKit board with the LCD on it which comes as part of the PK800 kit. There are two sets of holes labeled with Pxx numbers on them which are handy to probe with an oscilloscope. The Thunderboard Z-Wave (TBZ) also has 2 rows of holes which are ideal for probing or connecting to external devices for rapid prototyping.

NameZG23ZGM230WSTK2TBZALT
FUNC
Comments
PB2229P19EXP5
BTN1
Use the pins at the top of this list first as they are the most flexible
PB6NA5EXP15
I2CSDA
TBZ Qwiic I2C_SDA
PB5NA6EXP16
I2CSCL
TBZ Qwiic I2C_SCL
PB4NA7
PA103523
PC1235P1EXP4PC and PD are static in EM2/3
PC2336P3EXP6
PC3437P5EXP8
PC4538P35BLUE
PC6740P33EXP9
PC8942P31LED0
PC91043P37LED1
PD34530P26IMUEN
PB02411P15VDAC0CH0
PA02512P2GREENIDACVREF
PB12310P17REDEM4WU3
VDAC0CH1
EM4WUx pins can wake up from EM4 sleep mode on a transition of the GPIO
PB3218P21EXP3
BTN0
EM4WU4
PC0134P7EXP10EM4WU6
PC5639P12EXP7EM4WU7
PC7841P13SNSENEM4WU8
PD24631P6EXP11EM4WU9
PD0_LFXTAL_O4833XC32XC32BRD4210 and TBZ have 32KHz crystal mounted
PD1_LFXTAL_I4732XC32XC32Accurate timing while sleeping – Time CC
PA73220P10TraceD3Trace pins for debug & code coverage
PA63119P8TraceD2Trace is configurable for 4, 2 or 1 data pin
PA53017P4IMUINTEM4WU0
TraceD1
PA4_TDI2916P41EXP13JTAG_TDI
TraceCLK
JTAG data in
Trace Clock out
Pins below here should be used primarily for debug
PD4_PTIDATA4429P25Packet Trace Interface (PTI) data
PD5_PTISYNC4328P24EM4WU10PTI Sync
PA9_URX3422P11EXP14VCOM UART
PA8_UTX3321P9EXP12VCOM UART
PA3_SWO2815P16JTAG_TDO
TraceD0
RTT UART printf and Trace D0
PA2_SWDIO2714P18JTAG_TMSThese two SWD pins should ONLY be used for debug and programming
PA1_SWCLK2613P20JTAG_TCKSWD debug clock
Pins below here are fixed function only
SUBG_O118NANot used by Z-Wave
SUBG_I116NANot used by Z-Wave
SUBG_O0193RFIO on ZGM230
SUBG_I017NAMatching network to SMA
RESET_N131F4Push buttons on DevKit boards
HFXTAL_O12NA39MHz crystal
HFXTAL_I11NA39MHz crystal
DECOUPLE36181.0uF X8L cap (unconnected on ZGM230)
VREGSW37NAInductor to DVDD for DCDC – 3.3V
VREGVDD38253.3V In/Out based on mode
DVDD4024VDCDC on ZGM230
AVDD41NAHighest voltage – typically battery voltage
IOVDD42261.8-3.8V
PAVDD20NA3.3V for +20, 1.8V for +14dBm
RFVDD14NA1.8V or 3.3V but less than PAVDD
VREGVSS3927, 44GND
RFVSS152, 4GND

Power Supply Pins

Obviously the power supply pins are fixed function pins. The only really configurable parts to this set of pins is the voltage to apply to the IOVDD, AVDD and whether to use the on-chip DC to DC converter or not. If your device is battery powered, AVDD should be the battery voltage assuming the battery is nominally 3V (coin cells or CR123A). AVDD can be measured by the IADC in a divide by 4 mode to give an accurate voltage reading of the battery. This avoids using GPIOs and resistor dividers to measure the battery level thereby freeing up GPIOs and reducing battery drain. IOVDD should be set to whatever voltage needed by other chips on the board. Typically either 1.8 or 3.3V. The DCDC should be used in most battery powered applications unless a larger DCDC is present on the board already to power other chips.

The other configurable voltage is the RFVDD and PAVDD and the choice there depends on the radio Transmit Power you wish to use. For +14dBm PA an RF VDD are typically 1.8V. For +20dBm PAVDD must be 3.3V.

Every product has unique requirements and sources of power so I can’t enumerate all possible combinations here but follow the recommendations in the datasheets carefully. Copy the radio board or Thunderboard example schematics for most typical applications.

Debug, PTI and Trace Pins

The two Serial Wire Debug (SWD) pins (SWCLK and SWDIO) are necessary to program the chip FLASH and are the minimum required to be able to debug firmware. While it is possible to use these pins for other simple purposes like LEDs, it is best if they are used exclusively for programming/debug. These should be connected to a MiniSimplicity or other debug header.

The SWO debug pin is the next most valuable pin which can be used for debug printfs in the firmware and output to a debugging terminal. Alternatively, the UART TX and RX pins can also be used for debugging with both simple printfs and able to control the firmware using the receive side of the UART to send commands.

The two Packet Trace Interface (PTI) pins provide a “sniffer” feature for the radio. These pins are read by Simplicity Studios Network Analyzer to give a detailed view of all traffic both out of and into the radio. The main advantage of these pins is that they are exactly the received data by the radio. The Z-Wave Zniffer can also be used as a standalone sniffer thereby freeing these pins for any use. The standalone Zniffer however does not show you exactly the same traffic that the PTI pins do especially in noisy or marginal RF conditions. Thus, the PTI pins on the device provide a more accurate view of the traffic to the device under test.

The Trace pins provide additional levels of debug using the Segger J-Trace tool. These pins output compressed data that the debugger can interpret to track the exact program flow of a running program in real time. This level of debug is invaluable for debugging exceptions, interrupts, multi-tasking RTOS threads as well as tracking code coverage to ensure all firmware has been tested. Often these pins are used for other purposes that would not be necessary during firmware debug and testing. Typically LEDs or push buttons can be bypassed during trace debug. There are options to use either 4, 2 or even 1 trace data pin but each reduction in pins cuts the bandwidth and make debugging less reliable.

LFXO and EM4WU Pins

The Low Frequency Crystal Oscillator (LFXO) pins are typically connected to a 32KHz crystal to enable accurate time keeping within several seconds per day. If supporting the Time Command Class, I strongly suggest adding the 32KHz crystal. While you can rely on the LFRCO for time keeping, it can drift by as much as a minute per hour. While you can constantly get updated accurate time from the Hub every now and then, that wastes Z-Wave bandwidth and battery power. Both the Thunderboard and BRD4210 include a 32KHz crystal so you can easily compare the accuracy of each method.

Reserve the EM4WU pins for functions that need to wake the EFR32 from EM4 sleep mode. These are the ONLY pins that can wake from EM4! Note that ports PC and PD are NOT able to switch or input from peripherals while in EM2. See the datasheet and reference manual for more details.

Remaining GPIOs

Many of the remaining GPIOs have alternate functions too numerous for me to mention here. Refer to the datasheet for more details. Most GPIOs can have any of the digital functions routed to them via the PRS. Thus, I2C, SPI, UARTs, Timers and Counters can generally be connected to almost any GPIO but there are some limitations. Analog functions have some flexibility via the ABUS but certain pins are reserved for special functions. Hopefully these tables help you make wise choices about which pin to use for which function on your next Z-Wave product.

Tiny Headers for Reliable Debug

Here we go again… Once again I’ve been given yet another board with randomly placed test points instead of a nice neat, reliable header to connect via my MiniSimplicity cable. So I’m spending an hour on my microscope soldering thin little wires to the tiny little test points to be able to flash and then debug the firmware on a new ZG23 based product. Once I’m done soldering, I’m left with a very fragile board which is unreliable at best and at worst will result in even less hair on my thinning head. My post from 2019 described using a zero cost header for a reliable connection, but it seems not everyone is reading my blog!

On the flip side, a different customer sent me their board with a Tag-Connect Edge-Connect that I had not seen before but is absolutely brilliant. The Edge-Connect uses the EDGE of your PCB for the test points. Barely 1mm wide and about 20mm long it is possible to include this debug connector on virtually any PCB. There is a locking pin to hold the cable secure while the spring loaded tabs press into the castellated notches to ensure solid contact.

Close up of the locking pin and castellated notches

There are several sizes of the Edge-Connect but the recommended one is the 10-pin EC10-IDC-050 which matches the MiniSimplicity header on the WSTK DevKit board. Note that the the 6pin cable in the photo above is NOT the one I would recommend but it was the only one in stock at the time and it worked fine for debugging but doesn’t have the UART or PTI pins.

Tag-Connect has many other types of debug headers/cables of various configurations to hold the cable to the PCB securely. The original Tag-Connect cables have plastic clips that snap into fairly large thru-holes in your PCB. While this is a reliable connection, the thru-holes eat up a lot of PCB real estate. The next evolution was to use a small retaining clip under the PCB that grips onto the metal alignment pins. The photo below shows the PCB pads are not much bigger than an 0805 footprint and only requires three small thru-holes.

Note the smallest header is about the same as an 0805 in lower left corner

The lowest cost approach is to simply add a 10-pin header footprint on your PCB that matches the pinout of the MiniSimplicity header. See section 5.1.1 of Application Node AN958 for the pinout of the 10-pin MiniSimplicity header. You don’t need to solder the header onto the PCB except when debugging. Thus the header can be under a battery or some relatively inaccessible location as when you are debugging in the lab the PCB is usually not installed in the product enclosure.

Please use ANY of these standard connectors on your next project. Without a solid connection between your computer and the chip you will find yourself chasing ghosts and losing hair.