Within our EmberZNet and Silicon Labs Thread stacks we provide a number of pre-built NCP images. However, with the customability EFR32 Mighty Gecko, these NCP images don't always meet every application. This guide, along with reading AN1010: Building a Customized NCP Application, should give you the tools to build your own xNCP image.
Go to File -> New -> Project. This will bring up the New Project Wizard
Give your project a name, leave it in the default location. Click Next.
On the Project Setup Window remove any boards that are selected in the top section. In the bottom section select the chip you are using. Hit Finish.
Download the board header below for your particular stack and copy it into your project (you can drag and drop it into your Project in Studio, when prompted, make sure to Copy the file into your project).
EmberZNet 5.9.2 and prior: xNCP_board.h
EmberZNet 5.10.0 and later: xNCP_board_5.10.x.h
On the General Tab
Selected Architecture – verify the chip you selected is there
On the HAL Tab
Change Board Header from Default to Use Custom Board Header
Point the Custom Board Header to file you downloaded in step 8 (it should be in your Studio v4 Workspace)
On the Plugins Tab
In the Core section pick the Plug for either NCP-SPI or NCP-UART for the NCP version you are using
If you are building a Smart Energy NCP, you will need to enable the CBKE and ECC plugins required for your build.
On the Other Tab
(EmberZNet 5.9.2 and prior only) In the Additional .c and .h files section Add the following directories:
Open the board header file from step 8 and make these changes:
(EmberZNet 5.9.2 and prior)
Find the #define statements for which build to use
#define UART_XNCP_BUILD
#define SPI_XNCP_BUILD
Comment out the one you aren’t using and make sure the one you need is defined
Modify the section to match the interface you have selected. For UART, setup the Tx, Rx, CTS and RTS pins. For SPI, setup MOSI, MISO, CS and CLK as well as the nHOST, nWAKE and nSSEL (CS) pins.
See below for where to find ROUTELOC definitions to match these pins.
(EmberZNet 5.10.x)
If you are building a UART NCP, edit the section titled /* USART0 */. Setup Tx, Rx, CTS and RTS pins that you are using for your NCP.
See below for where to find ROUTELOC definitions to match these pins.
If you are building a SPI NCP, edit the section titled /* USART1 */. Setup the MOSI, MISO, CS and CLK pins.
Additonally, edit the section titled /* SPINCP */. You shouldn't have to change the USART port, but match the nHOST and nWAKE pins to your design.
See below for where to find ROUTELOC definitions to match these pins.
You can get the ROUTELOC definitions from the Mighty Gecko datasheet corresponding to your model of Mighty Gecko (MG1, MG12 or MG13). Links to the datasheets are below.
In Zigbee project, you can find lots of prebuild CLI commands can be used for debugging. It is very convenient for every engineer to develop their product. If you type “help” on console, you can find the below CLI commands, it includes but not limited to:
bsend
changekey
debugprint
echo
endpoint
events
help
info
interpan
keys
libs
network
option
plugin
print
raw
read
reset
security
send
send-using-multicast-binding
send_multicast
timesync
version
write
zcl
zdo
You can find the details/descriptions for every CLI command in the following documentation after you install the stack. Use your browser to open this or Simplicity studio relevant relative path like this one.
But for some customers, they would like to customize their custom CLI commands to implement some special functions, such as control the peripheral or sending some special command to other devices. In this situation, how to create the custom CLI commands base on the current CLI architecture?
The answer is easy. It is very easy to extend the custom CLI commands with following steps:
Enable the “Add Custom CLI Sub-menu” checkbox in “Printing and CLI” tab in your {project}.isc.
Then you should implement the emberAfCustomCommands[] in your {project}_callback.c file. There is a good example in the XncpLedHost_callback.c, please refer to the XncpLedHost sample. The key point is to implement the functions in emberAfCustomCommands[]. Here is the details as follows:
EmberCommandEntry emberAfCustomCommands[] = {
emberCommandEntryAction("get-led",
getLedCommand,
"",
"Get the state of an LED on the NCP."),
emberCommandEntryAction("set-led",
setLedCommand,
"u",
"Set the state of an LED on the NCP using a custom LED protocol command."),
emberCommandEntryAction("get-frequency",
getFrequencyCommand,
"",
"Get the current frequency of the LED strobe on the NCP."),
emberCommandEntryAction("set-frequency",
setFrequencyCommand,
"w",
"Set the frequency of the LED strobe on the NCP."),
emberCommandEntryAction("get-info",
getInfoCommand,
"",
"Display the XNCP information on the CLI."),
emberCommandEntryTerminator()
};
After doing that, compile the project and download the firmware to your hardware, launch the console and then you can see the “custom” CLI commands after you type the “help”. That is all steps to create the custom CLI command. Please feel free to contact us if you have further questions.
Types of input and their character representations:
In case of normal (non-nested) commands, argumentTypes is a string that specifies the number and types of arguments the command accepts. The argument specifiers are:
u: one-byte unsigned integer.
v: two-byte unsigned integer
w: four-byte unsigned integer
s: one-byte signed integer
r: two-byte signed integer
q: four-byte signed integer
b: string. The argument can be entered in ascii by using quotes, for example: "foo". Or it may be entered in hex by using curly braces, for example: { 08 A1 f2 }. There must be an even number of hex digits, and spaces are ignored.
*: zero or more of the previous type. If used, this must be the last specifier.
?: Unknown number of arguments. If used this must be the only character. This means, that command interpreter will not perform any validation of arguments, and will call the action directly, trusting it that it will handle with whatever arguments are passed in.
!: Optional argument delimiter.
If the command input has sufficient arguments such that the parser ends on a ! symbol, then the command will be considered valid, even if it does not necessarily process the entire argumentTypes string. If there are additional arguments beyond a !, but still fewer arguments than the next either the next ! or the end of the string, then the command will be considered invalid.
Note that this leaves the called CommandAction function to actually validate what number of optional arguments it actually got.
Example: Given a argumentTypes String: uu!vv!u!vv
The following inputs type orders are valid:
uu, uuvv, uuvvu, uuvvuvv
The following are invalid:
u, uuv, uuvvuv, uuvvuvvv
Integer arguments can be either decimal or hexidecimal.
A 0x prefix indicates a hexidecimal integer. Example: 0x3ed.
In case of a nested command (action is NULL), then this field contains a pointer to the nested EmberCommandEntry array.
Accepting CLI arguments in functions
Arguments can be passed along with CLI calls based on the type of input. These arguments are captured through relevant function call to:
1. uint32_t emberUnsignedCommandArgument(uint8_t argNum)
2. int32_t emberSignedCommandArgument(uint8_t argNum)
3. uint8_t *emberStringCommandArgument(int8_t argNum, uint8_t *length)
4. For special data types such as EUI64 address if a devuce, use emberCopyBigEndianEui64Argument(int8_t index, EmberEUI64 destination)
5. To copy string arguments, uint8_t emberCopyStringArgument(int8_t argNum,
uint8_t *destination,
uint8_t maxLength,
bool leftPad)
Example: uint8_t enable = (uint8_t)emberSignedCommandArgument(0);
When preparing EM35x devices for field deployments, it is often desirable to secure the flash contents of the EM35x chip to prevent accidental/unauthorized access or modification. This can be done using the chip’s memory protection (Read Protection and Write Protection) mechanism, described in the EM35x Datasheet in Sections 5.2.1 (Flash Memory) and 5.3 (Memory Protection Unit).
Below are some of the common questions that customers ask when considering this kind of protection for their devices:
Q: What kinds of protection are available and what is protected by them?
A: The chip offers Read Protection and Write Protection.
Read Protection, when enabled, disconnects all flash from everything else when the chip’s SerialWire/JTAG interface (SWJ) is connected to something. This effectively prevents reading of all flash memory on the device, including the full 128KB or 192KB of main flash block (which covers the bootloader area, application code & data areas, and SimEEPROM token area), plus the FIB (flash information block where Ember-programmed manufacturing tokens and low-level flash read/write routines are stored) and the CIB (customer information block where customer-programmable manufacturing tokens are stored). This also prevents the use of the SWJ bus for SerialWire and JTAG operations such as debugger access and flash programming. Since read protection can only be disabled by writing a specific, non-zero, non-0xFF value to a specific location, the act of erasing of the CIB memory page (where the read protection option byte is contained), whether intentional or accidental, will still leave the chip read-protected until the appropriate option byte is set to the appropriate value.
Write Protection, when enabled, prevents writing or erasing of the main flash block [MFB], either by external means or through execution of code from flash or RAM. Unlike read protection, write protection is enabled on a per-region basis with each region being 4 pages of flash or 8KB.
Q: What kind of protection does Ember recommend using for deployed devices into mass production?
A: For devices that are deployed into the field in scenarios where no further debug or advanced testing is required, Ember recommends enabling Read Protection (which is chip-wide) as well as Write Protection of the first 8KB region, which is the section of the MFB where the bootloader firmware resides.
Q: How do I enable these recommended protection settings using the ISA3 and ISA3 Utilities?
A: Enabling these settings requires the use of the ISA3 Utilities from the command line; InSight Desktop does not currently provide an interface for passing these options to the loader through its GUI.
Enabling Write Protection
To enable write protection of the first region of main flash (where the bootloader resides), clear (write 0) only Bit 0 of the first option byte for write protection (Option Byte 4) and leave all other bits set (erased state of 1) for a final bitmask of 0xFFFFFE (0xFFFFFFFE for any chips with 512 KB of flash). This can be accomplished with the “—programwrprot” option in em3xx_load or em3xx_buildimage such as:
em3xx_load.exe --programwrprot FFFFFE
Note that current Ember implementations are such that write protection of this first region is currently done automatically whenever read protection is enabled. However, setting the write protection mask explicitly to include this first flash region is recommended to ensure consistent results should this automatic behavior change in future tool/silicon revisions.
Enabling Read Protection
NOTE: Enabling read protection should always be the last operation you perform on the device with em3xx_load or em3xx_buildimage since setting this option effectively inhibits any future changes to the chip/image state until read protection is disabled (which, in turn, causes the MFB and CIB to be erased).
To enable read protection, Option Byte 0 of the CIB can be set to 0×00 (though any value other than the special value of 0xA5 will suffice). This can be done using the “—enablerdprot” flag in em3xx_load or em3xx_buildimage, such as:
em3xx_buildimage.exe --em357 --chipimage myimage.hex serial-uart-bootloader.s37 sensor.ebl --enablerdprot
This builds an EM357 chip image output file, myimage.hex, from the two input files, serial-uart-bootloader.s37 and sensor.ebl. At the same time, read protection is enabled in the CIB content of the HEX file by setting option byte 0 to the value 0×00. Programming this chip image (the HEX file) to a fresh device will ensure that it contains the necessary application code, bootloader code and read protection. Additional manufacturing token content in the CIB can be set using the “—cibtokenspatch” argument with a manufacturing tokens patch file (as explained by the “—cibtokenspatch-help” argument to em3xx_buildimage or em3xx_load).
Q: If I enable write protection, how will that affect the bootloader?
A: (Note that the following applies to all of the bootloader types offered by Ember.) By write-protecting the first 8KB portion of main flash, where the bootloader resides, you prevent accidental/unauthorized overwrites of the bootloader code and the chip’s reset vectors. However, if regions beyond this are write-protected, this will prevent the bootloader from writing the downloaded firmware image into the application area of the MFB, thus rendering it ineffective. This is why Ember recommends leaving write protection disabled for the remaining flash regions if a bootloader is used in the memory map.
If, for some reason, you wish to deploy a device that doesn’t allow bootloading, you may protect additional regions of the MFB. However, take care not to enable write protection over the area used for Simulated EEPROM, usually the last 8KB region of the MFB (or the last 32KB in some EZSP network coprocessor designs), as this will prevent the stack from writing to the network and security-related tokens that it requires as part of normal operation.
Q: What about the areas that aren't covered by the write protection settings? Aren't they vulnerable to writes from an external debugger/programmer then?
A: Yes, areas that are not covered by write protection are potentially vulnerable to erasure and writing from an external debugger/programmer or from errant code executing flash-writing routines, even if read protection is enabled. Read protection will prevent reading of the flash, but the erasing and writing occurs through a flash interface controller, which is never disconnected and is capable of working without needing to read. (Note that Ember’s programming tools will prohibit writing/erasing of the flash when read protection is found to be active, which prevents accidental or malicious corruption of flash data when using Ember’s tools.) Therefore, the safest and most secure mode of operation is to write protect all sensitive areas of flash, except the Simulated EEPROM which must remain writable, and enable read protection. (As discussed above, write-protecting flash regions covered by application code will inhibit updating of the code via the bootloader.)
Q: What happens if there is a failure, such as reset, while writing an option byte?
A: If the option bytes themselves were to somehow become corrupted, the chip has a means to detect this state and will only boot into deep sleep mode until the failure is corrected through erasing/reprogramming of the CIB memory page. When corruption is detected, the option bytes are assumed to be the erased state, which will activate read protection. Ember’s em3xx_load tool can detect this failure/corruption, and using the “—fixobfail” argument with this tool will fix the issue.
Q: What kinds of debugging mechanisms will still be available on a device that has read and write protection enabled in the recommended configuration?
A: The DEI Port features (which are just TTL interfaces to the GPIOs) of the ISA3 and the PacketTrace Interface [PTI] features (which use alternate functions of the GPIOs for a digital, 2-wire protocol) of the ISA3 are still viable even when Read Protection is enabled. Additionally, normal digital I/O and serial controller usage remain possible when read protection and/or write protection are enabled.
Q: What about the Virtual UART interface (Serial 0 in InSight Desktop Console)?
A: Since the Virtual UART mechanism is implemented on top of the ARM Cortex’s SerialWire protocol, which uses the SerialWire/JTAG [SWJ] bus, it isn’t available when read protection is enabled. Read protection and SWJ bus access are mutually exclusive. However, you can still utilize the physical UART of the chip (TXD and RXD pins, PB1 and PB2) if the chip’s running firmware enables it. These TTL signals can be routed through the DEI interface of the ISA3 for access as “Serial 1” in the InSight Desktop Console as illustrated on the EM35x Breakout Board hardware.
Q: If I enable read and write protection, can I disable them later?
A: Yes, it’s possible to disable read protection and/or write protection using the ISA3 Utilities.
Disabling read protection is accomplished through the use of the “—disablerdprot” command argument with em3xx_load or em3xx_buildimage, which causes Option Byte 0 to be set to the special value of 0xA5. Any other state for Option Byte 0 causes read protection to remain active. Note that disabling this feature on an actual chip (with em3xx_load) will cause its MFB and CIB (besides Option Byte 0) to be fully erased back to 0xFF bytes.
While enabling read protection with em3xx_load requires a file to be specified in the command, disabling read protection does not include a file in the command:
C:\>em3xx_load my_file.s37 --enablerdprot
C:\>em3xx_load --disablerdprot
In addition, depending on your version of Windows, em3xx_load may need to be explicitly run in Admin mode.
Disabling write protection is accomplished using the “—programwrprot” command argument to set the write protection option bytes back to an all-0xFF state, such as “em3xx_load —programwrprot FFFFFF”. (Note that a “programmed” state of 0xFFFFFF is handled differently than an erased [unprogrammed] state, since checksum values for each option byte are also programmed by the ISA3 Utilities when an option bye is programmed. Once an option byte is programmed, the CIB must be erased before that option byte’s value can be changed.)
Q: After disabling read protection, is anything NOT erased?
A: Yes, the FIB (where Ember-programmed manufacturing tokens are stored) is left intact after read protection has been disabled. The MFB and CIB are not preserved when read protection has been disabled. Although the chip’s automatic erasure during deactivation of read protection only affects the MFB (where stack and application tokens reside along with bootloader and stack/application firmware), the act of patching the option bytes in the CIB to deactivate read protection requires that the entire CIB page be erased and re-written (as erasures can only occur on a per-page basis), and since the existing CIB content is unreadable until the unprotected state (value 0xA5 for Option Byte 0) is written, the newly written CIB page resulting from the CIB patching process must consist of fully erased bytes (other than Option Byte 0), meaning that none of the original CIB content can be preserved.
We usually choose an external SPI flash for devices to storage firmware during OTA. For EFR32MGXX device, we configure USART1 as SPI to connect with the external SPI flash. So you can find a SPI master driver (btl_driver_spi.c) for the external SPI flash in Gecko Bootloader.
If you are interested in the SPI master driver source code, you will find the CS is controlled manually by software rather than being controlled directly by the USAR1.
Let's go through the source code btl_driver_spi.c. Please look at the function spi_init(void) in C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.1\platform\bootloader\driver\ btl_driver_spi.c
From above source code, you can find the function spi_init(void) in btl_driver_spi.c, which initial the SPI TX/RX/CLK. Both the registers ROUTEPEN and ROUTELOC0 are configured for these three pins. However, ROUTEPEN and ROUTELOC0 are not configured for CS. Instead, it is controlled manually by software.
In C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.1\platform\bootloader\driver\ btl_driver_spi.c
So far, you may have a concern why is the CS controlled manually by software rather than being controlled directly by the USAR1. The answer is:
The SPI master driver doesn’t use DMA. This means that if the AUTOCS functionality is used, CS will go high and low again between every single byte that is transmitted (because the hardware doesn’t know that there will be another byte, since software hasn’t put it in the FIFO). This doesn’t work with most SPI slaves/protocols, since they expect CS to go low at the start of a packet, and high at the end after multiple bytes. Therefore, CS is controlled by software.
A step-by-step guide to creating, building, and running your own Router Eligible End Device (REED) application based on the Silicon Labs Thread stack. Before tackling this tutorial, please checkout "Building Thread Sample Applications" tutorial first.
I. Launch Simplicity Studio and start a blank application
1. Make sure at least two nodes are present with EFR32s under Devices.
2. Go to File -> New -> Silicon Labs AppBuilder Project.
3. Select Silicon Labs Thread 2.7.1.
4. Check on "Start with a blank application". Click Next.
5. Name your project. For example ThreadReed271BRD4162A.
6. In next window (Project Setup), check if Simplicity Studio detected correct board, part, and toolchain. In this example we're using BRD4162A, EFR32MG12P332F1024GL125, and IAR ARM 7.80.
II. Configuring REED
1. Under the "General" tab:
a. Update the "Device name" to project's name (ie ThreadReed271BRD4162A).
b. Open "Device type" dialog:
i. Select EFR32 and add device to "Selected devices and plugins".
ii. Select SoC and add device to "Selected devices and plugins".
iii. Select Router and add device to "Selected devices and plugins".
iv. Close dialog by clicking OK.
2. Under the "HAL" tab:
a. Set Bootloader to Application type.
b. Set to Use Hardware Configurator.
3. Open Hardware Configurator
a. Under DefaultMode Peripherals tab
i. Check on GPIO, set SWO pin to PF2
ii. Check on Serial, set Port to USART0
iii. Check on Virtual COM Port, set enable pin to PA5
4. Save HWCONF file by going to File -> Save and go back to your project's ISC file.
5. Under the "Printing" tab:
a. Make sure "Enable debug printing" is checked.
b. Make sure under functional area Core and Application are checked in both "Compiled in" and Enabled at startup".
6. Under the "ZCL over IP" tab, we do not have anything to add.
7. Under the "Plugins" tab:
a. Add CoAP Debug under the Common section. This will give us CoAP debug output in the console.
b. Add ICMP Debug under the Common section. This will give us ICMP debug output in the console.
c. Add Serial Plugin (if not already added), and set port to USART0.
d. Add Debug JTAG and remove Debug JTAG stub.
e. Add Radio Coexistence to cover dependencies in HAL library.
8. Under the "Callbacks" tab:
a. Select emberFormNetworkReturn - check "Is Used"; Stub should be check automatically.
b. Select emberJoinNetworkReturn.
c. Select emberResetNetworkStateReturn.
d. Select emberResumeNetworkReturn.
9. Under the "Other" tab, we do not have anything to add.
10. Click "Generate". Notice project appeared in Project Explorer. Click OK.
11. Save ISC file.
III. Add Code and Build Projects
1. Go to Simplicity IDE perspective. In Project Explorer, expand your Reed project.
2. Add the following ifdef to thread-callbacks.c to enable debug printing.
3. Add the following code to thread-callbacks.c file. The functions should already be available after generating the project through AppBuilder. This will give us some useful output in serial console.
4. Compile your project by right-clicking on project name and using "Build project" option.
5. Make sure your build is successful and the compiled binary is located in project directory tree under "IAR ARM - Default" folder.
IV. Load Application and Bootloader to EFR32MG module on WSTK
1. As described in "Building Thread Sample Applications" section 7. Load the Reed application and bootloader to two available devices.
(To build a specific bootloader check out UG266 and AN1048.)
V. Adding nodes to a network using pre-commissioning
1. In Network Analyzer perspective, in the Devices view, right-click on a node and select "Connect" then right-click again and select "Launch Console".
a. Navigate to "Serial 1" tab and press the return key a few times to get a prompt.
b. Find out the state of your device using the "Info" command. The output should output network status of 0x00 (EMBER_NO_NETWORK).
c. If your device has an ip address, reset the network parameters by issuing the command:
network-management reset
2. For the first device on the network we will need to form the network
a. Set the master key issuing command:
network-management form <channel:1> <power:1> <node type:1> [<network id:0--16> [<ula prefix>]
Example:
network-management form 25 3 2 "Honey Badger" "FD00:0DB8::/64"
c. Check network status using the info command. Network status should be 0x03 (EMBER_JOINED_NETWORK_ATTACHED).
3. For the second node (or any node after)
a. In the "Serial 1" console make sure the node is not already in a network.
b. Set Commissioning information for the device. Note the PAN ID, Extended PAN ID, and Network ID are set by the Leader (our first node on the network). Use the info command on the Leader node to get proper parameters for the network. Gather the channel, channel mask (0x0C00), network id, ula prefix, extended pan id, master key (from above command), and pan id.
To use VCOM_RX and VCOM_TX through the 10-pin Mini Simplicity connector (section 4.1.1 of AN958), make the following edits in your project's ISC (App Builder) and HWCONF (Hardware Configurator):
Switch WSTK to DBG OUT in "Device configuration..." (right-click on node in Devices.)
Set Serial Plugin to USART0.
Set hwConf USART0 to Asynchronous, 115200, No flow Control.
Set hwConf Serial to USART0, set USART0 for serial to TRUE.
Save the HWCONF file and generate the AppBuilder project.
After compiling and flashing the firmware to the BRD4162A, do a hard reset of the WSTK by unplugging it and plugging it in again. This way the board controller is aware of the serial change. Open the Serial Console in Simplicity Studio and hit enter a few times under the Serial 1 tab.
Zigbee & Thread Knowledge Base
Make customized ZigBee xNCP images for EFR32MG parts
Within our EmberZNet and Silicon Labs Thread stacks we provide a number of pre-built NCP images. However, with the customability EFR32 Mighty Gecko, these NCP images don't always meet every application. This guide, along with reading AN1010: Building a Customized NCP Application, should give you the tools to build your own xNCP image.
EmberZNet 5.9.2 and prior: xNCP_board.h
EmberZNet 5.10.0 and later: xNCP_board_5.10.x.h
See below for where to find ROUTELOC definitions to match these pins.
See below for where to find ROUTELOC definitions to match these pins.
Additonally, edit the section titled /* SPINCP */. You shouldn't have to change the USART port, but match the nHOST and nWAKE pins to your design.
See below for where to find ROUTELOC definitions to match these pins.
Use the following KBA for building a bootloader:
Make customized ZigBee bootloader for the EFR32MG1 QFN32 parts
Additional Information:
AN1010: Building a Customized NCP Application
EFR32MG1 Mighty Gecko ZigBee & Thread SoC Family Data Sheet (Section 6.4)
EFR32MG12 Mighty Gecko Multi-Protocol Wireless SoC Family Data Sheet (Section 6.4)
EFR32MG13 Mighty Gecko Multi-Protocol Wireless SoC Family Data Sheet (Section 6.6)
How to create custom CLI commands in EmberZNet?
In Zigbee project, you can find lots of prebuild CLI commands can be used for debugging. It is very convenient for every engineer to develop their product. If you type “help” on console, you can find the below CLI commands, it includes but not limited to:
You can find the details/descriptions for every CLI command in the following documentation after you install the stack. Use your browser to open this or Simplicity studio relevant relative path like this one.
But for some customers, they would like to customize their custom CLI commands to implement some special functions, such as control the peripheral or sending some special command to other devices. In this situation, how to create the custom CLI commands base on the current CLI architecture?
The answer is easy. It is very easy to extend the custom CLI commands with following steps:
Types of input and their character representations:
In case of normal (non-nested) commands, argumentTypes is a string that specifies the number and types of arguments the command accepts. The argument specifiers are:
If the command input has sufficient arguments such that the parser ends on a ! symbol, then the command will be considered valid, even if it does not necessarily process the entire argumentTypes string. If there are additional arguments beyond a !, but still fewer arguments than the next either the next ! or the end of the string, then the command will be considered invalid.
Note that this leaves the called CommandAction function to actually validate what number of optional arguments it actually got.
Example: Given a argumentTypes String: uu!vv!u!vv
The following inputs type orders are valid:
uu, uuvv, uuvvu, uuvvuvv
The following are invalid:
u, uuv, uuvvuv, uuvvuvvv
Integer arguments can be either decimal or hexidecimal.
A 0x prefix indicates a hexidecimal integer. Example: 0x3ed.
In case of a nested command (action is NULL), then this field contains a pointer to the nested EmberCommandEntry array.
Accepting CLI arguments in functions
Arguments can be passed along with CLI calls based on the type of input. These arguments are captured through relevant function call to:
Enabling Read Protection or Write Protection for EM35x Chips
When preparing EM35x devices for field deployments, it is often desirable to secure the flash contents of the EM35x chip to prevent accidental/unauthorized access or modification. This can be done using the chip’s memory protection (Read Protection and Write Protection) mechanism, described in the EM35x Datasheet in Sections 5.2.1 (Flash Memory) and 5.3 (Memory Protection Unit).
Below are some of the common questions that customers ask when considering this kind of protection for their devices:
Q: What kinds of protection are available and what is protected by them?
A: The chip offers Read Protection and Write Protection.
Read Protection, when enabled, disconnects all flash from everything else when the chip’s SerialWire/JTAG interface (SWJ) is connected to something. This effectively prevents reading of all flash memory on the device, including the full 128KB or 192KB of main flash block (which covers the bootloader area, application code & data areas, and SimEEPROM token area), plus the FIB (flash information block where Ember-programmed manufacturing tokens and low-level flash read/write routines are stored) and the CIB (customer information block where customer-programmable manufacturing tokens are stored). This also prevents the use of the SWJ bus for SerialWire and JTAG operations such as debugger access and flash programming. Since read protection can only be disabled by writing a specific, non-zero, non-0xFF value to a specific location, the act of erasing of the CIB memory page (where the read protection option byte is contained), whether intentional or accidental, will still leave the chip read-protected until the appropriate option byte is set to the appropriate value.
Write Protection, when enabled, prevents writing or erasing of the main flash block [MFB], either by external means or through execution of code from flash or RAM. Unlike read protection, write protection is enabled on a per-region basis with each region being 4 pages of flash or 8KB.
Q: What kind of protection does Ember recommend using for deployed devices into mass production?
A: For devices that are deployed into the field in scenarios where no further debug or advanced testing is required, Ember recommends enabling Read Protection (which is chip-wide) as well as Write Protection of the first 8KB region, which is the section of the MFB where the bootloader firmware resides.
Q: How do I enable these recommended protection settings using the ISA3 and ISA3 Utilities?
A: Enabling these settings requires the use of the ISA3 Utilities from the command line; InSight Desktop does not currently provide an interface for passing these options to the loader through its GUI.
Enabling Write Protection
To enable write protection of the first region of main flash (where the bootloader resides), clear (write 0) only Bit 0 of the first option byte for write protection (Option Byte 4) and leave all other bits set (erased state of 1) for a final bitmask of 0xFFFFFE (0xFFFFFFFE for any chips with 512 KB of flash). This can be accomplished with the “—programwrprot” option in em3xx_load or em3xx_buildimage such as:
em3xx_load.exe --programwrprot FFFFFE
Note that current Ember implementations are such that write protection of this first region is currently done automatically whenever read protection is enabled. However, setting the write protection mask explicitly to include this first flash region is recommended to ensure consistent results should this automatic behavior change in future tool/silicon revisions.
Enabling Read Protection
NOTE: Enabling read protection should always be the last operation you perform on the device with em3xx_load or em3xx_buildimage since setting this option effectively inhibits any future changes to the chip/image state until read protection is disabled (which, in turn, causes the MFB and CIB to be erased).
To enable read protection, Option Byte 0 of the CIB can be set to 0×00 (though any value other than the special value of 0xA5 will suffice). This can be done using the “—enablerdprot” flag in em3xx_load or em3xx_buildimage, such as:
em3xx_buildimage.exe --em357 --chipimage myimage.hex serial-uart-bootloader.s37 sensor.ebl --enablerdprot
This builds an EM357 chip image output file, myimage.hex, from the two input files, serial-uart-bootloader.s37 and sensor.ebl. At the same time, read protection is enabled in the CIB content of the HEX file by setting option byte 0 to the value 0×00. Programming this chip image (the HEX file) to a fresh device will ensure that it contains the necessary application code, bootloader code and read protection. Additional manufacturing token content in the CIB can be set using the “—cibtokenspatch” argument with a manufacturing tokens patch file (as explained by the “—cibtokenspatch-help” argument to em3xx_buildimage or em3xx_load).
Q: If I enable write protection, how will that affect the bootloader?
A: (Note that the following applies to all of the bootloader types offered by Ember.) By write-protecting the first 8KB portion of main flash, where the bootloader resides, you prevent accidental/unauthorized overwrites of the bootloader code and the chip’s reset vectors. However, if regions beyond this are write-protected, this will prevent the bootloader from writing the downloaded firmware image into the application area of the MFB, thus rendering it ineffective. This is why Ember recommends leaving write protection disabled for the remaining flash regions if a bootloader is used in the memory map.
If, for some reason, you wish to deploy a device that doesn’t allow bootloading, you may protect additional regions of the MFB. However, take care not to enable write protection over the area used for Simulated EEPROM, usually the last 8KB region of the MFB (or the last 32KB in some EZSP network coprocessor designs), as this will prevent the stack from writing to the network and security-related tokens that it requires as part of normal operation.
Q: What about the areas that aren't covered by the write protection settings? Aren't they vulnerable to writes from an external debugger/programmer then?
A: Yes, areas that are not covered by write protection are potentially vulnerable to erasure and writing from an external debugger/programmer or from errant code executing flash-writing routines, even if read protection is enabled. Read protection will prevent reading of the flash, but the erasing and writing occurs through a flash interface controller, which is never disconnected and is capable of working without needing to read. (Note that Ember’s programming tools will prohibit writing/erasing of the flash when read protection is found to be active, which prevents accidental or malicious corruption of flash data when using Ember’s tools.) Therefore, the safest and most secure mode of operation is to write protect all sensitive areas of flash, except the Simulated EEPROM which must remain writable, and enable read protection. (As discussed above, write-protecting flash regions covered by application code will inhibit updating of the code via the bootloader.)
Q: What happens if there is a failure, such as reset, while writing an option byte?
A: If the option bytes themselves were to somehow become corrupted, the chip has a means to detect this state and will only boot into deep sleep mode until the failure is corrected through erasing/reprogramming of the CIB memory page. When corruption is detected, the option bytes are assumed to be the erased state, which will activate read protection. Ember’s em3xx_load tool can detect this failure/corruption, and using the “—fixobfail” argument with this tool will fix the issue.
Q: What kinds of debugging mechanisms will still be available on a device that has read and write protection enabled in the recommended configuration?
A: The DEI Port features (which are just TTL interfaces to the GPIOs) of the ISA3 and the PacketTrace Interface [PTI] features (which use alternate functions of the GPIOs for a digital, 2-wire protocol) of the ISA3 are still viable even when Read Protection is enabled. Additionally, normal digital I/O and serial controller usage remain possible when read protection and/or write protection are enabled.
Q: What about the Virtual UART interface (Serial 0 in InSight Desktop Console)?
A: Since the Virtual UART mechanism is implemented on top of the ARM Cortex’s SerialWire protocol, which uses the SerialWire/JTAG [SWJ] bus, it isn’t available when read protection is enabled. Read protection and SWJ bus access are mutually exclusive. However, you can still utilize the physical UART of the chip (TXD and RXD pins, PB1 and PB2) if the chip’s running firmware enables it. These TTL signals can be routed through the DEI interface of the ISA3 for access as “Serial 1” in the InSight Desktop Console as illustrated on the EM35x Breakout Board hardware.
Q: If I enable read and write protection, can I disable them later?
A: Yes, it’s possible to disable read protection and/or write protection using the ISA3 Utilities.
Disabling read protection is accomplished through the use of the “—disablerdprot” command argument with em3xx_load or em3xx_buildimage, which causes Option Byte 0 to be set to the special value of 0xA5. Any other state for Option Byte 0 causes read protection to remain active. Note that disabling this feature on an actual chip (with em3xx_load) will cause its MFB and CIB (besides Option Byte 0) to be fully erased back to 0xFF bytes.
While enabling read protection with em3xx_load requires a file to be specified in the command, disabling read protection does not include a file in the command:
In addition, depending on your version of Windows, em3xx_load may need to be explicitly run in Admin mode.
Disabling write protection is accomplished using the “—programwrprot” command argument to set the write protection option bytes back to an all-0xFF state, such as “em3xx_load —programwrprot FFFFFF”. (Note that a “programmed” state of 0xFFFFFF is handled differently than an erased [unprogrammed] state, since checksum values for each option byte are also programmed by the ISA3 Utilities when an option bye is programmed. Once an option byte is programmed, the CIB must be erased before that option byte’s value can be changed.)
Q: After disabling read protection, is anything NOT erased?
A: Yes, the FIB (where Ember-programmed manufacturing tokens are stored) is left intact after read protection has been disabled. The MFB and CIB are not preserved when read protection has been disabled. Although the chip’s automatic erasure during deactivation of read protection only affects the MFB (where stack and application tokens reside along with bootloader and stack/application firmware), the act of patching the option bytes in the CIB to deactivate read protection requires that the entire CIB page be erased and re-written (as erasures can only occur on a per-page basis), and since the existing CIB content is unreadable until the unprotected state (value 0xA5 for Option Byte 0) is written, the newly written CIB page resulting from the CIB patching process must consist of fully erased bytes (other than Option Byte 0), meaning that none of the original CIB content can be preserved.
Why is the CS controlled manually by software rather than being controlled directly by the USAR1 in SPI driver for Gecko Bootloader?
We usually choose an external SPI flash for devices to storage firmware during OTA. For EFR32MGXX device, we configure USART1 as SPI to connect with the external SPI flash. So you can find a SPI master driver (btl_driver_spi.c) for the external SPI flash in Gecko Bootloader.
If you are interested in the SPI master driver source code, you will find the CS is controlled manually by software rather than being controlled directly by the USAR1.
Let's go through the source code btl_driver_spi.c. Please look at the function spi_init(void) in C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.1\platform\bootloader\driver\ btl_driver_spi.c
From above source code, you can find the function spi_init(void) in btl_driver_spi.c, which initial the SPI TX/RX/CLK. Both the registers ROUTEPEN and ROUTELOC0 are configured for these three pins. However, ROUTEPEN and ROUTELOC0 are not configured for CS. Instead, it is controlled manually by software.
In C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.1\platform\bootloader\driver\ btl_driver_spi.c
In C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.1\platform\bootloader\plugin\storage\spiflash\btl_storage_spiflash.c
So far, you may have a concern why is the CS controlled manually by software rather than being controlled directly by the USAR1. The answer is:
The SPI master driver doesn’t use DMA. This means that if the AUTOCS functionality is used, CS will go high and low again between every single byte that is transmitted (because the hardware doesn’t know that there will be another byte, since software hasn’t put it in the FIFO). This doesn’t work with most SPI slaves/protocols, since they expect CS to go low at the start of a packet, and high at the end after multiple bytes. Therefore, CS is controlled by software.
Building a Thread Router Eligible End Device Application (with Silicon Labs Thread 2.7.1) Part 1.
A step-by-step guide to creating, building, and running your own Router Eligible End Device (REED) application based on the Silicon Labs Thread stack. Before tackling this tutorial, please checkout "Building Thread Sample Applications" tutorial first.
This KBA works with:
I. Launch Simplicity Studio and start a blank application
1. Make sure at least two nodes are present with EFR32s under Devices.
2. Go to File -> New -> Silicon Labs AppBuilder Project.
3. Select Silicon Labs Thread 2.7.1.
4. Check on "Start with a blank application". Click Next.
5. Name your project. For example ThreadReed271BRD4162A.
6. In next window (Project Setup), check if Simplicity Studio detected correct board, part, and toolchain. In this example we're using BRD4162A, EFR32MG12P332F1024GL125, and IAR ARM 7.80.
II. Configuring REED
1. Under the "General" tab:
a. Update the "Device name" to project's name (ie ThreadReed271BRD4162A).
b. Open "Device type" dialog:
i. Select EFR32 and add device to "Selected devices and plugins".
ii. Select SoC and add device to "Selected devices and plugins".
iii. Select Router and add device to "Selected devices and plugins".
iv. Close dialog by clicking OK.
2. Under the "HAL" tab:
a. Set Bootloader to Application type.
b. Set to Use Hardware Configurator.
3. Open Hardware Configurator
a. Under DefaultMode Peripherals tab
i. Check on GPIO, set SWO pin to PF2
ii. Check on Serial, set Port to USART0
iii. Check on Virtual COM Port, set enable pin to PA5
4. Save HWCONF file by going to File -> Save and go back to your project's ISC file.
5. Under the "Printing" tab:
a. Make sure "Enable debug printing" is checked.
b. Make sure under functional area Core and Application are checked in both "Compiled in" and Enabled at startup".
6. Under the "ZCL over IP" tab, we do not have anything to add.
7. Under the "Plugins" tab:
a. Add CoAP Debug under the Common section. This will give us CoAP debug output in the console.
b. Add ICMP Debug under the Common section. This will give us ICMP debug output in the console.
c. Add Serial Plugin (if not already added), and set port to USART0.
d. Add Debug JTAG and remove Debug JTAG stub.
e. Add Radio Coexistence to cover dependencies in HAL library.
8. Under the "Callbacks" tab:
a. Select emberFormNetworkReturn - check "Is Used"; Stub should be check automatically.
b. Select emberJoinNetworkReturn.
c. Select emberResetNetworkStateReturn.
d. Select emberResumeNetworkReturn.
9. Under the "Other" tab, we do not have anything to add.
10. Click "Generate". Notice project appeared in Project Explorer. Click OK.
11. Save ISC file.
III. Add Code and Build Projects
1. Go to Simplicity IDE perspective. In Project Explorer, expand your Reed project.
2. Add the following ifdef to thread-callbacks.c to enable debug printing.
3. Add the following code to thread-callbacks.c file. The functions should already be available after generating the project through AppBuilder. This will give us some useful output in serial console.
4. Compile your project by right-clicking on project name and using "Build project" option.
5. Make sure your build is successful and the compiled binary is located in project directory tree under "IAR ARM - Default" folder.
IV. Load Application and Bootloader to EFR32MG module on WSTK
1. As described in "Building Thread Sample Applications" section 7. Load the Reed application and bootloader to two available devices.
(To build a specific bootloader check out UG266 and AN1048.)
V. Adding nodes to a network using pre-commissioning
1. In Network Analyzer perspective, in the Devices view, right-click on a node and select "Connect" then right-click again and select "Launch Console".
a. Navigate to "Serial 1" tab and press the return key a few times to get a prompt.
b. Find out the state of your device using the "Info" command. The output should output network status of 0x00 (EMBER_NO_NETWORK).
c. If your device has an ip address, reset the network parameters by issuing the command:
2. For the first device on the network we will need to form the network
a. Set the master key issuing command:
b. Set network parameters for the network.
Example:
c. Check network status using the info command. Network status should be 0x03 (EMBER_JOINED_NETWORK_ATTACHED).
3. For the second node (or any node after)
a. In the "Serial 1" console make sure the node is not already in a network.
b. Set Commissioning information for the device. Note the PAN ID, Extended PAN ID, and Network ID are set by the Leader (our first node on the network). Use the info command on the Leader node to get proper parameters for the network. Gather the channel, channel mask (0x0C00), network id, ula prefix, extended pan id, master key (from above command), and pan id.
Example for a node joining pan id 0x6F29 on channel 12:
4. Join the pre-commissioned device to the network.
a. Use the following command
Example for radio tx power set to 1dBm on a router:
5. Check the status of the node by using the info command. Network status should be 0x03 (EMBER_JOINED_NETWORK_ATTACHED).
VI. Sending Messages
1. In the Console ping one of the devices in the network, for example ping the Leader's IP address using:
Example:
2. In the Console send a CoAP POST message
Example:
VII. Expanding Application
The second part of the tutorial adds functionality to the receiving node.
Communication with external EFR32 based device
This KBA works with:
Also checkout the following application note for more information:
AN958: Debugging and Programming Interfaces for Custom Designs
To use VCOM_RX and VCOM_TX through the 10-pin Mini Simplicity connector (section 4.1.1 of AN958), make the following edits in your project's ISC (App Builder) and HWCONF (Hardware Configurator):
To use vUART skip steps 2 thru 4 and follow steps from "Setting up vUART with Hardware Configurator".