-
Notifications
You must be signed in to change notification settings - Fork 3
05 ‐ Boards
All boards share the same nRF52840 MCU, u-blox M10Q GNSS, and SoftDevice S140 v7.2.0. They differ in their communication module, power management, and peripherals.
| LinkIt V4 KIM | LinkIt V4 SMD | LinkIt V4 LoRa | RSPB | |
|---|---|---|---|---|
| Comm Module | KIM2 (CLS) | SMD (Arribada) | RAK3172-SiP | SMD (Arribada) |
| Comm Interface | UART | SPI | UART | SPI |
| Protocol | Argos Legacy | Argos A+ | LoRaWAN 1.0.3 | Argos A+ |
| Coverage | Global (satellite) | Global (satellite) | Terrestrial (gateway) | Global (satellite) |
| Battery Monitor | Analog ADC | Analog ADC | Analog ADC | STC3117 fuel gauge |
| Power-on | Reed switch (3s) | Reed switch (3s) | Reed switch (3s) | TPL5111 timer |
| Debug Log | USB CDC | USB CDC | USB CDC | UART (J3) |
| Thermistor | Optional | Optional | Optional | Always enabled |
| Wireless Charging | Yes | Yes | Yes | No |
| BSP | linkitv4_v1.0/ |
linkitv4_v1.0/ |
linkitv4_v1.0/ |
rspbtracker_v1.0/ |
| Build Script | build_linkitv4_kim.sh |
build_linkitv4_smd.sh |
build_linkitv4_lora.sh |
build_rspb.sh |
| Build Dir | build/LINKIT/ |
build/LINKIT_SMD/ |
build/LINKIT_LORA/ |
build/RSPB/ |
| CMake Key Flags | BOARD=LINKIT |
BOARD=LINKIT ARGOS_SMD=ON |
BOARD=LINKIT LORA_RAK3172=ON |
BOARD=RSPB ARGOS_SMD=ON |
| Hardware Repo | kim-only | smd-only | - | - |
For build and flash instructions, see Building and Programming.
The power-down mechanism differs significantly between LinkIt V4 and RSPB. Understanding this is critical for battery lifetime estimation and deployment procedures.
| LinkIt V4 (KIM/SMD/LoRa) | RSPB | |
|---|---|---|
| Mechanism | Pseudo power-off (System OFF) | Real power-off (TPL5111) |
| Define | PSEUDO_POWER_OFF |
EXTERNAL_WAKEUP |
| Power control |
POWER_CONTROL_PIN has hardware pull-up — nRF cannot cut its own supply |
POWER_CONTROL_PIN drives SMD board rail, MCU_DONE_PIN signals TPL5111 |
| Sleep current | ~0.4 µA (nRF52840 System OFF) | ~0.1 µA (TPL5111 cuts all power) |
| Wakeup source | Reed switch GPIO SENSE (magnet) | TPL5111 timer (periodic) or reed switch |
| RAM state | Lost (full reboot on wake) | Lost (full reboot on wake) |
| VSYS at sleep | 1.8V (VSYS_SEL LOW) | N/A (power cut entirely) |
The POWER_CONTROL_PIN has a hardware pull-up on the PCB, so the nRF52840 cannot cut its own supply by driving the pin LOW. Instead, the firmware enters nRF52840 System OFF mode directly:
PMU::powerdown()
1. Save cooldown state + RTC to flash
2. Shut down ALL peripherals:
- LEDs OFF
- SENSORS_PWR OFF
- GPS OFF + held in reset
- SAT module OFF + held in reset + VPA LOW
- SWS OFF
3. VSYS_SEL → 1.8V (reduces DCDC quiescent)
4. Configure reed switch pin as SENSE HIGH (wakeup source)
5. sd_power_system_off()
→ nRF52840 enters System OFF (~0.4 µA)
→ All RAM lost, all peripherals off
→ Only SENSE pin and RTC (if configured) remain active
[Magnet applied → reed switch pin goes HIGH]
6. nRF52840 wakes up → full POR reset
7. Boot sequence starts → reed switch 3s hold required to confirm
Important: System OFF mode loses ALL RAM content. The noinit section, nRF registers, and SoftDevice state are all cleared. The firmware boots fresh as if from a power-on reset, but RESETREAS shows GPIO wakeup instead of POR.
The RSPB uses a TPL5111 external timer that periodically wakes the device and cuts power when done. The POWER_CONTROL_PIN controls the SMD satellite module board power rail (separate from the nRF rail):
PMU::powerdown()
1. Save cooldown state + RTC to flash
2. Shut down ALL peripherals (same as LinkIt V4)
3. GPIOPins::clear(POWER_CONTROL_PIN)
→ Cuts SMD board power rail (STM32WL, PA, TCXO)
→ Wait 1000ms for power rail to collapse
4. GPIOPins::set(MCU_DONE_PIN) → pulse 100ms
→ TPL5111 sees MCU_DONE → cuts main power to nRF52840
→ Device is completely off (~0.1 µA, only TPL5111 timer running)
[TPL5111 timer expires after WAKEUP_PERIOD]
5. TPL5111 asserts DONE → nRF52840 power restored
6. Full POR reset → boot sequence
7. Boot counter check (BOOT_COUNTER_MODULO) → run or powerdown again
Important: The TPL5111 cuts ALL power including the nRF52840. This is a true power-off, not a sleep mode. The WAKEUP_PERIOD parameter (default 3600s = 1h, set via build_rspb.sh) controls the TPL5111 timer interval — it must match the fitted TPL5111 timing resistor. The BOOT_COUNTER_MODULO parameter allows skipping boots to save battery (e.g., modulo=2 means TX every 2nd wakeup = every 3.5h).
| Trigger | Path | Both boards |
|---|---|---|
| Magnet long hold (6s) → confirm | OffState → PMU::powerdown()
|
Yes |
| Battery critical | BatteryCriticalState → PMU::powerdown()
|
Yes |
| BLE inactivity timeout (20 min) | ConfigurationState → OffState → PMU::powerdown()
|
Yes |
| Session TX limit reached | ArgosTxService → PMU::powerdown()
|
Yes |
| Boot counter check (skip this boot) | main.cpp → PMU::powerdown()
|
RSPB only |
The default variant. Uses the CLS KIM2 module for Argos satellite communication over UART.

