Keil下载时的具体指令详解

当您在Keil MDK中点击"Download"或"Load"按钮时,会触发一个完整的CMSIS-DAP协议通信流程。以下是从点击按钮到程序运行 的完整过程,包含每一个DAP_Transfer命令及其具体参数。

第一阶段:连接初始化(约10-15个DAP命令)

1.1 获取DAPLink信息

复制代码
Keil发送: DAP_Info(0x00) [查询固件版本]
请求包: [0x00] [0x01] [0xF1] [0x00...]
解释: 查询固件版本信息,确认DAPLink设备
响应: [0x00] [0x01] [0x00] ["CMSIS-DAP V2.0"...]

1.2 连接SWD接口

复制代码
Keil发送: DAP_Connect(0x02) [选择SWD模式]
请求包: [0x02] [0x01] [0x01] [0x00...]
解释: 0x01表示选择SWD模式
响应: [0x02] [0x01] [0x00] [0x01]

1.3 配置SWD时钟频率

复制代码
Keil发送: DAP_SWJ_Clock(0x0A) [设置4MHz时钟]
请求包: [0x0A] [0x04] [0x00 0x00 0x00 0x3D 0x09 0x00 0x00]
解释: 0x00093D00 = 4,000,000 Hz (4MHz)
响应: [0x0A] [0x01] [0x00]

1.4 配置传输参数

复制代码
Keil发送: DAP_TransferConfigure(0x04) [优化传输]
请求包: [0x04] [0x03] [0x00] [0x64] [0x00] [0x0A] [0x00]
解释: 
  空闲周期 = 0x00 (0个空闲周期)
  重试次数 = 0x0064 (100次)
  匹配重试 = 0x000A (10次)
响应: [0x04] [0x01] [0x00]

1.5 配置SWD时序

复制代码
Keil发送: DAP_SWD_Configure(0x05) [设置Trn周期]
请求包: [0x05] [0x01] [0x01] [0x00...]
解释: 设置Trn周期为1个时钟周期
响应: [0x05] [0x01] [0x00]

第二阶段:调试端口初始化(约8-12个DAP_Transfer)

2.1 读取DP-IDCODE验证连接

复制代码
Keil发送: DAP_Transfer(0x07) [读DP-IDCODE]
请求包: [0x07] [0x01] [0x00] [0x0F] [0x00...]
解释: 
  0x07 - DAP_Transfer命令
  0x01 - 1个传输请求
  0x00 - DAP索引
  0x0F - 传输请求: RnW=1(读), APnDP=0(DP), 地址=0xC(DP_RDBUFF)
响应: [0x07] [0x01] [0x00] [0x00] [0x77] [0x14] [0xA0] [0x2B]
解释: 返回IDCODE 0x2BA01477 (STM32F103)

2.2 清除错误状态

复制代码
Keil发送: DAP_Transfer(0x07) [写DP-ABORT]
请求包: [0x07] [0x01] [0x00] [0x08] [0x1F] [0x00] [0x00] [0x00]
解释: 
  0x08 - 写DP, 地址0x0 (DP_ABORT)
  0x0000001F - 清除所有错误标志
响应: [0x07] [0x01] [0x00] [0x00]

2.3 配置调试电源

复制代码
Keil发送: DAP_Transfer(0x07) [写DP-CTRL/STAT]
请求包: [0x07] [0x01] [0x00] [0x09] [0x00] [0x00] [0x00] [0x50]
解释: 
  0x09 - 写DP, 地址0x4 (DP_CTRLSTAT)
  0x50000000 - 设置CDBGPWRUPREQ和CSYSPWRUPREQ
响应: [0x07] [0x01] [0x00] [0x00]

2.4 轮询电源就绪

复制代码
Keil发送: DAP_Transfer(0x07) [读DP-CTRL/STAT]
请求包: [0x07] [0x01] [0x00] [0x0D] [0x00...]
解释: 0x0D - 读DP, 地址0x4 (DP_CTRLSTAT)
响应: [0x07] [0x01] [0x00] [0x00] [0xF0] [0x00] [0x00] [0x50]
解释: 返回0x500000F0, 确认CDBGPWRUPACK和CSYSPWRUPACK已置位

2.5 选择AP0(MEM-AP)

复制代码
Keil发送: DAP_Transfer(0x07) [写DP-SELECT]
请求包: [0x07] [0x01] [0x00] [0x08] [0x00] [0x00] [0x00] [0x00]
解释: 
  0x08 - 写DP, 地址0x8 (DP_SELECT)
  0x00000000 - 选择AP0
