Try   HackMD

學習如何建立一個 stm32 的 bare-metal 專案,完整專案可見 cm4bm

使用設備: NUCLEO-F303ZE

  1. 官方文件規格
  2. 開發板: STM32F303ZE
  1. 記得要安裝必要的模組和工具

sudo apt-get install git make cmake libusb-1.0-0-dev
sudo apt-get install gcc build-essential

  1. 下載並構建ST-Link v2驅動程式

cd ~
git clone https://github.com/stlink-org/stlink
cd stlink
cmake .
make

cmake 成功可以看到以下結果

-- Rewrite /home/benson/stlink/.version with 1.7.0!
-- stlink version: 1.7.0-201-g254a525
-- Major 1 Minor 7 Patch 0
-- Found libusb: /usr/lib/x86_64-linux-gnu/libusb-1.0.so  
-- Looking for __stack_chk_fail in ssp
-- Looking for __stack_chk_fail in ssp - not found
-- Looking for sys/mman.h
-- Looking for sys/mman.h - found
-- Looking for sys/time.h
-- Looking for sys/time.h - found
-- Looking for unistd.h
-- Looking for unistd.h - found
-- Looking for dirent.h
-- Looking for dirent.h - found
-- STLINK_LIB_SHARED: stlink-shared
-- PROJECT_VERSION_MAJOR: 1
-- VERSION: 1.7.0
-- STLINK_LIB_STATIC: stlink-static
-- PROJECT_VERSION_MAJOR: 1
-- VERSION: 1.7.0
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1") 
-- Checking for module 'gtk+-3.0'
--   No package 'gtk+-3.0' found
-- GTK3 not found!
-- Debian-based Linux OS detected
-- Manpage generation disabled
-- Configuring done
-- Generating done
-- Build files have been written to: /home/benson/stlink

make 成功可以看到以下結果 (擷取部份)

[ 60%] Building C object CMakeFiles/stlink-static.dir/src/stlink-lib/logging.c.o
[ 62%] Building C object CMakeFiles/stlink-static.dir/src/stlink-lib/md5.c.o
[ 64%] Building C object CMakeFiles/stlink-static.dir/src/stlink-lib/sg.c.o
[ 66%] Building C object CMakeFiles/stlink-static.dir/src/stlink-lib/usb.c.o
[ 68%] Building C object CMakeFiles/stlink-static.dir/src/stlink-lib/helper.c.o
[ 70%] Linking C static library lib/libstlink.a
[ 70%] Built target stlink-static
Scanning dependencies of target st-trace
[ 72%] Building C object CMakeFiles/st-trace.dir/src/st-trace/trace.c.o
[ 75%] Linking C executable bin/st-trace
[ 75%] Built target st-trace
Scanning dependencies of target st-flash
[ 77%] Building C object CMakeFiles/st-flash.dir/src/st-flash/flash.c.o
[ 79%] Building C object CMakeFiles/st-flash.dir/src/st-flash/flash_opts.c.o
[ 81%] Linking C executable bin/st-flash
[ 81%] Built target st-flash
Scanning dependencies of target st-info
[ 83%] Building C object CMakeFiles/st-info.dir/src/st-info/info.c.o
[ 85%] Linking C executable bin/st-info
[ 85%] Built target st-info
Scanning dependencies of target test-flash
[ 87%] Building C object tests/CMakeFiles/test-flash.dir/flash.c.o
[ 89%] Building C object tests/CMakeFiles/test-flash.dir/__/src/st-flash/flash_opts.c.o
[ 91%] Linking C executable ../bin/test-flash
[ 91%] Built target test-flash
Scanning dependencies of target test-sg
[ 93%] Building C object tests/CMakeFiles/test-sg.dir/sg.c.o
[ 95%] Linking C executable ../bin/test-sg
[ 95%] Built target test-sg
Scanning dependencies of target test-usb
[ 97%] Building C object tests/CMakeFiles/test-usb.dir/usb.c.o
[100%] Linking C executable ../bin/test-usb
[100%] Built target test-usb
  1. 將重構的二進位制檔案複製到其系統位置
