ターミナルからマイクロコントローラのデバッグに GDB (Gnu Debugger) と OpenOCD を使用するにはどうすればよいでしょうか? 質問する

ターミナルからマイクロコントローラのデバッグに GDB (Gnu Debugger) と OpenOCD を使用するにはどうすればよいでしょうか? 質問する

ARM マイクロコントローラをプログラムする標準的な (低コストの) 方法は、複雑なツールチェーンが組み込まれた Eclipse を使用することです。Eclipse には確かに利点がありますが、私はこの IDE から独立したいと思っています。ソフトウェアをビルド (コンパイル - リンク - フラッシュ) するとき、およびデバッグ セッションを実行するときに、舞台裏で何が起きているのかを知りたいです。このような深い理解を得るには、コマンド ラインから手順全体を実行できればすばらしいでしょう。

注: 私は 64 ビットの Windows 10 を使用しています。ただし、ここで説明されているほとんどの内容は Linux システムにも適用されます。すべてのコマンド ターミナルを管理者権限で開いてください。これにより、多くの問題を回避できます。

1. ソフトウェアの構築

最初の「ミッション」は達成されました。これで、コマンド ラインを使用してソフトウェアをコンパイルし、バイナリ.bin.elfイメージにリンクできるようになりました。成功の鍵は、Eclipse が特定のプロジェクトの make-file をどこに置くかを見つけることでした。make-file の場所がわかれば、あとはコマンド ターミナルを開いてGNU makeコマンドを入力するだけです。

ここに画像の説明を入力してください

そのために Eclipse はもう必要ありません! 特に、プロジェクトの進行に合わせて makefile を読んで (理解して) ニーズに合わせて調整できる場合はそうです。

SW4STM32 (System Workbench for STM32) をインストールした後、次のフォルダーに GNU ツール (コンパイラ、リンカー、make ユーティリティ、GDB など) が見つかったことに注意してください。

C:\Ac6\SystemWorkbench\plugins\fr.ac6.mcu.externaltools.arm-none.win32_1.7.0.201602121829\tools\compiler\

次に、ハードドライブに新しいフォルダーを作成し、そこにこれらの GNU ツールをすべてコピーしました。

C:\Apps\AC6GCC
           |-> arm-none-eabi
           |-> bin
           '-> lib

そして、次のエントリを「環境パス変数」に追加します。

 - C:\Apps\AC6GCC\bin
 - C:\Apps\AC6GCC\lib\gcc\arm-none-eabi\5.2.1

やった、これで私のシステムですべての GNU ツールが稼働するようになりました! 次のbuild.batファイルを と同じフォルダに置きましたmakefile:

@echo off
echo.
echo."--------------------------------"
echo."-           BUILD              -"
echo."--------------------------------"
echo.

make -j8 -f makefile all

echo.

この bat ファイルを実行すると、作業は完了します。すべてがうまくいけば、コンパイルの結果として1 つ.binのバイナリ ファイルが生成されます。.elf

2. ファームウェアのフラッシュとデバッグ

当然の次のステップは、ファームウェアをチップにフラッシュしてデバッグ セッションを開始することです。Eclipse では、少なくとも Eclipse がマイクロコントローラ用に正しく構成されている場合は、ボタンを 1 回クリックするだけです。しかし、舞台裏では何が起こっているのでしょうか。OpenOCD の開発者である Dominic Rath の修士論文 (の一部) を読みました。こちらでご覧いただけます。http://openocd.net/私が学んだことは次のとおりです。

  • Eclipse は、「デバッグ」アイコンをクリックすると OpenOCD ソフトウェアを起動します。Eclipse は OpenOCD にいくつかの構成ファイルも提供し、OpenOCD がマイクロコントローラへの接続方法を認識できるようにします。「接続方法」は簡単なことではありません。OpenOCD は JTAG アダプタ (STLink など) に接続するための適切な USB ドライバを見つける必要があります。JTAG アダプタとその USB ドライバは、通常、チップ製造元 (STMicroelectronics など) によって提供されます。Eclipse は、マイクロコントローラの仕様を記述した構成ファイルも OpenOCD に渡します。OpenOCD がこれらすべてのことを認識すると、ターゲット デバイスへの信頼性の高い JTAG 接続を確立できます。

  • OpenOCD は 2 つのサーバーを起動します。1 つ目は TCP ポート 4444 上の Telnet サーバーです。OpenOCD CLI (コマンド ライン インターフェイス) へのアクセスを提供します。Telnet クライアントは OpenOCD に接続してコマンドを送信できます。これらのコマンドは単純な「停止」、「実行」、「ブレークポイントの設定」などです。

  • このようなコマンドはマイクロコントローラのデバッグには十分かもしれませんが、多くの人はすでに Gnu Debugger (GDB) に精通しています。このため、OpenOCD は TCP ポート 3333 で GDB サーバーも起動します。GDB クライアントはそのポートに接続して、マイクロコントローラのデバッグを開始できます。

  • Gnu デバッガーはコマンド ライン ソフトウェアです。多くの人はビジュアル インターフェイスを好みます。Eclipse はまさにそれを実現します。Eclipse は OpenOCD に接続する GDB クライアントを起動しますが、これはすべてユーザーには表示されません。Eclipse は、舞台裏で GDB クライアントと対話するグラフィカル インターフェイスを提供します。

