高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)

3月18日注:修改USB最大包长度到1024(HS支持),USB初始化前增加等待100ms。

CMSIS-DAP Debugger 是 ARM 发布的面向 Cortex 系列 MCU 的开源(Apache 2.0协议)JTAG 与 SWD 调试器,现已被 Keil MDK 和 IAR EWARM 等 IDE 支持,用于包括主流的 STM32、NXP LPC、Freescale 等在内的多种 MCU 的程序下载与调试。
这里介绍一下 CMSIS-DAP 1.10 在 STM32F 上实现的高速 USB 2.0 调试器。

实际上这货还可以在 ARM DS-5 上调试 Cortex-A,不过这个超出本文讨论范围。

Keil MDK 工程和源代码(不包括 CMSIS 库已有部分)已上传至
https://code.csdn.net/K_O_Carnivist/cmsis_dap_stm32_hs/

我的试验平台

初版硬件原理图

用了 STM32F405RGT6。理论上只要支持 MDK Middleware 的、带 USB 的单片机都可以,包括更便宜的 STM32F205。
原理图省略了一些退耦电容。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第1张图片

STM32 与 USB3300 常规连接,公用一个 24MHz 晶振。几个 74LV1T125 做电平转换,其中 SWDIO/TMS 信号用 3 个引脚分别控制输入、输出和方向。

软件

Keil MDK 5.17,需要 Pro License;

安装了如下 Software Pack:
  Keil::STM32F4xx_DFP 2.6.0
  Keil::MDK-Middleware 7.0.0
  Keil::ARM_Compiler
  ARM::CMSIS 4.5.0

MDK 5 建立一个 USB 工程

这一步主要参考 http://www.keil.com/appnotes/files/apnt_268.pdf 及 USB Middleware 帮助文档。

新建工程

菜单 Project - New μVision Project。

选个工程存放的位置。

选设备的地方找到 STM32F405RGTx。

Run-Time Environment 选中这几个:
  CMSIS - CORE
  CMSIS - RTOS (API) - Keil RTX
  CMSIS Driver - USB Device (API) - High-speed
  Device - Startup
  Device - STM32Cube Framework (API) - Classic
  Device - STM32Cube HAL - Common
  Device - STM32Cube HAL - Cortex
  Device - STM32Cube HAL - GPIO
  Device - STM32Cube HAL - PWR
  Device - STM32Cube HAL - RCC
  USB - CORE
  USB - Device = 1
  USB - Device - HID = 1
一个简便方法是先把 USB - Device - HID 设成 1,然后按照左下角的提示把依赖的项目选上就好。

新建好的工程有这些内容:

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第2张图片

配置工程

设置 HSE_VALUE

在 Target 设置里面设置正确的晶振频率。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第3张图片

配置 CMSIS-Driver

这一步配置 USB 相关的硬件初始化。

打开 RTE_Device.h 并点击编辑区域下方进入 Configuration Wizard 模式,选中 USB High-speed,并设置 USB 相关的引脚。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第4张图片

配置 USB

这一步配置 USB 相关的软件初始化。

打开 USBD_Config_0.c 并进入 Configuration Wizard 模式,修改 Device Settings 和 String Settings。主要是把 Max Endpoint 0 Packet Size 改成 64 Bytes。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第5张图片

打开 USBD_Config_HID_0.h 并进入 Configuration Wizard 模式,按下图修改。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第6张图片

配置 CMSIS-RTOS

这一步为 USB 配置 RTOS 的资源。

打开 startup_stm32f405xx.s 并进入 Configuration Wizard,把 Stack Size 改成 0x600。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第7张图片

打开 RTX_Conf_CM.c 并进入 Configuration Wizard:
  将 RTOS Kernel Timer input clock frequency [Hz] 改为 168000000,
  将 Number of concurrent running threads 改为 4,
  将 Number of threads with user-provided stack size 改为 3,
  将 Total stack size [bytes] for threads with user-provided stack size 改为 1536,
  将 Timer Thread stack size [bytes] 改为 512,
  其他设置参考下图。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第8张图片

