DEV Community

loading...

Mystery of addresses on ARM SWD port

Rajeev Bharol
An Embedded Software guy
・3 min read

Serial Wire Debug (SWD) is a two-wire protocol for accessing the
ARM debug interface. It is part of the ARM Debug Interface Specification v5. In may projects you may need to program or debug the ARM chip over the SWD interface. For me, the most confusing part was understanding the addressing. This article is written to help those may be in same situation as me.

On SWD interface is a Debug port (DP) that is the gateway to the inside of the processor. It provides access to many Access Ports (APs). Access ports are specific to the processor and can be more than one. I will not go into details of various APs. I just want to demystify the addressing for DP and APs in this post.

The 8 bit header in a SWD transaction packet looks like:

----------------------------------------------------------
| Start | AP/DP | R/W | ADDR[0:1] | Parity | Stop | Park |
----------------------------------------------------------
Enter fullscreen mode Exit fullscreen mode

The header has two bits reserved for addressing. Anybody trying to write any application to use SWD would be stuck at this step for a while trying to figure what can I do with two bit address! Many examples on the internet will talk about DP addresses to be 0x00, 0x04, 0x08 and 0x0C which is correct but how can you have these 8 bit addresses with two bits? Answer is in ARM debug architecture document here. The lower two bits of the address [Bits A1:A0] are always 00. Those when used with these two bits in the SWD transaction packet i.e., [Bits A3:A2] gives us one full nibble:

A3 A2 A1 A0
0  0  0  0    = 0x0
0  1  0  0    = 0x4
1  0  0  0    = 0x8
1  1  0  0    = 0xC
Enter fullscreen mode Exit fullscreen mode

But where does that upper nibble '0' of 0x00, 0x04, 0x08 and 0x0C come from to make the addresses 0x00, 0x04, 0x08 and 0x0C? That comes from Select register's DP BANKSELECT field. Confused yet? It is confusing.

There is a 32 bit "Select" Register in DP which has three useful fields:

Bits [31:24] -> Access port ID
Bits [23:8]  -> Reserved, not used
Bits [7:4]   -> AP Bank select
Bits [3:0]   -> DP Bank Select
Enter fullscreen mode Exit fullscreen mode

These 4 bits (bits 3:0) in DP Bank select field make the upper nibble of the DP register address. On power up the values of these bits is always 0 on DP architecture rev 0 (on other revs it can be non zeros and addresses changes accordingly) so the register addresses at power up are:
Bits [3:0] of DP Bank Select + [A3 A2 A1 A0]

That makes up the Debug Port address:
0x00
0x04
0x08
0x0C

This explains how the Debug Port addresses are created. There is one more twist to it. In the SWD packet header you will see the address bits marked as A[2:3]. Bit 2 is written first because LSB is sent on the bus first. If desired address is say, 0x08, these two bits will be written and sent as 01 (not 10)

Same logic of addressing applies to Access Port addresses when we are trying to access the Access port registers. From bits A3 and A2 in the SWD packet we make to the lower nibble of the address. A1 and A0 are always zeros so we get

A3 A2 A1 A0
0  0  0  0    = 0x0
0  1  0  0    = 0x4
1  0  0  0    = 0x8
1  1  0  0    = 0xC
Enter fullscreen mode Exit fullscreen mode

Similar to Debug port addressing, Upper nibble of the address comes from the AP Bank select field of the Select register. These are bits [7:4] of the select register. Suppose we want to access register 0x14 in Access port #0. we will write 0x01 to Bits [7:4] in the DP select register so the upper nibble of the address now is 0x1. The DP will combine this with Bits A3:A0 to create address 0x14. So effectively it is a two step process to access the AP. I hope it helps those looking for this information.

Discussion (0)