cd bin
sudo cp st-* /usr/local/bin
cd ../lib
sudo cp *.so* /lib32

cd ../config/udev/rules.d/
sudo cp 49-stlinkv* /etc/udev/rules.d/

使用命令 lsusb 查看裝置,可以看到已經有連到 ST-LINK/v2.1

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 0bda:57f2 Realtek Semiconductor Corp. HD WebCam
Bus 001 Device 003: ID 04ca:3015 Lite-On Technology Corp. 
Bus 001 Device 002: ID 046d:c092 Logitech, Inc. G102 LIGHTSYNC Gaming Mouse
Bus 001 Device 020: ID 0483:374b STMicroelectronics ST-LINK/V2.1
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

安裝 GNU ARM Toolchain

ARM gcc 編譯指令

參考 How To Install gcc-arm-none-eabi on Ubuntu 20.04 更新 apt-get 及下載 arm toolchain

sudo apt-get update
sudo apt-get -y install gcc-arm-none-eabi

下載完後新增環境變數

vim ~/.bashrc

# 在最後一行加上
export PATH=$PATH:/home/benson/tmp/gcc-arm-none-eabi-10.3-2021.10/bin    

測試是否成功加到環境變數,可以輸入命令 arm-none-eabi-gcc --version

arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

OpenOCD

首先輸入以下命令安裝 openOCD

sudo apt install openocd

接著測試有無安裝成功,輸入命令 openocd -v 測試,有成功可以看到以下訊息

Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html

putty

都安裝好後可以開始測試啦,首先安裝 putty

sudo apt-get install putty

安裝完畢後輸入命令 sudo putty 並選擇 serial 的選項,可以看到以下的樣子

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

接著輸入命令 sudo dmesg | grep tty 可以看到 serial 連接了哪些裝置

[    0.076626] printk: console [tty0] enabled
[    0.521220] tty tty2: hash matches
[   19.317722] cdc_acm 1-2:1.2: ttyACM0: USB ACM device
[  145.002427] cdc_acm 1-2:1.2: ttyACM0: USB ACM device
[ 2628.688812] cdc_acm 1-2:1.2: ttyACM0: USB ACM device
[ 3436.742686] cdc_acm 1-1:1.2: ttyACM0: USB ACM device
[ 3553.949930] cdc_acm 1-1:1.2: ttyACM0: USB ACM device

經測試,測試的開發板使用 ttyACM0 ,因此需要在 serial line 上輸入 /dev/ttyACM0 並給出正確的鮑率,最後就會成功開啟並列印出訊息

Input a data!!
255
data = 255
Input a data!!

在 VS code 上使用 Cortex-Debug 做 debug

首先需要安裝 OpenOCD 以及 VS code 的模組 Cortex_Debug

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

目前 Cortex-Debug 的版本使用 1.6.3

而 OpenOCD 比較特別,需要使用版本 0.11.0 以後才可以 (用 0.10.0 會失敗) ,這裡就使用 ST 給的 STMicroelectronics/OpenOCD

首先先 clone 該專案

git clone https://github.com/STMicroelectronics/OpenOCD.git
cd OpenOCD

接著先安裝需要的函式庫

sudo apt-get install make
sudo apt-get install libtool
sudo apt-get install pkg-config
sudo apt-get install autoconf
sudo apt-get install automake
sudo apt-get install texinfo
sudo apt-get install libusb-1.0

可以開始建構專案了

./bootstrap
./configure
sudo make install

成功完成後可以確認 openocd 版本,使用命令 openocd -v