响应: [0x07] [0x01] [0x00] [0x00]

2.6 配置AP-CSW(32位访问)

复制代码
Keil发送: DAP_Transfer(0x07) [写AP-CSW]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x12] [0x00] [0x00] [0x23]
解释: 
  0x0B - 写AP, 地址0x0 (AP_CSW)
  0x23000012 - Size=2(32位), AddrInc=1(自动递增)
响应: [0x07] [0x01] [0x00] [0x00]

第三阶段:Flash算法加载(约20-50个DAP_TransferBlock)

3.1 设置RAM起始地址

复制代码
Keil发送: DAP_Transfer(0x07) [写AP-TAR]
请求包: [0x07] [0x01] [0x00] [0x0D] [0x00] [0x00] [0x00] [0x20]
解释: 
  0x0D - 写AP, 地址0x4 (AP_TAR)
  0x20000000 - RAM起始地址
响应: [0x07] [0x01] [0x00] [0x00]

3.2 批量写入Flash算法(以第一个块为例)

复制代码
Keil发送: DAP_TransferBlock(0x06) [批量写入算法数据]
请求包: [0x06] [0x40 0x00] [0x00] [0x0B] 
       [0x00 0x10 0x00 0x20]  // 第一个字: 0x20001000
       [0x01 0x20 0x00 0x20]  // 第二个字: 0x20002001
       [0x02 0x30 0x00 0x20]  // 第三个字: 0x20003002
       ... // 总共64个字(256字节)
解释: 
  0x06 - DAP_TransferBlock命令
  0x0040 - 64个传输请求
  0x00 - DAP索引
  0x0B - 写AP, 地址0x0 (AP_DRW)
响应: [0x06] [0x03] [0x00] [0x40 0x00] [0x00]
解释: 返回64个成功传输

3.3 设置算法参数结构体地址

复制代码
Keil发送: DAP_Transfer(0x07) [写AP-TAR]
请求包: [0x07] [0x01] [0x00] [0x0D] [0x00] [0x10 0x00 0x20]
解释: 设置AP_TAR = 0x20001000 (参数结构体地址)
响应: [0x07] [0x01] [0x00] [0x00]

3.4 写入算法参数

复制代码
Keil发送: DAP_TransferBlock(0x06) [写入参数]
请求包: [0x06] [0x06 0x00] [0x00] [0x0B]
       [0x00 0x00 0x80 0x08]  // device_base = 0x08000000
       [0x00 0x00 0x01 0x00]  // device_size = 0x00010000 (64KB)
       [0x00 0x04 0x00 0x00]  // sector_size = 0x00000400 (1KB)
       [0x40 0x00 0x00 0x00]  // sector_count = 0x00000040 (64)
       [0x00 0x01 0x00 0x00]  // program_page = 0x00000100 (256字节)
       [0x00 0x00 0x7A 0x00]  // clock_speed = 0x00007A00 (8MHz)
响应: [0x06] [0x03] [0x00] [0x06 0x00] [0x00]

第四阶段:CPU控制与Flash操作(约15-30个DAP_Transfer)

4.1 停止CPU内核

复制代码
Keil发送: DAP_Transfer(0x07) [写DHCSR停止CPU]
请求包: [0x07] [0x01] [0x00] [0x0D] [0xF0 0xED 0x00 0xE0]
解释: 设置AP_TAR = 0xE000EDF0 (DHCSR地址)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写DHCSR值]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x03 0x00 0x5F 0xA0]
解释: 
  0x0B - 写AP_DRW
  0xA05F0003 - C_DEBUGEN=1, C_HALT=1
响应: [0x07] [0x01] [0x00] [0x00]

4.2 验证CPU已停止

复制代码
Keil发送: DAP_Transfer(0x07) [读DHCSR]
请求包: [0x07] [0x01] [0x00] [0x2F] [0x00...]
解释: 0x2F - 读AP_DRW
响应: [0x07] [0x01] [0x00] [0x00] [0x03 0x00 0x5F 0xA0]
解释: 返回0xA05F0003, 确认CPU已停止

4.3 调用Flash算法初始化函数

