logo elektroda
logo elektroda
X
logo elektroda

[BK7231T] A simple BLE device project using WB2L. Comments and help welcome.

jitsirakowsk 4107 11

TL;DR

  • A simple BLE device project initializes a WB2L module based on BK7231T.
  • It uses no Tuya libraries and only sends data to the host, so it serves as a minimal BLE bring-up example rather than a useful end device.
  • A long write-up in the doc directory covers BLE basics and related topics, and the archive extraction command should be tar xzvf bk_ble.tar.zip.
AI summary based on the discussion. May contain errors.
ADVERTISEMENT
📢 Listen (AI voice):
  • Hi! In case anyone is interested, here is a simple project to initialize a simple BLE device on WB2L. No Tuya libraries. This is not a fully functional device (in the sense that it does not do anything useful but sends some data to the host). There is a (long) write-up in the doc directory on the project and related topics (overview of BLE, etc.) that my friend and I wrote for a local group of enthusiasts. Apologies for it being too elementary for many of you, some of our participants are students. Also, the original archive had a bz2 extension but the forum only accepts zip files, so the instruction for extraction should read tar xzvf bk_ble.tar.zip.

    Andy
    Edit: there is a newer version of the project later in this thread with a lot more details.
    Attachments:
    • bk_ble.tar.zip (2.48 MB) You must be logged in to download this attachment.

    Cool? Ranking DIY
    About Author
    jitsirakowsk
    Level 7  
    Offline 
    jitsirakowsk wrote 17 posts with rating 10, helped 2 times. Been with us since 2023 year.
  • ADVERTISEMENT
  • #2 20653668
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14743
    Help: 659
    Rate: 12839
    Very impressive documentation. Comprehensive and well written. I will have to find some time to analyze it.

    Are you planning to support N platform as well (BK7231N)?
    Helpful post? Buy me a coffee.
  • Planning to reverse engineer Beken BLE profile API

    #3 20654018
    jitsirakowsk
    Level 7  
    Posts: 17
    Help: 2
    Rate: 10
    We are. I think we have `N' powered devices lying around as well so as soon as we hook it up we should be able to get something similar. In the meanwhile we are planning to use Beken's BLE profile api to get a full `transparent UART' and reverse engineer the lower level calls (setting registers, basically). We try to write about details, we found that it helps beginners ask the right questions.

    Andy
  • Suggesting OpenOCD to confirm register changes

    #4 20654137
    DeDaMrAz
    Level 23  
    Posts: 620
    Help: 34
    Rate: 130
    jitsirakowsk wrote:
    We are. I think we have `N' powered devices lying around as well so as soon as we hook it up we should be able to get something similar. In the meanwhile we are planning to use Beken's BLE profile api to get a full `transparent UART' and reverse engineer the lower level calls (setting registers, basically). We try to write about details, we found that it helps beginners ask the right questions.

    Andy


    Hi Andy,

    That writeup looks very, very nice and thank you for sharing it with us!

    Disclaimer - haven't read the paper yet so ignore the question if irrelevant.
    Have you considered using OpenOCD to confirm the possible register changes??
  • ADVERTISEMENT
  • Helpful post

    JTAG working over existing SPI programming pins

    #5 20654215
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14743
    Help: 659
    Rate: 12839
    There was a JTAG config by @xabean somewhere.
    xabean wrote:
    I got JTAG working, it's the same pins used for SPI programming, so I didn't need to rewire anything. Drop the below config into bk7321t.cfg, and run openocd -f bk7321t.cfg to start it up.

    
    source [find interface/raspberrypi2-native.cfg]
    
    ## https://docs.microsoft.com/en-us/windows/iot-core/learn-about-hardware/pinmappings/pinmappingsrpi
    ##
    ## CEN  -> (bcm)GPIO 22 / RPI3b pin 15
    ## SCLK -> (bcm)GPIO 11 / RPI3b pin 23
    ## CSN  -> (bcm)GPIO 08 / RPI3b pin 24
    ## SI   -> (bcm)GPIO 10 / RPI3b pin 19
    ## SO   -> (bcm)GPIO 9 / RPI3b pin 21
    
    
    # Each of the JTAG lines need a (bcm) gpio number set:
    #                     tck tms tdi tdo
    bcm2835gpio_jtag_nums 11  8   10  9
    
    #                     srst
    bcm2835gpio_srst_num  22
    
    # we only have CEN (aka chip enable, system reset)
    reset_config srst_only
    
    # CEN is normally pulled high, but sometimes it can help to force it high, not just low.
    reset_config srst_push_pull
    
    # on connect, deassert (reset to HIGH) the SRST pin
    reset_config connect_deassert_srst
    
    # we have no TRST pin, tell OpenOCD to imagine it's tied to SRST.
    reset_config srst_pulls_trst
    
    # use JTAG.
    transport select jtag
    
    # go slow.
    adapter speed 100
    
    # wait 200ms after releasing srst before we send JTAG commands over TMS,
    # we will never reset into halt because we have no tRST pin :(
    adapter srst delay 200
    
    if { [info exists CHIPNAME] } {
       set _CHIPNAME $CHIPNAME
    } else {
       set _CHIPNAME bk7321t
    }
    
    if { [info exists ENDIAN] } {
       set _ENDIAN $ENDIAN
    } else {
      # this defaults to a little endian
       set _ENDIAN little
    }
    
    if { [info exists CPUTAPID] } {
       set _CPUTAPID $CPUTAPID
    } else {
       set _CPUTAPID 0x15968001
    }
    
    jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID
    
    set _TARGETNAME $_CHIPNAME.cpu
    target create $_TARGETNAME arm966e -endian $_ENDIAN -chain-position $_TARGETNAME
    


    Then you can read the flash chip ID over the OpenOCD telnet interface on port 4444,

    
    xabean@raspberrypi:~ $ telnet localhost 4444
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    Open On-Chip Debugger
    > mww 0x00803000 74
    > mdw 0x00803010 1
    0x00803010: 001c7015
    
    > bk7321t.cpu arm reg                
    System and User mode registers
          r0: 00000001       r1: 00000069       r2: 00090080       r3: 00100000 
          r4: 00408b5e       r5: 00000001       r6: 00405d80       r7: 00000010 
          r8: 08080808       r9: 09090909      r10: 10101010      r11: 11111111 
         r12: 0000000a   sp_usr: 00420870   lr_usr: 00016dfd       pc: 00016dc2 
        cpsr: 6000003f 
    
    FIQ mode shadow registers
      r8_fiq: 00000000   r9_fiq: 00000000  r10_fiq: 00000000  r11_fiq: 00000000 
     r12_fiq: 00000000   sp_fiq: 00400fe0   lr_fiq: b51edf9b spsr_fiq: 00000010 
    
    Supervisor mode shadow registers
      sp_svc: 004027a0   lr_svc: 00016dc6 spsr_svc: 6000003f 
    
    Abort mode shadow registers
      sp_abt: 004007e0   lr_abt: df9ff7e5 spsr_abt: 00000010 
    
    IRQ mode shadow registers
      sp_irq: 00401fd0   lr_irq: 00059ae8 spsr_irq: 6000001f 
    
    Undefined instruction mode shadow registers
      sp_und: 004007e0   lr_und: bb0de3bc spsr_und: 00000010 
    
    
    
    Helpful post? Buy me a coffee.
  • ADVERTISEMENT
  • OpenOCD and JTAG flashing via serial bootloader

    #6 20654311
    jitsirakowsk
    Level 7  
    Posts: 17
    Help: 2
    Rate: 10
    >>20654137
    Hi! Thanks for the question and the info about JTAG. No, we have not done anything with it but OpenOCD with jtag would be fantastic. If I understand correctly this requires access to SPI pins and a few others. Not a major problem in itself, of course. I noticed in the original Makefile by Tuya that they have a setup using OpenOCD (and jlink) with the serial bootloader on the chip. This would speed things up tremendously as one would be able to use gdb and there would be no need for the second serial port to print to. By the way, has there been any effort to replace the bootloader with something better known?

    Andy
  • #7 20654334
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14743
    Help: 659
    Rate: 12839
    Here is a guide for SPI flashing of BK7231. It can be used to reconstruct bootloader if it was overwritten:
    https://www.elektroda.com/rtvforum/topic3931424.html
    I will, however, note here that WB2L may not have easily accessible SPI pins. I remember there was a problem with that. I used SPI method succesfully for WB3S. You need to consult the module datasheet to be sure.
    Helpful post? Buy me a coffee.
  • WB2L flash access via exposed test pins

    #8 20654654
    jitsirakowsk
    Level 7  
    Posts: 17
    Help: 2
    Rate: 10
    Yes, we have seen the guide (excellent work by the way) and judging by the datasheet for WB2L pins 20-23, as well as reset are exposed as test pins on the back of the pcb. The datasheet also explicitly says that these pins can be used to read and write flash, so it should be doable. In our case, there is a complication of having to desolder the module itself which is also glued to the mother-pcb it seems. It should be possible but naturally we are putting it off until we are done experimenting with the code (or have to rebuild the bootloader). It is getting more and more tempting though.
  • Helpful post

    New BLE reverse engineering guide and N-chip register differences

    #9 20742145
    jitsirakowsk
    Level 7  
    Posts: 17
    Help: 2
    Rate: 10
    Hi everyone!

    Here is a new version of the tutorial and the project. Not much new code, although we have reverse engineered three somewhat large functions in the link layer driver. There is a detailed guide on how it was done in case anyone wants to continue the work (we are planning to continue, as well, probably concentrating more on reverse engineering itself, and less on the description of the process). There are guides (albeit of varying quality) on several topics, from assembly to computer arithmetic (whatever the members of our little group asked about), a small glossary, a literature guide. There are even exercises, in case someone wants to practice!

    We have also looked at the BLE subsystem on the `N' chip. It turned out that the register map is different and the registers themselves are also not the same (although similar; it seems the `N' chips use a newer BLE cell). The functions have different prototypes, as well, although the overall organization of the code is not that different. We have not started reverse engineering the corresponding BLE library yet but it is `on the agenda'. As always, comments, requests, and questions are welcome.

    Andy
    Attachments:
    • bk_ble.tar.zip (3.59 MB) You must be logged in to download this attachment.
  • Disassembler added for libble.a and rwnx.a libraries

    #10 21847848
    jitsirakowsk
    Level 7  
    Posts: 17
    Help: 2
    Rate: 10
    >>20742145 Hi Everyone! Just wanted to share updates for this project. It was used to teach a reverse engineering lab at a local college, some student projects have been incorporated. The manual is included, as before. While there are no additions to the BLE part of the project there is something that may be of general interest. We have written a disassembler (from scratch, in perl, don't ask...) and disassembled the libble.a and rwnx.a libraries for both the N and T chips. The disassembly is pretty structured and modifiable which makes it very suitable for experimentation (there are no hard coded offsets left as is common in any assembly code). BLE register names have been put into the code, as well. Each disassembled function comes with a comment section that shows its C prototype, names and types of local libraries, etc. The variables used by each library object are separated in a C file where their declarations are listed. We wrote a script to check that the recompiled binaries are for all purposes identical to the original ones (.text sections are the same, .(ro)data sections are the same and the relocations are the same). The ble project works with the newly rebuilt library as well. We will be teaching the lab again this semester and next (it's a year long course) so we hope to add more to the Bluetooth part of the project. The disassembler is included and contains both elf and dwarf parsers (although for DWARF v4 and earlier only) which can also be useful.
    Attachments:
    • n_libs.tar.zip (653.77 KB) You must be logged in to download this attachment.
    • bk_ble.tar.zip (4.78 MB) You must be logged in to download this attachment.
  • ADVERTISEMENT
  • #11 21848057
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14743
    Help: 659
    Rate: 12839
    Interesting, keep us posted. What would be the practical applications of that? We didn't really touch internal drivers in OBK yet.
    Helpful post? Buy me a coffee.
  • Intermediate assembly layer eases reverse engineering and BLE/WiFi coexistence

    #12 21848239
    jitsirakowsk
    Level 7  
    Posts: 17
    Help: 2
    Rate: 10
    >>21848057 Our original goal was to reverse engineer the libraries and we noticed that the disassembly was a bit laborious so we wanted something intermediate between a full C source and the machine code. This does it. It is easy to insert printf statements, function calls, save registers, etc, if one knows a little bit of assembly (and the manual teaches enough of it for this purpose). While we have not done it yet, all of the KE kernel functions are relatively easy to reverse engineer. One issue we considered is porting the libraries to a newer version of gcc, and a recent FreeRTOS.

    On the practical side, we would like to enable the wireless arbiter to be able to use BLE and WiFi on the same antenna, at the same time. This way you would be able to, say change the lighting according to the nearest BLE device, etc.

    Andy