注:在 Run-Time Environment 设置的地方把 USB 对应的链接打开,是 USB Middleware 的文档,可以查看到以上设置的详细说明。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第9张图片

添加主函数并测试

右键点击 Project 栏的 Source Group 1,选择 Add New Item to Group ‘Source Group 1’…。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第10张图片

选择 User Code Template 里面的 ‘main’ module for STM32Cube。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第11张图片

会出现一个 main.c 模板。

这个 main.c 模板是针对 8MHz 晶振的,我们在 SystemClock_Config 函数里把 RCC_OscInitStruct.PLL.PLLM 改成 24,这样就可以用在 24MHz 晶振环境下。

直接编译并下载到板子上。

这中间还需要在 Target 设置的地方配置下载器,就不详述了。

进入 Debug 模式,在 Watch 窗口手动添加一个 SystemCoreClock。
在 main.c 的 SystemClock_Config(); 这一行添加断点,并 Step Over,应该可以看到 SystemCoreClock 从 16M 变化到 168M,这说明时钟配置是正确的。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第12张图片

上面做的这些其实就是在 CMSIS 框架下,利用 MDK Middleware 从头建立 USB 工程的前半部分过程。
如果是一般的 USB 工程,后面步骤是继续利用 User Code Template 添加 USB 线程的文件(就像刚才添加 main.c 一样),就可以直接得到能运行的程序了。
但这次我们会从外部复制 CMSIS-DAP 的代码进来,其中包含 USB 线程部分。

添加 CMSIS-DAP 源码

CMSIS-DAP 源码在 CMSIS 那个 Software Pack 中,一般是放在 Keil 安装目录\ARM\Pack\ARM\CMSIS\4.5.0\CMSIS\DAP\Firmware
这里面有 5 个文件夹:ConfigExamplesIncludeSourceTemplate

复制 Config 里面的 DAP_config.h 到工程目录下,
复制 Template\MDK5 里面的 osObjects.hUSBD_User_HID_0.c 到工程目录下,前一个可能要覆盖已存在的文件。注意不要复制 main.c,因为我们需要用到刚才的时钟配置函数。

将复制进来的 USBD_User_HID_0.cDAP_config.h 添加到工程中的 Source Group 1 中。
在工程源文件中另外建一个 Group 叫 CMSIS DAP,将源码 Source 文件夹中的 DAP.cJTAG_DP.cSW_DP.cSWO.c 四个文件添加进来。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第13张图片

Target 设置的 C/C++ 选项卡里添加两个 Include Paths:.Keil 安装目录\ARM\Pack\ARM\CMSIS\4.5.0\CMSIS\DAP\Firmware\Include

最后直接在 Keil MDK 里修改 main.c
  增加四个 include

#include "osObjects.h"
#include "rl_usb.h"
#include "DAP_config.h"
#include "DAP.h"

  把 main 函数按如下修改:

int main(void)
{
  HAL_Init();                           // STM32F4xx HAL Library Initialization
  SystemClock_Config();                 // Configure the system clock to 168 MHz

  DAP_Setup();                          // DAP Setup
  Delayms(100U);                        // Wait for 100ms
  USBD_Initialize(0U);                  // USB Device Initialization
  USBD_Connect(0U);                     // USB Device Connect
  while (!USBD_Configured(0U));         // Wait for USB Device to configure

  // Create HID Thread
  HID0_ThreadId = osThreadCreate(osThread(HID0_Thread), NULL);
  osThreadSetPriority(osThreadGetId(), osPriorityIdle);

  // Infinite loop
  while (1)
  {
  }
}

CMSIS-DAP 说明文档见 http://www.keil.com/pack/doc/CMSIS/DAP/html/index.html。

修改代码以适配硬件

打开 DAP_config.h(需要先把这个文件变成非只读)。
这个文件大体上分成四个部分,中间以大段注释分割:
  CMSIS-DAP Debug Unit Information 部分定义了调试器的参数,
  CMSIS-DAP Hardware I/O Pin Access 是 JTAG 和 SWD 接口的引脚操作函数,
  CMSIS-DAP Hardware Status LEDs 是 LED 引脚操作函数,
  CMSIS-DAP Initialization 是这些 IO 引脚的初始化函数。
