jlink: Add variant "J-Link Lite-XMC4000"
[openocd.git] / src / flash / nor / stellaris.c
1 /***************************************************************************
2 * Copyright (C) 2006 by Magnus Lundin *
3 * lundin@mlu.mine.nu *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
23
24 /***************************************************************************
25 * STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more.
26 ***************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "jtag/interface.h"
33 #include "imp.h"
34 #include <target/algorithm.h>
35 #include <target/armv7m.h>
36
37 #define DID0_VER(did0) ((did0 >> 28)&0x07)
38
39 /* STELLARIS control registers */
40 #define SCB_BASE 0x400FE000
41 #define DID0 0x000
42 #define DID1 0x004
43 #define DC0 0x008
44 #define DC1 0x010
45 #define DC2 0x014
46 #define DC3 0x018
47 #define DC4 0x01C
48
49 #define RIS 0x050
50 #define RCC 0x060
51 #define PLLCFG 0x064
52 #define RCC2 0x070
53 #define NVMSTAT 0x1a0
54
55 /* "legacy" flash memory protection registers (64KB max) */
56 #define FMPRE 0x130
57 #define FMPPE 0x134
58
59 /* new flash memory protection registers (for more than 64KB) */
60 #define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */
61 #define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */
62
63 #define USECRL 0x140
64
65 #define FLASH_CONTROL_BASE 0x400FD000
66 #define FLASH_FMA (FLASH_CONTROL_BASE | 0x000)
67 #define FLASH_FMD (FLASH_CONTROL_BASE | 0x004)
68 #define FLASH_FMC (FLASH_CONTROL_BASE | 0x008)
69 #define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C)
70 #define FLASH_CIM (FLASH_CONTROL_BASE | 0x010)
71 #define FLASH_MISC (FLASH_CONTROL_BASE | 0x014)
72 #define FLASH_FSIZE (FLASH_CONTROL_BASE | 0xFC0)
73 #define FLASH_SSIZE (FLASH_CONTROL_BASE | 0xFC4)
74
75 #define AMISC 1
76 #define PMISC 2
77
78 #define AMASK 1
79 #define PMASK 2
80
81 /* Flash Controller Command bits */
82 #define FMC_WRKEY (0xA442 << 16)
83 #define FMC_COMT (1 << 3)
84 #define FMC_MERASE (1 << 2)
85 #define FMC_ERASE (1 << 1)
86 #define FMC_WRITE (1 << 0)
87
88 /* STELLARIS constants */
89
90 /* values to write in FMA to commit write-"once" values */
91 #define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */
92 #define FLASH_FMA_PPE(x) (2 * (x) + 1) /* for FMPPPEx */
93
94 static void stellaris_read_clock_info(struct flash_bank *bank);
95 static int stellaris_mass_erase(struct flash_bank *bank);
96
97 struct stellaris_flash_bank {
98 /* chip id register */
99 uint32_t did0;
100 uint32_t did1;
101 uint32_t dc0;
102 uint32_t dc1;
103 uint32_t fsize;
104 uint32_t ssize;
105
106 const char *target_name;
107 uint8_t target_class;
108
109 uint32_t sramsiz;
110 /* flash geometry */
111 uint32_t num_pages;
112 uint32_t pagesize;
113
114 /* main clock status */
115 uint32_t rcc;
116 uint32_t rcc2;
117 uint8_t mck_valid;
118 uint8_t xtal_mask;
119 uint32_t iosc_freq;
120 uint32_t mck_freq;
121 const char *iosc_desc;
122 const char *mck_desc;
123 };
124
125 /* Autogenerated by contrib/gen-stellaris-part-header.pl */
126 /* From Stellaris Firmware Development Package revision 9453 */
127 static const struct {
128 uint8_t class;
129 uint8_t partno;
130 const char *partname;
131 } StellarisParts[] = {
132 {0x00, 0x01, "LM3S101"},
133 {0x00, 0x02, "LM3S102"},
134 {0x01, 0xBF, "LM3S1110"},
135 {0x01, 0xC3, "LM3S1133"},
136 {0x01, 0xC5, "LM3S1138"},
137 {0x01, 0xC1, "LM3S1150"},
138 {0x01, 0xC4, "LM3S1162"},
139 {0x01, 0xC2, "LM3S1165"},
140 {0x01, 0xEC, "LM3S1166"},
141 {0x01, 0xC6, "LM3S1332"},
142 {0x01, 0xBC, "LM3S1435"},
143 {0x01, 0xBA, "LM3S1439"},
144 {0x01, 0xBB, "LM3S1512"},
145 {0x01, 0xC7, "LM3S1538"},
146 {0x01, 0xDB, "LM3S1601"},
147 {0x03, 0x06, "LM3S1607"},
148 {0x01, 0xDA, "LM3S1608"},
149 {0x01, 0xC0, "LM3S1620"},
150 {0x04, 0xCD, "LM3S1621"},
151 {0x03, 0x03, "LM3S1625"},
152 {0x03, 0x04, "LM3S1626"},
153 {0x03, 0x05, "LM3S1627"},
154 {0x01, 0xB3, "LM3S1635"},
155 {0x01, 0xEB, "LM3S1636"},
156 {0x01, 0xBD, "LM3S1637"},
157 {0x04, 0xB1, "LM3S1651"},
158 {0x01, 0xB9, "LM3S1751"},
159 {0x03, 0x10, "LM3S1776"},
160 {0x04, 0x16, "LM3S1811"},
161 {0x04, 0x3D, "LM3S1816"},
162 {0x01, 0xB4, "LM3S1850"},
163 {0x01, 0xDD, "LM3S1911"},
164 {0x01, 0xDC, "LM3S1918"},
165 {0x01, 0xB7, "LM3S1937"},
166 {0x01, 0xBE, "LM3S1958"},
167 {0x01, 0xB5, "LM3S1960"},
168 {0x01, 0xB8, "LM3S1968"},
169 {0x01, 0xEA, "LM3S1969"},
170 {0x04, 0xCE, "LM3S1B21"},
171 {0x06, 0xCA, "LM3S1C21"},
172 {0x06, 0xCB, "LM3S1C26"},
173 {0x06, 0x98, "LM3S1C58"},
174 {0x06, 0xB0, "LM3S1D21"},
175 {0x06, 0xCC, "LM3S1D26"},
176 {0x06, 0x1D, "LM3S1F11"},
177 {0x06, 0x1B, "LM3S1F16"},
178 {0x06, 0xAF, "LM3S1G21"},
179 {0x06, 0x95, "LM3S1G58"},
180 {0x06, 0x1E, "LM3S1H11"},
181 {0x06, 0x1C, "LM3S1H16"},
182 {0x04, 0x0F, "LM3S1J11"},
183 {0x04, 0x3C, "LM3S1J16"},
184 {0x04, 0x0E, "LM3S1N11"},
185 {0x04, 0x3B, "LM3S1N16"},
186 {0x04, 0xB2, "LM3S1P51"},
187 {0x04, 0x9E, "LM3S1R21"},
188 {0x04, 0xC9, "LM3S1R26"},
189 {0x04, 0x30, "LM3S1W16"},
190 {0x04, 0x2F, "LM3S1Z16"},
191 {0x01, 0x51, "LM3S2110"},
192 {0x01, 0x84, "LM3S2139"},
193 {0x03, 0x39, "LM3S2276"},
194 {0x01, 0xA2, "LM3S2410"},
195 {0x01, 0x59, "LM3S2412"},
196 {0x01, 0x56, "LM3S2432"},
197 {0x01, 0x5A, "LM3S2533"},
198 {0x01, 0xE1, "LM3S2601"},
199 {0x01, 0xE0, "LM3S2608"},
200 {0x03, 0x33, "LM3S2616"},
201 {0x01, 0x57, "LM3S2620"},
202 {0x01, 0x85, "LM3S2637"},
203 {0x01, 0x53, "LM3S2651"},
204 {0x03, 0x80, "LM3S2671"},
205 {0x03, 0x50, "LM3S2678"},
206 {0x01, 0xA4, "LM3S2730"},
207 {0x01, 0x52, "LM3S2739"},
208 {0x03, 0x3A, "LM3S2776"},
209 {0x04, 0x6D, "LM3S2793"},
210 {0x01, 0xE3, "LM3S2911"},
211 {0x01, 0xE2, "LM3S2918"},
212 {0x01, 0xED, "LM3S2919"},
213 {0x01, 0x54, "LM3S2939"},
214 {0x01, 0x8F, "LM3S2948"},
215 {0x01, 0x58, "LM3S2950"},
216 {0x01, 0x55, "LM3S2965"},
217 {0x04, 0x6C, "LM3S2B93"},
218 {0x06, 0x94, "LM3S2D93"},
219 {0x06, 0x93, "LM3S2U93"},
220 {0x00, 0x19, "LM3S300"},
221 {0x00, 0x11, "LM3S301"},
222 {0x00, 0x1A, "LM3S308"},
223 {0x00, 0x12, "LM3S310"},
224 {0x00, 0x13, "LM3S315"},
225 {0x00, 0x14, "LM3S316"},
226 {0x00, 0x17, "LM3S317"},
227 {0x00, 0x15, "LM3S328"},
228 {0x03, 0x08, "LM3S3634"},
229 {0x03, 0x43, "LM3S3651"},
230 {0x04, 0xC8, "LM3S3654"},
231 {0x03, 0x44, "LM3S3739"},
232 {0x03, 0x49, "LM3S3748"},
233 {0x03, 0x45, "LM3S3749"},
234 {0x04, 0x42, "LM3S3826"},
235 {0x04, 0x41, "LM3S3J26"},
236 {0x04, 0x40, "LM3S3N26"},
237 {0x04, 0x3F, "LM3S3W26"},
238 {0x04, 0x3E, "LM3S3Z26"},
239 {0x03, 0x81, "LM3S5632"},
240 {0x04, 0x0C, "LM3S5651"},
241 {0x03, 0x8A, "LM3S5652"},
242 {0x04, 0x4D, "LM3S5656"},
243 {0x03, 0x91, "LM3S5662"},
244 {0x03, 0x96, "LM3S5732"},
245 {0x03, 0x97, "LM3S5737"},
246 {0x03, 0xA0, "LM3S5739"},
247 {0x03, 0x99, "LM3S5747"},
248 {0x03, 0xA7, "LM3S5749"},
249 {0x03, 0x9A, "LM3S5752"},
250 {0x03, 0x9C, "LM3S5762"},
251 {0x04, 0x69, "LM3S5791"},
252 {0x04, 0x0B, "LM3S5951"},
253 {0x04, 0x4E, "LM3S5956"},
254 {0x04, 0x68, "LM3S5B91"},
255 {0x06, 0x2E, "LM3S5C31"},
256 {0x06, 0x2C, "LM3S5C36"},
257 {0x06, 0x5E, "LM3S5C51"},
258 {0x06, 0x5B, "LM3S5C56"},
259 {0x06, 0x5F, "LM3S5D51"},
260 {0x06, 0x5C, "LM3S5D56"},
261 {0x06, 0x87, "LM3S5D91"},
262 {0x06, 0x2D, "LM3S5G31"},
263 {0x06, 0x1F, "LM3S5G36"},
264 {0x06, 0x5D, "LM3S5G51"},
265 {0x06, 0x4F, "LM3S5G56"},
266 {0x04, 0x09, "LM3S5K31"},
267 {0x04, 0x4A, "LM3S5K36"},
268 {0x04, 0x0A, "LM3S5P31"},
269 {0x04, 0x48, "LM3S5P36"},
270 {0x04, 0xB6, "LM3S5P3B"},
271 {0x04, 0x0D, "LM3S5P51"},
272 {0x04, 0x4C, "LM3S5P56"},
273 {0x04, 0x07, "LM3S5R31"},
274 {0x04, 0x4B, "LM3S5R36"},
275 {0x04, 0x47, "LM3S5T36"},
276 {0x06, 0x7F, "LM3S5U91"},
277 {0x04, 0x46, "LM3S5Y36"},
278 {0x00, 0x2A, "LM3S600"},
279 {0x00, 0x21, "LM3S601"},
280 {0x00, 0x2B, "LM3S608"},
281 {0x00, 0x22, "LM3S610"},
282 {0x01, 0xA1, "LM3S6100"},
283 {0x00, 0x23, "LM3S611"},
284 {0x01, 0x74, "LM3S6110"},
285 {0x00, 0x24, "LM3S612"},
286 {0x00, 0x25, "LM3S613"},
287 {0x00, 0x26, "LM3S615"},
288 {0x00, 0x28, "LM3S617"},
289 {0x00, 0x29, "LM3S618"},
290 {0x00, 0x27, "LM3S628"},
291 {0x01, 0xA5, "LM3S6420"},
292 {0x01, 0x82, "LM3S6422"},
293 {0x01, 0x75, "LM3S6432"},
294 {0x01, 0x76, "LM3S6537"},
295 {0x01, 0x71, "LM3S6610"},
296 {0x01, 0xE7, "LM3S6611"},
297 {0x01, 0xE6, "LM3S6618"},
298 {0x01, 0x83, "LM3S6633"},
299 {0x01, 0x8B, "LM3S6637"},
300 {0x01, 0xA3, "LM3S6730"},
301 {0x01, 0x77, "LM3S6753"},
302 {0x01, 0xE9, "LM3S6911"},
303 {0x01, 0xE8, "LM3S6918"},
304 {0x01, 0x89, "LM3S6938"},
305 {0x01, 0x72, "LM3S6950"},
306 {0x01, 0x78, "LM3S6952"},
307 {0x01, 0x73, "LM3S6965"},
308 {0x06, 0xAA, "LM3S6C11"},
309 {0x06, 0xAC, "LM3S6C65"},
310 {0x06, 0x9F, "LM3S6G11"},
311 {0x06, 0xAB, "LM3S6G65"},
312 {0x00, 0x38, "LM3S800"},
313 {0x00, 0x31, "LM3S801"},
314 {0x00, 0x39, "LM3S808"},
315 {0x00, 0x32, "LM3S811"},
316 {0x00, 0x33, "LM3S812"},
317 {0x00, 0x34, "LM3S815"},
318 {0x00, 0x36, "LM3S817"},
319 {0x00, 0x37, "LM3S818"},
320 {0x00, 0x35, "LM3S828"},
321 {0x01, 0x64, "LM3S8530"},
322 {0x01, 0x8E, "LM3S8538"},
323 {0x01, 0x61, "LM3S8630"},
324 {0x01, 0x63, "LM3S8730"},
325 {0x01, 0x8D, "LM3S8733"},
326 {0x01, 0x86, "LM3S8738"},
327 {0x01, 0x65, "LM3S8930"},
328 {0x01, 0x8C, "LM3S8933"},
329 {0x01, 0x88, "LM3S8938"},
330 {0x01, 0xA6, "LM3S8962"},
331 {0x01, 0x62, "LM3S8970"},
332 {0x01, 0xD7, "LM3S8971"},
333 {0x06, 0xAE, "LM3S8C62"},
334 {0x06, 0xAD, "LM3S8G62"},
335 {0x04, 0xCF, "LM3S9781"},
336 {0x04, 0x67, "LM3S9790"},
337 {0x04, 0x6B, "LM3S9792"},
338 {0x04, 0x2D, "LM3S9971"},
339 {0x04, 0x20, "LM3S9997"},
340 {0x04, 0xD0, "LM3S9B81"},
341 {0x04, 0x66, "LM3S9B90"},
342 {0x04, 0x6A, "LM3S9B92"},
343 {0x04, 0x6E, "LM3S9B95"},
344 {0x04, 0x6F, "LM3S9B96"},
345 {0x04, 0x1D, "LM3S9BN2"},
346 {0x04, 0x1E, "LM3S9BN5"},
347 {0x04, 0x1F, "LM3S9BN6"},
348 {0x06, 0x70, "LM3S9C97"},
349 {0x06, 0xA9, "LM3S9D81"},
350 {0x06, 0x7E, "LM3S9D90"},
351 {0x06, 0x92, "LM3S9D92"},
352 {0x06, 0x9D, "LM3S9D96"},
353 {0x06, 0x7B, "LM3S9DN5"},
354 {0x06, 0x7C, "LM3S9DN6"},
355 {0x06, 0x60, "LM3S9G97"},
356 {0x06, 0x79, "LM3S9GN5"},
357 {0x04, 0x1B, "LM3S9L71"},
358 {0x04, 0x18, "LM3S9L97"},
359 {0x06, 0xA8, "LM3S9U81"},
360 {0x06, 0x7D, "LM3S9U90"},
361 {0x06, 0x90, "LM3S9U92"},
362 {0x06, 0x9B, "LM3S9U96"},
363 {0x05, 0x01, "LM4F120B2QR/TM4C1233C3PM"},
364 {0x05, 0x02, "LM4F120C4QR/TM4C1233D5PM"},
365 {0x05, 0x03, "LM4F120E5QR/TM4C1233E6PM"},
366 {0x05, 0x04, "LM4F120H5QR/TM4C1233H6PM"},
367 {0x05, 0x08, "LM4F121B2QR/TM4C1232C3PM"},
368 {0x05, 0x09, "LM4F121C4QR/TM4C1232D5PM"},
369 {0x05, 0x0A, "LM4F121E5QR/TM4C1232E6PM"},
370 {0x05, 0x0B, "LM4F121H5QR/TM4C1232H6PM"},
371 {0x05, 0x10, "LM4F110E5QR/TM4C1231E6PM"},
372 {0x05, 0x11, "LM4F110H5QR/TM4C1231H6PM"},
373 {0x05, 0x18, "LM4F110B2QR/TM4C1231C3PM"},
374 {0x05, 0x19, "LM4F110C4QR/TM4C1231D5PM"},
375 {0x05, 0x20, "LM4F111E5QR/TM4C1230E6PM"},
376 {0x05, 0x21, "LM4F111H5QR/TM4C1230H6PM"},
377 {0x05, 0x22, "LM4F111B2QR/TM4C1230C3PM"},
378 {0x05, 0x23, "LM4F111C4QR/TM4C1230D5PM"},
379 {0x05, 0x30, "LM4F112E5QC/TM4C1231E6PZ"},
380 {0x05, 0x31, "LM4F112H5QC/TM4C1231H6PZ"},
381 {0x05, 0x35, "LM4F112H5QD/TM4C1231H6PGE"},
382 {0x05, 0x36, "LM4F112C4QC/TM4C1231D5PZ"},
383 {0x05, 0x40, "LM4F130E5QR/TM4C1237E6PM"},
384 {0x05, 0x41, "LM4F130H5QR/TM4C1237H6PM"},
385 {0x05, 0x48, "LM4F130C4QR/TM4C1237D5PM"},
386 {0x05, 0x50, "LM4F131E5QR/TM4C1236E6PM"},
387 {0x05, 0x51, "LM4F131H5QR/TM4C1236H6PM"},
388 {0x05, 0x52, "LM4F131C4QR/TM4C1236D5PM"},
389 {0x05, 0x60, "LM4F132E5QC/TM4C1237E6PZ"},
390 {0x05, 0x61, "LM4F132H5QC/TM4C1237H6PZ"},
391 {0x05, 0x65, "LM4F132H5QD/TM4C1237H6PGE"},
392 {0x05, 0x66, "LM4F132C4QC/TM4C1237D5PZ"},
393 {0x05, 0x70, "LM4F210E5QR/TM4C123BE6PM"},
394 {0x05, 0x73, "LM4F210H5QR/TM4C123BH6PM"},
395 {0x05, 0x80, "LM4F211E5QR/TM4C123AE6PM"},
396 {0x05, 0x83, "LM4F211H5QR/TM4C123AH6PM"},
397 {0x05, 0xA0, "LM4F230E5QR/TM4C123GE6PM"},
398 {0x05, 0xA1, "LM4F230H5QR/TM4C123GH6PM"},
399 {0x05, 0xB0, "LM4F231E5QR/TM4C123FE6PM"},
400 {0x05, 0xB1, "LM4F231H5QR/TM4C123FH6PM"},
401 {0x05, 0xC0, "LM4F232E5QC/TM4C123GE6PZ"},
402 {0x05, 0xC1, "LM4F232H5QC/TM4C123GH6PZ"},
403 {0x05, 0xC3, "LM4F212E5QC/TM4C123BE6PZ"},
404 {0x05, 0xC4, "LM4F212H5QC/TM4C123BH6PZ"},
405 {0x05, 0xC5, "LM4F232H5QD/TM4C123GH6PGE"},
406 {0x05, 0xC6, "LM4F212H5QD/TM4C123BH6PGE"},
407 {0x05, 0xD0, "LM4F122C4QC/TM4C1233D5PZ"},
408 {0x05, 0xD1, "LM4F122E5QC/TM4C1233E6PZ"},
409 {0x05, 0xD2, "LM4F122H5QC/TM4C1233H6PZ"},
410 {0x05, 0xD6, "LM4F122H5QD/TM4C1233H6PGE"},
411 {0x05, 0xE1, "LM4FSXLH5BB"},
412 {0x05, 0xE3, "LM4F232H5BB/TM4C123GH6ZRB"},
413 {0x05, 0xE4, "LM4FS99H5BB"},
414 {0x05, 0xE5, "LM4FS1AH5BB"},
415 {0x05, 0xE9, "LM4F212H5BB/TM4C123BH6ZRB"},
416 {0x05, 0xEA, "LM4FS1GH5BB"},
417 {0x05, 0xF0, "TM4C123GH6ZXR"},
418 {0x0A, 0x19, "TM4C1290NCPDT"},
419 {0x0A, 0x1B, "TM4C1290NCZAD"},
420 {0x0A, 0x1C, "TM4C1292NCPDT"},
421 {0x0A, 0x1E, "TM4C1292NCZAD"},
422 {0x0A, 0x1F, "TM4C1294NCPDT"},
423 {0x0A, 0x21, "TM4C1294NCZAD"},
424 {0x0A, 0x22, "TM4C1297NCZAD"},
425 {0x0A, 0x23, "TM4C1299NCZAD"},
426 {0x0A, 0x24, "TM4C129CNCPDT"},
427 {0x0A, 0x26, "TM4C129CNCZAD"},
428 {0x0A, 0x27, "TM4C129DNCPDT"},
429 {0x0A, 0x29, "TM4C129DNCZAD"},
430 {0x0A, 0x2D, "TM4C129ENCPDT"},
431 {0x0A, 0x2F, "TM4C129ENCZAD"},
432 {0x0A, 0x30, "TM4C129LNCZAD"},
433 {0x0A, 0x32, "TM4C129XNCZAD"},
434 {0x0A, 0x34, "TM4C1294KCPDT"},
435 {0x0A, 0x35, "TM4C129EKCPDT"},
436 {0x0A, 0x36, "TM4C1299KCZAD"},
437 {0x0A, 0x37, "TM4C129XKCZAD"},
438 {0xFF, 0x00, "Unknown Part"}
439 };
440
441 static const char * const StellarisClassname[] = {
442 "Sandstorm",
443 "Fury",
444 "Unknown",
445 "DustDevil",
446 "Tempest",
447 "Blizzard/TM4C123x",
448 "Firestorm",
449 "",
450 "",
451 "",
452 "Snowflake",
453 };
454
455 /***************************************************************************
456 * openocd command interface *
457 ***************************************************************************/
458
459 /* flash_bank stellaris <base> <size> 0 0 <target#>
460 */
461 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command)
462 {
463 struct stellaris_flash_bank *stellaris_info;
464
465 if (CMD_ARGC < 6)
466 return ERROR_COMMAND_SYNTAX_ERROR;
467
468 stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
469 bank->base = 0x0;
470 bank->driver_priv = stellaris_info;
471
472 stellaris_info->target_name = "Unknown target";
473
474 /* part wasn't probed for info yet */
475 stellaris_info->did1 = 0;
476
477 /* TODO Specify the main crystal speed in kHz using an optional
478 * argument; ditto, the speed of an external oscillator used
479 * instead of a crystal. Avoid programming flash using IOSC.
480 */
481 return ERROR_OK;
482 }
483
484 static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size)
485 {
486 int printed;
487 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
488
489 if (stellaris_info->did1 == 0)
490 return ERROR_FLASH_BANK_NOT_PROBED;
491
492 /* Read main and master clock freqency register */
493 stellaris_read_clock_info(bank);
494
495 printed = snprintf(buf,
496 buf_size,
497 "\nTI/LMI Stellaris information: Chip is "
498 "class %i (%s) %s rev %c%i\n",
499 stellaris_info->target_class,
500 StellarisClassname[stellaris_info->target_class],
501 stellaris_info->target_name,
502 (int)('A' + ((stellaris_info->did0 >> 8) & 0xFF)),
503 (int)((stellaris_info->did0) & 0xFF));
504 buf += printed;
505 buf_size -= printed;
506
507 printed = snprintf(buf,
508 buf_size,
509 "did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32
510 ", eproc: %s, ramsize: %ik, flashsize: %ik\n",
511 stellaris_info->did1,
512 stellaris_info->did1,
513 "ARMv7M",
514 stellaris_info->sramsiz,
515 stellaris_info->num_pages * stellaris_info->pagesize / 1024);
516 buf += printed;
517 buf_size -= printed;
518
519 snprintf(buf,
520 buf_size,
521 "master clock: %ikHz%s, "
522 "rcc is 0x%" PRIx32 ", rcc2 is 0x%" PRIx32 ", "
523 "pagesize: %" PRIu32 ", pages: %" PRIu32,
524 (int)(stellaris_info->mck_freq / 1000),
525 stellaris_info->mck_desc,
526 stellaris_info->rcc,
527 stellaris_info->rcc2,
528 stellaris_info->pagesize,
529 stellaris_info->num_pages);
530
531 return ERROR_OK;
532 }
533
534 /***************************************************************************
535 * chip identification and status *
536 ***************************************************************************/
537
538 /* Set the flash timimg register to match current clocking */
539 static void stellaris_set_flash_timing(struct flash_bank *bank)
540 {
541 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
542 struct target *target = bank->target;
543 uint32_t usecrl = (stellaris_info->mck_freq/1000000ul-1);
544
545 /* only valid for Sandstorm and Fury class devices */
546 if (stellaris_info->target_class > 1)
547 return;
548
549 LOG_DEBUG("usecrl = %i", (int)(usecrl));
550 target_write_u32(target, SCB_BASE | USECRL, usecrl);
551 }
552
553 static const unsigned rcc_xtal[32] = {
554 [0x00] = 1000000, /* no pll */
555 [0x01] = 1843200, /* no pll */
556 [0x02] = 2000000, /* no pll */
557 [0x03] = 2457600, /* no pll */
558
559 [0x04] = 3579545,
560 [0x05] = 3686400,
561 [0x06] = 4000000, /* usb */
562 [0x07] = 4096000,
563
564 [0x08] = 4915200,
565 [0x09] = 5000000, /* usb */
566 [0x0a] = 5120000,
567 [0x0b] = 6000000, /* (reset) usb */
568
569 [0x0c] = 6144000,
570 [0x0d] = 7372800,
571 [0x0e] = 8000000, /* usb */
572 [0x0f] = 8192000,
573
574 /* parts before DustDevil use just 4 bits for xtal spec */
575
576 [0x10] = 10000000, /* usb */
577 [0x11] = 12000000, /* usb */
578 [0x12] = 12288000,
579 [0x13] = 13560000,
580
581 [0x14] = 14318180,
582 [0x15] = 16000000, /* usb */
583 [0x16] = 16384000,
584 };
585
586 /** Read clock configuration and set stellaris_info->usec_clocks. */
587 static void stellaris_read_clock_info(struct flash_bank *bank)
588 {
589 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
590 struct target *target = bank->target;
591 uint32_t rcc, rcc2, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
592 unsigned xtal;
593 unsigned long mainfreq;
594
595 target_read_u32(target, SCB_BASE | RCC, &rcc);
596 LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc);
597
598 target_read_u32(target, SCB_BASE | RCC2, &rcc2);
599 LOG_DEBUG("Stellaris RCC2 %" PRIx32 "", rcc);
600
601 target_read_u32(target, SCB_BASE | PLLCFG, &pllcfg);
602 LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg);
603
604 stellaris_info->rcc = rcc;
605 stellaris_info->rcc = rcc2;
606
607 sysdiv = (rcc >> 23) & 0xF;
608 usesysdiv = (rcc >> 22) & 0x1;
609 bypass = (rcc >> 11) & 0x1;
610 oscsrc = (rcc >> 4) & 0x3;
611 xtal = (rcc >> 6) & stellaris_info->xtal_mask;
612
613 /* NOTE: post-Sandstorm parts have RCC2 which may override
614 * parts of RCC ... with more sysdiv options, option for
615 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
616 * as zero, so the "use RCC2" flag is always clear.
617 */
618 if (rcc2 & (1 << 31)) {
619 sysdiv = (rcc2 >> 23) & 0x3F;
620 bypass = (rcc2 >> 11) & 0x1;
621 oscsrc = (rcc2 >> 4) & 0x7;
622
623 /* FIXME Tempest parts have an additional lsb for
624 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
625 */
626 }
627
628 stellaris_info->mck_desc = "";
629
630 switch (oscsrc) {
631 case 0: /* MOSC */
632 mainfreq = rcc_xtal[xtal];
633 break;
634 case 1: /* IOSC */
635 mainfreq = stellaris_info->iosc_freq;
636 stellaris_info->mck_desc = stellaris_info->iosc_desc;
637 break;
638 case 2: /* IOSC/4 */
639 mainfreq = stellaris_info->iosc_freq / 4;
640 stellaris_info->mck_desc = stellaris_info->iosc_desc;
641 break;
642 case 3: /* lowspeed */
643 /* Sandstorm doesn't have this 30K +/- 30% osc */
644 mainfreq = 30000;
645 stellaris_info->mck_desc = " (±30%)";
646 break;
647 case 8: /* hibernation osc */
648 /* not all parts support hibernation */
649 mainfreq = 32768;
650 break;
651
652 default: /* NOTREACHED */
653 mainfreq = 0;
654 break;
655 }
656
657 /* PLL is used if it's not bypassed; its output is 200 MHz
658 * even when it runs at 400 MHz (adds divide-by-two stage).
659 */
660 if (!bypass)
661 mainfreq = 200000000;
662
663 if (usesysdiv)
664 stellaris_info->mck_freq = mainfreq/(1 + sysdiv);
665 else
666 stellaris_info->mck_freq = mainfreq;
667 }
668
669 /* Read device id register, main clock frequency register and fill in driver info structure */
670 static int stellaris_read_part_info(struct flash_bank *bank)
671 {
672 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
673 struct target *target = bank->target;
674 uint32_t did0, did1, ver, fam;
675 int i;
676
677 /* Read and parse chip identification register */
678 target_read_u32(target, SCB_BASE | DID0, &did0);
679 target_read_u32(target, SCB_BASE | DID1, &did1);
680 target_read_u32(target, SCB_BASE | DC0, &stellaris_info->dc0);
681 target_read_u32(target, SCB_BASE | DC1, &stellaris_info->dc1);
682 LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32 "",
683 did0, did1, stellaris_info->dc0, stellaris_info->dc1);
684
685 ver = DID0_VER(did0);
686 if ((ver != 0) && (ver != 1)) {
687 LOG_WARNING("Unknown did0 version, cannot identify target");
688 return ERROR_FLASH_OPERATION_FAILED;
689 }
690
691 if (did1 == 0) {
692 LOG_WARNING("Cannot identify target as a Stellaris");
693 return ERROR_FLASH_OPERATION_FAILED;
694 }
695
696 ver = did1 >> 28;
697 fam = (did1 >> 24) & 0xF;
698 if (((ver != 0) && (ver != 1)) || (fam != 0)) {
699 LOG_WARNING("Unknown did1 version/family.");
700 return ERROR_FLASH_OPERATION_FAILED;
701 }
702
703 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
704 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
705 * even give _both_ numbers! We'll use current numbers; IOSC is
706 * always approximate.
707 *
708 * For Tempest: IOSC is calibrated, 16 MHz
709 * For Blizzard: IOSC is calibrated, 16 MHz
710 * For Firestorm: IOSC is calibrated, 16 MHz
711 */
712 stellaris_info->iosc_freq = 12000000;
713 stellaris_info->iosc_desc = " (±30%)";
714 stellaris_info->xtal_mask = 0x0f;
715
716 /* get device class */
717 if (DID0_VER(did0) > 0) {
718 stellaris_info->target_class = (did0 >> 16) & 0xFF;
719 } else {
720 /* Sandstorm class */
721 stellaris_info->target_class = 0;
722 }
723
724 switch (stellaris_info->target_class) {
725 case 0: /* Sandstorm */
726 /*
727 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
728 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
729 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
730 */
731 if (((did0 >> 8) & 0xff) < 2) {
732 stellaris_info->iosc_freq = 15000000;
733 stellaris_info->iosc_desc = " (±50%)";
734 }
735 break;
736
737 case 1: /* Fury */
738 break;
739
740 case 4: /* Tempest */
741 case 5: /* Blizzard */
742 case 6: /* Firestorm */
743 case 0xa: /* Snowflake */
744 stellaris_info->iosc_freq = 16000000; /* +/- 1% */
745 stellaris_info->iosc_desc = " (±1%)";
746 /* FALL THROUGH */
747
748 case 3: /* DustDevil */
749 stellaris_info->xtal_mask = 0x1f;
750 break;
751
752 default:
753 LOG_WARNING("Unknown did0 class");
754 }
755
756 for (i = 0; StellarisParts[i].partno; i++) {
757 if ((StellarisParts[i].partno == ((did1 >> 16) & 0xFF)) &&
758 (StellarisParts[i].class == stellaris_info->target_class))
759 break;
760 }
761
762 stellaris_info->target_name = StellarisParts[i].partname;
763
764 stellaris_info->did0 = did0;
765 stellaris_info->did1 = did1;
766
767 if (stellaris_info->target_class == 5) { /* Blizzard */
768 target_read_u32(target, FLASH_FSIZE, &stellaris_info->fsize);
769 target_read_u32(target, FLASH_SSIZE, &stellaris_info->ssize);
770
771 stellaris_info->num_pages = 2 * (1 + (stellaris_info->fsize & 0xFFFF));
772 stellaris_info->sramsiz = (1 + (stellaris_info->ssize & 0xFFFF)) / 4;
773 stellaris_info->pagesize = 1024;
774 } else if (stellaris_info->target_class == 0xa) { /* Snowflake */
775 target_read_u32(target, FLASH_FSIZE, &stellaris_info->fsize);
776 target_read_u32(target, FLASH_SSIZE, &stellaris_info->ssize);
777
778 stellaris_info->pagesize = (1 << ((stellaris_info->fsize >> 16) & 7)) * 1024;
779 stellaris_info->num_pages = 2048 * (1 + (stellaris_info->fsize & 0xFFFF)) /
780 stellaris_info->pagesize;
781 stellaris_info->sramsiz = (1 + (stellaris_info->ssize & 0xFFFF)) / 4;
782 } else {
783 stellaris_info->num_pages = 2 * (1 + (stellaris_info->dc0 & 0xFFFF));
784 stellaris_info->sramsiz = (1 + ((stellaris_info->dc0 >> 16) & 0xFFFF)) / 4;
785 stellaris_info->pagesize = 1024;
786 }
787
788 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
789 * That exposes a 32-word Flash Write Buffer ... enabling
790 * writes of more than one word at a time.
791 */
792
793 return ERROR_OK;
794 }
795
796 /***************************************************************************
797 * flash operations *
798 ***************************************************************************/
799
800 static int stellaris_protect_check(struct flash_bank *bank)
801 {
802 struct stellaris_flash_bank *stellaris = bank->driver_priv;
803 struct target *target = bank->target;
804 uint32_t flash_sizek = stellaris->pagesize / 1024 *
805 stellaris->num_pages;
806 uint32_t fmppe_addr;
807 int status = ERROR_OK;
808 unsigned i;
809
810 if (stellaris->did1 == 0)
811 return ERROR_FLASH_BANK_NOT_PROBED;
812
813 for (i = 0; i < (unsigned) bank->num_sectors; i++)
814 bank->sectors[i].is_protected = -1;
815
816 /* Read each Flash Memory Protection Program Enable (FMPPE) register
817 * to report any pages that we can't write. Ignore the Read Enable
818 * register (FMPRE).
819 */
820
821 if (stellaris->target_class >= 0x0a || flash_sizek > 64)
822 fmppe_addr = SCB_BASE | FMPPE0;
823 else
824 fmppe_addr = SCB_BASE | FMPPE;
825
826 unsigned int page = 0, lockbitnum, lockbitcnt = flash_sizek / 2;
827 unsigned int bits_per_page = stellaris->pagesize / 2048;
828 /* Every lock bit always corresponds to a 2k region */
829 for (lockbitnum = 0; lockbitnum < lockbitcnt; lockbitnum += 32) {
830 uint32_t fmppe;
831
832 target_read_u32(target, fmppe_addr, &fmppe);
833 for (i = 0; i < 32 && lockbitnum + i < lockbitcnt; i++) {
834 bool protect = !(fmppe & (1 << i));
835 if (bits_per_page) {
836 bank->sectors[page++].is_protected = protect;
837 i += bits_per_page - 1;
838 } else { /* 1024k pages, every lockbit covers 2 pages */
839 bank->sectors[page++].is_protected = protect;
840 bank->sectors[page++].is_protected = protect;
841 }
842 }
843 fmppe_addr += 4;
844 }
845
846 return status;
847 }
848
849 static int stellaris_erase(struct flash_bank *bank, int first, int last)
850 {
851 int banknr;
852 uint32_t flash_fmc, flash_cris;
853 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
854 struct target *target = bank->target;
855
856 if (bank->target->state != TARGET_HALTED) {
857 LOG_ERROR("Target not halted");
858 return ERROR_TARGET_NOT_HALTED;
859 }
860
861 if (stellaris_info->did1 == 0)
862 return ERROR_FLASH_BANK_NOT_PROBED;
863
864 if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
865 return ERROR_FLASH_SECTOR_INVALID;
866
867 if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
868 return stellaris_mass_erase(bank);
869
870 /* Refresh flash controller timing */
871 stellaris_read_clock_info(bank);
872 stellaris_set_flash_timing(bank);
873
874 /* Clear and disable flash programming interrupts */
875 target_write_u32(target, FLASH_CIM, 0);
876 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
877
878 /* REVISIT this clobbers state set by any halted firmware ...
879 * it might want to process those IRQs.
880 */
881
882 for (banknr = first; banknr <= last; banknr++) {
883 /* Address is first word in page */
884 target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
885 /* Write erase command */
886 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
887 /* Wait until erase complete */
888 do {
889 target_read_u32(target, FLASH_FMC, &flash_fmc);
890 } while (flash_fmc & FMC_ERASE);
891
892 /* Check acess violations */
893 target_read_u32(target, FLASH_CRIS, &flash_cris);
894 if (flash_cris & (AMASK)) {
895 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "",
896 banknr, flash_cris);
897 target_write_u32(target, FLASH_CRIS, 0);
898 return ERROR_FLASH_OPERATION_FAILED;
899 }
900
901 bank->sectors[banknr].is_erased = 1;
902 }
903
904 return ERROR_OK;
905 }
906
907 static int stellaris_protect(struct flash_bank *bank, int set, int first, int last)
908 {
909 struct stellaris_flash_bank *stellaris = bank->driver_priv;
910 struct target *target = bank->target;
911 uint32_t flash_fmc, flash_cris;
912 unsigned int bits_per_page = stellaris->pagesize / 2048;
913
914 if (target->state != TARGET_HALTED) {
915 LOG_ERROR("Target not halted");
916 return ERROR_TARGET_NOT_HALTED;
917 }
918
919 if (!set) {
920 LOG_ERROR("Hardware doesn't support page-level unprotect. "
921 "Try the 'recover' command.");
922 return ERROR_COMMAND_SYNTAX_ERROR;
923 }
924
925 if (stellaris->did1 == 0)
926 return ERROR_FLASH_BANK_NOT_PROBED;
927
928 if (stellaris->target_class == 0x03 &&
929 !((stellaris->did0 >> 8) & 0xFF) &&
930 !((stellaris->did0) & 0xFF)) {
931 LOG_ERROR("DustDevil A0 parts can't be unprotected, see errata; refusing to proceed");
932 return ERROR_FLASH_OPERATION_FAILED;
933 }
934
935 if (!bits_per_page && (first % 2 || !(last % 2))) {
936 LOG_ERROR("Can't protect unaligned pages");
937 return ERROR_FLASH_SECTOR_INVALID;
938 }
939
940 /* Refresh flash controller timing */
941 stellaris_read_clock_info(bank);
942 stellaris_set_flash_timing(bank);
943
944 /* Clear and disable flash programming interrupts */
945 target_write_u32(target, FLASH_CIM, 0);
946 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
947
948 uint32_t flash_sizek = stellaris->pagesize / 1024 *
949 stellaris->num_pages;
950 uint32_t fmppe_addr;
951
952 if (stellaris->target_class >= 0x0a || flash_sizek > 64)
953 fmppe_addr = SCB_BASE | FMPPE0;
954 else
955 fmppe_addr = SCB_BASE | FMPPE;
956
957 int page = 0;
958 unsigned int lockbitnum, lockbitcnt = flash_sizek / 2;
959 /* Every lock bit always corresponds to a 2k region */
960 for (lockbitnum = 0; lockbitnum < lockbitcnt; lockbitnum += 32) {
961 uint32_t fmppe;
962
963 target_read_u32(target, fmppe_addr, &fmppe);
964 for (unsigned int i = 0;
965 i < 32 && lockbitnum + i < lockbitcnt;
966 i++) {
967 if (page >= first && page <= last)
968 fmppe &= ~(1 << i);
969
970 if (bits_per_page) {
971 if (!((i + 1) % bits_per_page))
972 page++;
973 } else { /* 1024k pages, every lockbit covers 2 pages */
974 page += 2;
975 }
976 }
977 target_write_u32(target, fmppe_addr, fmppe);
978
979 /* Commit FMPPE* */
980 target_write_u32(target, FLASH_FMA, 1 + lockbitnum / 16);
981 /* Write commit command */
982 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT);
983
984 /* Wait until commit complete */
985 do {
986 target_read_u32(target, FLASH_FMC, &flash_fmc);
987 } while (flash_fmc & FMC_COMT);
988
989 /* Check access violations */
990 target_read_u32(target, FLASH_CRIS, &flash_cris);
991 if (flash_cris & (AMASK)) {
992 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
993 target_write_u32(target, FLASH_CRIS, 0);
994 return ERROR_FLASH_OPERATION_FAILED;
995 }
996
997 fmppe_addr += 4;
998 }
999
1000 return ERROR_OK;
1001 }
1002
1003 /* see contib/loaders/flash/stellaris.s for src */
1004
1005 static const uint8_t stellaris_write_code[] = {
1006 /* write: */
1007 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */
1008 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */
1009 /* wait_fifo: */
1010 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
1011 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
1012 0x17, 0xD0, /* beq exit */
1013 0x47, 0x68, /* ldr r7, [r0, #4] */
1014 0x47, 0x45, /* cmp r7, r8 */
1015 0xF7, 0xD0, /* beq wait_fifo */
1016 /* mainloop: */
1017 0x22, 0x60, /* str r2, [r4, #0] */
1018 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */
1019 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */
1020 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */
1021 0xA5, 0x60, /* str r5, [r4, #8] */
1022 /* busy: */
1023 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */
1024 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */
1025 0xFA, 0xD1, /* bne busy */
1026 0x8F, 0x42, /* cmp r7, r1 */
1027 0x28, 0xBF, /* it cs */
1028 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
1029 0x47, 0x60, /* str r7, [r0, #4] */
1030 0x01, 0x3B, /* subs r3, r3, #1 */
1031 0x03, 0xB1, /* cbz r3, exit */
1032 0xE2, 0xE7, /* b wait_fifo */
1033 /* exit: */
1034 0x00, 0xBE, /* bkpt #0 */
1035
1036 /* pFLASH_CTRL_BASE: */
1037 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
1038 /* FLASHWRITECMD: */
1039 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
1040 };
1041 static int stellaris_write_block(struct flash_bank *bank,
1042 const uint8_t *buffer, uint32_t offset, uint32_t wcount)
1043 {
1044 struct target *target = bank->target;
1045 uint32_t buffer_size = 16384;
1046 struct working_area *source;
1047 struct working_area *write_algorithm;
1048 uint32_t address = bank->base + offset;
1049 struct reg_param reg_params[4];
1050 struct armv7m_algorithm armv7m_info;
1051 int retval = ERROR_OK;
1052
1053 /* power of two, and multiple of word size */
1054 static const unsigned buf_min = 128;
1055
1056 /* for small buffers it's faster not to download an algorithm */
1057 if (wcount * 4 < buf_min)
1058 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1059
1060 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
1061 bank, buffer, offset, wcount);
1062
1063 /* flash write code */
1064 if (target_alloc_working_area(target, sizeof(stellaris_write_code),
1065 &write_algorithm) != ERROR_OK) {
1066 LOG_DEBUG("no working area for block memory writes");
1067 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1068 };
1069
1070 /* plus a buffer big enough for this data */
1071 if (wcount * 4 < buffer_size)
1072 buffer_size = wcount * 4;
1073
1074 /* memory buffer */
1075 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
1076 buffer_size /= 2;
1077 if (buffer_size <= buf_min) {
1078 target_free_working_area(target, write_algorithm);
1079 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1080 }
1081 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1082 target_name(target), (unsigned) buffer_size);
1083 };
1084
1085 target_write_buffer(target, write_algorithm->address,
1086 sizeof(stellaris_write_code),
1087 stellaris_write_code);
1088
1089 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
1090 armv7m_info.core_mode = ARM_MODE_THREAD;
1091
1092 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
1093 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
1094 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
1095 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
1096
1097 buf_set_u32(reg_params[0].value, 0, 32, source->address);
1098 buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
1099 buf_set_u32(reg_params[2].value, 0, 32, address);
1100 buf_set_u32(reg_params[3].value, 0, 32, wcount);
1101
1102 retval = target_run_flash_async_algorithm(target, buffer, wcount, 4,
1103 0, NULL,
1104 4, reg_params,
1105 source->address, source->size,
1106 write_algorithm->address, 0,
1107 &armv7m_info);
1108
1109 if (retval == ERROR_FLASH_OPERATION_FAILED)
1110 LOG_ERROR("error %d executing stellaris flash write algorithm", retval);
1111
1112 target_free_working_area(target, write_algorithm);
1113 target_free_working_area(target, source);
1114
1115 destroy_reg_param(&reg_params[0]);
1116 destroy_reg_param(&reg_params[1]);
1117 destroy_reg_param(&reg_params[2]);
1118 destroy_reg_param(&reg_params[3]);
1119
1120 return retval;
1121 }
1122
1123 static int stellaris_write(struct flash_bank *bank, const uint8_t *buffer,
1124 uint32_t offset, uint32_t count)
1125 {
1126 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1127 struct target *target = bank->target;
1128 uint32_t address = offset;
1129 uint32_t flash_cris, flash_fmc;
1130 uint32_t words_remaining = (count / 4);
1131 uint32_t bytes_remaining = (count & 0x00000003);
1132 uint32_t bytes_written = 0;
1133 int retval;
1134
1135 if (bank->target->state != TARGET_HALTED) {
1136 LOG_ERROR("Target not halted");
1137 return ERROR_TARGET_NOT_HALTED;
1138 }
1139
1140 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
1141 bank, buffer, offset, count);
1142
1143 if (stellaris_info->did1 == 0)
1144 return ERROR_FLASH_BANK_NOT_PROBED;
1145
1146 if (offset & 0x3) {
1147 LOG_WARNING("offset size must be word aligned");
1148 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1149 }
1150
1151 if (offset + count > bank->size)
1152 return ERROR_FLASH_DST_OUT_OF_BANK;
1153
1154 /* Refresh flash controller timing */
1155 stellaris_read_clock_info(bank);
1156 stellaris_set_flash_timing(bank);
1157
1158 /* Clear and disable flash programming interrupts */
1159 target_write_u32(target, FLASH_CIM, 0);
1160 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1161
1162 /* REVISIT this clobbers state set by any halted firmware ...
1163 * it might want to process those IRQs.
1164 */
1165
1166 /* multiple words to be programmed? */
1167 if (words_remaining > 0) {
1168 /* try using a block write */
1169 retval = stellaris_write_block(bank, buffer, offset,
1170 words_remaining);
1171 if (retval != ERROR_OK) {
1172 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
1173 LOG_DEBUG("writing flash word-at-a-time");
1174 } else if (retval == ERROR_FLASH_OPERATION_FAILED) {
1175 /* if an error occured, we examine the reason, and quit */
1176 target_read_u32(target, FLASH_CRIS, &flash_cris);
1177
1178 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
1179 return ERROR_FLASH_OPERATION_FAILED;
1180 }
1181 } else {
1182 buffer += words_remaining * 4;
1183 address += words_remaining * 4;
1184 words_remaining = 0;
1185 }
1186 }
1187
1188 while (words_remaining > 0) {
1189 if (!(address & 0xff))
1190 LOG_DEBUG("0x%" PRIx32 "", address);
1191
1192 /* Program one word */
1193 target_write_u32(target, FLASH_FMA, address);
1194 target_write_buffer(target, FLASH_FMD, 4, buffer);
1195 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1196 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1197 /* Wait until write complete */
1198 do {
1199 target_read_u32(target, FLASH_FMC, &flash_fmc);
1200 } while (flash_fmc & FMC_WRITE);
1201
1202 buffer += 4;
1203 address += 4;
1204 words_remaining--;
1205 }
1206
1207 if (bytes_remaining) {
1208 uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
1209
1210 /* copy the last remaining bytes into the write buffer */
1211 memcpy(last_word, buffer+bytes_written, bytes_remaining);
1212
1213 if (!(address & 0xff))
1214 LOG_DEBUG("0x%" PRIx32 "", address);
1215
1216 /* Program one word */
1217 target_write_u32(target, FLASH_FMA, address);
1218 target_write_buffer(target, FLASH_FMD, 4, last_word);
1219 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1220 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1221 /* Wait until write complete */
1222 do {
1223 target_read_u32(target, FLASH_FMC, &flash_fmc);
1224 } while (flash_fmc & FMC_WRITE);
1225 }
1226
1227 /* Check access violations */
1228 target_read_u32(target, FLASH_CRIS, &flash_cris);
1229 if (flash_cris & (AMASK)) {
1230 LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
1231 return ERROR_FLASH_OPERATION_FAILED;
1232 }
1233 return ERROR_OK;
1234 }
1235
1236 static int stellaris_probe(struct flash_bank *bank)
1237 {
1238 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1239 int retval;
1240
1241 /* If this is a stellaris chip, it has flash; probe() is just
1242 * to figure out how much is present. Only do it once.
1243 */
1244 if (stellaris_info->did1 != 0)
1245 return ERROR_OK;
1246
1247 /* stellaris_read_part_info() already handled error checking and
1248 * reporting. Note that it doesn't write, so we don't care about
1249 * whether the target is halted or not.
1250 */
1251 retval = stellaris_read_part_info(bank);
1252 if (retval != ERROR_OK)
1253 return retval;
1254
1255 if (bank->sectors) {
1256 free(bank->sectors);
1257 bank->sectors = NULL;
1258 }
1259
1260 /* provide this for the benefit of the NOR flash framework */
1261 bank->size = stellaris_info->num_pages * stellaris_info->pagesize;
1262 bank->num_sectors = stellaris_info->num_pages;
1263 bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
1264 for (int i = 0; i < bank->num_sectors; i++) {
1265 bank->sectors[i].offset = i * stellaris_info->pagesize;
1266 bank->sectors[i].size = stellaris_info->pagesize;
1267 bank->sectors[i].is_erased = -1;
1268 bank->sectors[i].is_protected = -1;
1269 }
1270
1271 return retval;
1272 }
1273
1274 static int stellaris_mass_erase(struct flash_bank *bank)
1275 {
1276 struct target *target = NULL;
1277 struct stellaris_flash_bank *stellaris_info = NULL;
1278 uint32_t flash_fmc;
1279
1280 stellaris_info = bank->driver_priv;
1281 target = bank->target;
1282
1283 if (target->state != TARGET_HALTED) {
1284 LOG_ERROR("Target not halted");
1285 return ERROR_TARGET_NOT_HALTED;
1286 }
1287
1288 if (stellaris_info->did1 == 0)
1289 return ERROR_FLASH_BANK_NOT_PROBED;
1290
1291 /* Refresh flash controller timing */
1292 stellaris_read_clock_info(bank);
1293 stellaris_set_flash_timing(bank);
1294
1295 /* Clear and disable flash programming interrupts */
1296 target_write_u32(target, FLASH_CIM, 0);
1297 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1298
1299 /* REVISIT this clobbers state set by any halted firmware ...
1300 * it might want to process those IRQs.
1301 */
1302
1303 target_write_u32(target, FLASH_FMA, 0);
1304 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1305 /* Wait until erase complete */
1306 do {
1307 target_read_u32(target, FLASH_FMC, &flash_fmc);
1308 } while (flash_fmc & FMC_MERASE);
1309
1310 /* if device has > 128k, then second erase cycle is needed
1311 * this is only valid for older devices, but will not hurt */
1312 if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) {
1313 target_write_u32(target, FLASH_FMA, 0x20000);
1314 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1315 /* Wait until erase complete */
1316 do {
1317 target_read_u32(target, FLASH_FMC, &flash_fmc);
1318 } while (flash_fmc & FMC_MERASE);
1319 }
1320
1321 return ERROR_OK;
1322 }
1323
1324 COMMAND_HANDLER(stellaris_handle_mass_erase_command)
1325 {
1326 int i;
1327
1328 if (CMD_ARGC < 1)
1329 return ERROR_COMMAND_SYNTAX_ERROR;
1330
1331 struct flash_bank *bank;
1332 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1333 if (ERROR_OK != retval)
1334 return retval;
1335
1336 if (stellaris_mass_erase(bank) == ERROR_OK) {
1337 /* set all sectors as erased */
1338 for (i = 0; i < bank->num_sectors; i++)
1339 bank->sectors[i].is_erased = 1;
1340
1341 command_print(CMD_CTX, "stellaris mass erase complete");
1342 } else
1343 command_print(CMD_CTX, "stellaris mass erase failed");
1344
1345 return ERROR_OK;
1346 }
1347
1348 /**
1349 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1350 * This performs a mass erase and then restores all nonvolatile registers
1351 * (including USER_* registers and flash lock bits) to their defaults.
1352 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1353 *
1354 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1355 * can affect this operation if flash protection has been enabled.
1356 */
1357 COMMAND_HANDLER(stellaris_handle_recover_command)
1358 {
1359 struct flash_bank *bank;
1360 int retval;
1361
1362 if (CMD_ARGC < 1)
1363 return ERROR_COMMAND_SYNTAX_ERROR;
1364
1365 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1366 if (retval != ERROR_OK)
1367 return retval;
1368
1369 /* REVISIT ... it may be worth sanity checking that the AP is
1370 * inactive before we start. ARM documents that switching a DP's
1371 * mode while it's active can cause fault modes that need a power
1372 * cycle to recover.
1373 */
1374
1375 Jim_Eval_Named(CMD_CTX->interp, "catch { hla_command \"debug unlock\" }", 0, 0);
1376 if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL), "0")) {
1377 retval = ERROR_OK;
1378 goto user_action;
1379 }
1380
1381 /* assert SRST */
1382 if (!(jtag_get_reset_config() & RESET_HAS_SRST)) {
1383 LOG_ERROR("Can't recover Stellaris flash without SRST");
1384 return ERROR_FAIL;
1385 }
1386 adapter_assert_reset();
1387
1388 for (int i = 0; i < 5; i++) {
1389 retval = dap_to_swd(bank->target);
1390 if (retval != ERROR_OK)
1391 goto done;
1392
1393 retval = dap_to_jtag(bank->target);
1394 if (retval != ERROR_OK)
1395 goto done;
1396 }
1397
1398 /* de-assert SRST */
1399 adapter_deassert_reset();
1400 retval = jtag_execute_queue();
1401
1402 /* wait 400+ msec ... OK, "1+ second" is simpler */
1403 usleep(1000);
1404
1405 user_action:
1406 /* USER INTERVENTION required for the power cycle
1407 * Restarting OpenOCD is likely needed because of mode switching.
1408 */
1409 LOG_INFO("USER ACTION: "
1410 "power cycle Stellaris chip, then restart OpenOCD.");
1411
1412 done:
1413 return retval;
1414 }
1415
1416 static const struct command_registration stellaris_exec_command_handlers[] = {
1417 {
1418 .name = "mass_erase",
1419 .usage = "<bank>",
1420 .handler = stellaris_handle_mass_erase_command,
1421 .mode = COMMAND_EXEC,
1422 .help = "erase entire device",
1423 },
1424 {
1425 .name = "recover",
1426 .handler = stellaris_handle_recover_command,
1427 .mode = COMMAND_EXEC,
1428 .usage = "bank_id",
1429 .help = "recover (and erase) locked device",
1430 },
1431 COMMAND_REGISTRATION_DONE
1432 };
1433 static const struct command_registration stellaris_command_handlers[] = {
1434 {
1435 .name = "stellaris",
1436 .mode = COMMAND_EXEC,
1437 .help = "Stellaris flash command group",
1438 .usage = "",
1439 .chain = stellaris_exec_command_handlers,
1440 },
1441 COMMAND_REGISTRATION_DONE
1442 };
1443
1444 struct flash_driver stellaris_flash = {
1445 .name = "stellaris",
1446 .commands = stellaris_command_handlers,
1447 .flash_bank_command = stellaris_flash_bank_command,
1448 .erase = stellaris_erase,
1449 .protect = stellaris_protect,
1450 .write = stellaris_write,
1451 .read = default_flash_read,
1452 .probe = stellaris_probe,
1453 .auto_probe = stellaris_probe,
1454 .erase_check = default_flash_blank_check,
1455 .protect_check = stellaris_protect_check,
1456 .info = get_stellaris_info,
1457 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)