Firmware for the STx familiy of LoraWan sensors.
The HAL scaffold is generated by STM32CubeMX, i.e. generates C code. The code is not optimized for beauty but for being able to take over the code from the various sources without too much friction to have an easy upgrade path.
This firmware is compatile with the following devices:
Part Number / Variant | Description |
---|---|
sta-lr |
action variant with a tactile switch. |
stx-lr |
multisensor variant with five sensor measurements. |
ste-lr |
environment sensor with Bosch BME680. |
Build is configured by macros in Inc/main.h described by FEATURE_FLAGS.md. Selecting device variant and behaviour.
- LoRa Class A modem
- Tuned for ultra low power consumption
- Integration with a variety of other sensors specific to variant
- LoRaWAN params and sensor configuration programmable through NFC
- Firmware upgrade through NFC
- 3 button press gestures for triggering events (single, double, long) for sta-variant
- Link Check/ ADR for LoRa not availabe in MM https://www.bjoerns-techblog.de/2019/02/adr-mit-the-things-network/ and https://www.sghoslya.com/p/how-does-lorawan-nodes-changes-their.html
- 915 MHz (not working in MM)
- Migration to LoRaMAC Node
- Flash size: 192 kiB
- RAM: 128 KiB
- Flash programming only possible in bytes or nibbles
- Page size: 32 words
Addresses:
- ST25DV: 0xAE 0xA6
- BMA400: 0x28
- HDC2080: 0x80
- SFH7776: 0x72
- BME680: 0xEC
- ATECC608A: 0xC0?
- Single press
- Double press (two presses within 1.5 s)
- Long press (longer than 2s and shorter than 8s)
- 3 gesture mode (w/o
SIMPLE_TWO_GESTURE_MODE
)- 1x Green: Single press
- 2x Green: Double press
- 3x Green: Long press
- 2 gesture mode (w/
SIMPLE_TWO_GESTURE_MODE
)- 1x Green: Single press
- 1x Red: Long press
- 1x Red, 1x Green: Join successful
- 3x Red: Join failed
The message formats for NFC and LoRaWAN communication are defined in MESSAGE_FORMAT_NFC.md and MESSAGE_FORMAT_LORA.md.
STM32L0x1 has 12 byte Unique Device ID, which we fit into 8 byte Dev EUI. See
BoardGetUniqueId()
. Redesigned to prevent past collisions.
Bitmask:
Bitmask | deveui[3] | deveui[2] | lotchar | uid0 | uid1 | Description |
---|---|---|---|---|---|---|
0b1??? |
??? | ??? | ??? | ??? | ??? | Implies that Dev EUI was manually changed, since its always 0 otherwise. |
0b0111 |
uid1 | uid0 | ??? | ? | ? | Means collision is possible, since all 3 fields are proven to be relevant. |
0b0110 |
uid1 | uid0 | 0x47 | ? | ? | |
0b0101 |
uid1 | lotchar | ? | 0x00 | ? | |
0b0100 |
uid1 | lotchar | 0x47 | 0x00 | ? | |
0b0011 |
uid0 | lotchar | ? | ? | 0x00 | |
0b0010 |
uid0 | lotchar | 0x47 | ? | 0x00 | |
0b0001 |
uid0 | lotchar | ? | 0x00 | 0x00 | |
0b0000 |
uid0 | lotchar | 0x47 | 0x00 | 0x00 | All known assumptions are true. |
Segments:
Name | MCU Register | Dev EUI Mapping | Description |
---|---|---|---|
uuid | 0x00YY_00XX at 0x1ff80064 |
0x0000_0000_0000_YYXX |
(4 byte) Unique ID. 2 bytes always been 0x00, thus potentially discarded. |
uid0 | 0x0000_XX00 at 0x1ff80064 |
0x0000_0000_????_0000 |
(4 byte) Unique ID. Always been 0x00. Might be encoded. (default) |
uid1 | 0xXX00_0000 at 0x1ff80064 |
0x0000_0000_??00_0000 |
(4 byte) Unique ID. Always been 0x00. Might be encoded. |
lotchar | 0x00XX_0000 at 0x1ff80050 |
0x0000_0000_00??_0000 |
(7 byte) Lot Number ASCII. Always been 0x47. Might be encoded. (default) |
lotnr | 0x0i0i_0i0i at 0x1ff80054,0x0000_0I0I at 0x1ff80050 |
0x0nnn_nn00_0000_0000 |
(7 byte) Lot Number ASCII. Each byte is [0x30, 0x39]. 6 digit ASCII turned into 2.5 byte number. |
wafnr | 0xXX00_0000 at 0x1ff80050 |
0x0000_00XX_0000_0000 |
(1 byte) Wafer Number. |
bitmask | N/A | 0xX000_0000_0000_0000 |
(4 bits) n-fuse bitmask describing Dev EUI contents. |
The ATECC608A secure element is the foundation of the device's security. It is used for the various key calculations like during the network join. Once the join is performed, no secrets leave the chip again.
Description of the key handling using an ECC608 chip with pre-provisioned TTI keys can be found in this document.
The following equipment is required:
- Segger J-Link Debug Probe
- n-fuse ARM/ JTAG/ J-Link 20-Pin to TC2030 6-Pin Power providing Programmer Adapter
- Tag-Connect TC2030-IDC-NL Cable and Retainer Clip
It's important to issue the power on perm
command to the J-Link to make it supply 5 V to the programmer adapter.
...and the following software tools:
- STM32CubeMX scaffold project/ code generator.
- STM32CubeIDE.
- GNU Arm Embedded Toolchain
The firmware is RTT enabled, the output can be read using netcat, telnet or similar like this:
nc localhost 19021
- mainfw: Application at
0x0800_8000 stx-fw
. Chainloaded by bootloader. - bootldr: Bootloader at
0x0800_0000 stm32-update-bootloader
. Started by MCU reset or power-on.
Build mainfw:
- Select
Debug
configuration in STM32CubeIDE. - Build.
Flash:
- Start JTAG debugger
JLinkExe -If swd -Device STM32L071KZ -Speed 4000 -RTTTelnetPort 2329 -AutoConnect 1
- Start GDB server
JLinkGDBServer -device STM32L071KZ -if swd -port 2331 -speed 4000 -endian little -localhostonly
- Start GDB client
arm-none-eabi-gdb -ex 'target remote :2331' -ex 'symbol-file /hw/stx-fw/Offset/stx-fw.elf'
- Flash
(gdb) load /hw/stx-fw/Offset/stx-fw.elf
onto device. - Reset device
(gdb) monit reset 2
(SEGGER J-Link vendor command).
Build mainfw:
- Setup defines in
Inc/main.h
- Device Family: Uncomment one of STA (button), STX (multisensor), STE (environment). Leave other two commented.
- If STA, select operation mode: Uncomment or Comment SIMPLE_TWO_GESTURE_MODE.
- Audit every
#PRODUCTION
piece in project. (e.g.grep -IrwnA5 '#PRODUCTION'
) - Select
Offset
configuration in STM32CubeIDE. - Build.
Build bootloader:
- Select
Debug
configuration in STM32CubeIDE. - Build.
Flash both:
- Connect debugger
(gdb) target remote :2331
. - Flash
(gdb) load /hw/stx-fw/Offset/stx-fw.elf
onto device. - Flash
(gdb) load /hw/stm32-nfc-update-bootloader/Debug/stm32-update-bootloader.elf
onto device. - Reset device
(gdb) monit reset 2
(SEGGER J-Link vendor command).
Clear EEPROM:
- Clear
(gdb) set *(char[0x1800] *)0x08080000 = {0}
onto device.
PS: Firmware may reuse previous DevEUI, gesture counters, etc. values if EEPROM is valid and not cleared.
Suggestion: Avoid configuring default values via source code. As factory reset
would recover these values. Instead you may configure DevCfg
at flash-time
via GDB, as demonstrated below.
It also demonstrates how to obtain generated DevCfg from device at flash-time.
pw='12345678'
arm-none-eabi-gdb \
-n -batch \
-ex 'target remote :2331' \
-ex 'symbol-file /tmp/hw/upstream/mainfw/Offset/stx-fw.elf' \
-ex 'load /tmp/hw/upstream/mainfw/Offset/stx-fw.elf' \
-ex 'load /tmp/hw/upstream/bootldr/Debug/stm32-update-bootloader.elf' \
-ex 'set *(char[0x1800] *)0x08080000 = {0}' \
-ex "set *(uint32_t*)0x08080008 = $(<<<$pw awk '{print "0x"$7$8$5$6$3$4$1$2}' FS=)" \
-ex "set *(uint32_t*)0x0808000c = ~$(<<<$pw awk '{print "0x"$7$8$5$6$3$4$1$2}' FS=)" \
-ex 'monit reset 2' \
-ex 'b main' \
-ex 'c' \
-ex 'set DevCfg.appEui = { 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }' \
-ex 'set DevCfg.appKey = { 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }' \
-ex 'b EEPROM_Save' \
-ex 'c' \
-ex 'finish' \
-ex 'printf "'$'\33[32;1m''DevEui: %02x%02x%02x%02x%02x%02x%02x%02x'$'\33[m''\n", DevCfg.devEui[0], DevCfg.devEui[1], DevCfg.devEui[2], DevCfg.devEui[3], DevCfg.devEui[4], DevCfg.devEui[5], DevCfg.devEui[6], DevCfg.devEui[7]' \
-ex 'quit'
To join device to ttn application via TTN Console, three important values are necessary:
DevEui
Device EUI: Public, like your name or device MAC address.AppEui
App EUI: Public, like your house address or WiFi name.- Lesser known as
JoinEui
.
- Lesser known as
AppKey
App Key: Secret, like door keys or WiFi password.
-
Determine values from device (via RTT Logs or NFC)
EEPROM ROM BackUpFlash.devEui 11 22 33 44 55 66 77 88 EEPROM ROM BackUpFlash.appEui 22 33 44 55 66 77 88 99 EEPROM ROM BackUpFlash.appKey 33 44 55 66 77 88 99 AA BB CC DD EE FF 00 11 22
-
Register device to application using values above via TTN Console
Note, by default the Web UI wants to generate the App Key, but you must tap the pencil and enter above. -
Assert that you're joined.
Device joined blink pattern 1xRed 1xGreen. In case of button, gesture blinks are disabled if not joined.
TTN Console provides traffic view at Application side and Gateway side.
Contains automatically generated and manually written copyrighted code from the following legal entities:
- Arm Limited
- SEGGER Microcontroller GmbH
- STMicroelectronics
- Bosch Sensortec GmbH
- Microchip Technology Inc.
These copyrights are noted in the head of the respective files. All other code is subject to the LGPL.