复制代码
Keil发送: DAP_Transfer(0x07) [设置R0=参数地址]
请求包: [0x07] [0x01] [0x00] [0x0D] [0xFC 0xED 0x00 0xE0]
解释: 设置AP_TAR = 0xE000EDFC (DCRDR地址)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写DCRDR]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x00 0x10 0x00 0x20]
解释: 设置R0 = 0x20001000 (参数地址)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [设置PC=初始化函数地址]
请求包: [0x07] [0x01] [0x00] [0x0D] [0xFC 0xED 0x00 0xE0]
解释: 设置AP_TAR = 0xE000EDFC (DCRDR地址)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写PC值]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x00 0x00 0x00 0x20]
解释: 设置PC = 0x20000000 (算法入口地址)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [清除HALT位运行CPU]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x01 0x00 0x5F 0xA0]
解释: 写DHCSR = 0xA05F0001 (清除C_HALT)
响应: [0x07] [0x01] [0x00] [0x00]

4.4 等待初始化完成(轮询)

复制代码
Keil发送: DAP_Transfer(0x07) [读DHCSR检查状态]
请求包: [0x07] [0x01] [0x00] [0x2F] [0x00...]
解释: 读取DHCSR检查C_HALT位
响应: [0x07] [0x01] [0x00] [0x00] [0x01 0x00 0x5F 0xA0]
解释: 返回0xA05F0001, C_HALT=0表示CPU在运行

// 循环读取直到C_HALT=1
Keil发送: DAP_Transfer(0x07) [再次读DHCSR]
请求包: [0x07] [0x01] [0x00] [0x2F] [0x00...]
响应: [0x07] [0x01] [0x00] [0x00] [0x03 0x00 0x5F 0xA0]
解释: 返回0xA05F0003, C_HALT=1表示初始化完成

第五阶段:Flash擦除(约5-10个DAP_Transfer)

5.1 解锁Flash(针对STM32)

复制代码
Keil发送: DAP_Transfer(0x07) [设置Flash KEYR地址]
请求包: [0x07] [0x01] [0x00] [0x0D] [0x04 0x20 0x00 0x40]
解释: 设置AP_TAR = 0x40022004 (FLASH_KEYR地址)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写KEY1]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x23 0x01 0x56 0x45]
解释: 写KEY1 = 0x45670123
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写KEY2]
请求包: [0x07] [0x01] [0x00] [0x0B] [0xAB 0x89 0xEF 0xCD]
解释: 写KEY2 = 0xCDEF89AB
响应: [0x07] [0x01] [0x00] [0x00]

5.2 执行擦除操作

复制代码
Keil发送: DAP_Transfer(0x07) [设置Flash CR地址]
请求包: [0x07] [0x01] [0x00] [0x0D] [0x10 0x20 0x00 0x40]
解释: 设置AP_TAR = 0x40022010 (FLASH_CR地址)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写擦除命令]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x02 0x02 0x00 0x00]
解释: 写FLASH_CR = 0x00000202 (SER=1, STRT=1, SNB=0)
响应: [0x07] [0x01] [0x00] [0x00]

5.3 等待擦除完成(轮询)

复制代码
Keil发送: DAP_Transfer(0x07) [设置Flash SR地址]
请求包: [0x07] [0x01] [0x00] [0x0D] [0x0C 0x20 0x00 0x40]
解释: 设置AP_TAR = 0x4002200C (FLASH_SR地址)
响应: [0x07] [0x01] [0x00] [0x00]

// 循环读取SR直到BSY位清除
Keil发送: DAP_Transfer(0x07) [读Flash状态]
请求包: [0x07] [0x01] [0x00] [0x2F] [0x00...]
响应: [0x07] [0x01] [0x00] [0x00] [0x01 0x00 0x00 0x00]
解释: 返回0x00000001, BSY=1表示正在擦除

// 继续轮询...
Keil发送: DAP_Transfer(0x07) [再次读Flash状态]
请求包: [0x07] [0x01] [0x00] [0x2F] [0x00...]
响应: [0x07] [0x01] [0x00] [0x00] [0x00 0x00 0x00 0x00]
解释: 返回0x00000000, BSY=0表示擦除完成

第六阶段:Flash编程(大量DAP_TransferBlock)

6.1 设置Flash编程地址

复制代码
Keil发送: DAP_Transfer(0x07) [设置Flash起始地址]
请求包: [0x07] [0x01] [0x00] [0x0D] [0x00 0x00 0x80 0x08]
解释: 设置AP_TAR = 0x08000000 (Flash起始地址)
响应: [0x07] [0x01] [0x00] [0x00]

6.2 批量编程数据(以第一页256字节为例)

复制代码
Keil发送: DAP_TransferBlock(0x06) [编程64个字]
请求包: [0x06] [0x40 0x00] [0x00] [0x0B]
       [0x00 0x00 0x00 0x20]  // 第一个指令字
       [0x01 0x00 0x00 0x20]  // 第二个指令字
       [0x02 0x00 0x00 0x20]  // 第三个指令字
       ... // 总共64个字(256字节)
