ARM CMSIS DAP源码分析

ARM CMSIS DAP源码分析(一)_穿透灵魂的鼓点的博客-CSDN博客

结合ARM文档ADIv5,分析一下ARM提供的CMSIS DAP的开源代码,写点个人心得。

1.USB的整个传输有2个全局变量二维数组用作缓冲区,如下:

static          uint8_t  USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE];  // Request  Buffer
static          uint8_t  USB_Response[DAP_PACKET_COUNT][DAP_PACKET_SIZE];  // Response Buffer
1
2
分别是输入缓冲和输出缓冲,固件从上位机接收数据后都会存放在这两个缓冲区,之后才会对缓冲区中的数据慢慢进行处理。

2.大概分析了一下SWD通信协议下,USB请求的结构被定义成为uint8_t类型的数组:
1)Request[0]:DAP Command IDs,该变量取值为

/* DAP Command IDs */
#define ID_DAP_Info                     0x00
#define ID_DAP_LED                      0x01
#define ID_DAP_Connect                  0x02
#define ID_DAP_Disconnect               0x03
#define ID_DAP_TransferConfigure        0x04
#define ID_DAP_Transfer                 0x05
#define ID_DAP_TransferBlock            0x06
#define ID_DAP_TransferAbort            0x07
#define ID_DAP_WriteABORT               0x08
#define ID_DAP_Delay                    0x09
#define ID_DAP_ResetTarget              0x0A
#define ID_DAP_SWJ_Pins                 0x10
#define ID_DAP_SWJ_Clock                0x11
#define ID_DAP_SWJ_Sequence             0x12
#define ID_DAP_SWD_Configure            0x13
#define ID_DAP_JTAG_Sequence            0x14
#define ID_DAP_JTAG_Configure           0x15
#define ID_DAP_JTAG_IDCODE              0x16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2)Request[1]:DAP Index;该字段在ID_DAP_Transfer命令中会被忽略
3)Request[2]:request_count;该字段表示当前请求的数量
4)Request[3]:request_value;该字段的含义比较多

/* DAP Transfer Request */
#define DAP_TRANSFER_APnDP              (1<<0)
#define DAP_TRANSFER_RnW                (1<<1)
#define DAP_TRANSFER_A2                 (1<<2)
#define DAP_TRANSFER_A3                 (1<<3)
#define DAP_TRANSFER_MATCH_VALUE        (1<<4)
#define DAP_TRANSFER_MATCH_MASK         (1<<5)
1
2
3
4
5
6
7
该字段在SWD传输协议中也很重要,分别用于表示
a)访问AP/DP(1为AP操作)
b)读操作/写操作(1为读操作)
c)A2,A3表示两个bit,用于确定AP或者DP中的具体寄存器,在确定寄存器时,Bits [1:0]一直都是0b00,例如,在DP访问时,[A3:A2] = 0b10,那么代表访问的寄存器偏移就是[A3:A2]+Bits [1:0] = 0b1000 = 0x08,根据ARM手册,该地址应该是SELECT寄存器,如下图:

d)最后两个用于推动比较和推动验证操作(Pushed compare and pushed verify)
 

今天分析的是RDDI_DAP_GetARMRegs(DWORD *regs, DWORD *rfpu, ULONG64 mask)和RDDI_DAP_SetARMRegs(DWORD *regs, DWORD *rfpu, ULONG64 mask)这两个函数。
以RDDI_DAP_GetARMRegs(DWORD *regs, DWORD *rfpu, ULONG64 mask)为例,代码如下:

// RDDI-DAP Get ARM Registers
//   regs   : Pointer to ARM Registers
//   rfpu   : Pointer to FPU Registers
//   mask   : Register Mask
//   return value: error status
int RDDI_DAP_GetARMRegs (DWORD *regs, DWORD *rfpu, ULONG64 mask) {
  int   status;
  int   regID  [3*64];
  int   regData[3*64];
  int   i, n, m;
  DWORD val;

  if (rddiHandle == NULL) return (RDDI_DAP_ERROR_INTERNAL);

  if (mask == 0) return (RDDI_DAP_ERROR_INTERNAL);

  // Match Retry = 100
  regID[0] = DAP_REG_MATCH_RETRY;
  regData[0] = 100;

  // Match Mask = 0x00010000
  regID[1] = DAP_REG_MATCH_MASK;
  regData[1] = 0x00010000;

  // TAR = DBG_Addr
  regID[2] = DAP_AP_REG_TAR;
  regData[2] = DBG_Addr;

  // SELECT = AP_Sel | 0x10
  regID[3] = DAP_DP_REG_APSEL;
  regData[3] = AP_Sel | 0x10;

  // R/W DAP Registers
  status = rddi_DAP_RegAccessBlock(rddiHandle, rddiDAP_ID, 4, regID, regData);
  status = RDDI_DAP_CheckStatus(status);
  if (status) return (status);

  AP_Bank = 0x10;

  // Prepare Register Access
  for (i = 0, n = 0; n < 64; n++) {
    if (mask & (1ULL << n)) {
      // Get register selector
      if (n < 21) {
        m = n;                  // Core Registers
      } else if (n >= 32) {
        m = 64 + (n - 32);      // FPU Sn
      } else if (n == 31) {
        m = 33;                 // FPU FPCSR
      } else {
        continue;
      }

      // Select register to read (write to DCRSR)
      regID  [i+0] = DAP_REG_AP_0x4;
      regData[i+0] = m;
      // Read and wait for register ready flag (read DHCSR.16)
      regID  [i+1] = DAP_REG_AP_0x0 | DAP_REG_RnW | DAP_REG_WaitForValue;
      regData[i+1] = 0x00010000;  // Value to Match
      // Read register value (read DCRDR)
      regID  [i+2] = DAP_REG_AP_0x8 | DAP_REG_RnW;

      i += 3;
    }
  }

  // R/W DAP Registers
  status = rddi_DAP_RegAccessBlock(rddiHandle, rddiDAP_ID, i, regID, regData);
  status = RDDI_DAP_CheckStatus(status);
  if (status) return (status);

  status = RDDI_DAP_StickyError();
  if (status) return (status);

  // Store register values
  for (i = 0, n = 0; n < 64; n++) {
    if (mask & (1ULL << n)) {
      val = regData[i+2];
      i  += 3;
      if ((n < 21) && regs) {
        *((DWORD *)regs + n) = val;
      } else if ((n >= 32) && rfpu) {
        *((DWORD *)rfpu + (n - 32)) = val;
      } else if ((n == 31) && rfpu) {
        //rfpu->FPSCR = val;
      }
    }
  }

  return (0);
}

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
83
84
85
86
87
88
89
90
91
1.根据ARM的注释,

