diff --git a/docs/.images/raspberry_pi_gpio_pinout.png b/docs/.images/raspberry_pi_gpio_pinout.png new file mode 100644 index 0000000000..4796a8f41e Binary files /dev/null and b/docs/.images/raspberry_pi_gpio_pinout.png differ diff --git a/docs/flashing/README.md b/docs/flashing/README.md new file mode 100644 index 0000000000..64d41ce0e3 --- /dev/null +++ b/docs/flashing/README.md @@ -0,0 +1,11 @@ +# Flashing Guides + +Instructions for flashing custom firmware onto Zigbee modules. + +## By Chip Type + +| Chip Family | Guide | +|-------------|-------| +| Silicon Labs (EFR32MG21) | [SiLabs Flashing](silabs.md) | +| Telink (TLSR8258) | [Telink Flashing](telink.md) | +| ZBMINIL2 | [ZBMINIL2 Flashing](zbminil2.md) | diff --git a/docs/flashing/silabs.md b/docs/flashing/silabs.md index 60ce0e9db4..eb569b5ed6 100644 --- a/docs/flashing/silabs.md +++ b/docs/flashing/silabs.md @@ -1,93 +1,17 @@ -# How to Flash via Wire +# Silicon Labs (EFR32MG21) Flashing -### What You'll Need +Guides for flashing custom firmware onto Silicon Labs EFR32MG21 chips (Tuya ZS3L module). -- A J-Link programmer (JLink v9 confirmed to work) -- A soldering iron -- Some spare jumper wires +## Flashing Methods -### Step 1: Disassemble the Device +| Method | Hardware Required | +|--------|-------------------| +| [J-Link v9](silabs_jlink_v9.md) | J-Link programmer | +| [Raspberry Pi GPIO](silabs_raspberry_pi.md) | Raspberry Pi 3B+ | -Unplug the device from the mains. **Never attempt to disassemble it while it is plugged in!** +## ZS3L Module -In general, you need to disassemble devices until you have access to the ZS3L module or MCU itself. Here is a detailed example guide for the Moes 4 Gang switch. +- Chip: EFR32MG21A020 +- Flash: 768 KiB +- Pinout: [Tuya ZS3L Documentation](https://developer.tuya.com/en/docs/iot/zs3l?id=K97r37j19f496) -First, pop the front glass panel: - -![Front glass disassembly](/docs/.images/moes_4_gang_disassemble_front.jpg) - -Then gently detach the PCB from the device. Alternate the sides you use for leverage to avoid damage to the connector. - -![PCB disassembly](/docs/.images/moes_4_gang_disassemble_pcb.jpg) - -### Step 2: Solder the Wires - -You'll need to solder five wires as shown in the photos: GND, 3.3V, SWDIO, SWCLK, RST. - -If you have a ZS3L module, you can use the following [Tuya docs](https://developer.tuya.com/en/docs/iot/zs3l?id=K97r37j19f496) for reference. Or just follow this schema: - -![PCB connections](/docs/.images/meos_4_gang_pcb.jpg) - -For Moes 4 gang, we can re-use the connector to plug in power: - -![PCB power](/docs/.images/moes_4_gang_pcb_power.jpg) - -But you have to solder to the other pins. There is no need for a long-term connection, but be sure not to bridge the pins together. - -![PCB power](/docs/.images/moes_4_gang_pcb_wires.jpg) - -Finally, attach the wires to your J-Link programmer (for JLINK V9, the connection should look like this, following the color schema used above): - -![PCB power](/docs/.images/jlink_wires.jpg) - -### Step 3: Flash the Firmware - -Download both the bootloader and firmware for your device from [bin/](https://github.com/romasku/tuya-zigbee-switch/raw/refs/heads/main/bin). You'll need the generic `efr32mg21_bootloader.s37` and the `.s37` file specific for your device. - -#### Using Commander Software - -There are different software options that you can use for flashing, but one of the easiest options is to use Simplicity Commander from Silicon Labs. Download Commander from [this page](https://www.silabs.com/software-and-tools/simplicity-studio/simplicity-commander?tab=getting-started). - -Plug the J-Link into your PC, then open Commander and select your flasher. It may be named as some random set of numbers, that's ok. - -![commander select device](/docs/.images/commander_select_kit.png) - -**Check the connection:** - -Open the device info page to verify that the connection is good: - -![commander device info](/docs/.images/commander_device_info.png) - -If this doesn't work, you can try constantly tapping on the device touch button. This is because the device can be in deep sleep and the flasher cannot communicate with it. If this is your case, keep tapping until you erase the chip. - -**Erase the chip:** - -Open the flash tab and erase the chip. **THIS WILL DELETE STOCK FIRMWARE!** If you want to keep it, press "Open shell" below and use this command to backup the stock firmware: - -``` -commander readmem --device EFR32MG21 --region @mainflash --outfile stock_dump.bin -``` - -![commander erase](/docs/.images/commander_erase.png) - -**Flash the bootloader and firmware:** - -Now you'll need to flash both the bootloader and firmware separately. - -1. Press "Browse": - - ![commander ](/docs/.images/commander_browse.png) - -2. Select the bootloader file (`efr32mg21_bootloader.s37`): - - ![commander ](/docs/.images/commander_select_bootloader.png) - -3. Press "Flash" and wait until the process finishes: - - ![commander ](/docs/.images/commander_flash.png) - -4. Now select your device-specific firmware file and press "Flash" again. Wait until the process finishes: - - ![commander ](/docs/.images/commander_select_firmware.png) - -If done correctly, the onboard LED will start flashing automatically. You can try joining the device to a Zigbee network to verify that it connects properly. Once confirmed, disconnect everything, unsolder the wires, and reassemble the case. diff --git a/docs/flashing/silabs_jlink_v9.md b/docs/flashing/silabs_jlink_v9.md new file mode 100644 index 0000000000..60ce0e9db4 --- /dev/null +++ b/docs/flashing/silabs_jlink_v9.md @@ -0,0 +1,93 @@ +# How to Flash via Wire + +### What You'll Need + +- A J-Link programmer (JLink v9 confirmed to work) +- A soldering iron +- Some spare jumper wires + +### Step 1: Disassemble the Device + +Unplug the device from the mains. **Never attempt to disassemble it while it is plugged in!** + +In general, you need to disassemble devices until you have access to the ZS3L module or MCU itself. Here is a detailed example guide for the Moes 4 Gang switch. + +First, pop the front glass panel: + +![Front glass disassembly](/docs/.images/moes_4_gang_disassemble_front.jpg) + +Then gently detach the PCB from the device. Alternate the sides you use for leverage to avoid damage to the connector. + +![PCB disassembly](/docs/.images/moes_4_gang_disassemble_pcb.jpg) + +### Step 2: Solder the Wires + +You'll need to solder five wires as shown in the photos: GND, 3.3V, SWDIO, SWCLK, RST. + +If you have a ZS3L module, you can use the following [Tuya docs](https://developer.tuya.com/en/docs/iot/zs3l?id=K97r37j19f496) for reference. Or just follow this schema: + +![PCB connections](/docs/.images/meos_4_gang_pcb.jpg) + +For Moes 4 gang, we can re-use the connector to plug in power: + +![PCB power](/docs/.images/moes_4_gang_pcb_power.jpg) + +But you have to solder to the other pins. There is no need for a long-term connection, but be sure not to bridge the pins together. + +![PCB power](/docs/.images/moes_4_gang_pcb_wires.jpg) + +Finally, attach the wires to your J-Link programmer (for JLINK V9, the connection should look like this, following the color schema used above): + +![PCB power](/docs/.images/jlink_wires.jpg) + +### Step 3: Flash the Firmware + +Download both the bootloader and firmware for your device from [bin/](https://github.com/romasku/tuya-zigbee-switch/raw/refs/heads/main/bin). You'll need the generic `efr32mg21_bootloader.s37` and the `.s37` file specific for your device. + +#### Using Commander Software + +There are different software options that you can use for flashing, but one of the easiest options is to use Simplicity Commander from Silicon Labs. Download Commander from [this page](https://www.silabs.com/software-and-tools/simplicity-studio/simplicity-commander?tab=getting-started). + +Plug the J-Link into your PC, then open Commander and select your flasher. It may be named as some random set of numbers, that's ok. + +![commander select device](/docs/.images/commander_select_kit.png) + +**Check the connection:** + +Open the device info page to verify that the connection is good: + +![commander device info](/docs/.images/commander_device_info.png) + +If this doesn't work, you can try constantly tapping on the device touch button. This is because the device can be in deep sleep and the flasher cannot communicate with it. If this is your case, keep tapping until you erase the chip. + +**Erase the chip:** + +Open the flash tab and erase the chip. **THIS WILL DELETE STOCK FIRMWARE!** If you want to keep it, press "Open shell" below and use this command to backup the stock firmware: + +``` +commander readmem --device EFR32MG21 --region @mainflash --outfile stock_dump.bin +``` + +![commander erase](/docs/.images/commander_erase.png) + +**Flash the bootloader and firmware:** + +Now you'll need to flash both the bootloader and firmware separately. + +1. Press "Browse": + + ![commander ](/docs/.images/commander_browse.png) + +2. Select the bootloader file (`efr32mg21_bootloader.s37`): + + ![commander ](/docs/.images/commander_select_bootloader.png) + +3. Press "Flash" and wait until the process finishes: + + ![commander ](/docs/.images/commander_flash.png) + +4. Now select your device-specific firmware file and press "Flash" again. Wait until the process finishes: + + ![commander ](/docs/.images/commander_select_firmware.png) + +If done correctly, the onboard LED will start flashing automatically. You can try joining the device to a Zigbee network to verify that it connects properly. Once confirmed, disconnect everything, unsolder the wires, and reassemble the case. diff --git a/docs/flashing/silabs_raspberry_pi.md b/docs/flashing/silabs_raspberry_pi.md new file mode 100644 index 0000000000..f02744f458 --- /dev/null +++ b/docs/flashing/silabs_raspberry_pi.md @@ -0,0 +1,207 @@ +# Flashing Tuya ZS3L (EFR32MG21) via Raspberry Pi + +This guide covers flashing custom Zigbee firmware onto Tuya ZS3L using Raspberry Pi GPIO as SWD programmer. + +### What You'll Need + +- Raspberry Pi (or similar with GPIO) (tested on Raspberry Pi 3B+) +- Jumper wires +- Soldering iron + +### ZS3L Chip Pinout + +If you have a ZS3L module, you can use the following [Tuya docs](https://developer.tuya.com/en/docs/iot/zs3l?id=K97r37j19f496) for reference. Or just follow this schema: + +![PCB connections](/docs/.images/meos_4_gang_pcb.jpg) + +ℹ **Note:** Sometimes there is no need to solder 3.3V/GND. You can find them on the board and use a connector. + +ℹ **Note:** No need to solder nRST pin. It causes connection issues. + +## Step 1: Hardware Wiring + +![Raspberry Pi GPIO diagram](/docs/.images/raspberry_pi_gpio_pinout.png) + +Connect ZS3L to Raspberry Pi (BCM numbering): + +| ZS3L Pin | Raspberry Pi | Physical Pin | +|----------|--------------|--------------| +| SWDIO | GPIO 24 | Pin 18 | +| SWCLK | GPIO 25 | Pin 22 | +| GND | GND | Pin 14 | +| VCC | 3.3V | Pin 1 or 17 | + +⚠️ **NEVER use 5V - it will destroy the chip!** + +ℹ **Note:** No need for nRST pin. It causes connection issues. + +## Step 2: Compile Custom OpenOCD + +Standard OpenOCD doesn't support EFM32 Series 2. Use [knieriem's fork](https://github.com/knieriem/openocd-efm32-series2): + +```bash +sudo apt-get update +sudo apt-get install git autoconf libtool make pkg-config + +git clone https://github.com/knieriem/openocd-efm32-series2.git +cd openocd-efm32-series2 + +./setup-openocd-src.sh +``` + +You will be asked to run `./build.sh`, but skip this step — it's not needed when using GPIO. +If you use a USB programmer, you may need to run `./build.sh` to compile the driver. + +Compile the driver: + +```bash +cd openocd +./configure --enable-bcm2835gpio +make +make install +``` + +## Step 3: OpenOCD Configuration + +Create `openocd.cfg`: + +```tcl +transport select swd + +adapter gpio swdio 24 +adapter gpio swclk 25 + +set CHIPNAME efr32 +source [find target/efm32s2.cfg] + +reset_config srst_only srst_nogate +adapter speed 1000 + +init +targets +halt +``` + +## Step 4: Start Connection + +**Terminal 1** - Start OpenOCD daemon: + +```bash +openocd +``` + +You should see something like this: +``` +$ openocd +Open On-Chip Debugger 0.12.0+dev-01294-g2e60e2eca-dirty (2026-03-01-09:48) +Licensed under GNU GPL v2 +For bug reports, read + http://openocd.org/doc/doxygen/bugs.html +Warn : TMS/SWDIO moved to GPIO 8 (pin 24). Check the wiring please! +Info : BCM2835 GPIO JTAG/SWD bitbang driver +Info : clock speed 1000 kHz +Info : SWD DPIDR 0x6ba02477 +Info : [efr32.cpu] Cortex-M33 r0p3 processor detected +Info : [efr32.cpu] target has 8 breakpoints, 4 watchpoints +Info : starting gdb server for efr32.cpu on 3333 +Info : Listening on port 3333 for gdb connections +Warn : [efr32.cpu] target was in unknown state when halt was requested +Info : Listening on port 6666 for tcl connections +Info : Listening on port 4444 for telnet connections +Info : accepting 'telnet' connection on tcp/4444 +Info : detected part: MG21A020, rev 51 +Info : flash size = 768 KiB +Info : flash page size = 8192 B +Warn : Don't know EFR/EFM Gx family number, can't set MSC register. Defaulting to EF{M,R}xG22 values.. +``` + +**Terminal 2** - Connect via Telnet: + +```bash +telnet localhost 4444 +``` + +## Step 5: Verify, Backup, Erase, and Flash + +Execute in Telnet console (`>` prompt). ZS3L has 768 KiB flash (`0x000c0000`). + +### Verify Connection + +```shell +> halt +> targets +> flash info 0 +> flash probe 0 +> flash banks +> flash list +``` + +
+Example output + +```shell +> halt +> targets +TargetName Type Endian TapName State +-- ------------------ ---------- ------ ------------------ ------------ +0* efr32.cpu cortex_m little efr32.cpu halted +> flash info 0 +detected part: MG21A020, rev 51 +flash size = 768 KiB +flash page size = 8192 B +Don't know EFR/EFM Gx family number, can't set MSC register. Defaulting to EF{M,R}xG22 values.. +#0 : efm32s2 at 0x00000000, size 0x000c0000, buswidth 0, chipwidth 0 +# 0: 0x00000000 (0x2000 8kB) protected +# +# 94: 0x000bc000 (0x2000 8kB) protected +# 95: 0x000be000 (0x2000 8kB) protected +MG21A020, rev 51 +> flash probe 0 +detected part: MG21A020, rev 51 +flash size = 768 KiB +flash page size = 8192 B +Don't know EFR/EFM Gx family number, can't set MSC register. Defaulting to EF{M,R}xG22 values.. +flash 'efm32s2' found at 0x00000000 +> flash banks +#0 : efr32.flash (efm32s2) at 0x00000000, size 0x000c0000, buswidth 0, chipwidth 0 +#1 : userdata.flash (efm32s2) at 0x0fe00000, size 0x00000000, buswidth 0, chipwidth 0 +> flash list +{ +name efr32.flash +driver efm32s2 +base 0x00000000 +size 0xc0000 +bus_width 0 +chip_width 0 +target efr32.cpu +} +{ +name userdata.flash +driver efm32s2 +base 0x0fe00000 +size 0x0 +bus_width 0 +chip_width 0 +target efr32.cpu +} +``` + +
+ +### Backup + +```shell +> dump_image flash_dump.bin 0x0 0xc0000 +> dump_image userdata_dump.bin 0x0fe00000 0x400 +``` + +### Erase and Flash +```shell +> flash erase_address 0x0 0xc0000 +> flash write_image erase efr32mg21_bootloader_generic.s37 +> flash write_image erase tlc_switch-1.1.2-9a4eb422.s37 +> reset run +``` + +Device will enter pairing mode automatically. Disconnect wires and reassemble. +