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.
このバットファイルを実行すると、うまくいくはずです! すべてがうまくいけば、コンパイルの結果として.bin
1 つのバイナリ ファイルが得られます。.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を起動することができました。方法を説明します。
- まず、STLink-V2 JTAG プログラマが正しくインストールされていることを確認してください。STMicroelectronics の「STLink Utility ツール」を使用してインストールをテストできます。素敵な GUI を備えており、接続ボタンをクリックするだけです。
- 次に、Web サイトhttp://gnutoolchains.com/arm-eabi/openocd/から OpenOCD ソフトウェア実行可能ファイルをダウンロードします。それをインストールし、「C:\Apps\」のようなハード ドライブのフォルダーに配置します。
コマンド ターミナルを開き、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"
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
ターミナル ウィンドウがブロックされていることに注意してください。コマンドを入力することはできなくなります。しかし、それは正常です。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.exe
GDB クライアントを起動するだけです。すべてがうまくいけば、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 ユーティリティのかなりの機能を使用しているようです。もう少し説明をお願いします。ボーナスを差し上げます ;-)