Skip to content

Instantly share code, notes, and snippets.

@SeppoTakalo
Last active October 31, 2023 14:53
Show Gist options
  • Save SeppoTakalo/5b10d517a70942c38992ece55333f2fc to your computer and use it in GitHub Desktop.
Save SeppoTakalo/5b10d517a70942c38992ece55333f2fc to your computer and use it in GitHub Desktop.
Debugging Mbed OS in Mac OS X

Debugging Mbed OS in Mac OS X (and Linux)

Pre-requisities

For succesfully building Mbed OS applications in Mac OS X, following tools are required

Homebrew

https://brew.sh/

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install bash-completion

This might require command line compilers to be installed.

Add following to your ~/.bash_profile

if [ -d $HOME/bin ]; then
    PATH=$HOME/bin:$PATH
fi

if [ -f $(brew --prefix)/etc/bash_completion ]; then
	. $(brew --prefix)/etc/bash_completion
fi

ARM GCC

GNU Arm Embedded version 6. Download from https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads

tar xf <package>

Add to your path

General info

These instructions always use arm-none-eabi-gdb for debugging. Once it is working UI is up to user's preference.

First, create .gdbinit to your home folder

# Load .gdbinit also from working directory
set auto-load local-gdbinit

# Unknown memory addresses will be treated as RAM
set mem inaccessible-by-default off

# Helper for hard faults
define armv7m_break
    echo Created HardFault_Handler() breakpoint\n
    break HardFault_Handler
    commands
        printf "=== Hard fault location: ===\n"
        # Check CONTROL.SPSEL bit to figure calling stack (Thread vs Process)
        if ($lr & 0x4)
            list **((uint32_t*)($psp+6*sizeof($psp)))
        else
            list **((uint32_t*)($msp+6*sizeof($msp)))
        end
        if (*0xE000ED29 & 0x4)
            printf "IMPRECISERR=1, Asyncronous fault, PC is not precise\n"
        end
    end
end

# When PC location is not accurate, you can try disabling write buffering
define disable_writebuf
    # Set DISDEFWBUF bit(1) in Auxiliary Control Register
    # http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/CHDCBHEE.html
    set *0xE000E008 = *0xE000E008|2
end

This contains helper for crash dumps and allows applications to provide .gdbinit in the root folder.

In the application folder, you create .gdbinit file like this:

! pyocd gdbserver &
target remote localhost:3333
monitor reset halt

NOTE: This starts PyOCD automatically into background. NOTE: With Open OCD use target extended-remote localhost:3333

And start debugger with arm-none-eabi-gdb BUILD/UBLOX_EVK_ODIN_W2/GCC_ARM/Hello-TLSSocket.elf

Below are the board specific instructions to get GDB server running.

K64F and K66F and other Daplink boards

Just install PyOCD:

pip install -U pyocd

Now check whether the board is supported with

$ pyocd list
## => Board Name | Unique ID
-- -- ----------------------
 0 => FRDM-K64F [k64f] | 02400201CCB03E70314EC3C8

You can now start PyOCD with pyocd gdbserver --persist

Also, you can start PyOCD with debugger: arm-none-eabi-gdb -iex '! pyocd gdbserver &' <other parameter>

Ublox EVK ODIN W2 and other ST-link based

For Unix, there is ST-Link clone in https://github.com/texane/stlink which does not seem to work properly. So ignore it.

OpenOCD does not understand RTX kernel (mbed OS) so ignore it as well.

Install up-to-date PyOCD, it supports now ST-Link as well.

Might require CMSIS Pack to be installed for your board. For example NUCLEO_F303RE requires:

$ pyocd pack -f *F303RE
  Part            Vendor       Pack            Version  
--------------------------------------------------------
  GD32F303RE      GigaDevice   GD32F30x_DFP    1.0.3    
  STM32F303RETx   Keil         STM32F3xx_DFP   2.1.0 

$ pyocd pack -i STM32F303RETx
Downloading packs (press Control-C to cancel):
    Keil::STM32F3xx_DFP::2.1.0

$ pyocd pack -s
  Vendor   Pack            Version  
------------------------------------
  Keil     STM32F3xx_DFP   2.1.0    

If the CMSIS Pack is not available, or other reasons, you might still want to try OpenOCD. Install:

brew install open-ocd

Start debugger:

Board/Target OpenOCD command
DISCO_L475VG_IOT01A openocd -f board/stm32l4discovery.cfg
NUCLEO_F429ZI openocd -f board/st_nucleo_f4.cfg
UBLOX_EVK_ODIN_W2 openocd -f board/st_nucleo_f4.cfg

Or with specific interface and chip

openocd -f interface/stlink-v2-1.cfg -f target/stm32f4x.cfg -c init -c "reset init"

Daplink with OpenOCD

Some targets that have Daplink also work with OpenOCD. In those cases use cmsis-dap.cfg as a interface and try to find the closes matching target.

For example, K64F work with K60 target definition:

openocd -f /usr/local/Cellar/open-ocd/0.10.0/share/openocd/scripts/interface/cmsis-dap.cfg -f /usr/local/Cellar/open-ocd/0.10.0/share/openocd/scripts/target/k60.cfg -c init -c "reset init"

Debugging a Greentea test case

See https://os.mbed.com/docs/mbed-os/v5.12/tools/greentea-testing-applications.html#debugging-tests

You need to do following steps:

  1. Build a test case: mbed test -m K64F -t GCC_ARM --compile -n <name of the testcase> Take a note of the produced test binary name. For example Image: BUILD/tests/K64F/GCC_ARM/TESTS/netsocket/tcp/tcp.bin
  2. Start gdbserver on another console: pyocd gdbserver --persist
  3. Start GDB frontend. Any frontend will do. For example: arm-none-eabi-gdb -ex "target remote localhost:3333" -ex "monitor reset halt" ./BUILD/tests/K64F/GCC_ARM/TESTS/netsocket/tcp/tcp.elf Note: Replace .bin with .elf from the test binary path.
  4. Issue commands load and continue to GDB
  5. Start tests from another console: mbedhtrun --skip-flashing --skip-reset -p /dev/tty.usbmodem33402:9600 (Use correct serial port path)

External links

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment