logo elektroda
logo elektroda
X
logo elektroda

STM32F103C8T6 Blue Pill as CK-Link Debugger: C-SKY/T-Head/XuanTie CK804 Flash Backup Investigations

divadiow 594 4
ADVERTISEMENT
  • Helpful post
    #1 21539711
    divadiow
    Level 34  
    Here I'll document my journey with a cheap STM32F103C8T6 "blue pill" dev/hobby board bought from Ali Express. Despite the IC labelled as "STM32F103C8T6" the internal flash appears to be 128k instead of 64k making it more like an STM32F103CBT6. It seems this is not unexpected with STM32 fakes/clones.

    The purpose of this purchase is to make a cheap C-SKY CK-Link / T-Head CPU debugger in the hope that I can access and dump the flash of C-SKY based chips like the WinnerMicro W800/W801/W806 which are C-SKY CK804FGT.

    Close-up of an STM32F103C8T6 microcontroller on a blue PCB, with visible chip markings and soldered pins.
    STM32F103C8T6 blue pill development board with microcontroller, pin headers, and micro USB port, shown from top and bottom views.

    I bought 3 from the YouKeyi Store https://www.aliexpress.com/item/1005006999051681.html

    Photo of two blue STM32F103C8T6 development boards with gold pins, part of an online offer from YouKeyi Store.

    Using cjacker's developments at https://github.com/cjacker/cklink-lite-fw-convertor we can convert the 'cklink_lite.hex' file that ships with the T-Head debug server so it will run on the STM32 after flashing. cjacker also supplies a binary that's already been converted https://github.com/cjacker/cklink-lite-fw-con.../blob/main/cklink_lite-2.36_for-stm32f103.hex and version 2.37, along with a Windows-compatible Python conversion script can be found in this PR https://github.com/cjacker/cklink-lite-fw-convertor/pull/1/files. I'll attach all files here for safe-keeping.

    But how do we program the STM32? SWD - Serial Wire Debug!

    Using one of these cheap clone J-Link programmer/debuggers we can flash the STM32 using J-Flash.

    Cheap J-link OB programmer/debugger board with wires, USB-C type, on an online shop page, promo price £1.99.

    J-Flash can be downloaded from https://www.segger.com/products/debug-probes/j-link/technology/flash-download/

    Connect like so
    J-Link GND -> STM32 GND
    J-Link SWDIO -> STM32 SWIO
    J-Link SWCLK -> STM32 SWCLK
    J-Link 3V3/VCC - <disconnected>

    STM32F103C8T6 blue pill development board wired to another module on a blue electronics mat. J-Link programmer and STM32 blue pill board connected with jumper wires on a blue work mat.

    run J-Flash, make a new project and select "STM32F103CB" (128kb) from the target device list

    SEGGER J-Flash program window creating a new project for STM32F103CB microcontroller.

    with both devices powered from their micro-USB ports 'Target' and 'Connect' in J-Flash menus should see the device connect successfully
    SEGGER J-Flash V8.30 window displaying project information and log, showing successful connection to an STM32F103CB microcontroller.

    Now you can erase/write or read entire chip from the Target-> Manual Programming menu. First I read the Keil USB memory stick emulator demo thing that shipped with the STM32.

    Screenshot of the J-Flash tool with the “Target” menu and “Manual Programming” submenu open.

    To flash cklink_lite-2.37_for-stm32f103.hex just drag the file into J-Flash window -> Erase Chip -> Program & Verify

    SEGGER J-Flash program window with a successful target programming and verification message displayed.

    Power off the STM32 and re-plug it. If using Windows it should be detected as a C-Sky CKLink-Lite device

    Properties window of C-Sky CKLink-Lite device showing driver details tab.

    Now that this is done we need to engage with the T-Head debugging server so we can interface with C-SKY-based devices.

    Register for and download the T-Head debug server from https://www.xrvm.cn/community/download?id=4380347564587814912 - I'll be demonstrating the Windows variant. I attach Windows and Linux downloads at the latest version at time of writing, as well as the debug user guide PDF.

    The CPU I'll be connecting to is the CK804 in a Hi-Link HLK-W806-KIT dev board, the same as explained here https://github.com/cjacker/opensource-toolcha...your-own-ck-link-lite-debugger-with-stm32f103

    STM32 is connected to the HLK like so
    Table comparing the pinout of STM32F103 microcontroller with XT-E804 module.

    Two electronic modules connected with wires on a blue work mat.

    With power to STM32 and the W806, running the DebugServerConsole app should put the CPU into debug mode and show information about the CK-Link firmware version and the W806 CPU

    Code: Text
    Log in, to see the code


    DebugServerConsole window displaying T-HEAD Debugger Server and T-HEAD XuanTie CPU parameters.

    Extract the attached w806.elf file and put it into the \bin folder alongside the debug console executable - C:\Users\xxxx\AppData\Roaming\T-Head\T-HeadDebugServer\bin if installed to default location

    Code: Text
    Log in, to see the code


    Information about the elf file can be obtained with command flash -al w806.elf from the debug console

    DebuggerServer$ flash -al w806.elf
    Code: Text
    Log in, to see the code


    For reference the entire flash command list is as follows

    Code: Text
    Log in, to see the code


    so we should be able to dump the W806 flash content with a command like this

    Code: Text
    Log in, to see the code


    those arguments meaning:

    Code: Text
    Log in, to see the code


    The dump appears to work. 1mb took 56 seconds.

    Code: Text
    Log in, to see the code


    The dump lands in \bin folder
    Screenshot of a Windows folder named bin showing various files and folders, including dump.bin.

    The resultant file appears to contain data and even some plain text from the W806 demo flashed using Upgrade Tools

    Unfortunately flashing back as-is using command flash program -f blinkydump.bin -b -a 0x08000000 -al w806.elf does not appear to result in a bootable app, leaving the device waiting for an upload in the xmodem "CCCCCCCCCCC" mode

    Upgrade Tools V1.5.9 window with a long string of the letter c in the text field.

    Also curious is that erasing flash even though 'successful', doesn't appear to actually zero the flash, a subsequent dump appears to be almost identical to one taken before the erase - this is also true if using wm_tool (wm_tool_1.0.4.exe -c com79 -eo all) to erase the W806 over UART - no empty flash, though it does appear to go into CCCCC mode after the erase, so maybe it's changing some byte to mark as empty?
    debug console erase commands tried:

    flash erase -a 0x08000000 -s 0x100000 -al w806.elf
    flash erase -c -al w806.elf


    Other observations:

    COM port outputs this during read operations
    Code: Text
    Log in, to see the code

    and this with write
    Code: Text
    Log in, to see the code


    That's where I've got to right now. A working restore of the flash I think is the priority thing to work out. Unfortunately I do not have any C-Sky devices with their original firmware on to dump something new and interesting from a company like Tuya.
  • ADVERTISEMENT
  • #2 21542722
    divadiow
    Level 34  
    since posting, I've taken a different approach. I've opened up Upgrade_Tools_V1.5.9.exe with pyinstxtractor in search of the main flashing code. The most interesting stuff (I've seen so far) is in

    SerialThread.pyc
    icons_rc.pyc
    ImageThread.pyc
    MainWindow.pyc
    ConfigHelper.pyc

    after uncompyle6 on each we see commands like these that will be used to return information seen in the Upgrade Tools GUI when flashing

    Code: Python
    Log in, to see the code


    Code: Python
    Log in, to see the code


    A flashing tool window with process logs, showing BLE and WiFi MAC addresses, and a progress bar.

    These commands, and others, can be seen in various WinnerMicro documentation eg https://arduino.winnermicro.com/w800/en/2.3-beta.1/component_guides/rom.html

    We know the GUI doesn't offer a flash read option, but there might be something in the code to suggest this is possible.

    In SerialThread.py:

    Code: Python
    Log in, to see the code


    but how and what is needed to be running on the chip before these commands can be received and actioned?

    Screenshot of a code editor showing a Python function loadfirmware_ram with a file path highlighted.

    there is no sign of w800_fls_erase.img in any of the extractions so far. Fast-forward several hours of trying things, it turns out to be some virtual path in some Qt resource. It's pieced together from this Python byte code string in icons_rc.py

    Screenshot of a decompiled Python code fragment with the “qt_resource_data” field highlighted.

    Confirming the extraction was sound took some working out.
    As it happens, you can also see the same code in HxD live memory viewer. Here's the start of the same data as from byte code extraction

    Screenshot of a hex editor with the file Upgrade_Tools_V1.5.9.exe open and a block of data highlighted.

    Screenshot of a hex editor with a binary file open, displaying hexadecimal and decoded text data.

    Using SerialThread as a reference point GPT and I made some script to mimic resetting the device via AT+Z command and RTS, waiting for Xmodem CCC, uploading flash stub and sending commands. This script gets wifi mac, ble mac, flash ID and gain info from the device, it also asks which com port you want to use first.

    Terminal window running a Python script that reads data via serial port, displaying MAC IDs and Gain values in hexadecimal format.

    Flash ID 85, 15 = manufacturer and size, so, Puya and 2mb.

    The official tool uses this to detect flash size

    A code snippet in Python that checks flash memory capacity based on an identifier.

    Script correctly detects 14 as the flash size on W806 - 1MB

    Screenshot of a console displaying COM port selection and serial communication with commands and responses from a bootloader.
    (wifi and ble macs are FF even in GUI flasher tool, so not worried about that)

    what about adapting the flash read so the whole 2mb can be captured?
    Terminal displaying the process of reading flash memory from a device via serial port.

    in the dump we see data at 2400, the main image
    Screenshot of a hex editor showing the contents of a binary file, with hexadecimal addresses and data, as well as decoded text.

    and some other bits before that 0 and 2000
    Screenshot of a hex editor displaying binary data from a file.

    Diagram of flash memory layout showing key parameter, header, and image areas with addresses.

    Screenshot showing a section of a file opened in a hex editor.

    I've had quite a few variation of script and it seems timing and flushes are critical to a clean dump. Oftentimes without the right flush or pause the end or beginning of flash would contain Xmodem CCC.

    I also played with set gain a little, but I think this is in ROM so cannot be changed. My 3 boards return this though for the gain read

    HLK-W806
    Code: Text
    Log in, to see the code


    HLK-W801
    Code: Text
    Log in, to see the code


    HLK-W800
    Code: Text
    Log in, to see the code


    In ConfigHelper.py we see a gain value for W600 and W800. I'm not sure why this is set or its effect. It does not appear to be persistent.

    A snippet of Python code with dictionary assignments and configuration saving.

    I think that's as far as I've got for now. I'll attach the scripts used in the screenshots (and more - some may not work), the stub and the py files. If anyone wants more let me know.

    TODO/questions:
    Where does official flasher start writing from and how does it handle .fls and .img files differently?
    Can a device backup be flashed back to make a working device?
    What differences are there between a backup taken from CKLink method and UART?
    Why does W806 not read flash when W800/W801 does?
    Does this work on a real device? And does anyone have a real W800 with factory Tuya firmware intact?
  • ADVERTISEMENT
  • #3 21544784
    divadiow
    Level 34  
    I remembered I had a Hi-Link HLK-B36 - a W800 module - that I had not flashed OBK to. It still boots Hi-Link firmware

    HK-B36-V1.1 electronic module with W800-B800 chip and visible SMD components.

    Code: Text
    Log in, to see the code


    and broadcasts AP "HI-LINK-184C"
    Wi-Fi network name HI-LINK_184C with signal and lock icon.

    Dump using w800_flash_read_crc_flush_double.py shows no captured CCCC whereas w800_flash_read.py does

    Code: Text
    Log in, to see the code


    we clearly see data at the expected points in file

    Screenshot of a hex editor displaying hexadecimal and ASCII data. A section of a file in a hex editor, showing addresses, hex values, and corresponding ASCII characters.
    A file fragment in a hex editor showing the ‘MAGI’ signature and ASCII text on the right.
    and signs of HLK
    A section of a hex editor with the text HLK-BLE_184C visible and IP addresses shown.

    despite soldering and short cables, I have not been able to get the CK-Link method to connect to the CPU :(

    Two electronic modules connected with wires on a blue service mat.
  • ADVERTISEMENT
  • #4 21550397
    divadiow
    Level 34  
    and following the Bouffalo Lab part we can connect to BL602 MCU with the T-Head debug server too
    https://github.com/cjacker/opensource-toolchain-bouffalo-lab

    T-HeadDebugServer window displaying debugger connection and RISC-V CPU information.

    Code: Text
    Log in, to see the code


    I am using BL602 Ai-Thinker NodeMCU Ai-WB2-32S-Kit
    Two electronic modules connected with wires on a blue mat.

    STM32F103 assignments for BL
    STM32F103FunctionBL602/BL604BL702/BL704/BL706BL616/BL618BL808
    A5TMSGPIO12GPIO0GPIO0GPIO6
    A1TCKGPIO14GPIO2GPIO1GPIO12
    A4TDOGPIO11GPIO9GPIO2GPIO7
    B9TDIGPIO17GPIO1GPIO3GPIO13


    This is maybe how you could fix your BL602 @p.kaczmarek2 if UART is not successful
ADVERTISEMENT