これらすべてを説明するために図を作成しました:

ここに画像の説明を入力してください

>> OpenOCDの起動

コマンドラインから OpenOCD を起動することができました。その方法を説明します。

  1. まず、STLink-V2 JTAG プログラマーが正しくインストールされていることを確認します。STMicroelectronics の「STLink ユーティリティ ツール」を使用してインストールをテストできます。このツールには優れた GUI があり、接続ボタンをクリックするだけです。ここに画像の説明を入力してください
  2. 次に、この Web サイトから OpenOCD ソフトウェアの実行可能ファイルをダウンロードします。ARM の ARM ライブラリインストールして、ハードドライブ上の「C:\Apps\」などのフォルダに保存します。
  3. コマンド ターミナルを開き、OpenOCD を起動します。OpenOCD にいくつかの構成ファイルを渡す必要があります。これにより、OpenOCD はマイクロコントローラを探す場所を認識できます。通常、JTAG プログラマーを説明する構成ファイルと、マイクロコントローラを定義する構成ファイルを渡す必要があります。これらのファイルを、コマンド ラインの引数で OpenOCD に渡します。また、引数で渡すことにより、-fOpenOCD にフォルダーへのアクセスを許可する必要があります。これが、コマンド ラインを使用してコンピューターで OpenOCD を起動する方法です。scripts-s

    > "C:\Apps\OpenOCD-0.9.0-Win32\bin\openocd" -f "C:\Apps\OpenOCD-0.9.0-Win32\share\openocd\scripts\interface\stlink-v2.cfg" -f "C:\Apps\OpenOCD-0.9.0-Win32\share\openocd\scripts\target\stm32f7x.cfg" -s "C:\Apps\OpenOCD-0.9.0-Win32\share\openocd\scripts"
    
  4. OpenOCD を適切に (正しい引数で) 起動すると、次のメッセージが表示されます。

    Open On-Chip Debugger 0.9.0 (2015-08-15-12:41)
    Licensed under GNU GPL v2
    For bug reports, read
            http://openocd.org/doc/doxygen/bugs.html
    Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
    Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
    adapter speed: 2000 kHz
    adapter_nsrst_delay: 100
    srst_only separate srst_nogate srst_open_drain connect_deassert_srst
    Info : Unable to match requested speed 2000 kHz, using 1800 kHz
    Info : Unable to match requested speed 2000 kHz, using 1800 kHz
    Info : clock speed 1800 kHz
    Info : STLINK v2 JTAG v24 API v2 SWIM v4 VID 0x0483 PID 0x3748
    Info : using stlink api v2
    Info : Target voltage: 3.231496
    Info : stm32f7x.cpu: hardware has 8 breakpoints, 4 watchpoints
    Info : accepting 'gdb' connection on tcp/3333
    Info : flash size probed value 1024
    
  5. ターミナル ウィンドウがブロックされていることに注意してください。コマンドを入力できなくなりました。しかし、これは正常です。OpenOCD はバックグラウンドで実行されており、ターミナルをブロックしています。OpenOCD と対話するには、別のターミナルで Telnet セッションを開始し、TCP ポート にログオンしてlocalhost:4444、OpenOCD にコマンドを送信し、フィードバックを受け取るという 2 つのオプションがあります。または、GDB クライアント セッションを開始して、TCP ポート に接続しますlocalhost:3333

