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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
/* swdp-m0sub.c
*
* Copyright 2015 Brian Swetland <swetland@frotz.net>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <app.h>
#include <debug.h>
#include <string.h>
#include <stdlib.h>
#include <printf.h>
#include <platform.h>
#include <arch/arm.h>
#include <kernel/thread.h>
#include <platform/lpc43xx-gpio.h>
#include <platform/lpc43xx-sgpio.h>
#include <platform/lpc43xx-clocks.h>
#define PIN_LED PIN(1,1)
#define PIN_RESET PIN(2,5)
#define PIN_RESET_TXEN PIN(2,6)
#define PIN_SWDIO_TXEN PIN(1,5) // SGPIO15=6
#define PIN_SWDIO PIN(1,6) // SGPIO14=6
#define PIN_SWO PIN(1,14) // U1_RXD=1
#define PIN_SWCLK PIN(1,17) // SGPIO11=6
#define GPIO_LED GPIO(0,8)
#define GPIO_RESET GPIO(5,5)
#define GPIO_RESET_TXEN GPIO(5,6)
#define GPIO_SWDIO_TXEN GPIO(1,8)
#define GPIO_SWDIO GPIO(1,9)
#define GPIO_SWCLK GPIO(0,12)
static void gpio_init(void) {
pin_config(PIN_LED, PIN_MODE(0) | PIN_PLAIN);
pin_config(PIN_RESET, PIN_MODE(4) | PIN_PLAIN);
pin_config(PIN_RESET_TXEN, PIN_MODE(4) | PIN_PLAIN);
pin_config(PIN_SWDIO_TXEN, PIN_MODE(6) | PIN_PLAIN | PIN_FAST);
pin_config(PIN_SWDIO, PIN_MODE(6) | PIN_PLAIN | PIN_INPUT | PIN_FAST);
pin_config(PIN_SWCLK, PIN_MODE(6) | PIN_PLAIN | PIN_FAST);
pin_config(PIN_SWO, PIN_MODE(1) | PIN_PLAIN | PIN_INPUT | PIN_FAST);
gpio_set(GPIO_LED, 0);
gpio_set(GPIO_RESET, 1);
gpio_set(GPIO_RESET_TXEN, 0);
gpio_config(GPIO_LED, GPIO_OUTPUT);
gpio_config(GPIO_RESET, GPIO_OUTPUT);
gpio_config(GPIO_RESET_TXEN, GPIO_OUTPUT);
}
/* returns 1 if the number of bits set in n is odd */
static unsigned parity(unsigned n) {
n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1);
n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2);
n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4);
n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8);
n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16);
return n & 1;
}
#include "fw-m0sub.h"
#define M0SUB_ZEROMAP 0x40043308
#define M0SUB_TXEV 0x40043314 // write 0 to clear
#define M4_TXEV 0x40043130 // write 0 to clear
#define RESET_CTRL0 0x40053100
#define M0_SUB_RST (1 << 12)
#define COMM_CMD 0x18004000
#define COMM_ARG1 0x18004004
#define COMM_ARG2 0x18004008
#define COMM_RESP 0x1800400C
#define CMD_ERR 0
#define CMD_NOP 1
#define CMD_READ 2
#define CMD_WRITE 3
#define CMD_RESET 4
#define CMD_SETCLOCK 5
#define RSP_BUSY 0xFFFFFFFF
void swd_init(void) {
gpio_init();
writel(BASE_CLK_SEL(CLK_PLL1), BASE_PERIPH_CLK);
spin(1000);
// SGPIO15 SWDIO_TXEN
writel(CFG_OUT_GPIO | CFG_OE_GPIO, SGPIO_OUT_CFG(15));
// SGPIO14 SWDIO
writel(CFG_OUT_GPIO | CFG_OE_GPIO, SGPIO_OUT_CFG(14));
// SGPIO11 SWCLK
writel(CFG_OUT_GPIO | CFG_OE_GPIO, SGPIO_OUT_CFG(11));
// all outputs enabled and high
writel((1 << 11) | (1 << 14) | (1 << 15), SGPIO_OUT);
writel((1 << 11) | (1 << 14) | (1 << 15), SGPIO_OEN);
writel(0, M4_TXEV);
writel(M0_SUB_RST, RESET_CTRL0);
writel(0x18000000, M0SUB_ZEROMAP);
writel(0xffffffff, 0x18004000);
memcpy((void*) 0x18000000, zero_bin, sizeof(zero_bin));
DSB;
writel(0, RESET_CTRL0);
}
int swd_write(unsigned hdr, unsigned data) {
unsigned n;
unsigned p = parity(data);
writel(CMD_WRITE, COMM_CMD);
writel((hdr << 8) | (p << 16), COMM_ARG1);
writel(data, COMM_ARG2);
writel(RSP_BUSY, COMM_RESP);
DSB;
asm("sev");
while ((n = readl(COMM_RESP)) == RSP_BUSY) ;
//printf("wr s=%d\n", n);
return n;
}
int swd_read(unsigned hdr, unsigned *val) {
unsigned n, data, p;
writel(CMD_READ, COMM_CMD);
writel(hdr << 8, COMM_ARG1);
writel(RSP_BUSY, COMM_RESP);
DSB;
asm("sev");
while ((n = readl(COMM_RESP)) == RSP_BUSY) ;
if (n) {
return n;
}
data = readl(COMM_ARG1);
p = readl(COMM_ARG2);
if (p != parity(data)) {
return 2;
}
//printf("rd s=%d p=%d d=%08x\n", n, p, data);
*val = data;
return 0;
}
void swd_reset(void) {
unsigned n;
writel(CMD_RESET, COMM_CMD);
writel(RSP_BUSY, COMM_RESP);
DSB;
asm("sev");
while ((n = readl(COMM_RESP)) == RSP_BUSY) ;
}
unsigned swd_set_clock(unsigned khz) {
unsigned n;
if (khz > 8000) {
khz = 8000;
}
writel(CMD_SETCLOCK, COMM_CMD);
writel(khz/1000, COMM_ARG1);
writel(RSP_BUSY, COMM_RESP);
DSB;
asm("sev");
while ((n = readl(COMM_RESP)) == RSP_BUSY) ;
// todo: accurate value
return khz;
}
void swd_hw_reset(int assert) {
if (assert) {
gpio_set(GPIO_RESET, 0);
gpio_set(GPIO_RESET_TXEN, 1);
} else {
gpio_set(GPIO_RESET, 1);
gpio_set(GPIO_RESET_TXEN, 0);
}
}
|