Door locks, thermostats and other Z-Wave devices often need to know at least the time and day of the week. In many cases they need to know the full date and time to enable a lock User Code when a renters code is valid or set the thermostat into energy save mode. These devices need a way to determine the current date and time to within a few seconds of accuracy.
Z-Wave provides three different command classes (CC) for getting various parts of the date/time. Time Command Class is mandatory for all Gateways. Unfortunately, not all gateways support it yet, so most devices need to support one of the other command classes for use with older hubs. The question then is how is a device supposed to get the current date/time so the schedule can operate properly?
Time CC – Recommended
Time command class is described in SDS13782 (Z-Wave Management Command Class Specification). Time CC is mandatory for all Z-Wave Plus Gateways and thus is the recommended method for a device to set its clock to the current local date and time. Time CC Version 2 adds time zones and daylight savings time support if desired however V1 provides the necessary data in most cases.
The Z-Wave specification recommends having an association group to identify the time server node however the Gateway is expected to have an accurate time reference so using the Lifeline is acceptable.
The Time CC does NOT have a date/time SET command. Thus, the hub cannot set the date/time and instead must wait for the device to GET it. When a device is included in a network, it must send a Time GET command within the first few minutes to accurately set its internal clock. The device should then periodically send a Time GET to ensure the internal clock remains accurate to the local time. Note that for certification purposes a device CONTROLs Time CC, it does not SUPPORT it. The Hub is required to SUPPORT Time CC.
Time Parameters CC – Optional
The Time Parameters command can SET/GET/REPORT the year, month, day, hour, minute & second of the UTC time. However, it does not set the time zone which must be done via the Time CC V2. Thus, Time Parameters CC relies on the hub to send the current UTC time but the device can also send a GET and adjust its internal clock to match the one from the hub. However, this requires support on the hub software which is not mandatory so not all hubs will be able to provide the current date/time.
Clock CC – NOT Recommended
Clock command class is sent by a Hub and can set the local weekday and time. Thus, it only supports a 7-day schedule since it cannot set the date, just the day of the week. Typically, the Hub would send a Clock Set as part of inclusion in the network. Since the clock on the device will drift, the device must periodically send a Clock Get to the Hub and to maintain time accurately. This method is NOT recommended. However, on some old hubs this is the only method available.
Recommended Time Setting Algorithm
Wait for Inclusion into a Z-Wave Network
Wait for Security negotiation to complete
Send a Time CC DATE GET
Wait for a Time CC DATE REPORT for ~30s
If DATE REPORT arrives, Send a Time CC TIME GET and wait for ~30s
if the Time REPORT arrives then the date/time is now set and use Time CC for future clock adjustments
Exit the search for the local time
If Time CC DATE REPORT times out:
Retry 2 more times with random delay of a few minutes between each retry
During steps 3-6, If a Time Parameters CC SET or a Clock CC REPORT is received, use those to update the date/time but if a Time CC report arrives use Time CC
Send a Clock CC GET
If a REPORT arrives within ~30s then use Clock CC GET to update the date/time
If CLOCK fails
Send Time Parameters CC GET to get the current date/time
If those fail, there is no source for the current date/time, disable all scheduling features
Depending on the accuracy of the local clock circuitry, the functioning time setting command class should be used to update the local clock at a sufficient rate to match the desired settings. Typically, this would be once per day assuming a 100ppm or better 32Khz crystal is used for the 700 series low frequency external crystal oscillator (LFXCO).
Conclusion
End Devices should send a Time CC Date/Time GET shortly after inclusion in a Z-Wave network and then periodically send Date/Time GETs based on the accuracy of the real-time clock circuitry. Updating at 3:10am ensures the clock will be accurate to daylight savings time should be sufficient for a low-cost 32kHz crystal. The algorithm above works for just about any hub that has at least minimal support for time keeping.
You have a second MCU or other data files you want to update using Over-The-Air (OTA) via Z-Wave. How can you reuse the Bootloader firmware to verify the signature and decrypt the data?
The code to verify and decrypt the file already exists in the bootloader and is known good. Reusing the existing bootloader code is smaller and safer than re-inventing the wheel – or in this case encryption.
The attached project is a modified Z-Wave Door Lock Key Pad sample application that demonstrates how to OTA code/data other than the Z-Wave firmware. OTA of the Z-Wave firmware works in the sample application already – but first the encryption keys MUST be generated. See https://www.silabs.com/community/wireless/z-wave/knowledge-base.entry.html/2019/04/09/z-wave_700_ota_ofe-i00M on how to generate the keys. See the two .BAT files in the comments section which will run all the necessary commands for you. They are also included in this .sls file in the KEYS directory. You MUST create your own project keys to OTA either the Z-Wave Firmware or any other data.
To OTA other types of files you need to start with a binary file. Most microprocessor development environments will output a binary file so use that instead of a HEX file. If you have an Intel hex or Mototola S record file, use a utility like SREC_CAT to convert it to a binary file. SREC_CATcan convert just about any file type into any other file type. If the file is more than 200K bytes, you will need to break the file into 200K or smaller files and OTA each, one at a time. Doing that is beyond the scope of this project. Note there is no need to encrypt the file. We will be using Commander to sign and encrypt it using the keys generated here.
Theory of Operation:
Changes to the SSv4 DoorlockKeyPad sample project are indicated with the comment “AKER” – search for these to find what changed. You can also diff the files with a fresh copy of the DoorLockKeyPad sample app from SSv4. Most of the code to support OTA of an external processor is in this file. A few changes have been made to ota_util.c in ZAF_CommandClasses_FirmwareUpdate but these are expected to be included in a future release of the SDK (currently tested on 7.13).
Commander is used to generate a pair of public and private keys. The private key is then programmed into every device to be OTAed. Commander then encrypts and signs the binary file and wraps it with bootloader tokens. The gbl file is downloaded, the signature checked and the encrypted data is then passed to a callback function 64 bytes at a time. You then have to store the data or pass it to the external MCU. This example simply prints the data out a UART.
Procedure:
Step 1: Generate the keys
There two .BAT files in the KEYS directory for this project. These are windows script files. For other platforms you can easily convert them to the platform specific commands. See the comments in the files for more details. In a windows shell type: GenGblToken.bat This will use Commander to generate a project set of keys in the files vendor_*.*. Only execute this command ONCE. The same keys are used for the duration of the project. If you change the keys then you cannot OTA the devices as the keys no longer match.
Step 2: Program the key into a devkit and every DUT
Each device manufactured must have the private key programmed into FLASH. Use the PgmToken.bat to program the key into a target device connected via USB. Note that EVERY unit manufactured must have these keys programmed into it.
Step 3: Generate the .gbl file
Create the .gbl file from the binary file using the following command: commander gbl create <OTA_FileName>.gbl –metadata <BinaryFile> –sign vendor_sign.key –encrypt vendor_encrypt.key The –metadata option will wrap the binary data with the necessary tokens for the bootloader to parse the data. Do not use the –compress option. If the data needs to be compressed, use your own algorithm for that. There are 3 sample binary files in the KEYS directory – a small .WAV audio file, a large .M4A audio file and a PNG image file. Use the command above to wrap the file with the necessary tokens for OTA.
Step 4: OTA the .gbl file
Use the PC Controller or other application to send the gbl file over Z-Wave. Once the entire file has been sent and the CRC checked to be good, the FinishFwUpdate function is called to begin processing the image. Note that in the PCC you have to first GET the Current Firmware, then select the Target: 1 to download the metadata. Then click on UPDATE and the OTA will begin. Connect a terminal to the VCOM port of the WSTK to view the data streaming down during the OTA. Once all the data is sent down, the signature is checked and the decrypted data is sent out the UART. This is where you would need to change the code to store the data instead of printing it out the UART.
Step 5: Verify the Signature and pass in the callback function
The bootloader_verifyImage() function is called and the metadataCallback function is passed in. bootloader_verifyImage first returns a zero if the signature matches. If the signature fails an error value is returned giving some details on why it failed. The time to verify the signature can be fairly long depending on the size of the image so the watchdog timer is disabled during the processing.
Step 6: MetadataCallback passes blocks of 64 bytes of the decrypted data
The function passed in to bootloader_verifyImage is called with a pointer to the data and the number of bytes in each block. The size of the block can vary up to 64 bytes. In this example the data is simply printed out the UART. In your application you would replace this function with code to store the data as needed on the other MCU or external NVM.
Step 7: Reboot
It is recommended to reboot after the image data has been stored to ensure the FLASH is cleaned up properly. The current demo however does not reboot.
Note: This is an SSv4 SDK 7.13 sample but the same concepts should work in SSv5. The changes to ota_util.c will be folded into the SDK in a future release but for now those changes are necessary.
What does an SDO mean you might ask? An SDO is a Standards Development Organization and the Z-Wave Alliance has now legally become a non-profit SDO. What this means to you is that Silicon Labs no longer control the progress of Z-Wave, the members of the SDO now control it. Read more details about the SDO in the Z-Wave Alliance Press Release.
There are seven founding members: Alarm.com, Assa Abloy, Leedarson, Ring, Silicon Labs, StratIS, and Qolsys. If you’re employed by one of these companies, join a working group and make your ideas known! There are six different membership levels with varying “voting rights” and costs so your organization can choose a level based on interest and budget.
How will this impact you and your IoT device development? In the short term probably not much, early next year however, expect to see the first Z-Wave product pass thru the new certification requirements based on the specifications produced by the SDO. Longer term this is all part of Z-Wave becoming an open standard with more silicon providers and software stack provides implementing new features all to make Z-Wave last for years to come.
The goal is to make Z-Wave THE sub-GigaHertz radio standard for IoT devices. Z-Wave is simple, low power, doesn’t require a lot of FLASH/RAM (IE: it runs on cheap MCUs) and most of all interoperable all the way back to devices released over two decades ago. Sub-GigaHertz means the radio passes thru walls and travels longer distances with less interference than the 2.4GHz protocols.
I want to remind everyone to register for the Works With Virtual Conference coming up in just a few weeks! Click below to check it out – HEY it’s FREE!
Works With is much more than just Z-Wave. All the key eco-system players are there explaining in detail how to be a part of their world. This is a technical conference so don’t miss it. I’ll be giving a demo of the latest version of Simplicity Studio V5 and how to quickly build, debug and certify Z-Wave applications.
Silicon Labs is hosting what was intended to be an in-person conference in Austin Texas but is now a virtual online conference on IoT ecosystems – the Works WithSmart Home Developer Event September 9-10. The best part is it is now FREE to attend any of the in-depth technical sessions and you don’t have to wear a mask. The downside is that we don’t get to experience all that great music down in Austin – well, there’s always next year!
I am hosting the Z-Wave track and will be making several presentations including a detailed look at Silicon Labs latest release of Simplicity Studio V5 which just came out yesterday. We’ll also have presentations on developing Z-Wave Smart Hubs and Z-Wave Certification. I’ll also be describing some IoT failures – you learn more from your failures than your successes. We have speakers and engineers from all of the ecosystem partners, not just Silicon Labs folks. Learn from the experts from across the industry!
What is Works With 2020? The smart home developer’s virtual event where you will have the opportunity to interact with our ecosystem partners from Amazon, Google, Samsung, and Z-Wave to connect devices, platforms and protocols and be able to immerse yourself in keynotes, a panel discussion on Project CHIP, hands-on, and technical sessions led by smart home engineers who are building the latest advanced IoT devices. The Works With event is live, all-online, free of charge, and you can join from anywhere around the world.
Click here to Register Today and feel free to forward to the rest of your team.
Here’s an overview of what you won’t want to miss:
Specialized Engineer-Led Tracks – Educational sessions and technical training designed for engineers, executives, developers, business development and product managers.
Hands-On Workshops More than 12 workshops and hands-on sessions to give you experience, knowledge and confidence to develop and accelerate smart home development.
One-on-One Developer Meetings – Schedule a meeting with Silicon Labs or an ecosystem partner to get 1:1 technical guidance.
Join me in September and learn how to smoothly get your IoT device plugged into any and all of the ecosystem partners. Register today, it’s totally free and you can join from anywhere in the world. See you September!
One of the most common questions in embedded programming is “How much FLASH/RAM am I using?” or more precisely, “How much do I have left before I run out?” or even “How much do I have to squeeze my code to fit in the available space?” Yikes! Very often the code size quickly fills to fit the available space and then you start struggling to fit all the features in your product. This problem afflicts the Z-Wave 700 series just as much as any other IoT development. I’ll give you a few hints on tools to measure the code size and figure out where the bloat is and options to squeeze a little more code in.
ZGM130S Resources
The first step is to understand how much FLASH/RAM we have in the Z-Wave ZGM130S. Open the datasheet and we see there is 512K FLASH and 64K RAM. Seems like a TON! But wait, a closer look at the datasheet and there is a note that only 64KB FLASH is available for the application and 8KB RAM. That’s not a lot for a complex IoT device like a thermostat with an OLED screen but is plenty for a simple on/off light switch. Like any engineering trade off, the chip balances the available resources to match the most common use cases.
The Z-Wave stack isn’t huge so fortunately there is sufficient space available for most applications. However, the stack developers have reserved most of the the FLASH and RAM space for future upgrades. There is no easy to use tool that precisely measures how much code space is being used for the stack versus the application. In this post I’ll give you some tools to see how close you are to the total and then subtract a typical sample application size to find the amount your application is using. INS14259 section 5.1 gives the typical FLASH usage for the Z-Wave sample applications.
Half of FLASH (256K) is reserved for the Over-The-Air (OTA) firmware image. This block of flash is used when the firmware is updated and the data is stored here temporarily until the signature is checked and the code can be decrypted. Once that test has passed then the code is copied down into the normal FLASH space and the chip reboots into the new firmware version. If you need a lot more than 64K of FLASH you can consider moving the OTA storage from the upper half of the ZGM130S to an external serial FLASH. This is supported in the Silicon Labs Gecko Bootloader but requires some coding to free up all that space. This also requires hardware support for the external FLASH chip. So if you think you’re going to be short on code space, I highly recommend adding a serial FLASH chip even if you don’t use it right away. I plan to describe the OTA to external FLASH process in a future blog posting so stay tuned.
ARM Tools
Before starting with code size analysis be sure you are working with the “release” build and not the debug build. Click on Project->Build Configurations->Set Active and select the Release build. Then build the project. The debug build uses minimal optimization and has tons of ASSERT and PRINTF code in it which invalidates the code size analysis.
ARM eabi-size
When you compile a Z-Wave project it will run the arm-none-eabi-size -A <project.axf> command which prints out an obscure listing of the sizes of various FLASH segments. The DoorLockKeyPad sample application produces the following:
.text = code which lives and runs out of on-chip FLASH
.data = initialized variables
IE: int myvar=12345; results in 12345 being stored in FLASH and then copied to RAM on power up
Thus .data uses both FLASH and RAM
The other 2 segments are in FLASH space but subtract from the total available
.nvmApp = Application non-volatile memory
.simee = SDK non-volatile memory
RAM = .bss + .data
.bss = Variables not explicitly initialized
gcc normally zeroes on power up
.data = initialized variables
.heap = heap used for dynamic memory allocation
.stack = the stack for pushing return addresses, function parameters and other things
The other segments can be largely ignored
The available FLASH is 256K minus the .simee and .nvmApp=256K-12K-36k=208K
The available RAM is 64K minus the heap/stack=64K-3K-1K=60K
Thus:
FLASH=168760+1132 = 169,892 bytes = 80% utilized
RAM=28956+1132 = 30,088 bytes = 49% utilized
You can see that the SDK code and the application are all mashed together without a way to identify how much the application is using. But at least you know when you are running out. Note that each release of the SDK will change the amount of flash used by the SDK code and possibly the ZAF. Note that the ZAF is considered part of the Application code.
Commander Flash Map
Another easy way to check how much FLASH is being utilized is to use Commander to display a map of FLASH. Start commander and connect to the DUT then use Device Info->Flash Map to get a chart like this one:
ARM eabi-nm
If you want to know which functions and variables are the biggest chunks of FLASH/RAM usage use the nm command: arm-none-eabi-nm <project.axf> --print-size --size-sort -l | tail -30
Address Size Type Symbol
00018c84 00000444 t process_event
0001c760 00000454 T IsMyExploreFrame
000172a4 00000454 T TransportService_ApplicationCommandHandler
000185aa 000004d2 T S2_application_command_handler
0001de00 000004e4 T crypto_scalarmult_curve25519
0001098c 0000054c T IsMyFrame
00017ee4 00000590 t S2_fsm_post_event
00010318 00000674 T IsMyFrame3ch
20006c14 00000708 B channelHoppingBuffer
000138a0 000007e8 T CommandHandler
00021960 00000888 T FRC_IRQHandler
00011790 00000890 T ReceiveHandler
2000628c 000008ac B the_context
20007590 00000c00 N __HeapBase
00019788 00000e04 T mbedtls_internal_sha1_process
00026f68 000019cc T RAILINT_0cdb976df793f6799e20dfa42e2be4c6
00074000 00003000 b nvm3AppStorage
00077000 00009000 B __nvm3Base
00077000 00009000 B nvm3Storage
The third column need a little decoding: T/t=.text (FLASH), B/b=.bss (RAM) D/d=.data (both FLASH and RAM)
You can also tell if it’s FLASH or RAM by the address – FLASH starts at 0 and RAM starts at 0x20000000. Starting from the bottom of the list above you can see that the NVM3Storage is 36K which is naturally the largest block of FLASH. Followed by the 12K of NVM3 Application storage. From there the sizes drop fairly quickly but you can guess the function based on the name. RAILINT is a bunch of Hardware Abstraction Layer (HAL) code. mbedtls is the Security S2 encryption functions. The HEAP is the largest single block of RAM followed by “the_context” which is a fairly large structure the ZAF and the SDK use to store the security and routing information.
Now that you can see the heavy users you can see if there is something amiss. Perhaps a buffer can be reused instead of using unique buffers for various functions. Look carefully for any unused functions in your source code. GCC often will leave “dead” code in place because it can’t tell if you’re using it as a dynamic callback function so to be safe it leaves the code in there. Thus, review your code and make sure you don’t have dead functions or variables or entire buffers that are never used.
The most common method to squeeze more code in is to try various options in the GCC compiler. The more recent versions of GCC have added Link Time Optimization (LTO) which can significantly reduce the code size (claims are up to 20%!). Simplicity Studio is moving to newer versions of GCC later this year so more of these options will be available. Worst case is to refactor your code to make it more efficient or drop features.
Other Tools
There are other tools like Puncover and Bloaty which can help with managing code size growth. I haven’t personally tried these but they seem like they would help. If you use a tool that helps manage code/RAM let me know in the comments below. We all need help in squeezing into the available space which is never enough!
Z-Wave Virtual Webinar Wednesdays at Noon Eastern US time
Doctor Z-Wave will be giving a hands-on live demo of getting started using Z-Wave with Simplicity Studio on Wednesday June 17. This is a live demo with just a couple of slides so you don’t want to miss it. The session is a short roughly 30 minutes with time for Q&A afterward. I will show you some simple things on setting up Simplicity to make your life easier when getting started. If you can’t make it, it will be recorded and available via the Alliance web site.
There are lots of other topics for Webinar Wednesdays:
Webinar Wednesday Schedule*:*This schedule will be updated regularly on the Z-Wave Alliance website as the series progresses
May 27, 2020 Manufacturing During a Global Pandemic: Insight & Strategy from Companies Who Are Coping Hosted by: Avi Rosenthal – Bluesalve Partners
June 3, 2020Social Distance Sales for Uncertain Times: Tips & Insight for Integrators Hosted by: Jeremy McLerran – Qolsys
June 10, 2020Residential Smart Lock Market: Trends, Use-Cases & Opportunities Hosted by: Colin DePree – Salto Systems
June 17, 2020Z-Wave 700 Series: Getting Started Hosted by: Eric Ryherd – Silicon Labs
June 24, 2020 Feature of Leedarson Z-Wave 700 Series Security Products Hosted by: Vincent Zhu & Michael Bailey Smith – Leedarson
I’m giving a presentation on Z-Wave where you can ask questions and get answers about the opening of the Z-Wave specification among other topics. There are more Tech Talks scheduled and several recent topics were recorded. Follow the links below.
Good news! We have added new Tech Talks. Join us on Tuesdays and Thursdays for live virtual, technical discussions hosted by a lead engineer with time allocated for your questions. We’ll cover topics like battery optimization with BG22, using Z-Wave for your Smart Home Solutions and more. You don’t want to miss these next talks.
Register by clicking here: Tech Talks: Z-Wave Smart Home Solutions by Doctor Z-Wave Tomorrow April 23 at 4 p.m ET
Battery Optimization with BG22 Tues, April 28 at 3 p.m. CT Max Performance on BLE – Simultaneous Connections, Beacons and Scanning Thurs, April 30 at 3 p.m. CT SubGHz Proprietary and Connect Software Stack Tues, May 5 at 3 p.m. CT How to Measure and Debug Network Performance – Using Silicon Labs Network Analyzer Thurs, May 7 at 3 p.m. CT
The Silicon Labs EFR32 family of IoT microcontrollers are very flexible and can do a ton of cool stuff. However, along with all that flexibility comes a lot of complexity. With that complexity are default settings that work fine for many applications but in some cases you want to dig into the details to come up with an optimal solution. In this post I’ll show how to speed up the wake up time for the Z-Wave ZGM130S chip from a GPIO.
But first – a caveat: This post applies to Z-Wave SDK 7.13.x. Future releases of the SDK may have different methods for sleep/wake and thus may require a different solution.
The Problem
Frequently Listening Routing Slaves (FLiRS) devices like door locks and many thermostats spend most of their time in Energy Mode 2 (EM2) to conserve battery power. Once per second they wake up briefly and listen for a Beam from an always-on device. If there is a beam, the FLiRS device will wakeup and receive the Z-Wave command. This allows battery powered devices to use very little power but still be able to respond to a Z-Wave command within one second. FLiRS devices use more battery power than fully sleeping devices like most sensors which use Hibernate Sleep mode (EM4). To wake every second the ZGM130 has to wake quickly and go right back to sleep to minimize power. The problem with EM4 is that it takes a few tens of milliseconds to wake up as the entire CPU and RAM have to be initialized as they were powered down to save power. For a FLiRS device, it’s more efficient to keep RAM powered but in a low-power state and resume quickly to go right back to sleep if there is no beam. Typically the ZGM130 can wake up in about 500 microseconds from EM2. But in many cases this is still too long of a time to stay awake if there are other interrupts such as UARTs or other sensors.
The scope shot above shows the processing that takes place by default on the ZGM130S. In this case I am using a WSTK to drive the SPI pins of another WSTK running the DoorLockKeyPad sample application. The chip is in EM2 at the start of the trace. When SPISEL signal goes low, the chip wakes up. But it is running on the HFRCO oscillator which is not accurate enough to run the radio but it is stable and usable in just a few microseconds. Thus, the SPI clock and data is captured in the USART using this clock. However, by default the Interrupt Service Routine is blocked waiting for the HFXO to stabilize. The 39MHz HFXO crystal oscillator has the accuracy required for the radio.
The question is what’s going on during this 500usec? The answer is the CPU is just waiting for the HFXO to stabilize. Can we use this time to do some other work? Fortunately, the answer is YES! The challenge is that it takes some understanding and some code which I’ll describe below.
The Solution
There are three functions that do the majority of the sleep processing. These are provided in source code so you can read the code but you should not change it. Instead you’ll provide a callback function to do your processing while the chip is waking up.
Simplified Sleep Processing Code:
SLEEP_Sleep in sleep.c: The main function called to enter sleep
CORE_ENTER_CRITICAL – PRIMASK=1 mask interrupts
DO-WHILE loop
Call enterEMx() – this is where the chip sleeps
Call restoreCallback (return 0 to wake, 1 to sleep)
Call EMU_Restore – waits for HFXO to be ready ~500us
CORE_EXIT_CRITICAL – ISRs will now run
enterEMx() in sleep.c:
sleepCallback called
Call EMU_EnterEM[1-4]
wakeupCallback after returning from EMU_EnterEMx
EMU_EnterEM2 in em_emu.c:
Scales voltage down
Call EMU_EM23PresleepHook()
__WFI – Wait-For-Interrupt instruction – ZGM130 sleeps here
Call EMU_EM23PostsleepHook() ~ 17usec after wakeup
Voltage Scale restored which takes ~20us
The code is in sleep.c in the SDK which has a lot more detail but at a high level this is what you need to know. The important part to understand here is where the “hooks” are and how to use them.
Use Sleep_initEx() to assign:
sleepCallback – called just before sleeping
restoreCallback – Return 0 to wake, 1 to sleep
wakeupCallback – called after waking
Sleep_initEx() input is a pointer to a structure with the three callbacks or NULL if not used
Define the function:
EMU_EM23PresleepHook()
EMU_EM23PostsleepHook()
These are both WEAK functions with nothing in them so if you define them then the compiler will install them
The two EMU_EM23* weak functions are run immediately before/after the Wait-For-Interrupt (WFI) instruction which is where the CPU sleeps. These are very low level functions and while you can use them I recommend using the callbacks from Sleep_initEx().
The SLEEP_initEx() function is the one we want to use and in particular the restoreCallback. The comments around the restoreCallback function talk about restoring the clocks but if the function returns a 0 the chip will wake up and if it returns a 1 then it will immediately go back to sleep which is what we want! You can use the other two hooks if you want but the restoreCallback is the key one since it will immediately put the chip back to sleep if everything is idle.
The key to using ANY of these function is that you CANNOT call ANY FreeRTOS functions! You cannot send any Z-Wave frames or call any Z-Wave function as they all require the RTOS. At this point in the wakeup processing the RTOS is not running! All you can do in these routines is to capture data and quickly decide if everything is idle and to go back to sleep. If there is more processing needed, then return 0 and wait for the event in the RTOS and process the data there. You also don’t want to spend too much time in these routines as it may interfere with the timing of the RTOS. A hundred microseconds is probably fine but longer you should wait for the HFXO.
In ApplicationInit() you will call Sleep_initEx() like this:
const SLEEP_Init_t sleepinit = {NULL, NULL, CheckSPI};
...
ZW_APPLICATION_STATUS ApplicationInit(EResetReason_t eResetReason) {
...
SLEEP_InitEx(&sleepinit); // call checkSPI() upon wakeup from EM2.
...
}
...
uint32_t CheckSPI(SLEEP_EnergyMode_t emode) {
uint32_t retval=0; // wake up by default
if (GPIO_IntGetEnabled() & 0x0000AAAA) { // Check SPI
GPIO_ODD_IRQHandler(); // service the GPIO interrupt
// wait for all the bytes to come in and compute checksum
NVIC->ICPR[0] = NVIC->ICPR[0]; //clear NVIC pending interrupts
if (!SPIDataError && !IsWakeupCausedByRtccTimeout()) {
retval=1; // go back to sleep!
}
}
return(retval); // 0=wakeup, 1=sleep
}
Recall that every second the FLiRS device has to check for a Z-Wave beam which is triggered by the RTCC timer. Thus the check for IsWakeupCausedByRtccTimer ensures that the beaming still works.
This scope shot shows the wake up processing of the ZGM130S:
SPISEL_N SPI chip select signal goes low triggering a GPIO_ODD interrupt
The chip wakes up, the HFRCO begins oscillating
HFRCO begins oscillating in a few microseconds
Once HFRCO is running, the peripherals are functional
SPI data can begin shifting once the HFRCO is running
The default HFRCO frequency is 19MHz but can be increased
Higher frequencies for HFRCO also may need more wait states for the CPU and will use more power
The WFI instruction that put the CPU to sleep is exited here
EMU_EM23PostSleepHook function is called if defined
After returning from PostSleepHook, the VSCALE is returned to full power which takes about 10usec
It is best to wait for the voltage to be powered up to ensure all logic is running at optimal speeds
EMU_EnterEM2 is exited and restoreCallback is called if initialized
This is the function where the ISR should be called to process data
If the data says things are idle and want to go back to sleep, return 1
If more analysis is needed, then return 0
Carefully clear the interrupt bits
First clear the peripheral Interrupt Flags
Then clear the NVIC Interrupt pending register
NVIC->ICPR[n]=NVIC->ICPR[n] where n is 0-1 depending on your interrupt
Make sure there aren’t other reasons to wake up fully
!IsWakeupCausedByRtccTimeout() is the 1s FLiRS interrupt
There may be other reasons to wake up which is application dependent
In this example the SPI data is being fetched from the USART at each toggle of the GPIO
The final toggle shows that the checksum was computed and the data is idle so go back to sleep
The chip returns back to sleep in a few more microseconds
Total processing time of this interrupt is less than 200usec which is a fraction of the time just waiting for the HFXO to stabilize
Much of that time is receiving and processing the SPI data
It is possible to sleep in under 50usec if the check for idle is quicker
If your peripheral processing will take significantly less than 500usec, then it may be more efficient to process the data using the HFRCO and not wait for the HFXO to power up. But if your application needs more processing, then you are probably better off waiting. Each application must make their own calculations to determine the most efficient path.
What About Sleeping Devices?
Fully sleeping devices (EM4 also known as RSS – Routing Sleeping Slaves) have entirely different wake/sleep processing. For sleeping slaves the processor and RAM have to be re-initialized and the chip essentially boots out of reset. All that initialization takes quite a bit of time – a few tens of milliseconds. If your device needs to do a lot of frequent checking of a sensor, then it might make more sense to force it to stay in EM2 by setting a Power Lock to PM_TYPE_PERIPHERAL. For more details on power locks see INS14259 section 7.6. Deciding which way to go is application specific so you have to make the calculations or measurements to find the right balance for your project.
This is a complex posting but I hope I’ve made it clear enough to enable you to optimize your application firmware. Let me know what you think by leaving a comment below.
This is a very specific posting for Z-Wave developers and specifically for those developing with the new 700 series chips. If you’re not a 700 series developer you can probably stop reading…
One of the challenges with using the Z-Wave developers kit is trying to figure out which pin is connected to what. Every pin of the ZGM130S can perform multiple functions but some pins are best used for certain things. This guide provides general recommendations, but these are not hard-and-fast rules. The ZGM130S provides a great deal of flexibility so feel free to explore the many options each pin and peripheral has to offer. I’m hoping I can guide you with some initial suggestions but feel free to delve into the details to find your ideal solution.
This guide is a compilation of a number of documents and while I’ve been thorough, I could easily have made a typo here or there. Please use the online documentation as the official reference and send me an email pointing out my error and I’ll fix it. I couldn’t possibly include every feature for every pin but the details are available in the reference documents below. The Decoder Ring below is an overview of the most commonly used features. The table below contains a lot of information, so you’ll need to view it on a computer with a big screen.
Reference Documents
ZGM130S ZGM130S Datasheet – See section 6 for the pin definitions EFR32XG13 Gecko Family Reference Manual – Each peripheral is detailed here UG381 ZGM130S Zen Gecko DevKit Users Guide – Section 3 describes connectors
ZGM130S GPIO Decoder Table
ZGM130S
GPIO port as described in the ZGM130S data sheet
Pin #
GPIO pin number of the ZGM130S SIP package
BRD4202A
Zen Gecko Developers kit board for the ZGM130S
BRD8029A
Button/LED board plugged into the WSTK EXP header for the sample apps
WSTK EXP
Pin number of the main WSTK board expansion header
WSTK
Main developers kit board with USB, LCD and Segger J-link debugger
The Pxx pins are the holes across the long side of the board
The Fxx pins are secondary functions that typically connect to the isolators
MiniDBG
Small 20 pin ribbon cable used to connect WSTK to a target DUT
ALT FUNCS
Alternate functions the GPIO can perform. All GPIOs can be simple digital 1/0s.
Some pins have special analog or peripheral functions.
Comments
Brief comments describing special functions of the GPIO
Description of the columns in the table below
General Purpose IOs – Use these for your application first
ZGM 130S
Pin #
BRD 4202A
BRD 8029A
WSTK EXP
WSTK
Mini DBG
ALT FUNCs
Comments
PD10
27
LED_R P201-35
P32
LED ON=low, Pullup Ideal for PWM
PD11
28
LED_G P201-37
P34
LED ON=low, Pullup
PD12
29
LED_B P200-3
P36
LED ON=low, Pullup
PC6
58
P201-4 P200-29
EXP4
P1 F16
Easy to use with WSTK since they are on EXP
PC7
59
P201-6
EXP6
P3
PF3
5
P201-13 P200-16
LED1
EXP13
P10
JTAG_TDI
PF4
6
P201-11 P200-23
LED0
EXP11
P8
PF6
8
P201-7 P200-25
BUTN0
EXP7
P4 F12
PC8
60
P201-8 P200-28
EXP8
P5 F15
PC9
61
P201-10
SW
EXP10
P7
PB14
46
P201-30
P27
LFXO – 32Khz osc crystal for accurate time
PB15
47
P201-32
P29
LFXO
PD9
26
P201-33
P30
PF5
7
P201-28 P200-24
P25 F11
PD13
30
P201-34 P200-31
P31 F18
OPA1P
Use for Analog functions
PD15
34
P201-38
P35
OPA1N
PA2
37
P201-3 P200-21
LED2
EXP3
P0 F8
OPA0P
PA4
39
P201-17
P14
OPA0N
PA5
40
P201-19 P200-18
P16 F5
VCOM_ENB Must be 1 for WSTK to pass USART0 to USB
Special Function Pins – Use these for their alternate function
ZGM 130S
Pin #
BRD 4202A
BRD 8029A
WSTK EXP
WSTK
Mini DBG
ALT FUNCs
Comments
PC10
62
P201-15
BUTN2
EXP15
P12
EM4WU12 I2C1_SDA
EM4WU pins are the ONLY pins that will wakeup from EM4
PC11
63
P201-16
BUTN3
EXP16
P13
I2C1_SCL
Use for I2C, will NOT wakeup from EM4
PD14
31
P201-36 P200-30
P33 F17
OPA1 EM4WU4
PF7
9
P201-9 P200-26
BUTN1
EXP9
P6 F13
EM4WU1
PA3
38
P201-5 P200-22
LED3
EXP5
P2 F9
VDAC0 OPA0 EM4WU8
PB11
41
P201-21 P200-34
P18 F21
OPA2P
PB12
42
P201-23 P200-33
P20 F20
10
OPA2
PTI_DATA Future Packet Trace debug
PB13
45
P201-25 P200-32
P22 F19
9
OPA2N EM4WU9
PTI_SYNC Always wire the 2 PTI pins on the ZG14 modem chip to GPIOs on your host CPU
Legend: WSTK = hole name (ZGM130 GPIO) EX: WSTK P100 pin 16 is hole P13, ZGM130S GPIO PC11, Button 3 on the BRD8029A BRD8029A is the Button/LED board. Functionality is: LEDs are ON when driven high BUTN pins are pulled up and go low when the button is pressed The SW can pull the pin either up or down depending on the slide setting left/on is 1, right/off is 0 thru 1MOhm resistors The VMCU powers the LEDs/Buttons but the board ID is powered via pin 20 Schematic is in Simplicity Studio
Mini-Simplicity Debug header: Top View
Name
Pin #
Pin #
Name
VAEM (3V3)
1
2
GND
RESET_N
3
4
VCOM_RX (PA1)
VCOM_TX (PA0)
5
6
SWO(PF2)
SWDIO(PF1)
7
8
SWCLK(PF0)
PTI_SYNC(PB13)
9
10
PTI_DATA(PB12)
On the DUT board with the ZGM130S on it, connect VCOM_RX to PA1 and VCOM_TX to PA0. The header is a 0.05” pitch 10 pin header. Typically use a Samtec FTSH-110 but to make the pads even smaller use just the pads for a thru-hole connector. See my post “700 series Debug Header” from October 2019 for more details on the debug header.
Recommendations
Remember that the GPIOs in all the Wireless Gecko chips from Silicon Labs are very flexible and most peripheral functions can be routed to almost any IO pin. That said, there are some pins that have fixed functions and some pins are best at certain other functions. Let’s start with the pins you can’t use.
Power Pins
Obviously, the power pins have to be connected to the proper voltage. The ZGM130 has a lot of ground pins so make sure every one of them is connected to a solid ground. The voltages for the power pins have a few rules but in most cases you’ll tie AVDD and VREGVDD to the same power source of 3.3V. The on-chip DC to DC regulator allows a wide voltage range on VREGVDD so there is some additional flexibility which requires careful consideration. But for most applications, tie these two power pins directly to the battery. Most of the time IOVDD is also tied to the battery though depending on other chips in your system you might need an LDO to keep the IOs at the proper voltage.
Debug Pins
The next set of pins you should not use for GPIOs are the debug pins. All ten IO pins on the Mini-Simplicity header should be wired up as shown in the table above. The UART pins are very important to print out debug information while the chip is running. The advantage here is that you can see things happening in real-time without using a scope or logic analyzer. And you can easily enable/disable blocks of debug statements as needed. The sample apps print all sorts of debug information so you’ll want to do the same in your code. The UART defaults to only 115200 baud but it’s easy to increase it up to roughly 1Mbaud to reduce the time impact of printing debug messages. Also, keep the messages short or else they may impact the timing so much that your code will fail. If you’re really in a pinch for one more IO, you could use the SWO or VCOM_RX pins as you probably don’t need them.
Special Function Pins
A number of pins have specific functions especially for certain analog functions. The ADC/DAC only have their primary and alternate IOs though you can route them thru the ABUS. Only a few of these pins can wake the chip from sleeping in EM4. Be very careful and utilize these pins for buttons or sensors that need to wake the chip up.
General Purpose IOs
The rest of the pins are available for any purpose. Most of the pins can be any digital IO function. Some pins are handy because of their connection on the DevKit. There are three IOs connected to an RGB LED on the 4202 board. These are really handy to visually observe PWM waveforms based on the color of the LED. The pins that are routed to the EXP header on the WSTK are easy to connect to a proto board. Be careful to avoid using PA5 as that is connected to the VCOM enable pin on the WSTK. PA5 has to be high to route the debug UART data to the USB bus. But this is a restriction only when using the DevKit 4202 board. If connecting to your own PCB via the Mini-Simplicity header you can freely use PA5.
Conclusion
The ZGM130S is a flexible chip with plenty of compute power, RAM and Flash. The GPIOs can largely be routed from any peripheral to any IO though there are some restrictions. The secret decoder ring given here maps out which pin can do what and which ones should be used for your application. This is only a guide and the chip has many more features than I can describe here. Refer to the Reference Documents for more in depth knowledge.