>> OpenOCDと対話するためのTelnetセッションを開始する

実行中の OpenOCD プログラムと対話するために Telnet セッションを開始する方法は次のとおりです。

> dism /online /Enable-Feature /FeatureName:TelnetClient

> telnet 127.0.0.1 4444

正常に動作した場合、ターミナルに次のメッセージが表示されます。

Open On-Chip Debugger
> ..

これで、OpenOCD にコマンドを送信する準備ができました。ただし、OpenOCD と対話するには GDB セッションが最も便利なので、GDB セッションに切り替えます。

>> OpenOCDと対話するためのGDBクライアントセッションを起動する

さらに別のターミナル ウィンドウを開き、次のコマンドを入力します。

> "C:\Apps\AC6GCC\bin\arm-none-eabi-gdb.exe"

このコマンドは、単にarm-none-eabi-gdb.exeGDB クライアントを起動します。すべてが正常に完了すると、GDB は次のメッセージとともに起動します。

    GNU gdb (GNU Tools for ARM Embedded Processors) 7.10.1.20151217-cvs
    Copyright (C) 2015 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "--host=i686-w64-mingw32 --target=arm-none-eabi".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>.
    Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.
    For help, type "help".
    Type "apropos word" to search for commands related to "word".
    (gdb)..

次に、この GDB クライアントを OpenOCD 内の GDB サーバーに接続します。

    (gdb) target remote localhost:3333

これで、OpenOCD に接続されました。知っておくと便利なこと: ネイティブの OpenOCD コマンドを使用する場合 (Telnet セッションで行うのと同じように)、コマンドの前にキーワード を付けますmonitor。この方法では、OpenOCD 内の GDB サーバーはコマンドを自分で処理せず、ネイティブの OpenOCD デーモンに渡します。

さて、チップをリセットし、消去して停止する時が来ました。

    (gdb) monitor reset halt
       target state: halted
       target halted due to debug-request, current mode: Thread
       xPSR: 0x01000000 pc: 0xfffffffe msp: 0xfffffffc
    (gdb) monitor halt

    (gdb) monitor flash erase_address 0x08000000 0x00100000
       erased address 0x08000000 (length 1048576) in 8.899024s (115.069 KiB/s)
    (gdb) monitor reset halt
       target state: halted
       target halted due to debug-request, current mode: Thread
       xPSR: 0x01000000 pc: 0xfffffffe msp: 0xfffffffc
    (gdb) monitor halt

これで、チップは私たちからの指示を受け取る準備ができました。まず、フラッシュ セクション 0 から 7 (1Mb チップ内のすべてのフラッシュ セクション) を保護しないようにチップに指示します。

    (gdb) monitor flash protect 0 0 7 off

    (gdb) monitor flash info 0
       #0 : stm32f7x at 0x08000000, size 0x00100000, buswidth 0, chipwidth 0
            #  0: 0x00000000 (0x8000 32kB) not protected
            #  1: 0x00008000 (0x8000 32kB) not protected
            #  2: 0x00010000 (0x8000 32kB) not protected
            #  3: 0x00018000 (0x8000 32kB) not protected
            #  4: 0x00020000 (0x20000 128kB) not protected
            #  5: 0x00040000 (0x40000 256kB) not protected
            #  6: 0x00080000 (0x40000 256kB) not protected
            #  7: 0x000c0000 (0x40000 256kB) not protected

次にチップを再度停止します。念のため。

    (gdb) monitor halt

.elf最後にバイナリファイルを GDB に渡します。

    (gdb) file C:\\..\\myProgram.elf
       A program is being debugged already.
       Are you sure you want to change the file? (y or n) y
       Reading symbols from C:\..\myProgram.elf ...done.

今が正念場です。GDB にこのバイナリをチップにロードするように指示します。うまくいくことを祈ります。

    (gdb) load
       Loading section .isr_vector, size 0x1c8 lma 0x8000000
       Loading section .text, size 0x39e0 lma 0x80001c8
       Loading section .rodata, size 0x34 lma 0x8003ba8
       Loading section .init_array, size 0x4 lma 0x8003bdc
       Loading section .fini_array, size 0x4 lma 0x8003be0
       Loading section .data, size 0x38 lma 0x8003be4
       Error finishing flash operation