Open On-Chip Debugger 0.11.0+dev-00454-gd3b71197b (2022-09-10-17:00) [https://github.com/STMicroelectronics/OpenOCD]
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html

兩者都安裝完後即可開啟 debugger ,開啟結果如下所示

要可以追蹤 source file 的話,記得要在編譯時新增 -g 選項

OpenOCD Debuger 測試

GDB Client

  1. 利用檔案 st_nucleo_f3.cfg 開啟 openOCD ,成功可以看到以下訊息
openocd -f board/st_nucleo_f3.cfg
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v38 API v2 SWIM v27 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 3.243541
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
  1. 在 cmd 上開啟 GDB client 並連上 openocd

arm-none-eabi-gdb.exe

$ arm-none-eabi-gdb
GNU gdb (GNU Arm Embedded Toolchain 10.3-2021.10) 10.2.90.20210621-git
Copyright (C) 2021 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=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://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) 

接著連到 openocd 上

target remote localhost:3333

接著列出比較常用的指令 (記得前面要加 monitor)

  • Reset

    1. reset
    2. reset run
    3. reset halt
    4. reset init
  • Halt: 暫停目前的執行

    monitor halt

  • Resume: 結束 halt 並開始執行程式

    monitor resume

  • 燒入程式

    monitor flash write_image erase Debug/main.elf

Telnet Client

  1. Install Putty

sudo apt-get install putty

  1. 利用檔案 st_nucleo_f3.cfg 開啟 openOCD ,成功可以看到以下訊息
openocd -f board/st_nucleo_f3.cfg
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v38 API v2 SWIM v27 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 3.243541
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
  1. 使用 putty 裡的 Telnet 連上 OpenOCD (Port 為 4444)
    • Hostname: localhost
    • Port: 4444

接著列出比較常用的指令

  • Reset

    1. reset
    2. reset run
    3. reset halt
    4. reset init
  • Halt: 暫停目前的執行

    halt

  • Resume: 結束 halt 並開始執行程式

    resume

  • 燒入程式

    flash write_image erase Debug/main.elf

錯誤紀錄

使用 GDB 的問題

使用命令 sudo apt-get -y install gcc-arm-none-eabi 所下載的編譯器並不含有 arm-none-eabi-gdb ,因此需要額外加入,可從 Arm GNU Toolchain Downloads 下載

下載後將 arm-none-eabi-gdb 加入到 Linux 的輸入命令的預測路徑 /usr/bin

$ mv arm-none-eabi-gdb /usr/bin/

接著執行 arm-none-eabi-gdb ,如果發生以下錯誤

/usr/bin/arm-none-eabi-gdb: error while loading shared libraries: libncursesw.so.5
: cannot open shared object file: No such file or directory

解法: 安裝對應的函式庫

$ sudo apt-get install libncursesw5

接著如果出現以下的問題

Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
Python path configuration:
  PYTHONHOME = (not set)
  PYTHONPATH = (not set)
  program name = '/usr/local/bld-tools/bld-tools-virtual-env/bin/python'
  isolated = 0
  environment = 1
  user site = 1
  import site = 1
  sys._base_executable = '/usr/local/bld-tools/bld-tools-virtual-env/bin/python'
  sys.base_prefix = '/usr'
  sys.base_exec_prefix = '/usr'
  sys.executable = '/usr/local/bld-tools/bld-tools-virtual-env/bin/python'
  sys.prefix = '/usr'
  sys.exec_prefix = '/usr'
  sys.path = [
    '/usr/lib/python38.zip',
    '/usr/lib/python3.8',
    '/usr/lib/lib-dynload',
  ]
Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'

Current thread 0x00007fd07c45ac00 (most recent call first):
<no Python frame>

問題就是該版本的 GDB 使用了 python3.8 的函式庫,而我的 Ubuntu 版本為 22.04 ,其 Python 的預設版本為 3.10.6 ,對應的函式庫不同,而導致這樣的錯誤。因此解法就是直接安裝 python3.8 的版本,命令如下

$ sudo apt install python3.8