响应: [0x06] [0x03] [0x00] [0x40 0x00] [0x00]

6.3 调用编程函数

复制代码
Keil发送: DAP_Transfer(0x07) [设置编程函数参数]
请求包: [0x07] [0x01] [0x00] [0x0D] [0xFC 0xED 0x00 0xE0]
解释: 设置AP_TAR = 0xE000EDFC (DCRDR地址)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写编程参数]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x00 0x00 0x80 0x08]
解释: 设置R0 = 0x08000000 (目标地址)
响应: [0x07] [0x01] [0x00] [0x00]

// 设置R1 = 数据长度
Keil发送: DAP_Transfer(0x07) [写数据长度]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x00 0x01 0x00 0x00]
解释: 设置R1 = 0x00000100 (256字节)
响应: [0x07] [0x01] [0x00] [0x00]

// 设置PC = 编程函数地址
Keil发送: DAP_Transfer(0x07) [写PC值]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x04 0x00 0x00 0x20]
解释: 设置PC = 0x20000004 (编程函数地址)
响应: [0x07] [0x01] [0x00] [0x00]

// 运行编程函数
Keil发送: DAP_Transfer(0x07) [清除HALT]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x01 0x00 0x5F 0xA0]
解释: 写DHCSR = 0xA05F0001
响应: [0x07] [0x01] [0x00] [0x00]

6.4 等待编程完成(轮询)

复制代码
// 轮询直到编程完成
Keil发送: DAP_Transfer(0x07) [读DHCSR]
请求包: [0x07] [0x01] [0x00] [0x2F] [0x00...]
响应: [0x07] [0x01] [0x00] [0x00] [0x03 0x00 0x5F 0xA0]
解释: C_HALT=1表示编程完成

6.5 重复6.1-6.4直到所有数据编程完成

复制代码
// 对于64KB Flash,可能需要重复256次(每次256字节)
// 每次重复都会发送:
// 1. 设置新的Flash地址
// 2. DAP_TransferBlock写入数据
// 3. 调用编程函数
// 4. 等待完成

第七阶段:校验与复位(约5-10个DAP_Transfer)

7.1 验证Flash数据

复制代码
Keil发送: DAP_Transfer(0x07) [设置验证函数参数]
请求包: [0x07] [0x01] [0x00] [0x0D] [0xFC 0xED 0x00 0xE0]
解释: 设置AP_TAR = 0xE000EDFC
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写验证参数]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x00 0x00 0x80 0x08]
解释: R0 = 0x08000000 (起始地址)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写数据长度]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x00 0x00 0x01 0x00]
解释: R1 = 0x00010000 (64KB)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写CRC值]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x78 0x56 0x34 0x12]
解释: R2 = 预期的CRC32值
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [设置PC=验证函数]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x08 0x00 0x00 0x20]
解释: PC = 0x20000008 (验证函数地址)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [运行验证]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x01 0x00 0x5F 0xA0]
解释: 清除C_HALT
响应: [0x07] [0x01] [0x00] [0x00]

// 等待验证完成
Keil发送: DAP_Transfer(0x07) [读验证结果]
请求包: [0x07] [0x01] [0x00] [0x2F] [0x00...]
响应: [0x07] [0x01] [0x00] [0x00] [0x00 0x00 0x00 0x00]
解释: R0 = 0表示验证成功

7.2 锁定Flash(可选)

复制代码
Keil发送: DAP_Transfer(0x07) [设置Flash CR地址]
请求包: [0x07] [0x01] [0x00] [0x0D] [0x10 0x20 0x00 0x40]
解释: AP_TAR = 0x40022010
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写LOCK位]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x80 0x00 0x00 0x00]
解释: FLASH_CR = 0x00000080 (LOCK=1)
响应: [0x07] [0x01] [0x00] [0x00]

7.3 复位目标芯片

复制代码
Keil发送: DAP_Transfer(0x07) [设置AIRCR地址]
请求包: [0x07] [0x01] [0x00] [0x0D] [0x0C 0xED 0x00 0xE0]
解释: AP_TAR = 0xE000ED0C (AIRCR地址)
响应: [0x07] [0x01] [0x00] [0x00]

Keil发送: DAP_Transfer(0x07) [写复位命令]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x04 0x00 0xFA 0x05]
解释: AIRCR = 0x05FA0004 (VECTKEY + SYSRESETREQ)
响应: [0x07] [0x01] [0x00] [0x00]

