ARM Mbed OS
是一款开源免费的物联网操作系统,包含有基于 ARM Cortex-M
微控制器开发智能连接产品所需的全部基础架构。其推出的 DAP-Link
同样是一个开源软件项目,它支持编程和调试运行在 ARM Cortex
微控制器上面的代码,主要运行于拥有 SWD 或者
JTAG 接口的微控制器当中,并且通过 USB 接口在计算机与
ARM Cortex
微控制器之间创建一个用于调试仿真的桥梁,为开发人员提供了下载调试 、串口通信 、拖拽烧录 等实用功能。
DAPLink 主要由 Mbed
硬件开发工具包 以及 DAPLink
固件 两个开源项目构成,而 UINIO-DAP-Link
则是由博主设计的一款开源 DAPLink
仿真器实现,相比于官方原版的硬件电路设计,在引出有 SWD
调试接口(由 ARM 制订)的同时,还引出了 JTAG 接口(IEEE
1149 国际标准)以及5V
和 3.3V
电源,并且附带有
SWD 至 JTAG 的转接板 PCB
设计,而固件部分则是基于 ARM
官方的原版固件移植而来,全部的原理图与固件程序都开源在博主的 GitHub 。
DAP Link 简介
DAPLink 总体上可以为开发人员提供如下一系列功能:
MSC - 通过拖拽编程 Flash 存储器;
CDC - 用于日志、跟踪和终端仿真的虚拟通信端口;
CMSIS-DAPv2 WinUSB - 兼容 CMSIS 的调试通道;
CMSIS-DAPv1 HID - 兼容 CMSIS 的调试通道;
WebUSB CMSIS-DAP HID - 兼容 CMSIS 的调试通道;
目前 DAPLink 已经取代 mbed CMSIS-DAP 接口固件项目。
如下品牌的 ARM 硬件接口电路(HIC ,Hardware Interface
Circuits)与 DAPLink 的固件完全兼容:
DAPLink
主要提供了拖放编程 、串口通信 、调试 三种接口:
拖拽烧录 :通过将 .bin
或者
.hex
格式的文件复制或者保存到 DAPLink
驱动器,从而实现对目标微控制器的编程。完成以后,驱动器将会重新进行挂载。如果下载出现问题,则驱动器上将会自动生成一个包含有故障信息的
FAIL.TXT
文件;
串口通信 :可以直接连接至目标 MCU
微控制器进行双向通信,支持
9600
、14400
、19200
、28800
、38400
、56000
、57600
、115200
等常见波特率;
下载调试 :可以使用任意支持 CMSIS-DAP 协议的 IDE
集成开发环境进行调试,例如 pyOCD 、uVision 、IAR ;
更新设备固件时,只需要连接上 USB 并且按住重置键,让设备进入
Bootloader
引导模式,从而开始下载固件。如果下载成功,那么设备将会离开引导模式,并且开始运行新的固件。如果下载失败,则设备将会自动生成显示有错误原因的
FAIL.TXT
文件。
编译 DAPLink 工程
DAPLink 的固件源代码使用 project-generator
项目下的 progen
命令进行构建,除此之外,编译过程当中还需要使用到如下一系列组件:
准备虚拟环境
获取源代码,并且创建 Python 虚拟环境:
1 2 3 4 $ git clone https://github.com/mbedmicro/DAPLink $ cd DAPLink $ pip install virtualenv $ virtualenv venv
激活 Python 虚拟环境,并且更新关联依赖:
1 2 3 $ venv/Scripts/activate (For Linux) $ venv/Scripts/activate.bat (For Windows) (venv) $ pip install -r requirements.txt
构建与编译
接下来开始构建 DAPLink 工程,可以使用 project-generator
中的 progen
命令或者 tools/progen_compile.py
脚本。
通过
progen_compile.py
脚本编译
1 (venv) $ python tools/progen_compile.py [-t <tool>] [--clean] [-v] [--parallel] [<project> [<project> ...]]
-t <tool>
:选择要构建的工具链,默认为
make_gcc_arm
,其它的可选项分别为
make_gcc_arm
、make_armclang
、make_armcc
、cmake_gcc_arm
、cmake_armclang
、cmake_armcc
;
--clean
:
清除现有的编译结果,并且强制重新编译所有文件;
-v
:
列出所有命令以及参数,将会使得编译过程更加冗长;
--parallel
: 启用并行编译;
<project>
: 待编译的目标项目(例如
stm32f103xb_bl
,
lpc11u35_if
),如果不指定将会编译所有工程;
通过 progen
命令和
Make 编译
如下的命令组合了生成与编译操作:
1 (venv) $ progen generate -t make_gcc_arm -p <project> -b
当然也可以将生成与编译操作分开执行:
1 2 (venv) $ progen generate -t make_gcc_arm -p <project> (venv) $ make -C projectfiles/make_gcc_arm/<project> [<target>] [VERBOSE=1]
<project>
: 等待编译的目标工程(例如
stm32f103xb_bl
和 lpc11u35_if
);
<target>
: 编译目标,可以选择为
all
、clean
、help
;
VERBOSE=1
: 显示额外的编译信息;
通过 progen
命令和
CMake 编译
下面的命令同样组合了生成与编译两个步骤:
1 (venv) $ progen generate -t cmake_gcc_arm -o generator=<generator> -p <project> -b
<generator>
: 指定使用如下的 CMake
生成器:
make
(Unix Makefiles
);
mingw-make
(MinGW Makefiles
);
msys-make
(MSYS Makefiles
,
untested);
ninja
(Ninja
);
nmake
(NMake Makefiles
);
<project>
: 等待编译的目标项目(例如
stm32f103xb_bl
, lpc11u35_if
);
通过 progen
命令和 MDK
编译
通过如下命令在 projectfiles/uvision
目录下生成 MDK
工程文件:
1 $ progen generate -t uvision
也可以使用如下的命令,仅仅生成一个指定的工程:
1 progen generate -f projects.yaml -p stm32f103xb_stm32f746zg_if -t uvision
-f
指定输入工程文件;
-p
指定工程名称;
-t
指定 IDE 名称;
在 STM32CubeIDE 使用 DAPLink
安装 arm-eabi 工具链
在 STM32CubeIDE 当中运用 DAPLink
调试与下载程序,需要使用到 ARM
嵌入式应用程序二进制接口 ,也就是 ARM
EABI 。包括了 Windows Toolchain for
ARM 和 OpenOCD
两个工具库:
首先,需要调用 openocd.exe
开启一个连接到 DAP-Link
与目标微控制器的 GDB 调试服务;
然后,STM32CubeIDE 就可以通过
arm-none-eabi-gdb.exe
访问这个 GDB 服务;
下载并且解压两个工具库之后,分别将它们的 bin
目录添加到操作系统的环境变量,再分别执行如下两个命令,测试其是否已经正确的进行安装:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 λ openocd Open On-Chip Debugger 0.11.0 (2021-11-18) [https://github.com/sysprogs/openocd] Licensed under GNU GPL v2 libusb1 09e75e98b4d9ea7909e8837b7a3f00dda4589dc3 For bug reports, read http://openocd.org/doc/doxygen/bugs.html embedded:startup.tcl:26: Error: Can't find openocd.cfg in procedure ' script' at file "embedded:startup.tcl", line 26 Info : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections Error: Debug Adapter has to be specified, see "adapter driver" command embedded:startup.tcl:26: Error: in procedure ' script' at file "embedded:startup.tcl", line 26
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 λ arm-none-eabi-gdb GNU gdb (GDB) 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=i686-w64-mingw32 --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
OpenOCD 命令的调用格式如下面的代码所示,其中的 -f
参数表示当前使用的是配置文件:
1 openocd.exe -f interface\调试器接口配置文件 -f target\目标微控制器配置文件
下面例出了 OpenOCD\share\openocd\scripts\interface
目录下的配置文件,由于这里使用的是 DAP-Link
作为调试器,所以通常都是以 cmsis-dap.cfg
作为参数:
1 2 3 4 5 6 7 8 9 10 11 12 λ ls OpenOCD\share\openocd\scripts\interface altera-usb-blaster.cfg dummy.cfg jtag_vpi.cfg raspberrypi2-native.cfg ti-icdi.cfg altera-usb-blaster2.cfg estick.cfg kitprog.cfg raspberrypi-native.cfg ti-icdi-auto.cfg arm-jtag-ew.cfg flashlink.cfg nds32-aice.cfg rlink.cfg ulink.cfg at91rm9200.cfg ft232r/ nulink.cfg rshim.cfg usb-jtag.cfg buspirate.cfg ft232r.cfg opendous.cfg stlink.cfg usbprog.cfg calao-usb-a9260.cfg ftdi/ openjtag.cfg stlink-dap.cfg vsllink.cfg cc3200lp.cfg imx-native.cfg osbdm.cfg stlink-v1.cfg xds110.cfg chameleon.cfg jlink.cfg parport.cfg stlink-v2.cfg cmsis-dap.cfg jtag_dpi.cfg parport_dlc5.cfg stlink-v2-1.cfg dln-2-gpiod.cfg jtag_hat_rpi2.cfg picoprobe.cfg sysfsgpio-raspberrypi.cfg
下面例出的是 OpenOCD\share\openocd\scripts\target
目录下的全部配置文件,这里需要根据目标微控制器的型号,酌情选择相应的配置文件作为参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 λ ls OpenOCD\share\openocd\scripts\target adsp-sc58x.cfg bluenrg-x.cfg lpc13xx.cfg samsung_s3c2440.cfg aduc702x.cfg c100.cfg lpc1549.cfg samsung_s3c2450.cfg aducm3027.cfg c100config.tcl lpc15xx.cfg samsung_s3c4510.cfg aducm3029.cfg c100helper.tcl lpc17xx.cfg samsung_s3c6410.cfg aducm302x.tcl c100regs.tcl lpc1850.cfg sharp_lh79532.cfg aducm360.cfg cc2538.cfg lpc1xxx.cfg sim3x.cfg aducm4050.cfg cs351x.cfg lpc2103.cfg smp8634.cfg aducm4x50.tcl davinci.cfg lpc2124.cfg snps_em_sk_fpga.cfg allwinner_v3s.cfg dragonite.cfg lpc2129.cfg snps_hsdk.cfg alphascale_asm9260t.cfg dsp56321.cfg lpc2148.cfg spear3xx.cfg altera_fpgasoc.cfg dsp568013.cfg lpc2294.cfg stellaris.cfg altera_fpgasoc_arria10.cfg dsp568037.cfg lpc2378.cfg stm32f0x.cfg am335x.cfg efm32.cfg lpc2460.cfg stm32f1x.cfg am437x.cfg em357.cfg lpc2478.cfg stm32f2x.cfg amdm37x.cfg em358.cfg lpc2900.cfg stm32f3x.cfg ampere_emag.cfg eos_s3.cfg lpc2xxx.cfg stm32f4x.cfg ar71xx.cfg epc9301.cfg lpc3131.cfg stm32f7x.cfg arm_corelink_sse200.cfg esi32xx.cfg lpc3250.cfg stm32g0x.cfg armada370.cfg exynos5250.cfg lpc40xx.cfg stm32g0x_alt.cfg at32ap7000.cfg faux.cfg lpc4350.cfg stm32g4x.cfg at91r40008.cfg feroceon.cfg lpc4357.cfg stm32g4x_alt.cfg at91rm9200.cfg fm3.cfg lpc4370.cfg stm32h7x.cfg at91sam3ax_4x.cfg fm4.cfg lpc546xx.cfg stm32h7x_dual_bank.cfg at91sam3ax_8x.cfg fm4_mb9bf.cfg lpc55sxx.cfg stm32h7x_dual_core.cfg at91sam3ax_xx.cfg fm4_s6e2cc.cfg lpc84x.cfg stm32l0.cfg at91sam3nXX.cfg gd32e23x.cfg lpc8nxx.cfg stm32l0_dual_bank.cfg at91sam3sXX.cfg gd32vf103.cfg lpc8xx.cfg stm32l1.cfg at91sam3u1c.cfg gp326xxxa.cfg ls1012a.cfg stm32l1x_dual_bank.cfg at91sam3u1e.cfg hi3798.cfg marvell/ stm32l4x.cfg at91sam3u2c.cfg hi6220.cfg max32620.cfg stm32l5x.cfg at91sam3u2e.cfg hilscher_netx10.cfg max32625.cfg stm32mp15x.cfg at91sam3u4c.cfg hilscher_netx50.cfg max3263x.cfg stm32u5x.cfg at91sam3u4e.cfg hilscher_netx500.cfg mc13224v.cfg stm32w108xx.cfg at91sam3uxx.cfg icepick.cfg mdr32f9q2i.cfg stm32wbx.cfg at91sam3XXX.cfg imx.cfg nds32v2.cfg stm32wlx.cfg at91sam4c32x.cfg imx21.cfg nds32v3.cfg stm32xl.cfg at91sam4cXXX.cfg imx25.cfg nds32v3m.cfg stm8l.cfg at91sam4lXX.cfg imx27.cfg nds32v5.cfg stm8l152.cfg at91sam4sd32x.cfg imx28.cfg nhs31xx.cfg stm8s.cfg at91sam4sXX.cfg imx31.cfg npcx.cfg stm8s003.cfg at91sam4XXX.cfg imx35.cfg nrf51.cfg stm8s103.cfg at91sam7a2.cfg imx51.cfg nrf52.cfg stm8s105.cfg at91sam7se512.cfg imx53.cfg nuc910.cfg str710.cfg at91sam7sx.cfg imx6.cfg numicro.cfg str730.cfg at91sam7x256.cfg imx6_dual.cfg omap2420.cfg str750.cfg at91sam7x512.cfg imx6_quad.cfg omap3530.cfg str912.cfg at91sam9.cfg imx6sx.cfg omap4430.cfg swj-dp.tcl at91sam9260.cfg imx6ul.cfg omap4460.cfg swj-dp-legacy.tcl at91sam9260_ext_RAM_ext_flash.cfg imx7.cfg omap5912.cfg swm050.cfg at91sam9261.cfg imx7ulp.cfg omapl138.cfg test_reset_syntax_error.cfg at91sam9263.cfg imx8m.cfg or1k.cfg test_syntax_error.cfg at91sam9g10.cfg imx8qm.cfg pic32mm.cfg ti_calypso.cfg at91sam9g20.cfg imxrt.cfg pic32mx.cfg ti_cc13x0.cfg at91sam9g45.cfg infineon/ psoc4.cfg ti_cc13x2.cfg at91sam9rl.cfg is5114.cfg psoc5lp.cfg ti_cc26x0.cfg at91sama5d2.cfg ixp42x.cfg psoc6.cfg ti_cc26x2.cfg at91samdXX.cfg k1921vk01t.cfg pxa255.cfg ti_cc3220sf.cfg at91samg5x.cfg k40.cfg pxa270.cfg ti_cc32xx.cfg atheros_ar2313.cfg k60.cfg pxa3xx.cfg ti_dm355.cfg atheros_ar2315.cfg ke02.cfg qualcomm_qca4531.cfg ti_dm365.cfg atheros_ar9331.cfg ke04.cfg quark_d20xx.cfg ti_dm6446.cfg atheros_ar9344.cfg ke06.cfg quark_x10xx.cfg ti_k3.cfg atmega128.cfg ke0x.cfg raspberry.cfg ti_msp432.cfg atmega128rfa1.cfg ke1xf.cfg raspberrypi2.cfg ti_rm4x.cfg atsame5x.cfg ke1xz.cfg raspberrypi3.cfg ti_tms570.cfg atsaml1x.cfg kex.cfg raspberrypi3_single.cfg ti_tms570ls1224.cfg atsamv.cfg kinetis_128k.cfg readme.txt ti_tms570ls20xxx.cfg avr32.cfg kinetis_1m.cfg renesas_r7s72100.cfg ti_tms570ls3137.cfg bcm2711.cfg kinetis_256k.cfg renesas_rcar_gen2.cfg ti-ar7.cfg bcm281xx.cfg kinetis_32k.cfg renesas_rcar_gen3.cfg ti-cjtag.cfg bcm2835.cfg kinetis_512k.cfg renesas_rcar_reset_common.cfg tmpa900.cfg bcm2836.cfg kinetis_64k.cfg renesas_rz_g2.cfg tmpa910.cfg bcm2837.cfg kinetis_generic.cfg renesas_s7g2.cfg tnetc4401.cfg bcm4706.cfg kl25.cfg rk3308.cfg u8500.cfg bcm4718.cfg kl46.cfg rk3399.cfg vybrid_vf6xx.cfg bcm47xx.cfg klx.cfg rm57x.cfg xilinx_zynqmp.cfg bcm5352e.cfg ks869x.cfg rp2040.cfg xmc1xxx.cfg bcm6348.cfg kx.cfg rp2040-core0.cfg xmc4xxx.cfg bluefield.cfg lpc11xx.cfg rs14100.cfg xmos_xs1-xau8a-10_arm.cfg bluenrg-lp.cfg lpc12xx.cfg samsung_s3c2410.cfg zynq_7000.cfg
这里以
STM32L0
、STM32F1
、STM32F4
系列微控制器为例,需要分别使用到如下几条 OpenOCD 命令:
1 2 3 openocd.exe -f interface\cmsis-dap.cfg -f target\stm32l0.cfg openocd.exe -f interface\cmsis-dap.cfg -f target\stm32f1x.cfg openocd.exe -f interface\cmsis-dap.cfg -f target\stm32f4x.cfg
接下来,具体以 STM32L051K8U6
微控制器作为示例,正确执行
OpenOCD 命令之后的效果如下所示,命令行会提示当前提供的 GDB 服务端口为
3333
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 λ openocd.exe -f interface\cmsis-dap.cfg -f target\stm32l0.cfg Open On-Chip Debugger 0.11.0 (2021-11-18) [https://github.com/sysprogs/openocd] Licensed under GNU GPL v2 libusb1 09e75e98b4d9ea7909e8837b7a3f00dda4589dc3 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : auto-selecting first available session transport "swd" . To override use 'transport select <transport>' . Info : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections Warn : could not read product string for device 0x058f:0x9540: Entity not found Info : CMSIS-DAP: SWD supported Info : CMSIS-DAP: JTAG supported Info : CMSIS-DAP: FW Version = 1.0 Info : CMSIS-DAP: Interface Initialised (SWD) Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 0 Info : CMSIS-DAP: Interface ready Info : clock speed 300 kHz Info : SWD DPIDR 0x0bc11477 Info : stm32l0.cpu: Cortex-M0+ r0p1 processor detected Info : stm32l0.cpu: target has 4 breakpoints, 2 watchpoints Info : starting gdb server for stm32l0.cpu on 3333 Info : Listening on port 3333 for gdb connections
简便起见,也可以将上述命令编写为 Windows 下一个名为
OpenOCD stm32l0.bat
的批处理文件,方便调试的时候快速进行调用:
1 2 3 echo Openocd Runing ... ... ...openocd.exe -f interface\cmsis-dap.cfg -f target\stm32l0.cfg pause
配置 STM32CubeIDE
启动 OpenOCD 服务之后,接着在
STM32CubeIDE 当中新建一个名称为
Test-STM32L051K8U6
的工程:
首先,选中 STM32CubeIDE
左侧的工程名称,点击鼠标右键菜单上的 【Build
Project 】, 编译生成出一个 Test-STM32L051K8U6.elf
二进制文件。点击工具栏上【Debug 】图标右侧的箭头,点击弹出菜单上的
Debug Configrations...
打开调试配置窗口,鼠标双击窗口上的
GDB Hardware Debugging
新建一条名为
Test-STM32L051K8U6 Debug
的 GDB
硬件调试配置,并在自动打开的【Main】选项卡界面进行如下一系列配置:
切换至【Debugger 】选项卡,将 GDB 命令修改为
D:\Software\Tech\ARMEabi\bin\arm-none-eabi-gdb.exe
,并且将连接地址设置为
localhost:3333
:
经过上述步骤的配置,鼠标点击【Debug 】按钮,就已经可以让
STM32CubeIDE 通过 UINIO-DAP-Link
实现固件下载,如果需要进入单步调试模式,则可以在【Startup 】选项卡当中,手动在
main
函数位置设置一个断点:
首先,需要在 STM32CubeIDE 的 External
Tool 当中添加 OpenOCD,依次点击顶部菜单栏当中的 【RUN
-> External Tools -> External Tools
Configrations... 】,新建一个名称为
Test-STM32L051K8U6 Run
的配置,并且将 OpenOCD
命令所在的位置指定为
D:\Software\Tech\ARMEabi\OpenOCD\bin\openocd.exe
,相应的参数设置为
-f interface\cmsis-dap.cfg -f target\stm32l0.cfg
:
打开 STM32CubeIDE 的 Debugger
Configration 窗口,鼠标双击左侧的【Launch
Group 】新建一个名为 UINIO-DAP-Link
的运行组 ,然后点击右侧的【Add... 】按钮:
此时添加的执行配置策略为,首先执行 OpenOCD
命令开启 GDB
服务,然后再通过 arm-none-eabi-gdb
执行调试任务:
最后,配置完成之后的 Launch Group
顺序如下图所示:
接下来,就可以在 STM32CubeIDE
顶部工具栏上【Run】和【Debug】按钮的下面,发现上面的配置的
UINIO-DAP-Link
运行组 ,点击之后就可以愉快的使用
UINIO-DAP-Link 执行 STM32
微控制器的程序调试工作了。
在 Keil µVision 使用 DAPLink