这些代码都与具体的硬件有关,需要根据硬件情况来编写。

CMSIS-DAP Debug Unit Information 部分按如下设置修改:

项目 修改为 备注
#include "device.h" `#include "stm32f4xx.h"
CPU_CLOCK 168000000 按实际设置
IO_PORT_WRITE_CYCLES 2U
DAP_SWD 1 使能 SWD
DAP_JTAG 1 使能 JTAG
DAP_JTAG_DEV_CNT 8U
DAP_DEFAULT_PORT 1U 默认是 SWD 方式
DAP_DEFAULT_SWJ_CLOCK 1000000U 默认 1MHz
DAP_PACKET_SIZE 1024U
DAP_PACKET_COUNT 4U
SWO_UART 0 暂时关闭 SWO,后面我们会再打开
SWO_MANCHESTER 0
TARGET_DEVICE_FIXED 0

͏

这时候如果整个工程重新编译的话,应该是没有错误的。可以尝试编译下载到板子上,然后复位 MCU,并连接 USB 接口。正常情况下系统会识别到这个 HID 设备,驱动程序安装成功后,Keil MDK 的调试器设置里面可以找到这个 CMSIS-DAP。
高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第14张图片
但现在还不能连接目标单片机进行下载调试,因为还没有添加 JTAG 和 SWD 引脚的操作程序。

JTAG 和 SWD 引脚操作

继续编辑 DAP_config.h

自上向下分别需要编写这些函数的实现:

函数名 功能
void PORT_JTAG_SETUP (void) 配置 JTAG 模式时的引脚模式和方向等。
void PORT_SWD_SETUP (void) 配置 SWD 模式时的引脚模式和方向等。
void PORT_OFF (void) 关闭所有输出引脚,但硬件上我们没实现,所以这个函数空着就行。
uint32_t PIN_SWCLK_TCK_IN (void) 返回 SWCLK_TCK 引脚的值。
void PIN_SWCLK_TCK_SET (void) SWCLK_TCK 引脚输出高电平。
void PIN_SWCLK_TCK_CLR (void) SWCLK_TCK 引脚输出低电平。
uint32_t PIN_SWDIO_TMS_IN (void) 返回 SWDIO_TMS_I 引脚的值。
void PIN_SWDIO_TMS_SET (void) SWDIO_TMS_O 引脚输出高电平。
void PIN_SWDIO_TMS_CLR (void) SWDIO_TMS_O 引脚输出低电平。
uint32_t PIN_SWDIO_IN (void) 返回 SWDIO_TMS_I 引脚的值。
void PIN_SWDIO_OUT (uint32_t bit) SWDIO_TMS_O 引脚按 bit 参数的值输出。
void PIN_SWDIO_OUT_ENABLE (void) SWDIO_TMS_nOE 引脚输出低电平。
void PIN_SWDIO_OUT_DISABLE (void) SWDIO_TMS_nOE 引脚输出高电平。
uint32_t PIN_TDI_IN (void) 返回 0 就行。
void PIN_TDI_OUT (uint32_t bit) TDI 引脚按 bit 参数的值输出。
uint32_t PIN_TDO_IN (void) 返回 TDO 引脚的值。
uint32_t PIN_nTRST_IN (void) 返回 0 就行。
void PIN_nTRST_OUT (uint32_t bit) 空着就行。
uint32_t PIN_nRESET_IN (void) 返回 0 就行。
void PIN_nRESET_OUT (uint32_t bit) nRESET 引脚按 bit 参数的值输出。
void LED_CONNECTED_OUT (uint32_t bit) LED_CONNECTED 引脚按 bit 参数的值输出。
void LED_RUNNING_OUT (uint32_t bit) LED_RUNNING 引脚按 bit 参数的值输出。
void DAP_SETUP (void) 所有用到的 GPIO 初始化,包括开启时钟、设置 GPIO 方向和速度等。

͏

这里有个细节需要小心。名为 PIN_xxxxx_OUT (uint32_t bit) 的几个函数在调用时,bit 参数的最低位应输出到引脚上。就是说这个参数可能不是 01,比如是 0x10 ,那么引脚应该输出低电平。

