IAR provides a very convenient #pragma mechanism for locating variables at specific memory addresses:
This #pragma is then followed by the specific variable declaration. Programming the DLW to lock debug access is thus as simple as:
#pragma location=(LOCKBITS_BASE + (127 << 2)) __root const uint32_t debug_lock_word = 0x0;
The first line specifies that the address of the following variable should be 0x0FE04000 + (127 << 2 ) = 0x0FE041FC. LOCKBITS_BASE is #defined in the CMSIS Cortex-M Peripheral Access Layer Header File for the device in question and is 0x0FE04000 for all current EFM32, EFR32, and EZR32 devices.
Naturally, the constant debug_lock_word sets the DLW to 0x0 (at the previously specified address), but what does the __root modifier do? As explained in the following IAR Technical Note...
__root prevents the linker from removing a variable or function if it is not referred to in the main() call-tree or in any interrupt call-tree. Short of perhaps checking the state of the debug_lock_word in firmware to enable/disable debugging features, there would usually be no reason for it to be referenced in main() or elsewhere, thus the need to prevent the linker from removing it.
Obviously, this same technique can be used for any of the other words in the lock bits page. For example, to have pin resets treated as hard instead of soft resets, it's necessary to clear bit 2 of lock bits page word 122, which is configuration word 0 (CLW0), and is done with (bit 1 of CLW0 enables the bootloader and remains set in this particular example):
#pragma location=(LOCKBITS_BASE + (122 << 2)) __root const uint32_t config_word_zero = 0xfffffffb;
Locations in user data space can be programmed with constant data in the same way. For example, a product and manufacturer name could be stored as follows:
#pragma location=USERDATA_BASE __root const uint8_t product_name = "Wiz-O-Matic XL"; #pragma location=USERDATA_BASE + 16 __root const uint8_t manufacturer_name = "Real Geniuses, Inc.";
A curious user might ask "How exactly do I know this works? The .hex file format is rather cryptic looking to the untrained eye. Is there a way to parse this .hex file output from the build process and verify the expected constants are there?"
Various binary tools can be used to dump and otherwise convert .hex files, but the output from the attached hexinfo program (attached to this article for Windows machines after compiling from the sources at https://github.com/bradgrantham/hex2bin) does the job conveniently enough:
Each contiguous region in the hex file can be associated with a section of the compiled binary data. The largest is, of course, the program code itself, while the three smaller regions correspond to the product_name, manufacturer_name, and debug_lock_word constant definitions at the addresses specified by the location #pragmas that precede them.