残念ながら成功しませんでした。OpenOCD で次のメッセージが表示されます。

    Error: error waiting for target flash write algorithm
    Error: error writing to flash at address 0x08000000 at offset 0x00000000

編集: ハードウェアの問題は修正されました。

どうやらハードウェアの問題だったようです。STLink ユーティリティ ツールを使用してバイナリをチップにロードすると問題なく動作したため、チップに欠陥があるとは思っていませんでした。OpenOCD だけがエラーを報告して文句を言っていました。そのため、当然私はチップ自体ではなく OpenOCD を責めました。詳細については、以下の私の回答を参照してください。


編集: チップをフラッシュする別のエレガントな方法 - makefile を使用!

問題は解決したので、今度はチップのフラッシュとデバッグを実行する別の方法に焦点を当てます。これはコミュニティにとって本当に興味深いことだと信じています。

必要な手順をすべて実行するために Windows の cmd コマンドを使用したことにお気づきかもしれません。これはバッチ ファイルで自動化できます。しかし、もっとエレガントな方法があります。makefile ですべてを自動化する方法です。Othane 氏は、Cortex-M? チップ用に次の makefile を提案しています。Cortex-M7 チップの手順も非常に似ていると思います。

            #################################################
            #        MAKEFILE FOR BUILDING THE BINARY       #
            #        AND EVEN FLASHING THE CHIP!            #
            # Author: Othane                                #
            #################################################

    # setup compiler and flags for stm32f373 build 
    SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) 


    CROSS_COMPILE ?= arm-none-eabi- 
    export CC = $(CROSS_COMPILE)gcc 
    export AS = $(CROSS_COMPILE)gcc -x assembler-with-cpp 
    export AR = $(CROSS_COMPILE)ar 
    export LD = $(CROSS_COMPILE)ld 
    export OD   = $(CROSS_COMPILE)objdump 
    export BIN  = $(CROSS_COMPILE)objcopy -O ihex 
    export SIZE = $(CROSS_COMPILE)size 
    export GDB = $(CROSS_COMPILE)gdb 


    MCU = cortex-m4 
    FPU = -mfloat-abi=hard -mfpu=fpv4-sp-d16 -D__FPU_USED=1 -D__FPU_PRESENT=1 -DARM_MATH_CM4 
    DEFS = -DUSE_STDPERIPH_DRIVER -DSTM32F37X -DRUN_FROM_FLASH=1 -DHSE_VALUE=8000000 
    OPT ?= -O0  
    MCFLAGS = -mthumb -mcpu=$(MCU) $(FPU) 


    export ASFLAGS  = $(MCFLAGS) $(OPT) -g -gdwarf-2 $(ADEFS) 
    CPFLAGS += $(MCFLAGS) $(OPT) -gdwarf-2 -Wall -Wno-attributes -fverbose-asm  
    CPFLAGS += -ffunction-sections -fdata-sections $(DEFS) 
    export CPFLAGS 
    export CFLAGS += $(CPFLAGS) 


    export LDFLAGS  = $(MCFLAGS) -nostartfiles -Wl,--cref,--gc-sections,--no-warn-mismatch $(LIBDIR) 


    HINCDIR += ./STM32F37x_DSP_StdPeriph_Lib_V1.0.0/Libraries/CMSIS/Include/ \ 
        ./STM32F37x_DSP_StdPeriph_Lib_V1.0.0/Libraries/CMSIS/Device/ST/STM32F37x/Include/ \ 
        ./STM32F37x_DSP_StdPeriph_Lib_V1.0.0/Libraries/STM32F37x_StdPeriph_Driver/inc/ \ 
        ./ 
    export INCDIR = $(patsubst %,$(SELF_DIR)%,$(HINCDIR)) 




    # openocd variables and targets 
    OPENOCD_PATH ?= /usr/local/share/openocd/ 
    export OPENOCD_BIN = openocd 
    export OPENOCD_INTERFACE = $(OPENOCD_PATH)/scripts/interface/stlink-v2.cfg 
    export OPENOCD_TARGET = $(OPENOCD_PATH)/scripts/target/stm32f3x_stlink.cfg 


    OPENOCD_FLASH_CMDS = '' 
    OPENOCD_FLASH_CMDS += -c 'reset halt' 
    OPENOCD_FLASH_CMDS += -c 'sleep 10'  
    OPENOCD_FLASH_CMDS += -c 'stm32f1x unlock 0' 
    OPENOCD_FLASH_CMDS += -c 'flash write_image erase $(PRJ_FULL) 0 ihex' 
    OPENOCD_FLASH_CMDS += -c shutdown 
    export OPENOCD_FLASH_CMDS 


    OPENOCD_ERASE_CMDS = '' 
    OPENOCD_ERASE_CMDS += -c 'reset halt' 
    OPENOCD_ERASE_CMDS += -c 'sleep 10'  
    OPENOCD_ERASE_CMDS += -c 'sleep 10'  
    OPENOCD_ERASE_CMDS += -c 'stm32f1x mass_erase 0' 
    OPENOCD_ERASE_CMDS += -c shutdown 
    export OPENOCD_ERASE_CMDS 


    OPENOCD_RUN_CMDS = '' 
    OPENOCD_RUN_CMDS += -c 'reset halt' 
    OPENOCD_RUN_CMDS += -c 'sleep 10' 
    OPENOCD_RUN_CMDS += -c 'reset run' 
    OPENOCD_RUN_CMDS += -c 'sleep 10'  
    OPENOCD_RUN_CMDS += -c shutdown 
    export OPENOCD_RUN_CMDS 


    OPENOCD_DEBUG_CMDS = '' 
    OPENOCD_DEBUG_CMDS += -c 'halt' 
    OPENOCD_DEBUG_CMDS += -c 'sleep 10' 


    .flash: 
        $(OPENOCD_BIN) -f $(OPENOCD_INTERFACE) -f $(OPENOCD_TARGET) -c init $(OPENOCD_FLASH_CMDS) 


    .erase: 
        $(OPENOCD_BIN) -f $(OPENOCD_INTERFACE) -f $(OPENOCD_TARGET) -c init $(OPENOCD_ERASE_CMDS) 


    .run: 
        $(OPENOCD_BIN) -f $(OPENOCD_INTERFACE) -f $(OPENOCD_TARGET) -c init $(OPENOCD_RUN_CMDS) 


    .debug: 
        $(OPENOCD_BIN) -f $(OPENOCD_INTERFACE) -f $(OPENOCD_TARGET) -c init $(OPENOCD_DEBUG_CMDS) 