> #define DAP_REG_MATCH_MASK      16  //!< ID to write virtual match mask (used as mask for read operation which waits for value match)
> #define DAP_REG_MATCH_RETRY     17  //!< ID to write virtual match retry (used as retry count for read operation which waits for value
> match)
1
2
3
这两个值是一个虚拟的,用于读操作的匹配掩码和对应的匹配值
,这个不是很重要。

2.

regID[2] = DAP_AP_REG_TAR;
  regData[2] = DBG_Addr;
1
2
这段代码设置的是AP的TAR寄存器。因为这个函数是用来访问ARM的内核寄存器,TAR设置为调试寄存器的基址0xE000EDF0,表示之后的读或者写操作的地址为TAR中写入的地址。
3.

regID[3] = DAP_DP_REG_APSEL;
  regData[3] = AP_Sel | 0x10;
1
2
这段代码设置的是DP的SELECT寄存器,0x10用于修改APBANKSEL字段,表示选择的是Bank 0x01。这种情况下对应的是AP的BD0~BD3寄存器,即读写对应地址0xE000EDF0~0xE000EDFC。
4.之后的for循环中,

regID  [i+0] = DAP_REG_AP_0x4;
regData[i+0] = m;
1
2
AP中TAR地址偏移0x4的位置是DCRSR寄存器
(1)[4:0]为REGSEL字段,具体含义如下:

00000=R0
00001=R1
...
01111=R15
10000=xPSR
10001=MSP
10010=PSP
10100=特殊功能寄存器组
    [31:24]:CONTROL
    [23:16]:FAULTMASK
    [15:8]:BASEEPRI
    [7:0]:PRIMASK
1
2
3
4
5
6
7
8
9
10
11
12
(2)[16]为REGWNR字段,1表示写寄存器,0表示读寄存器

5.regID [i+2] = DAP_REG_AP_0x8 | DAP_REG_RnW;
这一段表示的是访问相对TAR偏移0x08位置的寄存器,即0xE000EDF8,DCRDR寄存器。具体是读或者写操作,由4中的比特16来决定。

以上操作循环执行即可获取到对应的内核寄存器R0~R15等
————————————————
版权声明:本文为CSDN博主「穿透灵魂的鼓点」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/pengxiao618/article/details/47663773

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: CMSIS DAP CDC驱动下载是为了支持开发板与计算机之间进行数据交互和调试功能而设计的一种驱动程序。这种驱动程序的作用在于,通过将计算机连接到开发板上,并下载CMSIS DAP CDC驱动程序,使得计算机可以访问开发板内部的存储器,进行调试和数据传输。 CMSIS DAP CDC驱动程序是由ARM公司提供的一种通用驱动程序,用于与不同计算机系统之间建立通信协议。下载这个驱动程序可能有一些限制,比如需要知道自己所使用的计算机的操作系统,同时也需要知道开发板的具体型号和支持的协议。根据不同的使用需求,可能需要下载CMSIS DAP CDC的不同版本和对应的驱动程序。因此,在下载CMSIS DAP CDC驱动程序时,需要根据实际需求进行选择和匹配。 总之,CMSIS DAP CDC驱动下载是为了实现开发板和计算机之间的数据交互和调试功能而必须进行的一项操作。只有正确地下载和安装了这个驱动程序,才能够保证开发板和计算机之间稳定的数据传输和调试体验。 ### 回答2: CMSIS-DAP是一种将标准Debug Access Port(DAP)协议与ARM CMSIS软件库相结合的开源工具。它提供了一个轻便而强大的调试工具,可用于ARM Cortex-M微控制器的调试和编程。 CDC(Communication Device Class)驱动是一种指定计算机与通信设备(例如串口、USB隧道等)之间数据传输的通信协议。在CMSIS-DAP中,CDC是通过USB接口进行通信的,因此需要安装CDC驱动程序才能使CMSIS-DAP与计算机进行通信。 要下载CMSIS-DAP CDC驱动,可以前往ARM官网,转到“Tools and Software”页面,下载最新版本的CMSIS-DAP驱动程序。用户还可以到GitHub上获取最新版本的CMSIS-DAP和CDC驱动程序。在下载完驱动程序后,用户需要将其安装到计算机上,以便将CMSIS-DAP与系统进行通信。在安装完成后,用户可以选择使用各种IDE(集成开发环境)来进行ARM微控制器的调试和编程工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值