SWD(Serial Wire Debug) interface

Dependents:   USBMSD_LPC_HelloWorld lpcterm2 Simple-CMSIS-DAP 11u35_usbLocalFilesystem

Committer:
va009039
Date:
Sat Jul 05 07:52:18 2014 +0000
Revision:
1:794d2801ff94
Parent:
0:86fde86e144f
remove mydebug.h

Who changed what in which revision?

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