m3dev

cortex m3 debug tools -- superceded by mdebug
git clone http://frotz.net/git/m3dev.git
Log | Files | Refs | README | LICENSE

swdp.c (3861B)


      1 /* swdp.c
      2  *
      3  * Copyright 2011 Brian Swetland <swetland@frotz.net>
      4  * 
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 #include <fw/types.h>
     19 #include <fw/lib.h>
     20 #include <fw/io.h>
     21 
     22 #include <arch/hardware.h>
     23 
     24 #include <protocol/rswdp.h>
     25 #include "swdp.h"
     26 
     27 unsigned swdp_trace = 0;
     28 
     29 void printu(const char *fmt, ...);
     30 
     31 /* NOTES
     32  * host -> device:
     33  *   host writes DATA on falling edge of CLOCK
     34  *   device reads DATA on rising edge of CLOCK
     35  * device -> host
     36  *   device writes DATA on rising edge of CLOCK
     37  *   host samples DATA on falling edge of CLOCK
     38  * host parks (begins turnaround) by:
     39  *   releasing bus between falling and rising clock
     40  *   a turnaround cycle follows, in which the device does its first write on CK+
     41  * host unparks (reclaims bus) by:
     42  *   reasserting bus between falling and rising clock
     43  */
     44 
     45 #define GPIO_CLK 1
     46 #define GPIO_DAT 0
     47 
     48 #define D0 (1 << (GPIO_DAT + 16))
     49 #define D1 (1 << GPIO_DAT)
     50 #define C0 (1 << (GPIO_CLK + 16))
     51 #define C1 (1 << (GPIO_CLK))
     52 
     53 #define GPIOA (GPIOA_BASE + GPIO_BSR)
     54 
     55 #define XMIT(data) writel(data | C0, GPIOA), writel(data | C1, GPIOA)
     56 
     57 #define D_OUT() gpio_config(GPIO_DAT, GPIO_OUTPUT_10MHZ | GPIO_OUT_PUSH_PULL)
     58 #define D_IN() gpio_config(GPIO_DAT, GPIO_INPUT | GPIO_PU_PD)
     59 
     60 static unsigned recv(unsigned count) {
     61 	unsigned n = 0;
     62 	unsigned bit = 1;
     63 
     64 	while (count-- > 0) {
     65 		writel(D1 | C0, GPIOA);
     66 		if (readl(GPIOA_BASE + GPIO_IDR) & (1 << GPIO_DAT))
     67 			n |= bit;
     68 		bit <<= 1;
     69 		writel(D1 | C1, GPIOA);
     70 	}
     71 	return n;
     72 }
     73 
     74 static void send(unsigned n, unsigned count) {
     75 	unsigned p = 0;
     76 	while (count-- > 0) {
     77 		p ^= (n & 1);
     78 		if (n & 1) {
     79 			XMIT(D1);
     80 		} else {
     81 			XMIT(D0);
     82 		}	
     83 		n >>= 1;
     84 	}
     85 	if (p) {
     86 		XMIT(D1);
     87 	} else {
     88 		XMIT(D0);
     89 	}
     90 }
     91 
     92 static void clock_high(int n) {
     93 	while (n-- > 0)
     94 		XMIT(D1);
     95 }
     96 static void clock_low(int n) {
     97 	while (n-- > 0)
     98 		XMIT(D0);
     99 }
    100 static void clock_jtag2swdp() {
    101 	XMIT(D0); XMIT(D1); XMIT(D1); XMIT(D1);
    102 	XMIT(D1); XMIT(D0); XMIT(D0); XMIT(D1);
    103 	XMIT(D1); XMIT(D1); XMIT(D1); XMIT(D0);
    104 	XMIT(D0); XMIT(D1); XMIT(D1); XMIT(D1);
    105 }
    106 
    107 static void puth(unsigned hdr, unsigned n, unsigned v) {
    108 	printu("%s %s %b %s %x\n",
    109 		(hdr & 0x20) ? "RD" : "WR",
    110 		(hdr & 0x40) ? "AP" : "DP",
    111 		(hdr >> 3) & 3,
    112 		(n == 1) ? "OK" : "XX",
    113 		v);
    114 }
    115 
    116 int swdp_read(unsigned hdr, unsigned *v) {
    117 	unsigned n,m,o;
    118 
    119 	gpio_clr(2);
    120 	for (n = 0; n < 8; n++) {
    121 		if (hdr & 0x80) {
    122 			XMIT(D1);
    123 		} else {
    124 			XMIT(D0);
    125 		}
    126 		hdr <<= 1;
    127 	}
    128 	D_IN();
    129 	XMIT(D1); // turnaround
    130 	
    131 	n = recv(3);
    132 	m = recv(32);
    133 	o = recv(1);
    134 	D_OUT();
    135 	XMIT(D1); // turnaround
    136 	clock_low(8);
    137 	gpio_set(2);
    138 
    139 	if (swdp_trace || (n != 1))
    140 		puth(hdr >> 8, n, m);
    141 
    142 	*v = m;
    143 	return (n == 1) ? 0 : -1;
    144 }
    145 
    146 int swdp_write(unsigned hdr, unsigned val) {
    147 	unsigned n;
    148 
    149 	for (n = 0; n < 8; n++) {
    150 		if (hdr & 0x80) {
    151 			XMIT(D1);
    152 		} else {
    153 			XMIT(D0);
    154 		}
    155 		hdr <<= 1;
    156 	}
    157 	D_IN();
    158 	XMIT(D1); // turnaround
    159 	
    160 	n = recv(3);
    161 	D_OUT();
    162 	XMIT(D1);
    163 	send(val, 32);
    164 	clock_low(8);
    165 
    166 	if (swdp_trace || (n != 1))
    167 		puth(hdr >> 8, n, val);
    168 
    169 	return (n == 1) ? 0 : -1;
    170 }
    171 
    172 void swdp_reset(void) {
    173 	gpio_set(GPIO_CLK);
    174 	gpio_set(GPIO_DAT);
    175 	gpio_config(GPIO_CLK, GPIO_OUTPUT_10MHZ | GPIO_OUT_PUSH_PULL);
    176 	gpio_config(GPIO_DAT, GPIO_OUTPUT_10MHZ | GPIO_OUT_PUSH_PULL);
    177 
    178 	/* tracing */
    179 	gpio_set(2);
    180 	gpio_config(2, GPIO_OUTPUT_2MHZ | GPIO_OUT_PUSH_PULL);
    181 
    182 	clock_high(64);
    183 	clock_jtag2swdp();
    184 	clock_high(64);
    185 	clock_low(8);
    186 }
    187