7.4 恢复CPU运行

复制代码
Keil发送: DAP_Transfer(0x07) [清除调试使能]
请求包: [0x07] [0x01] [0x00] [0x0B] [0x00 0x00 0x00 0xA0]
解释: DHCSR = 0xA0000000 (清除C_DEBUGEN)
响应: [0x07] [0x01] [0x00] [0x00]

第八阶段:断开连接

8.1 断开DAP连接

复制代码
Keil发送: DAP_Disconnect(0x03) [断开连接]
请求包: [0x03] [0x00...]
响应: [0x03] [0x01] [0x00]

完整流程统计

DAP命令数量统计

阶段 DAP_Transfer数量 DAP_TransferBlock数量 其他DAP命令
连接初始化 10-15 0 3-5
调试端口初始化 8-12 0 0
Flash算法加载 5-10 20-50 0
CPU控制与Flash操作 15-30 0 0
Flash擦除 5-10 0 0
Flash编程 5-10 256-1024 0
校验与复位 5-10 0 0
总计 53-97 276-1074 3-5

典型64KB Flash下载的完整命令序列

复制代码
1. DAP_Info (获取信息)
2. DAP_Connect (连接SWD)
3. DAP_SWJ_Clock (设置时钟)
4. DAP_TransferConfigure (配置传输)
5. DAP_SWD_Configure (配置时序)
6. DAP_Transfer x12 (初始化调试端口)
7. DAP_TransferBlock x30 (加载算法)
8. DAP_Transfer x8 (停止CPU)
9. DAP_Transfer x6 (调用初始化函数)
10. DAP_Transfer x8 (解锁和擦除Flash)
11. DAP_Transfer x5 (设置编程地址)
12. DAP_TransferBlock x256 (编程数据,每256字节一次)
13. DAP_Transfer x6 (调用编程函数,每次编程后)
14. DAP_Transfer x8 (验证数据)
15. DAP_Transfer x4 (复位芯片)
16. DAP_Disconnect (断开连接)

关键时间节点

复制代码
t=0ms: Keil发送DAP_Info
t=5ms: 连接SWD完成
t=20ms: Flash算法加载完成
t=50ms: Flash擦除开始
t=500ms: Flash擦除完成(64KB约450ms)
t=501ms: Flash编程开始
t=3000ms: Flash编程完成(64KB约2500ms)
t=3005ms: 验证完成
t=3010ms: 复位完成
t=3015ms: 断开连接

总结

Keil点击下载时,通过CMSIS-DAP协议执行了300-1200个DAP命令,其中:

  1. DAP_Transfer命令:约50-100次,用于寄存器访问和CPU控制

  2. DAP_TransferBlock命令:约300-1100次,用于批量数据传输

  3. 其他DAP命令:约3-5次,用于连接和配置

整个流程严格按照ARM Cortex-M调试架构设计,通过SWD接口精确控制目标芯片的每一个操作。每个DAP_Transfer命令都对应特定的调试寄存器访问,共同完成了从连接、算法加载、Flash操作到验证复位的完整下载过程。

相关推荐
集芯微电科技有限公司2 小时前
PC5204集成700V/7.5A 400mΩ增强型氮化镓GaN HEMT驱动器具有高功率密度运行
数据结构·人工智能·单片机·嵌入式硬件·神经网络·机器学习·生成对抗网络
GodKK老神灭2 小时前
SWD协议底层实现完全详解
单片机·keil
夜月yeyue2 小时前
Linux 文件设备类型分析
linux·运维·网络·单片机
somi72 小时前
51单片机-03-串行通信
单片机·嵌入式硬件·51单片机
国科安芯2 小时前
星载电源遥测模块抗辐照RISC-V MCU的性能适配与应用
单片机·嵌入式硬件·无人机·cocos2d·risc-v
F133168929572 小时前
33V降5V,25V降12V,12A,WD5030A
人工智能·单片机·嵌入式硬件·汽车·智能家居
CWM-183125336392 小时前
士模微CM4101:低噪声精密运算放大器完美替代OP27
嵌入式硬件·音视频
三佛科技-134163842123 小时前
HN4004_40V10A 贴片SOP8 N沟道MOSFET场效应管详细分析
嵌入式硬件·物联网·智能家居·pcb工艺
羽获飞3 小时前
从零开始学嵌入式之STM32——26.STM32的通用定时器-生成PWM方波
stm32·单片机·嵌入式硬件