bluekitchen / raccoon

Raccoon BLE Sniffer
89 stars 30 forks source link

Targeting the nRF51822-based CJMCU-8223 #14

Open parzivail opened 1 year ago

parzivail commented 1 year ago

The generic CJMCU-8223 board uses an nRF51822, the same as the Adafruit blefriend32 boards. The Nordic sniffer firmware used on the pre-flashed Adafruit sniffer dongle works fine on the 8223 (both v1 and v2) but unfortunately, some of the UART flow control pins set up by the official firmware aren't broken out on the 8223, so I decided to give Raccoon a shot.

I thought it would be as simple as modifying firmware/nrf/blefriend32/config/custom_board.h to set the LED and UART pins I'd like, compile, flash, everything would work (considering it's the same chip) but Raccoon firmware immediately traps in a HardFault when building and flashing unmodified from git:

> halt
target halted due to debug-request, current mode: Handler HardFault
xPSR: 0x21000003 pc: 0x0000097e msp: 0x20007fe0

Flashing with openocd -f flash_blefriend32.cfg:

Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
WARNING: interface/stlink-v2.cfg is deprecated, please switch to interface/stlink.cfg
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
Info : clock speed 1000 kHz
Info : STLINK V2J29S7 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.304653
Info : nrf51.cpu: hardware has 4 breakpoints, 2 watchpoints
Info : starting gdb server for nrf51.cpu on 3333
Info : Listening on port 3333 for gdb connections
target halted due to debug-request, current mode: Thread 
xPSR: 0xc1000000 pc: 0x0000093c msp: 0x20008000
Info : nRF51822-QFAA(build code: H2) 256kB Flash, 16kB RAM
Info : Mass erase completed.
Info : A reset or power cycle is required if the flash was protected before.
target halted due to debug-request, current mode: Thread 
xPSR: 0xc1000000 pc: 0xfffffffe msp: 0xfffffffc
** Programming Started **
Warn : Adding extra erase range, 0x00007d6c .. 0x00007fff
** Programming Finished **
** Verify Started **
** Verified OK **

Please let me know what additional information you need, or additional things I should try. I'm not very experienced with the arm toolchain (and on-chip debugging) so any help would be greatly appreciated.

Fedora 36 arm-none-eabi-binutils-cs-1:2.37-4.fc36.x86_64 arm-none-eabi-gcc-cs-1:11.1.0-2.fc36.x86_64 arm-none-eabi-gcc-cs-c++-1:11.1.0-2.fc36.x86_64 arm-none-eabi-newlib-4.1.0-4.fc36.noarch

mringwal commented 1 year ago

Hi Colby. No idea what's different between our boards and yours. Please first make sure that you can flash and debug simple programs, e.g. a blink example. If this works, please try to single step Raccoon on your device. If you find that a hard fault is hit every time on a particular line in the code, please share a backtrace here.

parzivail commented 1 year ago

I've had success with the Nordic firmware, and both the blink and iBeacon examples from mbed. Here is my gdb output, I've indented it so it's easier to read.

raccoon_gdb_singlestep_1.txt

mringwal commented 1 year ago

Any idea why it doesn't show C code or at least assembly while stepping? It seems to crash during the Reset Handler. Usually that's where the memory is setup, e.g. the stack.

Anyway, I have the hunch that your board uses a different 51822 variant than the BLEFriend32. The BLEFriend32 uses a 51822-XXAC with 256 kB Flash and 32 kB RAM, while your board has a 51822-QFAA with 256 kB Flash and 16 kB RAM. You can try to use the linker script from your examples with 16 kB RAM / or try to modify the one from the BLEFriend32.

parzivail commented 1 year ago

Great catch! I hadn't noticed that, and it's likely the root cause. I've made the relevant modifications to the toolchain and the RAM is about 3kb too small, will need to find a way to shave 3k off somewhere.

Edit: No idea why gdb is acting the way that it is, it's completely possible I'm misusing it -- not super familiar with how to properly use gdb.

parzivail commented 1 year ago

Thanks!! Raccoon runs perfectly by (duh) setting the correct linker parameters for that specific chip. I shaved off 3k of RAM by reducing the rxQ size from 64 entries to 36 entries. If there's another area that can be shaved down without reducing the rx queue size, please let me know!

Since that issue is unrelated, I'm happy to open another issue for clarity, because the issue in the title is technically solved.

Thanks again!

Edit: According to nm, there's not much that can be done about the RAM situation, it seems. the rxQ and msgQ are the biggest contributors by far.

mringwal commented 1 year ago

Glad you were able to fix the hard fault. About memory: it's been a while that I've worked on that. If you've already used nm, you probably know more than me. How much RAM is used now?

parzivail commented 1 year ago

In the current working configuration (all values in decimal, annotated for clarity):

$ nm -Crtd --size-sort armgcc/_build/nrf51822_qfaa.out | grep -i ' [dbv] '
00009952 d __compound_literal.0 (main.c - rxQ with 36 entries)
00001552 d __compound_literal.1 (main.c - msgQ with 16 entries)
00000140 b _global_atexit0 (arm-none-eabi/lib/thumb/v6-m/nofp/libc_nano.a(lib_a-__atexit.o))
00000096 d impure_data (arm-none-eabi/lib/thumb/v6-m/nofp/libc_nano.a(lib_a-impure.o))
00000092 B ctx (main.c)
00000048 B h
00000044 b m_cb
00000036 b timers
00000024 b object.0
00000008 d uart_inst
00000004 B __malloc_sbrk_start
00000004 B __malloc_free_list
00000004 D _impure_ptr
00000004 b heap_end.0
00000004 B _global_atexit
00000004 B errno
00000002 B hop
00000001 b completed.1

With the original 64 entries in the rxQ, it alone consumed 17,680 bytes. If my math is correct, the rxQ costs a flat rate of 16 bytes plus 276 bytes for each entry. The msgQ similarly costs 16 bytes plus 96 per entry. Since the remaining RAM contributors are all basically negligible, I guess it's a tradeoff between RX queue size and message queue size. I'm not sure which is more important.