Skip to content

Instantly share code, notes, and snippets.

@j0uni
Created November 11, 2025 22:02
Show Gist options
  • Select an option

  • Save j0uni/dbffc6b1e8ce36be618c7441a1a65192 to your computer and use it in GitHub Desktop.

Select an option

Save j0uni/dbffc6b1e8ce36be618c7441a1a65192 to your computer and use it in GitHub Desktop.
Seeed Sensecap T1000-E firmware / flash recovery
# T1000-E Full Flash Corruption Recovery
## When You Need This
Your T1000-E is completely bricked:
- No LED, no USB, nothing works
- Device doesn't respond at all
- Flash is corrupted or erased
- Bootloader is gone
**Don't panic!** You can recover it with ST-Link.
## What You Need
### Hardware
- **ST-Link v2** (or compatible debugger)
- USB cable for ST-Link
- Jumper wires (SWDIO, SWCLK, GND, 3.3V)
- T1000-E board
### Software
- **OpenOCD** (usually comes with PlatformIO or install separately)
- **nrfjprog** (optional, but useful)
### Files You Need
1. **SoftDevice S140 v7.3.0** (or v7.2.0)
- Location: `[your_path]/s140_nrf52_7.3.0/s140_nrf52_7.3.0_softdevice.hex`
- Or download from Nordic: https://developer.nordicsemi.com/
2. **Bootloader hex file**
- Location: `[your_path]/t1000_e_bootloader-0.9.2_s140_7.3.0.hex`
- Or: `t1000_e_bootloader-0.9.1-5-g488711a_s140_7.3.0.hex`
3. **Your application firmware** (optional, can flash later)
- Built with PlatformIO: `.pio/build/tracker-t1000-e/firmware.hex`
## Quick Recovery Steps
### 1. Connect ST-Link
Pick up your favorite mini tool because it's time to do a hole in your unit. You can see the pads on right to the power button and led. The cover is probably glued together so only way to access JTAG connectors is to make a hole in your unit. WORK SLOWLY as the PCB is really close to the plastic case.
Wire it up:
```
ST-Link → T1000-E
SWDIO → SWDIO (usually labeled)
SWCLK → SWCLK (usually labeled)
GND → GND
3.3V → 3.3V (or VCC)
```
**Important:** Don't connect 5V! T1000-E is 3.3V only.
### 2. Verify ST-Link Connection
```bash
# Check if ST-Link is detected
system_profiler SPUSBDataType | grep -i "st-link\|stm32"
# Or test with OpenOCD
openocd -f interface/stlink.cfg -f target/nrf52.cfg
# Should see "target halted" or similar
# Press Ctrl+C to exit
```
### 3. Full Chip Erase
**This wipes everything** - bootloader, SoftDevice, application, settings. Clean slate.
```bash
# Method 1: Using OpenOCD (recommended)
openocd -f interface/stlink.cfg -f target/nrf52.cfg
# Then in telnet (another terminal):
telnet localhost 4444
> nrf52 mass_erase
> shutdown
```
```bash
# Method 2: Using nrfjprog (if you have it)
nrfjprog --recover
```
### 4. Flash SoftDevice
This is the Bluetooth stack. **Must be flashed first.**
```bash
openocd -f interface/stlink.cfg -f target/nrf52.cfg
# In telnet:
telnet localhost 4444
> halt
> reset halt
> program [your_path]/s140_nrf52_7.3.0/s140_nrf52_7.3.0_softdevice.hex verify
> reset
> shutdown
```
**Or use a script:**
```bash
# Create flash script
cat > /tmp/flash_sd.txt << EOF
halt
reset halt
sleep 500
program [your_path]/s140_nrf52_7.3.0/s140_nrf52_7.3.0_softdevice.hex verify
reset
shutdown
EOF
# Run it
openocd -f interface/stlink.cfg -f target/nrf52.cfg &
sleep 3
(sleep 1; cat /tmp/flash_sd.txt) | nc localhost 4444
```
### 5. Flash Bootloader
Now flash the bootloader. This enables USB serial and DFU mode.
```bash
openocd -f interface/stlink.cfg -f target/nrf52.cfg
# In telnet:
telnet localhost 4444
> halt
> reset halt
> program [your_path]/t1000_e_bootloader-0.9.2_s140_7.3.0.hex verify
> reset
> shutdown
```
**Or script it:**
```bash
cat > /tmp/flash_bl.txt << EOF
halt
reset halt
sleep 500
program [your_path]/t1000_e_bootloader-0.9.2_s140_7.3.0.hex verify
reset
shutdown
EOF
openocd -f interface/stlink.cfg -f target/nrf52.cfg &
sleep 3
(sleep 1; cat /tmp/flash_bl.txt) | nc localhost 4444
```
### 6. Flash Application (Optional)
You can flash your application now, or do it later via bootloader DFU.
```bash
# Build your firmware first
pio run -e tracker-t1000-e
# Flash via ST-Link
openocd -f interface/stlink.cfg -f target/nrf52.cfg
# In telnet:
telnet localhost 4444
> halt
> reset halt
> program .pio/build/tracker-t1000-e/firmware.hex verify
> reset
> shutdown
```
## One-Liner Recovery Script
Here's a complete recovery script that does everything:
```bash
#!/bin/bash
# Save as: recover_t1000e.sh
SOFTDEVICE="[your_path]/s140_nrf52_7.3.0/s140_nrf52_7.3.0_softdevice.hex"
BOOTLOADER="[your_path]/t1000_e_bootloader-0.9.2_s140_7.3.0.hex"
OCD_CONFIG="/tmp/recover.cfg"
cat > "$OCD_CONFIG" << 'EOF'
source [find interface/stlink.cfg]
transport select hla_swd
source [find target/nrf52.cfg]
adapter speed 1000
EOF
echo "Step 1: Full chip erase..."
openocd -f "$OCD_CONFIG" > /tmp/recover.log 2>&1 &
OCD_PID=$!
sleep 3
echo "nrf52 mass_erase" | nc localhost 4444 > /dev/null 2>&1
sleep 2
kill $OCD_PID 2>/dev/null || true
wait $OCD_PID 2>/dev/null || true
echo "Step 2: Flashing SoftDevice..."
openocd -f "$OCD_CONFIG" > /tmp/recover.log 2>&1 &
OCD_PID=$!
sleep 3
cat > /tmp/flash_sd.txt << CMDEOF
halt
reset halt
sleep 500
program ${SOFTDEVICE} verify
reset
shutdown
CMDEOF
(sleep 1; cat /tmp/flash_sd.txt) | nc localhost 4444
kill $OCD_PID 2>/dev/null || true
wait $OCD_PID 2>/dev/null || true
echo "Step 3: Flashing bootloader..."
openocd -f "$OCD_CONFIG" > /tmp/recover.log 2>&1 &
OCD_PID=$!
sleep 3
cat > /tmp/flash_bl.txt << CMDEOF
halt
reset halt
sleep 500
program ${BOOTLOADER} verify
reset
shutdown
CMDEOF
(sleep 1; cat /tmp/flash_bl.txt) | nc localhost 4444
kill $OCD_PID 2>/dev/null || true
wait $OCD_PID 2>/dev/null || true
rm -f "$OCD_CONFIG" /tmp/flash_sd.txt /tmp/flash_bl.txt
echo "✅ Recovery complete! Disconnect ST-Link and power cycle."
```
## Diagnostic Commands
Before and after recovery, these commands help you understand what's going on:
### Check ST-Link Connection
```bash
# Verify ST-Link is detected
system_profiler SPUSBDataType | grep -i "st-link\|stm32"
# Test OpenOCD connection
openocd -f interface/stlink.cfg -f target/nrf52.cfg
# Should see "target halted" - if not, wiring issue
```
### Check Processor State
```bash
# Start OpenOCD
openocd -f interface/stlink.cfg -f target/nrf52.cfg &
sleep 3
# Check processor registers
echo "halt" | nc localhost 4444
echo "reg pc" | nc localhost 4444 # Program counter
echo "reg sp" | nc localhost 4444 # Stack pointer
echo "reg lr" | nc localhost 4444 # Link register
echo "reg xpsr" | nc localhost 4444 # Program status register
# Check if processor is running or halted
echo "reg" | nc localhost 4444
```
**What to look for:**
- `PC = 0x00000a80` → SoftDevice reset handler (normal after reset)
- `PC = 0x0003d7ae` → Application code (device is running)
- `PC = 0x000fb3a1` → Bootloader code (bootloader is running)
- `PC = 0x00000000` or weird values → Corrupted flash
### Check Flash Contents
```bash
# Check SoftDevice vector table (should have valid SP and reset handler)
echo "mdw 0x00000000 4" | nc localhost 4444
# Should see: SP (RAM address like 0x200013c8), Reset handler (like 0x00000a81)
# Check application vector table (at 0x27000)
echo "mdw 0x27000 4" | nc localhost 4444
# Should see: SP (RAM address), Reset handler (application entry)
# Check bootloader code (at 0xF4000)
echo "mdw 0xF4000 8" | nc localhost 4444
# Should see: SP (RAM address), Reset handler (bootloader entry like 0x000fb3a1)
# If all 0xFF or 0x00 → bootloader is missing/corrupted
```
### Check Bootloader Settings
```bash
# Check bootloader settings page (0xFF000)
echo "mdw 0xFF000 8" | nc localhost 4444
# Should see:
# 0x00000001 = Magic
# 0x00000001 = Version
# 0x00000001 = App Valid
# 0x00000000 = CRC
# If all 0xFF → settings are empty/invalid
```
### Check UICR (User Information Configuration Register)
```bash
# Check UICR BOOTLOADERADDR (tells SoftDevice where bootloader is)
echo "mdw 0x10001014 1" | nc localhost 4444
# Should see: 0x000F4000 (bootloader address)
# If 0xFFFFFFFF → bootloader not registered with SoftDevice
```
### Check SoftDevice Integrity
```bash
# Check SoftDevice vector table
echo "mdw 0x00000000 4" | nc localhost 4444
# First word = Initial SP (should be RAM address like 0x200013c8)
# Second word = Reset handler (should be valid code address)
# If SP = 0x00000000 or Reset = 0x00000004 → SoftDevice is corrupted!
```
### Check Application Region
```bash
# Check if application is present
echo "mdw 0x27000 8" | nc localhost 4444
# Should see valid vector table if application is flashed
# If all 0xFF → application region is empty
```
### Check Fault Registers (if device crashed)
```bash
# Check why device might be in HardFault
echo "mdw 0xE000ED28 1" | nc localhost 4444 # CFSR (Configurable Fault Status)
echo "mdw 0xE000ED2C 1" | nc localhost 4444 # HFSR (Hard Fault Status)
echo "mdw 0xE000ED34 1" | nc localhost 4444 # MMFAR (MemManage Fault Address)
echo "mdw 0xE000ED38 1" | nc localhost 4444 # BFAR (Bus Fault Address)
# CFSR = 0x00000000 → No faults (good!)
# CFSR != 0 → Device had a fault/crash
```
### Quick Status Check Script
```bash
#!/bin/bash
# Save as: check_device_status.sh
OCD_CONFIG="/tmp/check_status.cfg"
cat > "$OCD_CONFIG" << 'EOF'
source [find interface/stlink.cfg]
transport select hla_swd
source [find target/nrf52.cfg]
adapter speed 1000
EOF
openocd -f "$OCD_CONFIG" > /tmp/check.log 2>&1 &
OCD_PID=$!
sleep 3
echo "=== Device Status Check ==="
echo ""
echo "Processor State:"
echo "halt" | nc localhost 4444 > /dev/null 2>&1
PC=$(echo "reg pc" | nc localhost 4444 2>&1 | grep -oE "0x[0-9a-f]+" | head -1)
SP=$(echo "reg sp" | nc localhost 4444 2>&1 | grep -oE "0x[0-9a-f]+" | head -1)
echo " PC: $PC"
echo " SP: $SP"
echo ""
echo "SoftDevice Vector Table:"
echo "mdw 0x00000000 2" | nc localhost 4444 2>&1 | grep "0x00000000" || true
echo ""
echo "Bootloader Code (0xF4000):"
echo "mdw 0xF4000 2" | nc localhost 4444 2>&1 | grep "0xf4000" || true
echo ""
echo "Bootloader Settings (0xFF000):"
echo "mdw 0xFF000 4" | nc localhost 4444 2>&1 | grep "0xff000" || true
echo ""
echo "UICR BOOTLOADERADDR:"
echo "mdw 0x10001014 1" | nc localhost 4444 2>&1 | grep "0x10001014" || true
echo ""
kill $OCD_PID 2>/dev/null || true
wait $OCD_PID 2>/dev/null || true
rm -f "$OCD_CONFIG"
```
### Check USB Device (After Recovery)
```bash
# Check if T1000-E appears as USB device
system_profiler SPUSBDataType | grep -i -A 5 "2886\|0057\|seeed\|t1000"
# Check for USB serial ports
ls -la /dev/cu.usbmodem*
# Check USB VID/PID (T1000-E should be 0x2886:0x0057)
system_profiler SPUSBDataType | grep -B 2 -A 2 "2886\|0057"
```
## Verification
After recovery, check if it worked:
```bash
# 1. Disconnect ST-Link
# 2. Connect T1000-E via USB only
# 3. Power cycle (unplug/replug USB)
# 4. Check for USB serial port
ls /dev/cu.usbmodem*
# 5. Check USB device
system_profiler SPUSBDataType | grep -i "2886\|0057\|seeed"
```
If you see a USB port, **you're saved!** 🎉
### Verify Boot Sequence
```bash
# Connect ST-Link and check where device boots
openocd -f interface/stlink.cfg -f target/nrf52.cfg &
sleep 3
# Reset and check PC
echo "reset" | nc localhost 4444
sleep 2
echo "halt" | nc localhost 4444
PC=$(echo "reg pc" | nc localhost 4444 2>&1 | grep -oE "0x[0-9a-f]+" | head -1)
PC_DEC=$((16#${PC#0x}))
if [ $PC_DEC -ge $((16#F4000)) ]; then
echo "✅ Bootloader is running"
elif [ $PC_DEC -ge $((16#27000)) ]; then
echo "✅ Application is running (bootloader jumped to app)"
else
echo "⚠️ Device in SoftDevice region (may be initializing)"
fi
```
## Before You Start: Check Device Status
Run diagnostics first to understand what's broken:
```bash
# Quick check - is device completely dead?
./check_device_status.sh # (use the script above)
# Or manually:
openocd -f interface/stlink.cfg -f target/nrf52.cfg
# In another terminal:
telnet localhost 4444
> halt
> reg pc
> mdw 0x00000000 2
> mdw 0xF4000 2
> mdw 0xFF000 4
```
**What you're looking for:**
- **All 0xFF or 0x00** → Flash is erased/corrupted (needs full recovery)
- **Valid vector tables** → Some parts are OK, maybe just need bootloader
- **PC in weird location** → Device crashed, needs reset + reflash
## Common Issues
### "OpenOCD can't connect"
- Check ST-Link wiring (SWDIO, SWCLK, GND)
- Try different USB port/cable
- Verify ST-Link is detected: `system_profiler SPUSBDataType | grep -i st-link`
### "Flash write failed"
- Device might be locked - do mass erase first
- Check file paths are correct
- Try slower adapter speed: `adapter speed 100` in OpenOCD config
### "Device still doesn't work"
- Verify SoftDevice and bootloader versions match (both S140 v7.3.0)
- Check bootloader settings page (should be auto-created)
- Try flashing application firmware
### "No USB serial after recovery"
- Bootloader might be jumping to app immediately
- Application needs to initialize USB serial
- Try double-tap RESET to enter DFU mode
## Pro Tips
1. **Always flash SoftDevice first** - bootloader depends on it
2. **Match versions** - SoftDevice and bootloader must match (both v7.3.0)
3. **Mass erase is safe** - when device is completely dead, you have nothing to lose
4. **Keep recovery files handy** - SoftDevice and bootloader hex files
5. **Test after each step** - flash SoftDevice, test; flash bootloader, test
## File Locations Summary
```
SoftDevice: [your_path]/s140_nrf52_7.3.0/s140_nrf52_7.3.0_softdevice.hex
Bootloader: [your_path]/t1000_e_bootloader-0.9.2_s140_7.3.0.hex
Application: .pio/build/tracker-t1000-e/firmware.hex (after building)
```
## TL;DR
1. Connect ST-Link
2. Mass erase: `nrf52 mass_erase` in OpenOCD
3. Flash SoftDevice hex
4. Flash bootloader hex
5. Disconnect ST-Link, power cycle
6. Device should work!
That's it. Your T1000-E is back from the dead. 💀→😊
@FlyFry20
Copy link
Copy Markdown

Can you tell me what version of OpenOCD you used in this example? I’ve tried it but without success - the mass_erase request doesn’t work. I downloaded the ‘official’ version V10 on a Mint version of Linux.

@j0uni
Copy link
Copy Markdown
Author

j0uni commented Mar 27, 2026

0.12.0 on MacOS

@FlyFry20
Copy link
Copy Markdown

Thank you so much for your response. I finally managed to get V12 onto my old laptop running Linux Mint and it worked - in the end.
I still couldn’t get the ‘mass_erase’ part to work, getting an error [Failed to erase reg: 0x4001e50c val: 0x00000001].
I continued through your steps to flash the soft device & bootloader hex and it’s now working as I wanted it to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment