Created
November 11, 2025 22:02
-
-
Save j0uni/dbffc6b1e8ce36be618c7441a1a65192 to your computer and use it in GitHub Desktop.
Seeed Sensecap T1000-E firmware / flash recovery
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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. 💀→😊 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.