SWD(Serial Wire Debug) interface

Dependents:   USBMSD_LPC_HelloWorld lpcterm2 Simple-CMSIS-DAP 11u35_usbLocalFilesystem

Committer:
va009039
Date:
Sat Sep 14 12:50:46 2013 +0000
Revision:
0:86fde86e144f
Child:
1:794d2801ff94
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:86fde86e144f 1 // SWD.cpp 2013/9/14
va009039 0:86fde86e144f 2 #include "SWD.h"
va009039 0:86fde86e144f 3 #include <algorithm>
va009039 0:86fde86e144f 4 #include "mydebug.h"
va009039 0:86fde86e144f 5
va009039 0:86fde86e144f 6 SWD::SWD(PinName swdio, PinName swclk, PinName reset)
va009039 0:86fde86e144f 7 : _swdio(swdio), _swclk(swclk), _nreset(reset)
va009039 0:86fde86e144f 8 {
va009039 0:86fde86e144f 9 conf.turnaround = 1;
va009039 0:86fde86e144f 10 conf.data_phase = 0;
va009039 0:86fde86e144f 11 idle_cycles = 0;
va009039 0:86fde86e144f 12 retry_count = 100;
va009039 0:86fde86e144f 13
va009039 0:86fde86e144f 14 _cpu_delay_count = 2;
va009039 0:86fde86e144f 15 TransferAbort = false;
va009039 0:86fde86e144f 16 }
va009039 0:86fde86e144f 17
va009039 0:86fde86e144f 18 void SWD::Setup()
va009039 0:86fde86e144f 19 {
va009039 0:86fde86e144f 20 _swclk = 1;
va009039 0:86fde86e144f 21 _swdio.output();
va009039 0:86fde86e144f 22 _swdio = 1;
va009039 0:86fde86e144f 23 _nreset.input();
va009039 0:86fde86e144f 24 _nreset.mode(PullUp);
va009039 0:86fde86e144f 25 }
va009039 0:86fde86e144f 26
va009039 0:86fde86e144f 27 void SWD::reset()
va009039 0:86fde86e144f 28 {
va009039 0:86fde86e144f 29 SWJPins(0x00, 0x80);
va009039 0:86fde86e144f 30 SWJPins(0x80, 0x80);
va009039 0:86fde86e144f 31 }
va009039 0:86fde86e144f 32
va009039 0:86fde86e144f 33 void SWD::SWJSequence(int count, const uint8_t* data)
va009039 0:86fde86e144f 34 {
va009039 0:86fde86e144f 35 for(int n = 0; n < count; n++) {
va009039 0:86fde86e144f 36 uint8_t val = data[n/8];
va009039 0:86fde86e144f 37 write_bit(val>>(n%8));
va009039 0:86fde86e144f 38 }
va009039 0:86fde86e144f 39 }
va009039 0:86fde86e144f 40
va009039 0:86fde86e144f 41 uint8_t SWD::SWJPins(uint32_t value, uint32_t select ,int waittime_us)
va009039 0:86fde86e144f 42 {
va009039 0:86fde86e144f 43 if (select & 0x01) { // swclk
va009039 0:86fde86e144f 44 _swclk = (value & 0x01) ? 1 : 0;
va009039 0:86fde86e144f 45 }
va009039 0:86fde86e144f 46 if (select & 0x02) { // swdio
va009039 0:86fde86e144f 47 _swdio = (value & 0x02) ? 1 : 0;
va009039 0:86fde86e144f 48 }
va009039 0:86fde86e144f 49 if (select & 0x80) { // nReset
va009039 0:86fde86e144f 50 if (value & 0x80) {
va009039 0:86fde86e144f 51 _nreset.input();
va009039 0:86fde86e144f 52 } else {
va009039 0:86fde86e144f 53 _nreset.output();
va009039 0:86fde86e144f 54 _nreset = 0;
va009039 0:86fde86e144f 55 }
va009039 0:86fde86e144f 56 }
va009039 0:86fde86e144f 57 if (waittime_us) {
va009039 0:86fde86e144f 58 waittime_us = std::min(waittime_us, 3000000);
va009039 0:86fde86e144f 59 Timer t;
va009039 0:86fde86e144f 60 t.reset();
va009039 0:86fde86e144f 61 t.start();
va009039 0:86fde86e144f 62 while(t.read_us() < waittime_us) {
va009039 0:86fde86e144f 63 if (select & 0x01) { // swclk
va009039 0:86fde86e144f 64 if (_swclk ^ ((value & 0x01) ? 1 : 0)) {
va009039 0:86fde86e144f 65 continue;
va009039 0:86fde86e144f 66 }
va009039 0:86fde86e144f 67 }
va009039 0:86fde86e144f 68 if (select & 0x02) { // swdio
va009039 0:86fde86e144f 69 if (_swdio ^ ((value & 0x02) ? 1 : 0)) {
va009039 0:86fde86e144f 70 continue;
va009039 0:86fde86e144f 71 }
va009039 0:86fde86e144f 72 }
va009039 0:86fde86e144f 73 if (select & 0x80) { // nReset
va009039 0:86fde86e144f 74 if (_nreset ^ ((value & 0x80) ? 1 : 0)) {
va009039 0:86fde86e144f 75 continue;
va009039 0:86fde86e144f 76 }
va009039 0:86fde86e144f 77 }
va009039 0:86fde86e144f 78 break;
va009039 0:86fde86e144f 79 }
va009039 0:86fde86e144f 80 }
va009039 0:86fde86e144f 81 return (_swclk ? 0x01 : 0x00) | (_swdio ? 0x02 : 0x00) | (_nreset ? 0x80 : 0x00);
va009039 0:86fde86e144f 82 }
va009039 0:86fde86e144f 83
va009039 0:86fde86e144f 84 void SWD::SWJClock(uint32_t clock_hz)
va009039 0:86fde86e144f 85 {
va009039 0:86fde86e144f 86 if (clock_hz) {
va009039 0:86fde86e144f 87 uint32_t scc = SystemCoreClock;
va009039 0:86fde86e144f 88 _cpu_delay_count = scc / 2 / clock_hz / 3;
va009039 0:86fde86e144f 89 }
va009039 0:86fde86e144f 90 }
va009039 0:86fde86e144f 91
va009039 0:86fde86e144f 92 void SWD::TransferConfigure(int _idle_cycles, int _retry_count)
va009039 0:86fde86e144f 93 {
va009039 0:86fde86e144f 94 idle_cycles = _idle_cycles;
va009039 0:86fde86e144f 95 retry_count = _retry_count;
va009039 0:86fde86e144f 96 }
va009039 0:86fde86e144f 97
va009039 0:86fde86e144f 98 void SWD::Configure(int turnaround, int data_phase)
va009039 0:86fde86e144f 99 {
va009039 0:86fde86e144f 100 conf.turnaround = turnaround;
va009039 0:86fde86e144f 101 conf.data_phase = data_phase;
va009039 0:86fde86e144f 102 }
va009039 0:86fde86e144f 103
va009039 0:86fde86e144f 104 uint8_t SWD::Transfer(uint8_t request, uint32_t *data)
va009039 0:86fde86e144f 105 {
va009039 0:86fde86e144f 106 for(int retry = retry_count; retry >= 0; retry--) {
va009039 0:86fde86e144f 107 uint8_t ack = rawTransfer(request, data);
va009039 0:86fde86e144f 108 if (ack != SWD_WAIT || TransferAbort) {
va009039 0:86fde86e144f 109 return ack;
va009039 0:86fde86e144f 110 }
va009039 0:86fde86e144f 111 }
va009039 0:86fde86e144f 112 return SWD_WAIT;
va009039 0:86fde86e144f 113 }
va009039 0:86fde86e144f 114
va009039 0:86fde86e144f 115 #pragma Otime
va009039 0:86fde86e144f 116
va009039 0:86fde86e144f 117 static uint32_t calc_parity(uint32_t data, int n)
va009039 0:86fde86e144f 118 {
va009039 0:86fde86e144f 119 uint32_t parity = 0;
va009039 0:86fde86e144f 120 for(int i = 0; i < n; i++) {
va009039 0:86fde86e144f 121 parity += data>>i;
va009039 0:86fde86e144f 122 }
va009039 0:86fde86e144f 123 return parity & 1;
va009039 0:86fde86e144f 124 }
va009039 0:86fde86e144f 125
va009039 0:86fde86e144f 126 uint8_t SWD::rawTransfer(uint8_t request, uint32_t *data)
va009039 0:86fde86e144f 127 {
va009039 0:86fde86e144f 128 write_bit(1); // start bit
va009039 0:86fde86e144f 129 write_bit(request, 4); // APnDP,RnW,A2,A3
va009039 0:86fde86e144f 130 write_bit(calc_parity(request, 4)); // parity bit
va009039 0:86fde86e144f 131 write_bit(0); // stop bit
va009039 0:86fde86e144f 132 write_bit(1); // park bit
va009039 0:86fde86e144f 133
va009039 0:86fde86e144f 134 _swdio.input();
va009039 0:86fde86e144f 135 clock_cycle(conf.turnaround);
va009039 0:86fde86e144f 136
va009039 0:86fde86e144f 137 uint8_t ack = read_bit(3);
va009039 0:86fde86e144f 138 if (ack == SWD_OK) {
va009039 0:86fde86e144f 139 if (request & SWD_RnW) { // read
va009039 0:86fde86e144f 140 uint32_t val = read_bit(32);
va009039 0:86fde86e144f 141 uint32_t parity = read_bit(1);
va009039 0:86fde86e144f 142 if (parity ^ calc_parity(val, 32)) {
va009039 0:86fde86e144f 143 ack = SWD_ERROR;
va009039 0:86fde86e144f 144 }
va009039 0:86fde86e144f 145 if (data) {
va009039 0:86fde86e144f 146 *data = val;
va009039 0:86fde86e144f 147 }
va009039 0:86fde86e144f 148 clock_cycle(conf.turnaround);
va009039 0:86fde86e144f 149 _swdio.output();
va009039 0:86fde86e144f 150 } else { // write
va009039 0:86fde86e144f 151 clock_cycle(conf.turnaround);
va009039 0:86fde86e144f 152 _swdio.output();
va009039 0:86fde86e144f 153 uint32_t val = *data;
va009039 0:86fde86e144f 154 write_bit(val, 32);
va009039 0:86fde86e144f 155 write_bit(calc_parity(val, 32));
va009039 0:86fde86e144f 156 }
va009039 0:86fde86e144f 157 if (idle_cycles) {
va009039 0:86fde86e144f 158 _swdio = 0;
va009039 0:86fde86e144f 159 clock_cycle(idle_cycles);
va009039 0:86fde86e144f 160 }
va009039 0:86fde86e144f 161 _swdio = 1;
va009039 0:86fde86e144f 162 return ack;
va009039 0:86fde86e144f 163 }
va009039 0:86fde86e144f 164
va009039 0:86fde86e144f 165 if (ack == SWD_WAIT || ack == SWD_FAULT) {
va009039 0:86fde86e144f 166 if (conf.data_phase && (request & SWD_RnW)) {
va009039 0:86fde86e144f 167 clock_cycle(32+1);
va009039 0:86fde86e144f 168 }
va009039 0:86fde86e144f 169 clock_cycle(conf.turnaround);
va009039 0:86fde86e144f 170 _swdio.output();
va009039 0:86fde86e144f 171 if (conf.data_phase && ((request & SWD_RnW) == 0)) {
va009039 0:86fde86e144f 172 _swdio = 0;
va009039 0:86fde86e144f 173 clock_cycle(32+1);
va009039 0:86fde86e144f 174 }
va009039 0:86fde86e144f 175 _swdio = 1;
va009039 0:86fde86e144f 176 return ack;
va009039 0:86fde86e144f 177 }
va009039 0:86fde86e144f 178 clock_cycle(32 + 1 + conf.turnaround);
va009039 0:86fde86e144f 179 _swdio.output();
va009039 0:86fde86e144f 180 return ack;
va009039 0:86fde86e144f 181 }
va009039 0:86fde86e144f 182
va009039 0:86fde86e144f 183 void SWD::pin_delay()
va009039 0:86fde86e144f 184 {
va009039 0:86fde86e144f 185 __IO int n = _cpu_delay_count;
va009039 0:86fde86e144f 186 while(n-- > 0)
va009039 0:86fde86e144f 187 ;
va009039 0:86fde86e144f 188 }
va009039 0:86fde86e144f 189
va009039 0:86fde86e144f 190 void SWD::clock_cycle(int n)
va009039 0:86fde86e144f 191 {
va009039 0:86fde86e144f 192 while(n-- > 0) {
va009039 0:86fde86e144f 193 _swclk = 0;
va009039 0:86fde86e144f 194 pin_delay();
va009039 0:86fde86e144f 195 _swclk = 1;
va009039 0:86fde86e144f 196 pin_delay();
va009039 0:86fde86e144f 197 }
va009039 0:86fde86e144f 198 }
va009039 0:86fde86e144f 199
va009039 0:86fde86e144f 200 void SWD::write_bit(uint32_t data, int n)
va009039 0:86fde86e144f 201 {
va009039 0:86fde86e144f 202 for(int i = 0; i < n; i++) {
va009039 0:86fde86e144f 203 _swdio = (data>>i) & 1;
va009039 0:86fde86e144f 204 clock_cycle();
va009039 0:86fde86e144f 205 }
va009039 0:86fde86e144f 206 }
va009039 0:86fde86e144f 207
va009039 0:86fde86e144f 208 uint32_t SWD::read_bit(int n)
va009039 0:86fde86e144f 209 {
va009039 0:86fde86e144f 210 uint32_t data = 0;
va009039 0:86fde86e144f 211 for(int i = 0; i < n; i++) {
va009039 0:86fde86e144f 212 _swclk = 0;
va009039 0:86fde86e144f 213 pin_delay();
va009039 0:86fde86e144f 214 uint32_t val = _swdio & 1;
va009039 0:86fde86e144f 215 data |= val<<i;
va009039 0:86fde86e144f 216 _swclk = 1;
va009039 0:86fde86e144f 217 pin_delay();
va009039 0:86fde86e144f 218 }
va009039 0:86fde86e144f 219 return data;
va009039 0:86fde86e144f 220 }