Debugging c code tips?

Posted on
Page
of 2
/ 2
Next
  • If i'm making changes in the bangleJS portion of the code. What options do i have for debugging the code. I have a nordic NRF 52840 development kit and a custom display i'm using. So it has a segger programmer attached to it over usb.

    I'm sorry for the very basic question.

  • So i see there are debugging flags.

    So there's a USE_DEBUGGER and a just a standard DEBUG flag. So i'm guessing USE_DEBUGGER is hardware?

    Unless USE_DEBUGGER is the flag to enable the javascript debugger?

  • So to get GDB working i need to hardcode the file and the arm directory.

    make -j BOARD=P8-SDK12-SPIFLASH PROJECTNAME=./bin/espruino_2v19.88_p8_SD­K12_SD30_SPIFLASH -j8 flash gdb
    
    ## ARM.make
    ./gcc-arm-none-eabi-8-2018-q4-major/bin/­arm-none-eabi-gdb -x gdbinit
    
  • So now it's complaining about that it can't connect to remote host?
    target extended-remote :4242

  • I'm confused as to why it's trying to do a remote session?

  • I'm confused as to why it's trying to do a remote session

    gdb runs on PC and the debugged code runs on ARM device so it needs to be a bit complicated, there is remote GDB server running somewhere. It can be OpenOCD running on your PC translating gdb commands to SWD/JTAG commands. It can be Segger GDB server for J-Link, it can be even running inside your debug probe for speed (Blackmagic probe has one).

    As for debugging Espruino I did it few times but there is issue with nrf52 with BLE stack running - you cannot stop and continue as it breaks Bluetooth timing and device reboots. With bluetooth turned off ( at least NRF.sleep()) it is better. But even with bluetooth turned on one can set breakpoint and has one shot at investigating stack trace and variables before rebooting and trying again.

    I used command line gdb with the elf file which is produced in each build, no extra compile flags are needed. I think the elf file produced by gcc should also work in any IDE but don't have any guide, try Google.

    EDIT: see also this post https://forum.espruino.com/conversations­/369539/#16249545

  • Thanks for the constantly good advice @fanoush!

    I'll give it a go and post my results.

  • Ok so i got something now.

    Things i had to do

    • No " DEBUG=1 ". No room for it
    • JLinkGDBServer -device nRF52832_xxAA -if swd -speed 4000 -port 4242
      Normal port is 2331 and the scripts looking for port 4242
  • Just for people new to this.

    First start your server

    • JLinkGDBServer/Openocd

    If its working you should see something like Waiting for GDB connection

    Then do your

    • make ...... gdb

    Then gdb will get ready to be started and then you just hit enter to start it or q to quite.

    This should build your program and then run the arm gdb client.

    If there's problems with with GDB for some reason the client side.
    You can look at make/targets/arm.make. There's a make file that has the commands for GDB. Basically it makes a file and then tells gdb to execute it.

  • Progress being made.

    helpful links
    debugging nordic chips
    gdb commands

    So after your running gdb is connect to your server you need to

    • load

    Which flashes the code onto the device. From there you can do your next and continue commands.

    You can also edit your ~/.gdbinit file so you don't have to hit enter every time.

    next problem

    So i have testing the above stuff on a nRF52840DK which has lots of flash. But the current micro is a nRF52832 with barely any. So my plan was to add the debug symbols to just the specific files i care about. So this compiles but doesn't seem to add any size to the code base. So thats the next thing to figure out.

    trying to add special debug symbols

    
    $(OBJDIR)/libs/banglejs/jswrap_bangle.o:­ libs/banglejs/jswrap_bangle.c 
    	@echo " $($(quiet_)compile) "
    
    	@mkdir -p $(shell dirname $@) # create directory if it doesn't exist
    	@$(CC) $(CFLAGS) $< -g -o $@
    
  • So my plan was to add the debug symbols to just the specific files i care about

    AFAIK there is no issue with debug symbols, you have all symbols even without DEBUG=1, they are in elf file and kept on PC side, not part of binary in device. What DEBUG=1 does is turning off optimizations so the binary is much larger. RELEASE=1 turns off extra assert checks (also not needed for debugging). You should be able to debug even without DEBUG=1 and with RELEASE=1. What can happen is that some code is optimized out so the debugger will not match all lines 1:1 when the code is not there, however mostly it works just fine.

    BTW, you can also run make BOARD=... lst to generate .lst text file with C and assembly language mix and all symbols so you can figure out how the code really looks if you get lost when debugging optimized code.

  • As @fanoush says - but if you do want to use the unoptimised bdebug dinary on an nRF52 you can maybe look at removing features from the BOARD.py file you're not using, for instance: https://github.com/espruino/Espruino/blo­b/master/boards/NRF52832DK.py#L34-L37

    you can even use the SAVE_ON_FLASH macro

  • @Gordon @fanoush - Thanks for clearing this up for me.

    I think i was getting confused because i see this when i start up GDB.
    "No symbol table is loaded. Use the "file" command."

    Which i'm guessing is because when you first load up gdb it doesn't load the file. Its currently commented out for some reason.

    https://github.com/espruino/Espruino/blo­b/255dbb036942c59c2e937d3c80c206d88586be­79/make/targets/ARM.make#L27

  • [Solution] is on #18 - but i'll keep these note for future reference.

    Right now i'm trying to figure out why the program completely crashes when i first run it? This is what happens when i try to debug my Pinetime. When i do my first step it just crashes. When i don't debug it, it the build works just fine?

    (gdb) load
    Loading section .text, size 0x449dc lma 0x1f000
    Loading section .ARM.exidx, size 0x8 lma 0x639dc
    Loading section .data, size 0xa0 lma 0x639e4
    Loading section .fs_data, size 0x10 lma 0x63a84
    Start address 0x1f7bc, load size 281236
    Transfer rate: 20 KB/sec, 13392 bytes/write.
    (gdb) step
    Single stepping until exit from function Reset_Handler,
    which has no line number information.
    Note: automatically using hardware breakpoints for read-only addresses.
    SystemInit () at targetlibs/nrf5x_12/components/toolchain­/system_nrf52.c:67
    67          if (errata_16()){
    
  • I still have to actually understand more about this. But the registers look wrong from the start?

    Start address 0x1f7bc, load size 281236
    Transfer rate: 20 KB/sec, 13392 bytes/write.
    (gdb) ls
    Undefined command: "ls".  Try "help".
    (gdb) info registers
    r0             0x0                 0
    r1             0x0                 0
    r2             0x0                 0
    r3             0x0                 0
    r4             0x0                 0
    r5             0x0                 0
    r6             0x0                 0
    r7             0x0                 0
    r8             0x0                 0
    r9             0x0                 0
    r10            0x0                 0
    r11            0x0                 0
    r12            0x0                 0
    sp             0xffffffd8          0xffffffd8
    lr             0xfffffff9          -7
    pc             0x1f7bc             0x1f7bc <Reset_Handler>
    xPSR           0x1000003           16777219
    fpscr          0x0                 0
    msp            0xfffffffc          0xfffffffc
    psp            0x0                 0x0
    primask        0x0                 0
    basepri        0x0                 0
    faultmask      0x0                 0
    control        0x0                 0
    
  • So i have a pine time and a nRF528340 dev board that i'm working with currently. I can seem to debug the nRF528340DK perfectly. But the pinetime just seems to not want to work from the start. From the the two build one thing that stand out to me is this line at the end. This overlap=replace doesn't seem to need to be set in the normal devboard.

    FIXME - had to set --overlap=replace
    python scripts/hexmerge.py --overlap=replace targetlibs/nrf5x_12/components/softdevic­e/s132/hex/s132_nrf52_3.1.0_softdevice.h­ex bin/bootloader_espruino_2v19_p8_SDK12_SD­30_SPIFLASH.hex bin/espruino_2v19_p8_SDK12_SD30_SPIFLASH­.app_hex obj/dfu_settings.hex -o bin/espruino_2v19_p8_SDK12_SD30_SPIFLASH­.hex

  • OK! Figured it out!!!!!!!!!!!!!!!!!

    So because of the FIXME line were it merges all the files. If you load the elf file it doesn't work.

    So the solution seems to be to load hex file! So now i can finally step through the code on the pinetime!

    load bin/espruino_2v19_p8_SDK12_SD30_SPIFLASH­.hex
    
  • As for debugging Espruino I did it few times but there is issue with nrf52 with BLE stack running - you cannot stop and continue as it breaks Bluetooth timing and device reboots. With bluetooth turned off ( at least NRF.sleep()) it is better.

    So now i think i'm at this step.

    When i'm stepping through the program from the very start.
    In targets/nrf5x/jshardware.c - once i hit jsble_init() the software crashes. It seems to happen both my NRF52840 dev board and my pinetime. Just in different spots.

    I just don't know were to stick this NRF.sleep() call?

  • current stack trace

    (gdb) bt
    #0  0x000008c8 in ?? ()
    =1  <signal handler called>
    =2  0x0000092e in ?? ()
    =3  <signal handler called>
    =4  0x00053c02 in sd_softdevice_enable (p_clock_lf_cfg=0x2000fe28, fault_handler=0x53bb1 <softdevice_fault_handler>)
        at targetlibs/nrf5x_12/components/softdevic­e/s132/headers/nrf_sdm.h:286
    =5  0x00038dc2 in softdevice_handler_init (p_ble_evt_buffer=0x2000b8c8 <BLE_EVT_BUFFER.2>, ble_evt_buffer_size=80, evt_schedule_func=0x0,
        p_clock_lf_cfg=0x2000fe28) at targetlibs/nrf5x_12/components/softdevic­e/common/softdevice_handler/softdevice_h­andler.c:277
    =6  softdevice_handler_init (p_ble_evt_buffer=0x2000b8c8 <BLE_EVT_BUFFER.2>, ble_evt_buffer_size=80, evt_schedule_func=0x0,
        p_clock_lf_cfg=0x2000fe28) at targetlibs/nrf5x_12/components/softdevic­e/common/softdevice_handler/softdevice_h­andler.c:277
    +7  ble_stack_init () at targets/nrf5x/bluetooth.c:2539
    +8  jsble_init () at targets/nrf5x/bluetooth.c:2862
    +9  0x0003a27c in jshInit () at targets/nrf5x/jshardware.c:961
    +10 main () at targets/nrf5x/main.c:27
    
  • I just don't know were to stick this NRF.sleep() call?

    well if you need to debug startup then I don't know about such way, in theory we could add some option to not start advertising automatically. You can also compile bluetooth module out for debugging startup. In other cases just run it fully, then execute NRF.sleep() in console or NRF.sleep() /wake() mapped to something like button click and then set breakpoints as you wish when it is sleeping. it is easier to do this with console over serial (or usb with that 52840 devboard), then you can type it directly as needed

    BTW som more info here https://devzone.nordicsemi.com/f/nordic-­q-a/9622/application-debug-with-softdevi­ce
    I've seen some macro somewhere for gdb for setting PRIMASK automatically when beakpoint is hit

  • Yes so i need to debug the initialization of all the hardware. But whats interesting is that it seems to fail just because its in GDB. without hitting any breakpoints and restarting?

    For example. i startup GDB and hit continue and it breaks? But if i just flash the software normally it works fine?

    A lot more hurtles then i was expecting to step through the software :/

    I think i'm just going to try and comment that line out and see it will work just without bluetooth. Just so i can make some forward progress. Then i'll try and figuring out the above link you sent me. Right now thats slightly more in the weeds then i want to be at.

  • For example. i startup GDB and hit continue and it breaks? But if i just flash the software normally it works fine?

    There should be no difference until you hit first breakpoint.

    I think I never used gdb to actually flash firmware to the device. I just do it the normal way first, then run gdb and attach elf file with 'file' command and use run command (?), I forgot exact way, I need to check. I use openocd for gdb server so I can cheat a bit by having both gdb attached to port 3333 and also normal console to port 4444, there I can reset device to start again without gdb knowing.

  • A normal console being a serial console? Do you remember what command you used to reset it?

  • I mean normal openocd console running on port 4444 , you connect to it e.g. via telnet command (telnet localhost 4444) https://openocd.org/doc/html/General-Com­mands.html , you flash hex file via 'program' command, reset via 'reset run' or 'reset halt'.

    As for espruino serial console with interpreter, yes I have it connected too - I mostly use use CMSIS-DAP debug dongles with SWD and UART pins connected to the device. CMSIS-DAP is nice because it needs no drivers and work in linux and windows with openocd out of box. Also you can turn almost any ARM board into CMIS-DAP dongle - easiest is probably the raspberry pico.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Debugging c code tips?

Posted by Avatar for user156811 @user156811

Actions