62

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

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

1. ソフトウェアの構築

最初の「使命」は達成されます。コマンド ラインを使用して、ソフトウェアをコンパイルし、バイナリ.binとイメージにリンクできるようになりました。.elf成功への鍵は、Eclipse が特定のプロジェクトのメイク ファイルを配置する場所を見つけることでした。それらがどこにあるかがわかったら、あとはコマンド ターミナルを開いてコマンドを入力するだけ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

Huray、これですべての GNU ツールをシステム上で稼働させることができました! build.batと同じフォルダに次のファイルを置きますmakefile

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

make -j8 -f makefile all

echo.

このバットファイルを実行すると、うまくいくはずです! すべてがうまくいけば、コンパイルの結果として.bin1 つのバイナリ ファイルが得られます。.elf

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

次の自然な手順は、ファームウェアをチップにフラッシュし、デバッグ セッションを開始することです。Eclipse では、「ボタンを 1 回クリックする」だけです。少なくとも、Eclipse がマイクロコントローラー用に正しく構成されていれば。しかし、舞台裏で何が起こっているのでしょうか? 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 Debugger はコマンド ライン ソフトウェアです。多くの人が視覚的なインターフェースを好みます。それはまさにEclipseが行うことです。Eclipse は OpenOCD に接続する GDB クライアントを開始しますが、それはすべてユーザーには隠されています。Eclipse は、舞台裏で GDB クライアントと対話するグラフィカル インターフェイスを提供します。

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

ここに画像の説明を入力

>> OpenOCDの起動

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

  1. まず、STLink-V2 JTAG プログラマが正しくインストールされていることを確認してください。STMicroelectronics の「STLink Utility ツール」を使用してインストールをテストできます。素敵な GUI を備えており、接続ボタンをクリックするだけです。 ここに画像の説明を入力
  2. 次に、Web サイトhttp://gnutoolchains.com/arm-eabi/openocd/から OpenOCD ソフトウェア実行可能ファイルをダウンロードします。それをインストールし、「C:\Apps\」のようなハード ドライブのフォルダーに配置します。
  3. コマンド ターミナルを開き、OpenOCD を起動します。マイクロコントローラを探す場所を OpenOCD が認識できるように、いくつかの構成ファイルを OpenOCD に与える必要があります。通常、JTAG プログラマーを記述する構成ファイルと、マイクロコントローラーを定義する構成ファイルを提供する必要があります。-fコマンドラインで引数を使用して、これらのファイルを OpenOCD に渡します。また、OpenOCD にフォルダーへのアクセス権を与える必要があります。これには、引数scriptsを渡します。-sこれは、コマンドラインを使用してコンピューターで OpenOCD を開始する方法です。

    > "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 とやり取りするには 2 つのオプションがあります。別の端末で Telnet セッションを開始し、TCP ポートlocalhost:4444にログオンして、OpenOCD にコマンドを送信し、フィードバックを受け取ることができます。または、GDB クライアント セッションを開始し、TCP ポートに接続しますlocalhost:3333

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

これは、Telnet セッションを開始して、実行中の OpenOCD プログラムと対話する方法です。

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

> telnet 127.0.0.1 4444

正常に動作すると、端末に次のメッセージが表示されます。

Open On-Chip Debugger
> ..

これで、コマンドを OpenOCD に送信する準備が整いました! しかし、ここで GDB セッションに切り替えます。それが OpenOCD と対話する最も便利な方法だからです。

>> 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 Utility ツールを使用してバイナリをチップにロードすると問題なく動作したので、自分のチップに欠陥があるとは思っていませんでした。OpenOCD だけが不平を言ってエラーを出していました。当然、私は OpenOCD を非難しました - チップ自体ではありません。詳細については、以下の私の回答を参照してください。


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

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

お気づきかもしれませんが、必要なすべての手順を実行するために Windows cmd コマンドを使用しました。これは、バッチ ファイルで自動化できます。しかし、もっと洗練された方法があります: makefile のすべてを自動化することです! さん/さん Othane は、彼/彼女の Cortex-M 用に次のメイクファイルを提案しましたか? チップ。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) 

親愛なる Mr./Mss. Othane さん、次の手順でこの makefile を使用する方法を説明していただけますか。

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

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

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

4

5 に答える 5

8

私が覚えているように、ストレートロードコマンドにも問題があったので、「flash write_image erase my_project.hex 0 ihex」に切り替えました..明らかに16進ファイルを使用していましたが、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

私はあなたが動けなくなることを願っています

于 2016-07-17T05:45:17.847 に答える
2

これは少し簡潔で素晴らしいスタックオーバーフロー スタイルではありませんが、STM32F4 および STM32F1 用の "mos" ライブラリ ( https://github.com/othane/mos ) 用にこれをセットアップしたコードを示します。 . これは答えるべき大きなトピックなので、例を挙げたほうがよいかもしれません

要するに、私のプロジェクトは Makefile のツリーです。コードをコンパイルして、関心のある主要なものをここにあるのでhttps://github.com/othane/mos/blob/master/hal/stm32f373/stm32f373.mk ...基本的にopenocdが必要です。次に、make .eraseまたはmake .flashまたはmake .debugと入力するだけで、チップを消去したり、新しいコードをフラッシュしてデバッグしたりできる一連のコマンドがあります

最後に、私の単体テスト (これらは基本的にサンプル プログラムです) を見ると、それをビルドするための Makefile + このような gdbinit ファイルが見つかりますhttps://github.com/othane/mos/blob/master/utest/gpio/ debug_gpio_utest.gdbinit ... 次に、1 つのターミナルで「make && make .flash && make .debug」を実行し、この「arm-none-eabi-gdb -x ./debug_gpio_utest.gdbinit」のようにクロス コンパイラ gdb を呼び出します。別の...これにより、コードをフラッシュした後にgdbが起動し、gdbなどからの通常のbreakおよびlistコマンドを使用してコードと対話できます(.gdbinitファイルでリセットコマンドを定義した方法に注意してください。monのヘルプをチェックアウトしてくださいcommand ... 基本的に、gdb を介してコマンドを openocd に直接送信できるようになり、非常に便利です)

申し訳ありませんが、答えは非常に簡潔で、多くのリンクがありますが、うまくいくことを願っています.

于 2016-06-30T09:35:05.220 に答える
1

「gdb」を呼び出して「リモートサーバー」に接続するだけです(サーバーとgdbが同じマシンで実行されている場合はlocalhost)。ソース コードの場所と ELF ファイルの場所を認識できるように GDB を構成します。GDB の基本的な使い方を行っている Web サイトはたくさんあります。

Windows用のGDBがあるようです(http://www.equation.com/servlet/equation.cmd?fa=gdb

GDB の次のコマンドで開始できます。

ターゲットのリモート localhost:3333

ディレクトリ /path/to/project

シンボル ファイル /path/to/project.elf

于 2016-06-28T02:01:12.393 に答える
0

どうやらハードウェアの問題だったようです。STLink Utility ツールを使用してバイナリをチップにロードすると問題なく動作したので、自分のチップに欠陥があるとは思っていませんでした。OpenOCD だけが不平を言ってエラーを出していました。当然、私は OpenOCD を非難しました - チップ自体ではありません。

今日、ボード上の新しいチップで同じ手順を試してみましたが、今ではうまくいきます!

loadコマンドを発行すると、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
       Start address 0x8003450, load size 15388
       Transfer rate: 21 KB/sec, 2564 bytes/write.
    (gdb)

私を助けるために最善を尽くしてくれたすべての人に感謝します:-)

于 2016-07-20T10:09:43.970 に答える