这里最直接的做法是用 bit-band。由于 bit-band 只操作最低位,可以不受 bit 参数其他位的影响。另外一个指令就能完成一个引脚的读或写。

例如写入 SWDIO 的函数可以写成

static __forceinline void PIN_SWDIO_OUT (uint32_t bit) {
  *((uint32_t *) 0x4240829C) = bit; // 0x42000000 + (0x020414 * 32) + (7 * 4)
}

其中 0x42000000 是外设 bit-banding 基地址,0x020414 是 GPIOB 输出寄存器的偏移,7 是 PB7 对应的第 7 位。

读取 SWDIO 的函数可以写成

static __forceinline uint32_t PIN_SWDIO_TMS_IN (void) {
  return *((uint32_t *) 0x42408218); // 0x42000000 + (0x020410 * 32) + (6 * 4)
}

其中 0x42000000 是外设 bit-banding 基地址,0x020410 是 GPIOB 输入寄存器的偏移,6 是 PB6 对应的第 6 位。

整个 DAP_config.h 我上传到这里管理:
https://code.csdn.net/K_O_Carnivist/cmsis_dap_stm32_hs/tree/master/DAP_config.h

这些都写完后,一个最简单功能的 DAPLink 就完成了。编译并下载程序。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第15张图片

图中是我们自己的调试器检测到 SWD 上的一个 STM32F1。

未完待续哦

后面会陆续补充 USB、SW-DP 测试的过程,和 CMSIS-DAP 更多功能的探索。


分割线


附:最简单的方式实现 CMSIS-DAP 调试器

这篇博客修改过内容。之前是一个老版本的 CMSIS-DAP 调试器在 LPC11U35 上的实现,应该算是最好做的调试器了,这里保留原来的内容。


本文用尽量简单的方式实现一个CMSIS-DAP调试器,并在Keil MDK中使用。

硬件

硬件可参考LPC800-MAX开发板的调试器部分,下面是精简后的原理图。原理图继承原始资料的Apache 2.0开源协议。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第16张图片

图中的MCU为LPC11U35FHI33/501,这个后缀需要注意,其他比如401后缀的不能直接使用下面的程序。
这个MCU不算便宜,零买20来块钱吧。嫌国内不好买的话可以去什么e络盟、Mouser、Digikey之类的分销商。

软件

直接使用LPC800-MAX的CMSIS-DAP固件:
https://developer.mbed.org/handbook/Firmware-LPC800-MAX
或者SWDAP固件:
https://developer.mbed.org/media/uploads/chris/0000_lpc11u35_cmsisdap.bin
或者IBDAP固件:
https://s3.amazonaws.com/armstart/Debug+Tools/IBDAP-LPC11U35/IBDAP-latest.bin

两个附件的区别是,前一个是ARM发布的程序主支,默认只开启SWD,没开JTAG;后一个是第三方发布的,默认开启了SWD和JTAG,但去掉了USB串口和U盘拖拽方式下载这两个功能,本文暂不使用这两个功能。

LPC11U35出厂自带ISP程序,插上USB之后会在电脑上生成一个U盘,把上面LPC800-MAX的固件BIN直接拷进去,然后重新连接USB线就行。
如果已经烧过程序了,可以通过USB上电时短接上面原理图的R?(BOOT),来运行自带ISP程序。

调试器的使用

只介绍Keil MDK中的使用,建议版本4.60以上。

至少连接MCU的SWCLK和SWDIO,有的MCU比如LPC的还需要连RST。

驱动程序在
https://developer.mbed.org/handbook/Windows-serial-configuration

在Target Options的debug选项卡中,选择“CMSIS-DAP Debugger”,并在其中的Settings中按如下设置。
注意时钟速度不要太快,取消“Reset after Connect”的选项。

高速USB 2.0的CMSIS-DAP调试器:CMSIS-DAP正确打开方式(3月18日更新速度和稳定性)_第17张图片

Flash Download里与其他调试器一样选择合适的flash算法,就可以下载程序了。

你可能感兴趣的:(自己玩,arm,stm32)