Othane 様、次の手順でこの makefile を使用する方法を説明していただけますか。

  • ソースコードからバイナリをビルドする
  • チップをフラッシュする

私はメイクファイルについて基本的なことは知っていますが、あなたのメイクファイルは本当に奥が深いですね。GNU の make ユーティリティの機能をかなり使っているようですね。もう少し説明していただければ、ボーナスを差し上げます ;-)

------------------------------

ベストアンサー1

覚えている限りでは、直接ロードコマンドでも問題があったので、「flash write_image eras my_project.hex 0 ihex」に切り替えました。明らかに hex ファイルを使用していましたが、elf ファイルでも機能するようです。http://openocd.org/doc/html/Flash-Commands.html...このコマンドの良いところは、書き込まれているフラッシュセクションのみを消去する点です。これは非常に便利で、消去コマンドは必要ありません。

上記のコマンドを実行する前に、「stm32f1x unlock 0」を実行して、チップがロック解除され、フラッシュに接続できることを確認する必要があります...これについてはデータシートを参照してください。

また、開始するには、コマンド「stm32f1x mass_erase 0」でチップを完全にすばやく消去できるので、既知の状態で開始することをお勧めします。

これらのコマンドのいくつかはF1用だと書かれていますが、信じてください、F4シリーズでも動作します。

ちなみにこのファイルには、私がF4をフラッシュするために使用するコマンドのほとんどが含まれているので、参考になるかもしれません。https://github.com/othane/mos/blob/master/hal/stm32f373/stm32f373.mk

それであなたは立ち往生から抜け出せるといいのですが

おすすめ記事