logo elektroda
logo elektroda
X
logo elektroda

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

divadiow 1407 15
ADVERTISEMENT
  • Helpful post
    #1 21539711
    divadiow
    Level 36  
    September 2025 Update:
    see here for details about converting STM32 over UART instead of J-Link (ie, J-Link not required) https://www.elektroda.com/rtvforum/viewtopic.php?p=21695356#21695356 (thanks @max4elektroda!)
    see here for higher version converted CK-Link Lite firmware for STM32 https://www.elektroda.com/rtvforum/topic4120455.html#21554694



    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
  • Helpful post
    #2 21542722
    divadiow
    Level 36  
    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?
  • Helpful post
    #3 21544784
    divadiow
    Level 36  
    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.
  • #4 21550397
    divadiow
    Level 36  
    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
  • #6 21642427
    Harbour
    Level 3  
    Anybody having the TXW8301 FLASH ALGORITHM ELF file ? Getting the error "ERROR: Current CPU is not in debug-mode, can't do any flash operations" while trying to dump the flash when using other elf files.

    P.S.

    The flash is SPI 16Mbit W25Q16JVSSIG

    The CPU inside TXW8301 is CK803SG:

    +--  Debug Arch is CKHAD.  --+
    +--  CPU 0  --+
    XuanTie CPU Info:
       WORD[0]: 0x04901053
       WORD[1]: 0x11000000
       WORD[2]: 0x21400417
       WORD[3]: 0x30c00000
    Target Chip Info:
       CPU Type is CK803SG, in LITTLE Endian.
       Bus type is AHB32.
       Signoff date is 04/0107.
       HWBKPT number is 9, HWWP number is 2.
  • #7 21643082
    divadiow
    Level 36  
    im not seeing any additional flash algorithm files in the TXW8301 SDK.

    Your error sounds more like a not connecting type of thing though rather than a flash read problem.

    looks like we have read CK803SG variant successfully here https://www.elektroda.com/rtvforum/topic4129331.html

    Maybe this is the kind of error you'd expect with wrong flash algo file?

    https://www.elektroda.com/rtvforum/topic4134923.html#21640179

    Have you tried lower ICE Clk speeds?
  • ADVERTISEMENT
  • #8 21643230
    Harbour
    Level 3  
    divadiow wrote:
    I'm not seeing any additional flash algorithm files in the TXW8301 SDK.


    The TXW8301 SDK never contained flash algorithm files. These files were supplied with programmer. I see the files:

    Taixin_TXW80X_FLASH_ALGORITHM.elf
    Taixin_TXW81X_FLASH_ALGORITHM.elf
    WinnerMicro_W800_FLASH_ALGORITHM.elf
    WinnerMicro_W806_FLASH_ALGORITHM.elf

    But there are no TXW83X files present!

    Quote:

    Your error sounds more like a not connecting type of thing though rather than a flash read problem.

    looks like we have read CK803SG variant successfully here https://www.elektroda.com/rtvforum/topic4129331.html


    This link is about TXW816 for which algorithm file is definitely present.

    Quote:

    Maybe this is the kind of error you'd expect with wrong flash algo file?


    Exactly as I have no TXW83X FLASH ALGORITHM file. This was the my question.

    Quote:


    Will try, but seems like Linux Debug server app just ignores ICE speed command line option and I do not use Windows.

    P.S. Tried with 12kHz

    XuanTie: CKLink_Lite_V2, App_ver 2.38, Bit_ver null, Clock 12.027KHz,
    


    The same error
  • #9 21643295
    divadiow
    Level 36  
    sure. The TXW80X and TX81X algorithm files were pulled from the SDKs for those platforms so I wondered if the TXW8301 SDK might also contain some specific to that platform

    List of ELF files and SDK paths for TXW806 and TXW81X in Windows File Explorer

    Quote:
    Maybe this is the kind of error you'd expect with wrong flash algo file?

    with reference to this error: https://obrazki.elektroda.pl/6958044300_1755725962_bigthumb.jpg

    anyway, I'm not sure what to suggest next regarding the TXW8301 and flash dump/programming.
  • ADVERTISEMENT
  • #10 21643718
    Harbour
    Level 3  
    Okay, debug mode error gone just after connecting gdb to the debugserver. But new error appeared:

    Quote:
    DebuggerServer$ flash dump -o dump.bin -b -a 0x0 -s 0x1000000 -al Taixin_TXW81X_FLASH_ALGORITHM.elf
    flash dump -o dump.bin -b -a 0x0 -s 0x1000000 -al Taixin_TXW81X_FLASH_ALGORITHM.elf
    ERROR: Load Flash Algorithm File: Failed to load algorithm to target.
    Can't run FlashAlgorithm to bkpt_label, restore destoryed registers and memory.
    Dump failed.


    Now is definitely clear that proper TXW83x elf file is needed.
  • #11 21646652
    divadiow
    Level 36  
    beginning to think it may be a different beast and a different approach may be required. may I ask what device you have with TXW8301 in? I do not have any so may try to source something if it's cheap enough.
  • #12 21646786
    Harbour
    Level 3  
    There are plenty of it. The famous is LilyGO T-Hallow, second is MaduinoZeroWiFiHalow and many others. I see that you are partially right - there is the flash template project in SDK. Usually they placed the compiled ELF file but not in TXW8301 case. Will try to compile and test it. The current main problem for me - is the buggy debug server. It is constantly failing to put CPU in debug mode. But the debug API example that is supplied with the debug server is constantly can do this:

    ./example/Output/Example 
     ---                                                    --- 
    |  XuanTie Debugger Server (Build: Jun 12 2025, Linux)      |
       User   Layer Version : 5.18.05 
       Target Layer version : 2.0
    |  Copyright (C) 2025 Hangzhou C-SKY MicroSystems Co., Ltd.|
     ---                                                    --- 
    XuanTie: CKLink_Lite_V2, App_ver 2.38, Bit_ver null, Clock 2526.316KHz,
           2-wire, With DDC, Cache Flush On, SN CKLink_Lite_V2-T000000D4B453139675A794.
     --  Debug Arch is CKHAD.  -- 
     --  CPU 0  -- 
    XuanTie CPU Info:
       WORD[0]: 0x04901053
       WORD[1]: 0x11000000
       WORD[2]: 0x21400417
       WORD[3]: 0x30c00000
    Target Chip Info:
       CPU Type is CK803SG, in LITTLE Endian.
       Bus type is AHB32.
       Signoff date is 04/0107.
       HWBKPT number is 9, HWWP number is 2.
    =================== memory access test ==================
    
    memory read/write successfully
    
    =================== register access test ==================
    
    CPU generate register:
    r0: write 0x12345678, read 0x12345678
    r1: write 0x12345678, read 0x12345678
    r2: write 0x12345678, read 0x12345678
    r3: write 0x12345678, read 0x12345678
    r4: write 0x12345678, read 0x12345678
    r5: write 0x12345678, read 0x12345678
    r6: write 0x12345678, read 0x12345678
    r7: write 0x12345678, read 0x12345678
    r8: write 0x12345678, read 0x12345678
    r9: write 0x12345678, read 0x12345678
    r10: write 0x12345678, read 0x12345678
    r11: write 0x12345678, read 0x12345678
    r12: write 0x12345678, read 0x12345678
    r13: write 0x12345678, read 0x12345678
    r14: write 0x12345678, read 0x12345678
    r15: write 0x12345678, read 0x12345678
    CPU PC register:
    PC: write 0x12345678, read 0x12345678
    
    
    =================== breakpoint test ==================
    
    WARNING: Address 0x00000000 can't be written when remove soft-bkpt.
    Breakpoint add successfully
    
    WARNING: CPU_0: success to enter debug mode asynchronously.
    Debug state: reason: 0x0, PC: 0x2e32, add_len: 0x4, status: 0x1302, status2: 0x0
  • Helpful post
    #13 21695356
    max4elektroda
    Level 21  
    divadiow wrote:
    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.


    Maybe you allow for a short alternate approach (if it's there and I simply overlooked it, sorry).

    I didn't have a J-Link programmer at hand, so I tried with a simple UART (as done here).

    Connect
    GND -> G
    UARTs RX -> A9
    UARTs TX -> A10

    Download Flasher from ST site https://www.st.com/en/development-tools/flasher-stm32.html#get-software (you'll need to get an access code with a valid mail address, mailinator.com works ;-))

    The process is straight forward, but you need to set the "Boot0" jumper (the one opposite to the button):

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

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


    Flash Loader Demonstrator window showing readable target and flash size of 128 KB.
    Flash Loader Demonstrator window showing STM32F1 flash memory mapping.
    Flash Loader Demonstrator interface with selected .hex file download options.
    Screenshot of Flash Loader Demonstrator after successful STM32F1 firmware download

    Setting both "BOOT" jumpers to 0 again and re-connecting STM to USB:


    USB device list showing CKLink-Lite under USB devices

    Done!
  • #14 21695365
    divadiow
    Level 36  
    oh wow. cool! that's a bit easier

    Added after 36 [seconds]:

    easier as in no J-Link requirement
  • #15 21695375
    max4elektroda
    Level 21  
    Yes, easier for me, for I didn't find my J-Link clone ;-)
    Thanks for your work, I just successfully dumped my X5 Cam and flashed OpenTXW81X with help of this and this post!

    Maybe you want to mention or even better "integrate" this approach in your initial post?
    Feel free to use all images or text
  • #16 21695389
    divadiow
    Level 36  
    cheers. added update note header for now

Topic summary

The discussion documents the use of a low-cost STM32F103C8T6 "Blue Pill" development board, which appears to have 128kB internal flash instead of the expected 64kB, resembling an STM32F103CBT6 variant, a known characteristic of some STM32 clones. The main goal is to repurpose this board as a C-SKY CK-Link / T-Head CPU debugger to access and dump flash memory from C-SKY CK804FGT-based chips such as the WinnerMicro W800/W801/W806 series. The user explores firmware conversion using cjacker's cklink-lite-fw-convertor to adapt the T-Head debug server's cklink_lite.hex file. Further investigation involves reverse engineering the Upgrade_Tools_V1.5.9.exe using pyinstxtractor and uncompyle6 to analyze Python bytecode files (SerialThread.pyc, MainWindow.pyc, etc.) revealing serial commands for reading BLE and Wi-Fi MAC addresses, consistent with WinnerMicro documentation. The user also tests a Hi-Link HLK-B36 W800 module running original firmware, observing UART debug output. Additionally, the T-Head debug server successfully connects to Bouffalo Lab BL602 MCU, with STM32F103 pin assignments detailed for various BL series chips. The latest CK-Link Lite firmware version 2.38 is noted, supporting XuanTie CK804 CPUs with features like 5-wire debug, DDC, and cache flush. The discussion highlights practical steps and tools for flashing, debugging, and interfacing with C-SKY/T-Head CPUs using affordable STM32 hardware.
Summary generated by the language model.
ADVERTISEMENT