📢 Listen (AI voice):

Topic summary

✨ Discussion centers on a simple BLE project for the WB2L module based on BK7231T, using no Tuya libraries and intended as an educational reverse-engineering tutorial rather than a fully functional application. The thread covers documentation quality, plans to extend support to BK7231N, and methods for analyzing BLE link-layer behavior and register changes. Participants discuss OpenOCD, JTAG, SPI flashing, bootloader reconstruction, and access to exposed test pins on WB2L. Later updates add a more detailed tutorial, reverse-engineered BLE link-layer functions, broader educational material, and a custom disassembler for libble.a and rwnx.a on BK7231T and BK7231N, with practical goals including easier experimentation, porting to newer GCC/FreeRTOS, and enabling concurrent BLE/Wi‑Fi operation via the wireless arbiter.
AI summary based on the discussion. May contain errors.

FAQ

TL;DR: This FAQ helps WB2L and BK7231 developers start BLE work fast. It highlights 3 reversed link-layer functions and one core lesson: "details help beginners ask the right questions." Use it to bring up a simple BLE device, compare BK7231T versus BK7231N, and choose between OpenOCD/JTAG and the serial bootloader for faster reverse-engineering work. [#20742145]

Why it matters: The thread shows a practical path from a minimal BLE demo to structured library reverse engineering on real BK7231 hardware.

Topic BK7231T / WB2L BK7231N
BLE register map Original project target Different map and different registers
BLE cell generation Older baseline in this thread Described as newer and similar, but not the same
Function prototypes Existing work and examples available Different prototypes
Reverse-engineering status Several functions already reversed BLE library work still pending

Key insight: The fastest route is to start with the simple BK7231T BLE project, then use structured disassembly and OpenOCD to validate behavior. The thread’s later updates show that rebuilding and checking vendor BLE libraries can move the work from guesswork to repeatable engineering.

Quick Facts

  • The first release was posted on 2023-07-14, and a newer tutorial update arrived on 2023-09-21 with 3 reverse-engineered link-layer functions and added training material. [#20742145]
  • The shared OpenOCD/JTAG setup uses 4 GPIO lines for JTAG, 1 reset line, an adapter speed of 100, and a 200 ms SRST delay. [#20654215]
  • On WB2L, pins 20-23 plus reset are exposed as test pads, and the datasheet explicitly says they can read and write flash. [#20654654]
  • The published OpenOCD workflow reads flash-chip data through the telnet interface on port 4444 and uses the expected TAP ID 0x15968001. [#20654215]
  • By 2026-02-24, the project included a custom Perl disassembler for libble.a and rwnx.a on both N and T chips, plus ELF and DWARF parsers up to DWARF v4. [#21847848]

How do I initialize a simple BLE device on a WB2L module using BK7231T without relying on Tuya libraries?

You start from the shared WB2L/BK7231T example project, which initializes a simple BLE device without Tuya libraries and sends data to the host. The author states it is not a full product yet, but it is enough for bring-up and study. Extract the archive with tar xzvf bk_ble.tar.zip, then use the documentation in the doc directory for the BLE overview and project setup. [#20653571]

What is a transparent UART in the context of Beken BLE profile APIs, and how would it work on BK7231 chips?

A transparent UART is a BLE-to-serial data bridge that forwards bytes with minimal application logic. "Transparent UART" is a BLE profile pattern that transports serial-style host data, a key characteristic being that the device mainly relays payloads instead of interpreting them. In this thread, it is a planned next step using Beken’s BLE profile API, followed by reverse engineering of the lower-level register calls on BK7231 chips. [#20654018]

Which differences between BK7231T and BK7231N matter most when working with their BLE subsystems and register maps?

The biggest differences are the register map, the registers themselves, and the BLE function prototypes. The 2023 update says BK7231N uses a newer BLE cell, so the N chip looks similar to T at a high level but does not match register-for-register. That means code and notes from BK7231T cannot be copied blindly to BK7231N during BLE reverse engineering. [#20742145]

How can OpenOCD and JTAG be used to confirm register changes while reverse engineering BLE behavior on BK7231T?

Use OpenOCD over JTAG to halt the chip, read memory-mapped registers, and compare values before and after BLE actions. The posted configuration lets you connect through shared SPI/JTAG pins, then inspect state through the OpenOCD telnet server on port 4444. The thread also notes this path would make GDB use practical and remove the need for a second serial port for prints during development. [#20654311]

What is the step-by-step process for setting up the shared SPI/JTAG pins on a BK7231T or WB2L for OpenOCD debugging?

Use the posted OpenOCD configuration and wire the shared SPI/JTAG pins directly. 1. Map CEN, SCLK, CSN, SI, and SO to Raspberry Pi GPIO 22, 11, 8, 10, and 9. 2. Set JTAG mode, adapter speed 100, SRST-only reset, and a 200 ms SRST delay. 3. Start OpenOCD with the BK7231T config, then use telnet on port 4444 to read registers or the flash ID. [#20654215]

Why are the SPI flash pins on WB2L harder to access in practice, and what workarounds are available when the module is glued to the main PCB?

They are harder to access because the needed WB2L pads are exposed as test points on the back, but the module may also need desoldering and can be glued to the main PCB. The thread says pins 20-23 and reset are available for flash access, yet the physical rework is the real obstacle. A practical workaround is to postpone SPI access until code experiments are done, then remove the module only if bootloader recovery or deeper flash work becomes necessary. [#20654654]

What is the wireless arbiter on BK7231 devices, and why is it important for running BLE and Wi-Fi on the same antenna at the same time?

The wireless arbiter is the control logic the authors want to enable so BLE and Wi-Fi can share one antenna concurrently. "Wireless arbiter" is radio-control logic that coordinates access between BLE and Wi-Fi, a key characteristic being that it manages coexistence on shared RF hardware. The stated goal is practical home automation, such as changing lighting based on the nearest BLE device while Wi-Fi remains active. [#21848239]

How does the BLE library on BK7231N differ from BK7231T in function prototypes, code organization, and reverse engineering difficulty?

BK7231N differs mainly in function prototypes and hardware details, while the overall code organization stays broadly similar. The thread says the N chip has a different register map and different registers, but the authors still describe the global software structure as not that different from BK7231T. The reverse engineering work for the N BLE library had not started by 2023-09-21, so it remained less mature than the T-side work. [#20742145]

What are the practical applications of reverse engineering libble.a and rwnx.a on BK7231N and BK7231T?

The practical uses include instrumenting vendor code, understanding kernel behavior, and porting libraries to newer toolchains or RTOS versions. By 2026-02-24, the team had disassembled libble.a and rwnx.a for both N and T chips and made the output easy to modify. They specifically mention inserting printf calls, saving registers, and exploring future ports to a newer GCC and a recent FreeRTOS. [#21848239]

How do you verify that a rebuilt BK7231 BLE library is functionally identical to the original binary, including .text, .rodata, and relocations?

You verify it by recompiling the disassembled library and comparing key binary sections against the original. The authors wrote a script that checks whether the .text sections match, the .(ro)data sections match, and the relocations match as well. They report that the BLE project also works with the rebuilt library, which adds a practical runtime check beyond the binary comparison itself. [#21847848]

What is the KE kernel mentioned in BK7231 reverse engineering work, and why are its functions considered easier to analyze?

The KE kernel is the internal kernel layer the authors identify as relatively accessible during reverse engineering. "KE kernel" is a software kernel component that provides internal runtime services, a key characteristic being that its functions appear simpler to trace than the BLE libraries around it. The thread says those functions are relatively easy to reverse engineer, making them a useful next target after basic BLE library analysis. [#21848239]

OpenOCD vs the serial bootloader on BK7231T: which approach is better for flashing, debugging with gdb, and development speed?

OpenOCD is better for interactive debugging speed, while the serial bootloader remains the simpler existing path. The thread says OpenOCD with JTAG would speed work up tremendously because you could use GDB and avoid dedicating a second serial port to debug prints. The serial bootloader is still referenced in Tuya’s original Makefile, so it remains a known baseline for flashing when JTAG is not wired. [#20654311]

How could replacing or reconstructing the BK7231 bootloader improve development, and what known alternatives or recovery methods are available?

Replacing or reconstructing the bootloader could make recovery safer and development more flexible after flash mistakes. The thread asks about better-known replacements, but the concrete recovery method provided is SPI flashing. A linked SPI-flashing guide is cited in the discussion as a way to reconstruct the bootloader if it was overwritten, though WB2L pad access can complicate that process. [#20654334]

What does a structured disassembly with ELF and DWARF parsing add to BK7231 BLE reverse engineering compared with raw assembly dumps?

It makes the output easier to modify, verify, and teach from than a raw dump. By 2026, the project’s disassembler produced structured output for libble.a and rwnx.a, added BLE register names, listed C prototypes and local variables, and included ELF plus DWARF parsers up to v4. The authors also removed hard-coded offsets, which they describe as common in assembly and a barrier to experimentation. [#21847848]

How might BLE and Wi-Fi coexistence on BK7231 be used in real projects such as proximity-based lighting control or other home automation features?

It can support automation that reacts to nearby BLE devices while keeping Wi-Fi connected on the same antenna. The thread gives a concrete example: changing lighting according to the nearest BLE device. That matters because the stated goal is not only library analysis, but also enabling the wireless arbiter so BLE and Wi-Fi can run together instead of forcing a one-radio-at-a-time workflow. [#21848239]
AI summary based on the discussion. May contain errors.
ADVERTISEMENT