| Packet Type | Size |
|---|---|
| SHORT_PACKET | 12 bytes |
| LONG_PACKET | 31 bytes |
| Mode | Value | Description |
|---|---|---|
| OFF | 0 | Argos TX disabled |
| PASS_PREDICTION | 1 | TX only during predicted satellite passes (recommended) |
| LEGACY | 2 | Periodic TX regardless of satellite position |
| DUTY_CYCLE | 3 | TX according to 24-bit duty cycle bitmask |
| DOPPLER | 4 | Doppler-based location mode |
The KIM module does not require credentials setup (unlike SMD).
| Command | Description |
|---|---|
| SATTX | Manual Argos satellite transmission |
| SATDP | Start periodic Doppler TX calibration |
| PASPW | Write pass prediction (AOP) data |
Build
cd ports/nrf52840/bootloader/secure_bootloader/linkitv4_v1.0/armgcc
make mergehexPARMW,ARP01,2 # ARGOS_MODE = Legacy
PARMW,ARP05,60 # TR_NOM = 60s
PARMW,GNP01,1 # GNSS enabled
PARMW,GNP05,240 # GNSS timeout = 240s
PARMW,UNP01,1 # Underwater detection enabled
PARMW,UNP10,0 # Detection source = SWS
PARMW,AXP01,1 # Accelerometer enabled
Uses the Arribada SMD module for Argos communication via SPI with the modern A+ protocol and built-in security.
| Packet Type | Size | Modulation | CRC |
|---|---|---|---|
| SHORT_PACKET | 12 bytes | LDK | Added by SMD/KIM2 module |
| LONG_PACKET | 24 bytes | LDA2 | Firmware-embedded CRC8 at byte 23 (modem doesn't add CRC for LDA2) |
The SMD module does not embed CRC for LDA2 frames — the firmware computes a CRC8 over bits 0..183 of every 24-byte LDA2 packet (long, sensor, fastloc, RSPB long, CloudLocate MEAS20) and stores it at byte 23. See Satellite Communication § Error correction & CRC.
The SMD module uses a framed protocol with:
- Magic bytes for frame identification
- Sequence numbers for reliable delivery
- CRC for data integrity
- Built-in security key management (KMAC)
- Radio configuration commands
Before the SMD module can transmit, credentials must be configured. Credentials are written to the config store via individual PARMW calls on each ID/key/RCONF param, and automatically pushed to the SMD hardware at the next power-on via the dirty flag mechanism: credentials are written once at first boot (m_credentials_dirty flag set on init), then cleared after write. The flag is re-set whenever ARGOS_HEXID, ARGOS_SECKEY, or ARGOS_RADIOCONF are changed via DTE. This avoids redundant flash writes on every TX cycle. To verify what is actually programmed on the SMD hardware (or force a re-write if it differs from the config store), use SATVF.
| Parameter | DTE Key | Description |
|---|---|---|
| ARGOS_DECID | IDP12 | Argos decimal platform ID |
| ARGOS_HEXID | IDT06 | Argos hex platform ID (address) |
| ARGOS_SECKEY | IDP13 | Security key (KMAC) for A+ protocol |
| ARGOS_RADIOCONF | IDP14 | Master radio configuration (used when adaptive modulation OFF) |
Adaptive modulation (ARP54): When enabled, per-modulation RCONFs are used instead of the master:
| Parameter | DTE Key | Default | Description |
|---|---|---|---|
| ARGOS_RADIOCONF_LDK | ARP51 | (factory) | RCONF for LDK modulation (16 bytes) |
| ARGOS_RADIOCONF_LDA2 | ARP52 | (factory) | RCONF for LDA2 modulation (24 bytes) |
| ARGOS_RADIOCONF_VLDA4 | ARP53 | (factory) | RCONF for VLDA4 modulation (3 bytes) |
Via pylinkit — write each credential individually via PARMW (the legacy
`--smdcd` flag was removed when SMDCD was replaced by SATVF in firmware
commit 32ab70f0). Re-write triggers the dirty flag and pushes to the SMD
at next power-on.
pylinkit --device xx:xx:xx:xx:xx:xx \
--parmw IDP12=<id> \
--parmw IDT06=<addr> \
--parmw IDP13=<seckey> \
--parmw IDP14=<radioconf>
# Then verify what was actually programmed on the SMD:
pylinkit --device xx:xx:xx:xx:xx:xx --satvf| Command | Description |
|---|---|
| SATTX | Manual Argos satellite transmission |
| SATDP | Start periodic Doppler TX calibration |
| PASPW | Write pass prediction (AOP) data |
| SMDDFU | SMD module firmware update (DFU over SPI). After DFU, a 3s LED feedback is shown (green=success, red=failure) via led_handle::dispatch, then LED restores to BLE connected state (blue). |
| SMDTST | SMD SPI connectivity test |
| SATVF |
Replaces SMDCD (removed in commit 32ab70f0). Verifies what's programmed on the SMD vs the config store; optional force=1 triggers a re-write if mismatch. See 06 DTE commands § SATVF. |
| Feature | SMD | KIM |
|---|---|---|
| Interface | SPI | UART |
| Protocol | A+ (modern, with security) | Legacy |
| Long packet size | 24 bytes | 31 bytes |
| Security | Built-in KMAC | None |
| DFU support | Yes (SMDDFU) | No |
| Credentials | Required (PARMW on IDP12/IDT06/IDP13/IDP14 + SATVF verify) | Not required |
Same as KIM (shared linkitv4_v1.0 BSP):
cd ports/nrf52840/bootloader/secure_bootloader/linkitv4_v1.0/armgcc
make mergehexPARMW,ARP01,2 # ARGOS_MODE = Legacy
PARMW,ARP05,60 # TR_NOM = 60s
PARMW,GNP01,1 # GNSS enabled
PARMW,GNP05,240 # GNSS timeout = 240s
PARMW,UNP01,1 # Underwater detection enabled
PARMW,UNP10,0 # Detection source = SWS
PARMW,AXP01,1 # Accelerometer enabled
Set SMD credentials
PARMW,IDP12,<dec_id>
PARMW,IDT06,<hex_id>
PARMW,IDP13,<security_key>
PARMW,IDP14,<radio_config>
SATVF,1 # verify + force re-write to SMD hardware if mismatch
Replaces the Argos satellite module with a RAK3172-SiP LoRaWAN module (Semtech SX1262) for terrestrial LPWAN communication.
| Feature | Details |
|---|---|
| LoRaWAN Version | 1.0.3 |
| Join Modes | OTAA (recommended) and ABP |
| Default Band | EU868 (configurable) |
| Device Class | A (default), B, C supported |
| Low Power | Standby (~1.7uA, ~10ms wake) or shutdown (0uA, ~2.5s wake) |
| Type | Content | Max Size |
|---|---|---|
| GPS_SINGLE | Single GPS fix + battery | 51 bytes |
| GPS_MULTI | Multiple GPS fixes with delta-time compression | Up to 222 bytes |
| SENSOR | Sensor data (temperature, pressure, etc.) | Variable |
| STATUS | Device status, battery, counters | Variable |
Payload size depends on the data rate (DR). Higher DR = more bandwidth = larger payloads.
| Parameter | DTE Key | Default | Description |
|---|---|---|---|
| LORA_DEVEUI | LRP01 | (from module) | Device EUI - read from RAK3172, read-only |
| LORA_APPEUI | LRP02 | "" | Application EUI (JoinEUI) - 16 hex chars |
| LORA_APPKEY | LRP03 | "" | Application Key - 32 hex chars |
| LORA_NJM | LRP07 | 1 | Network Join Mode: 0=ABP, 1=OTAA |
| Parameter | DTE Key | Default | Description |
|---|---|---|---|
| LORA_DEVADDR | LRP04 | "" | Device Address - 8 hex chars |
| LORA_APPSKEY | LRP05 | "" | Application Session Key - 32 hex chars |
| LORA_NWKSKEY | LRP06 | "" | Network Session Key - 32 hex chars |
| Parameter | DTE Key | Default | Description |
|---|---|---|---|
| LORA_BAND | LRP08 | 4 | Frequency band: 0=EU433, 1=CN470, 2=RU864, 3=IN865, 4=EU868, 5=US915, 6=AU915, 7=KR920, 8=AS923-1/2/3/4 |
| LORA_CLASS | LRP09 | 0 | Device class: 0=A, 1=B, 2=C |
| LORA_DR | LRP10 | 3 | Data rate (EU868: 0=SF12, 1=SF11, 2=SF10, 3=SF9, 4=SF8, 5=SF7) |
| LORA_ADR | LRP11 | false | Adaptive Data Rate (recommended OFF for mobile) |
| LORA_TXP | LRP12 | 0 | TX power index (0 = max) |
| LORA_CFM | LRP13 | false | Confirmed messages (ACK required) |
| LORA_FPORT | LRP14 | 2 | FPort for uplink (1-223) |
| LORA_LP_MODE | LRP15 | 1 | Low-power between TX: 0=shutdown, 1=standby |
| Command | Description |
|---|---|
| LORATX | Manual LoRa TX (for testing) |
| LORABR | LoRa UART bridge (USB ↔ RAK3172 AT passthrough) |
| GNSSBR | GNSS bridge mode (USB ↔ u-blox UART passthrough) |
All bridges require tracker in ConfigurationState. Exit via +++ (byte-stream for GNSSBR, line for LORABR/KIMBR) or $<CMD>#001;0\r. Debug logs are suppressed on USB while any bridge is active. See DTE Commands → Bridge Commands for full protocol spec.
GNSS bridge — direct UBX/NMEA access to u-blox M10Q for u-center connection or AssistNow loading:
$GNSSBR#001;1\r # Start (9600 baud forced)
$GNSSBR#001;0\r # Stop (or send +++)
LoRa bridge — direct AT command access to RAK3172 (RUI3):
$LORABR#001;1\r # Start (115200 baud, line-based)
$LORABR#001;0\r # Stop (or send +++\r\n)
KIM2 bridge — direct AT command access to CLS KIM2 (KIM builds only):
$KIMBR#001;1\r # Start (line-based, auto-power-on if off)
$KIMBR#001;0\r # Stop (or send +++\r\n)
| Feature | LoRa (RAK3172) | Argos (KIM/SMD) |
|---|---|---|
| Coverage | Terrestrial (gateway required) | Global (satellite) |
| Range | Up to 15km (line of sight) | Global |
| Data rate | 300bps - 11kbps | Fixed (low) |
| Power | Very low (~1.7uA standby) | Higher (satellite TX power) |
| Cost | Free (LoRaWAN) | Argos subscription |
| Latency | Near real-time | Hours (satellite pass) |
| Bidirectional | Yes (Class A/B/C) | Limited (RX windows) |
| Best for | Coastal, urban, farm | Open ocean, remote areas |
Same as KIM/SMD (shared linkitv4_v1.0 BSP):
cd ports/nrf52840/bootloader/secure_bootloader/linkitv4_v1.0/armgcc
make mergehex OTAA Configuration
PARMW,LRP02,<appeui_16hex> # Application EUI
PARMW,LRP03,<appkey_32hex> # Application Key
PARMW,LRP07,1 # OTAA mode
PARMW,LRP08,4 # EU868 band
PARMW,LRP10,3 # DR3 (SF9)
PARMW,LRP15,1 # Standby low-power mode
General tracker config
PARMW,GNP01,1 # GNSS enabled
PARMW,GNP05,240 # GNSS timeout = 240s
PARMW,UNP01,1 # Underwater detection enabled
PARMW,AXP01,1 # Accelerometer enabled
The RSPB (Royal Society for the Protection of Birds) board is designed for bird tracking. It uses the SMD module (like LinkIt V4 SMD) but with a completely different power management approach.
| Feature | RSPB | LinkIt V4 |
|---|---|---|
| Power-on | TPL5111 external timer | Reed switch (magnet 3s hold) |
| Debug log | UART via J3 connector | USB CDC |
| Battery monitor | STC3117 fuel gauge | Analog ADC |
| Thermistor | Always enabled | Optional |
| Wireless charging | No | Yes |
| Boot logic | Counter modulo filtering | Reed switch gate |
| LoRa support | No | Yes (with LORA_RAK3172=ON) |
The RSPB uses a TPL5111 external timer for ultra-low-power duty cycling:
- TPL5111 wakes the device periodically (every
WAKEUP_PERIODseconds, default 3600s = 1h) - A boot counter increments at each wakeup (
PWP02) - The firmware checks
boot_counter % BOOT_COUNTER_MODULO(PWP03)- Result != 0: device powers down immediately (not its turn)
- Result == 0: device runs its full operational cycle
- Applying a magnet during a modulo-skip overrides the skip (allows configuration access)
Effective duty cycle = WAKEUP_PERIOD x BOOT_COUNTER_MODULO (default: 3600s x 2 = 2 hours).
The RSPB board has specific power rail behavior:
- SENSORS_PWR_PIN is always ON at boot on RSPB. This is required because I2C pull-ups (R21/R24) are connected to the DCDC_3V3 rail controlled by this pin — without it, I2C communication with sensors fails. (FIXME: hardware workaround needed in future revisions to allow fully cutting sensor power.)
-
POWER_CONTROL_PIN controls the main board power rail (not just the SMD module). In
enter_deep_idle(), this pin is driven LOW to cut the rail, andexit_deep_idle()restores it. This is used during deep idle between TPL5111 wakeups to minimize quiescent current. -
VPA_EN (SMD voltage power amplifier enable): properly managed with
drive_low()when the SMD is powered off andrelease_to_highz()when the SMD is powered on. This prevents current leakage through the PA supply when idle.
The RSPB implements a pseudo-RTC since it may lack a battery-backed RTC:
- At each boot,
LAST_KNOWN_RTC(PWP06) is advanced byWAKEUP_PERIOD - This gives an approximate time immediately, before a GNSS fix corrects it
- The value is persisted to flash
All boards now persist
LAST_KNOWN_RTCafter GNSS sessions and powerdown. On LinkIt V4, the value is restored directly at boot (no period added) to enable MGA-ANO assistance and faster TTFF.
SHUTDOWN_TIMER (PWP01) controls max awake time per cycle. After this time, the device powers down. Set to 0 to disable (stays awake until task completion).
| Parameter | DTE Key | Default | Description |
|---|---|---|---|
| SHUTDOWN_TIMER | PWP01 | 0 | Max awake time per cycle in seconds (0 = no limit) |
| BOOT_COUNTER | PWP02 | 0 | Current boot counter (read-only) |
| BOOT_COUNTER_MODULO | PWP03 | 2 | Run every Nth boot |
| WAKEUP_PERIOD | PWP04 | 3600 | TPL5111 wakeup interval in seconds — writable via PWP04; compiled default set by build_rspb.sh (WAKEUP_PERIOD); MUST match the fitted TPL5111 resistor |
| SHUTDOWN_NTIME_SAT | PWP05 | 0 | Number of Argos TX before auto-shutdown (0 = disabled) |
| LAST_KNOWN_RTC | PWP06 | 0 | Persisted RTC for pseudo-RTC chain (read-only) |
Same as LinkIt V4 SMD — the SMD module requires credentials before it can transmit. See SMD Credentials above.
The RSPB uses its own bootloader:
cd ports/nrf52840/bootloader/secure_bootloader/rspbtracker_v1.0/armgcc
make mergehexPARMW,ARP01,1 # ARGOS_MODE = Pass Prediction
PARMW,ARP05,60 # TR_NOM = 60s repetition
PARMW,GNP01,1 # GNSS enabled
PARMW,GNP05,120 # GNSS acquisition timeout = 120s
PARMW,PWP03,2 # Run every 2nd boot (effective period = 3.5h)
PARMW,PWP01,3600 # Stay awake max 1 hour per cycle
# Mortality detection (optional)
PARMW,MTP01,1 # Enable mortality detection
PARMW,MTP02,10 # Activity < 10/255 = immobile
PARMW,MTP03,25 # Body temp < 25°C = hypothermic
PARMW,MTP04,50 # GPS < 50m between sessions = stationary
PARMW,MTP05,3 # 3 consecutive days to confirm
# Adaptive modulation (optional, for LDK short packets)
PARMW,ARP54,1 # Enable adaptive modulation
PARMW,RSP01,1 # Use RSPB_SHORT format (LDK, 122 bits)
The following sealed-device hardening features apply to all board variants (LinkIt V4 KIM, SMD, LoRa, RSPB):
Each non-exempt LED FSM state arms a 10 s timeout. If no FSM transition occurs in that window, the LED is forced off — protection against a stuck state machine (e.g. Argos TX that never returns a completion event) leaving the LED solid for hours. Exempt states (intentionally solid): all 4 pre-operational states, ConfigConnected, OTASuccess, BatteryCritical. Located in ledsm.cpp. Initially 5 s, bumped to 10 s to cover full SMD Argos TX (TCXO 5 s + RF ≈ 3 s + margin).
The brown-out interrupt handler no longer calls save_params() (commit 12fdd581). Writing to LittleFS at brown-out was corrupting the filesystem in rare cases. Cooldown state is still persisted to .noinit RAM in the handler — that's safe (RAM write, no flash IO). LFS writes are limited to the periodic config flush (30 min) and planned shutdown paths, both of which run with stable Vbatt.
LS17500_2P chemistry support (BATTERY_CHEMISTRY=BATT_CHEM_LS17500_2P) ships at firmware default. The local coin cell / supercap charging circuit on the GNSS rail is now driven by a scheduled charge mode:
-
GNSS_BCKP_CHARGE_INT(GNP47, default 0=disabled): scheduling interval in seconds -
GNSS_BCKP_CHARGE_DUR(GNP48, default 300=5 min): duration per session -
GNSS_BCKP_CHARGE_UW_ONLY(GNP49, default false): only charge while underwater
When activated, the M10Q is powered, parked in UBX-RXM-PMREQ backup (~15 µA), and the rail stays up for GNSS_BCKP_CHARGE_DUR to allow the charging RC network to top up the cell. Required for long-duration deployments where BBR / RTC / almanac must survive across multi-day power-down windows.
Boot-fail counter + 5 exception barriers + smart WDT kicks. See 07 — Architecture § Sealed-device hardening.
SMD-based boards (LinkIt V4 SMD, RSPB) additionally benefit from:
- FAST/SAFE timing autofallback (11 — Satellite Communication § Part D)
- Cold-reboot STM32WL on every soft reset (eliminates the "looks like a regression but isn't" pattern)
- SMP00 / SMP01 read-only DTE diagnostics for field engineers