1 /***************************************************************************
2 * Copyright (C) 2006 by Magnus Lundin *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
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. *
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. *
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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
24 /***************************************************************************
25 * STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more.
26 ***************************************************************************/
33 #include <target/algorithm.h>
34 #include <target/armv7m.h>
36 #define DID0_VER(did0) ((did0 >> 28)&0x07)
38 /* STELLARIS control registers */
39 #define SCB_BASE 0x400FE000
54 /* "legacy" flash memory protection registers (64KB max) */
58 /* new flash memory protection registers (for more than 64KB) */
59 #define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */
60 #define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */
64 #define FLASH_CONTROL_BASE 0x400FD000
65 #define FLASH_FMA (FLASH_CONTROL_BASE | 0x000)
66 #define FLASH_FMD (FLASH_CONTROL_BASE | 0x004)
67 #define FLASH_FMC (FLASH_CONTROL_BASE | 0x008)
68 #define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C)
69 #define FLASH_CIM (FLASH_CONTROL_BASE | 0x010)
70 #define FLASH_MISC (FLASH_CONTROL_BASE | 0x014)
78 /* Flash Controller Command bits */
79 #define FMC_WRKEY (0xA442 << 16)
80 #define FMC_COMT (1 << 3)
81 #define FMC_MERASE (1 << 2)
82 #define FMC_ERASE (1 << 1)
83 #define FMC_WRITE (1 << 0)
85 /* STELLARIS constants */
87 /* values to write in FMA to commit write-"once" values */
88 #define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */
89 #define FLASH_FMA_PPE(x) (2 * (x) + 1) /* for FMPPPEx */
91 static void stellaris_read_clock_info(struct flash_bank
*bank
);
92 static int stellaris_mass_erase(struct flash_bank
*bank
);
94 struct stellaris_flash_bank
{
95 /* chip id register */
101 const char *target_name
;
102 uint8_t target_class
;
109 uint32_t pages_in_lockregion
;
112 uint16_t num_lockbits
;
114 /* main clock status */
121 const char *iosc_desc
;
122 const char *mck_desc
;
125 /* Autogenerated by contrib/gen-stellaris-part-header.pl */
126 /* From Stellaris Firmware Development Package revision 8049 */
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, 0xD4, "LM3S2016"},
192 {0x01, 0x51, "LM3S2110"},
193 {0x01, 0x84, "LM3S2139"},
194 {0x03, 0x39, "LM3S2276"},
195 {0x01, 0xA2, "LM3S2410"},
196 {0x01, 0x59, "LM3S2412"},
197 {0x01, 0x56, "LM3S2432"},
198 {0x01, 0x5A, "LM3S2533"},
199 {0x01, 0xE1, "LM3S2601"},
200 {0x01, 0xE0, "LM3S2608"},
201 {0x03, 0x33, "LM3S2616"},
202 {0x01, 0x57, "LM3S2620"},
203 {0x01, 0x85, "LM3S2637"},
204 {0x01, 0x53, "LM3S2651"},
205 {0x03, 0x80, "LM3S2671"},
206 {0x03, 0x50, "LM3S2678"},
207 {0x01, 0xA4, "LM3S2730"},
208 {0x01, 0x52, "LM3S2739"},
209 {0x03, 0x3A, "LM3S2776"},
210 {0x04, 0x6D, "LM3S2793"},
211 {0x01, 0xE3, "LM3S2911"},
212 {0x01, 0xE2, "LM3S2918"},
213 {0x01, 0xED, "LM3S2919"},
214 {0x01, 0x54, "LM3S2939"},
215 {0x01, 0x8F, "LM3S2948"},
216 {0x01, 0x58, "LM3S2950"},
217 {0x01, 0x55, "LM3S2965"},
218 {0x04, 0x6C, "LM3S2B93"},
219 {0x06, 0x94, "LM3S2D93"},
220 {0x06, 0x93, "LM3S2U93"},
221 {0x00, 0x19, "LM3S300"},
222 {0x00, 0x11, "LM3S301"},
223 {0x00, 0x1A, "LM3S308"},
224 {0x00, 0x12, "LM3S310"},
225 {0x00, 0x13, "LM3S315"},
226 {0x00, 0x14, "LM3S316"},
227 {0x00, 0x17, "LM3S317"},
228 {0x00, 0x15, "LM3S328"},
229 {0x03, 0x08, "LM3S3634"},
230 {0x03, 0x43, "LM3S3651"},
231 {0x04, 0xC8, "LM3S3654"},
232 {0x03, 0x44, "LM3S3739"},
233 {0x03, 0x49, "LM3S3748"},
234 {0x03, 0x45, "LM3S3749"},
235 {0x04, 0x42, "LM3S3826"},
236 {0x04, 0x41, "LM3S3J26"},
237 {0x04, 0x40, "LM3S3N26"},
238 {0x04, 0x3F, "LM3S3W26"},
239 {0x04, 0x3E, "LM3S3Z26"},
240 {0x03, 0x81, "LM3S5632"},
241 {0x04, 0x0C, "LM3S5651"},
242 {0x03, 0x8A, "LM3S5652"},
243 {0x04, 0x4D, "LM3S5656"},
244 {0x03, 0x91, "LM3S5662"},
245 {0x03, 0x96, "LM3S5732"},
246 {0x03, 0x97, "LM3S5737"},
247 {0x03, 0xA0, "LM3S5739"},
248 {0x03, 0x99, "LM3S5747"},
249 {0x03, 0xA7, "LM3S5749"},
250 {0x03, 0x9A, "LM3S5752"},
251 {0x03, 0x9C, "LM3S5762"},
252 {0x04, 0x69, "LM3S5791"},
253 {0x04, 0x0B, "LM3S5951"},
254 {0x04, 0x4E, "LM3S5956"},
255 {0x04, 0x68, "LM3S5B91"},
256 {0x06, 0x2E, "LM3S5C31"},
257 {0x06, 0x2C, "LM3S5C36"},
258 {0x06, 0x5E, "LM3S5C51"},
259 {0x06, 0x5B, "LM3S5C56"},
260 {0x06, 0x5F, "LM3S5D51"},
261 {0x06, 0x5C, "LM3S5D56"},
262 {0x06, 0x87, "LM3S5D91"},
263 {0x06, 0x2D, "LM3S5G31"},
264 {0x06, 0x1F, "LM3S5G36"},
265 {0x06, 0x5D, "LM3S5G51"},
266 {0x06, 0x4F, "LM3S5G56"},
267 {0x04, 0x09, "LM3S5K31"},
268 {0x04, 0x4A, "LM3S5K36"},
269 {0x04, 0x0A, "LM3S5P31"},
270 {0x04, 0x48, "LM3S5P36"},
271 {0x04, 0xB6, "LM3S5P3B"},
272 {0x04, 0x0D, "LM3S5P51"},
273 {0x04, 0x4C, "LM3S5P56"},
274 {0x04, 0x07, "LM3S5R31"},
275 {0x04, 0x4B, "LM3S5R36"},
276 {0x04, 0x47, "LM3S5T36"},
277 {0x06, 0x7F, "LM3S5U91"},
278 {0x04, 0x46, "LM3S5Y36"},
279 {0x00, 0x2A, "LM3S600"},
280 {0x00, 0x21, "LM3S601"},
281 {0x00, 0x2B, "LM3S608"},
282 {0x00, 0x22, "LM3S610"},
283 {0x01, 0xA1, "LM3S6100"},
284 {0x00, 0x23, "LM3S611"},
285 {0x01, 0x74, "LM3S6110"},
286 {0x00, 0x24, "LM3S612"},
287 {0x00, 0x25, "LM3S613"},
288 {0x00, 0x26, "LM3S615"},
289 {0x00, 0x28, "LM3S617"},
290 {0x00, 0x29, "LM3S618"},
291 {0x00, 0x27, "LM3S628"},
292 {0x01, 0xA5, "LM3S6420"},
293 {0x01, 0x82, "LM3S6422"},
294 {0x01, 0x75, "LM3S6432"},
295 {0x01, 0x76, "LM3S6537"},
296 {0x01, 0x71, "LM3S6610"},
297 {0x01, 0xE7, "LM3S6611"},
298 {0x01, 0xE6, "LM3S6618"},
299 {0x01, 0x83, "LM3S6633"},
300 {0x01, 0x8B, "LM3S6637"},
301 {0x01, 0xA3, "LM3S6730"},
302 {0x01, 0x77, "LM3S6753"},
303 {0x01, 0xD1, "LM3S6816"},
304 {0x01, 0xE9, "LM3S6911"},
305 {0x01, 0xD3, "LM3S6916"},
306 {0x01, 0xE8, "LM3S6918"},
307 {0x01, 0x89, "LM3S6938"},
308 {0x01, 0x72, "LM3S6950"},
309 {0x01, 0x78, "LM3S6952"},
310 {0x01, 0x73, "LM3S6965"},
311 {0x06, 0xAA, "LM3S6C11"},
312 {0x06, 0xAC, "LM3S6C65"},
313 {0x06, 0x9F, "LM3S6G11"},
314 {0x06, 0xAB, "LM3S6G65"},
315 {0x00, 0x38, "LM3S800"},
316 {0x00, 0x31, "LM3S801"},
317 {0x00, 0x39, "LM3S808"},
318 {0x00, 0x32, "LM3S811"},
319 {0x00, 0x33, "LM3S812"},
320 {0x00, 0x34, "LM3S815"},
321 {0x00, 0x36, "LM3S817"},
322 {0x00, 0x37, "LM3S818"},
323 {0x00, 0x35, "LM3S828"},
324 {0x01, 0x64, "LM3S8530"},
325 {0x01, 0x8E, "LM3S8538"},
326 {0x01, 0x61, "LM3S8630"},
327 {0x01, 0x63, "LM3S8730"},
328 {0x01, 0x8D, "LM3S8733"},
329 {0x01, 0x86, "LM3S8738"},
330 {0x01, 0x65, "LM3S8930"},
331 {0x01, 0x8C, "LM3S8933"},
332 {0x01, 0x88, "LM3S8938"},
333 {0x01, 0xA6, "LM3S8962"},
334 {0x01, 0x62, "LM3S8970"},
335 {0x01, 0xD7, "LM3S8971"},
336 {0x06, 0xAE, "LM3S8C62"},
337 {0x06, 0xAD, "LM3S8G62"},
338 {0x04, 0xCF, "LM3S9781"},
339 {0x04, 0x67, "LM3S9790"},
340 {0x04, 0x6B, "LM3S9792"},
341 {0x04, 0x2D, "LM3S9971"},
342 {0x04, 0x20, "LM3S9997"},
343 {0x04, 0xD0, "LM3S9B81"},
344 {0x04, 0x66, "LM3S9B90"},
345 {0x04, 0x6A, "LM3S9B92"},
346 {0x04, 0x6E, "LM3S9B95"},
347 {0x04, 0x6F, "LM3S9B96"},
348 {0x04, 0x1D, "LM3S9BN2"},
349 {0x04, 0x1E, "LM3S9BN5"},
350 {0x04, 0x1F, "LM3S9BN6"},
351 {0x06, 0x70, "LM3S9C97"},
352 {0x06, 0x7A, "LM3S9CN5"},
353 {0x06, 0xA9, "LM3S9D81"},
354 {0x06, 0x7E, "LM3S9D90"},
355 {0x06, 0x92, "LM3S9D92"},
356 {0x06, 0xC8, "LM3S9D95"},
357 {0x06, 0x9D, "LM3S9D96"},
358 {0x06, 0x7B, "LM3S9DN5"},
359 {0x06, 0x7C, "LM3S9DN6"},
360 {0x06, 0x60, "LM3S9G97"},
361 {0x06, 0x79, "LM3S9GN5"},
362 {0x04, 0x1B, "LM3S9L71"},
363 {0x04, 0x18, "LM3S9L97"},
364 {0x06, 0xA8, "LM3S9U81"},
365 {0x06, 0x7D, "LM3S9U90"},
366 {0x06, 0x90, "LM3S9U92"},
367 {0x06, 0xB7, "LM3S9U95"},
368 {0x06, 0x9B, "LM3S9U96"},
369 {0x05, 0x18, "LM4F110B2QR"},
370 {0x05, 0x19, "LM4F110C4QR"},
371 {0x05, 0x10, "LM4F110E5QR"},
372 {0x05, 0x11, "LM4F110H5QR"},
373 {0x05, 0x22, "LM4F111B2QR"},
374 {0x05, 0x23, "LM4F111C4QR"},
375 {0x05, 0x20, "LM4F111E5QR"},
376 {0x05, 0x21, "LM4F111H5QR"},
377 {0x05, 0x36, "LM4F112C4QC"},
378 {0x05, 0x30, "LM4F112E5QC"},
379 {0x05, 0x31, "LM4F112H5QC"},
380 {0x05, 0x35, "LM4F112H5QD"},
381 {0x05, 0x01, "LM4F120B2QR"},
382 {0x05, 0x02, "LM4F120C4QR"},
383 {0x05, 0x03, "LM4F120E5QR"},
384 {0x05, 0x04, "LM4F120H5QR"},
385 {0x05, 0x08, "LM4F121B2QR"},
386 {0x05, 0x09, "LM4F121C4QR"},
387 {0x05, 0x0A, "LM4F121E5QR"},
388 {0x05, 0x0B, "LM4F121H5QR"},
389 {0x05, 0xD0, "LM4F122C4QC"},
390 {0x05, 0xD1, "LM4F122E5QC"},
391 {0x05, 0xD2, "LM4F122H5QC"},
392 {0x05, 0xD6, "LM4F122H5QD"},
393 {0x05, 0x48, "LM4F130C4QR"},
394 {0x05, 0x40, "LM4F130E5QR"},
395 {0x05, 0x41, "LM4F130H5QR"},
396 {0x05, 0x52, "LM4F131C4QR"},
397 {0x05, 0x50, "LM4F131E5QR"},
398 {0x05, 0x51, "LM4F131H5QR"},
399 {0x05, 0x66, "LM4F132C4QC"},
400 {0x05, 0x60, "LM4F132E5QC"},
401 {0x05, 0x61, "LM4F132H5QC"},
402 {0x05, 0x65, "LM4F132H5QD"},
403 {0x05, 0xA0, "LM4F230E5QR"},
404 {0x05, 0xA1, "LM4F230H5QR"},
405 {0x05, 0xB0, "LM4F231E5QR"},
406 {0x05, 0xB1, "LM4F231H5QR"},
407 {0x05, 0xC0, "LM4F232E5QC"},
408 {0x05, 0xE3, "LM4F232H5BB"},
409 {0x05, 0xC1, "LM4F232H5QC"},
410 {0x05, 0xC5, "LM4F232H5QD"},
411 {0x05, 0xE5, "LM4FS1AH5BB"},
412 {0x05, 0xE4, "LM4FS99H5BB"},
413 {0x05, 0xE0, "LM4FSXAH5BB"},
414 {0xFF, 0x00, "Unknown Part"}
417 static char *StellarisClassname
[7] = {
427 /***************************************************************************
428 * openocd command interface *
429 ***************************************************************************/
431 /* flash_bank stellaris <base> <size> 0 0 <target#>
433 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command
)
435 struct stellaris_flash_bank
*stellaris_info
;
438 return ERROR_COMMAND_SYNTAX_ERROR
;
440 stellaris_info
= calloc(sizeof(struct stellaris_flash_bank
), 1);
442 bank
->driver_priv
= stellaris_info
;
444 stellaris_info
->target_name
= "Unknown target";
446 /* part wasn't probed for info yet */
447 stellaris_info
->did1
= 0;
449 /* TODO Specify the main crystal speed in kHz using an optional
450 * argument; ditto, the speed of an external oscillator used
451 * instead of a crystal. Avoid programming flash using IOSC.
456 static int get_stellaris_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
459 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
461 if (stellaris_info
->did1
== 0)
462 return ERROR_FLASH_BANK_NOT_PROBED
;
464 /* Read main and master clock freqency register */
465 stellaris_read_clock_info(bank
);
467 printed
= snprintf(buf
,
469 "\nTI/LMI Stellaris information: Chip is "
470 "class %i (%s) %s rev %c%i\n",
471 stellaris_info
->target_class
,
472 StellarisClassname
[stellaris_info
->target_class
],
473 stellaris_info
->target_name
,
474 (int)('A' + ((stellaris_info
->did0
>> 8) & 0xFF)),
475 (int)((stellaris_info
->did0
) & 0xFF));
479 printed
= snprintf(buf
,
481 "did1: 0x%8.8" PRIx32
", arch: 0x%4.4" PRIx32
482 ", eproc: %s, ramsize: %ik, flashsize: %ik\n",
483 stellaris_info
->did1
,
484 stellaris_info
->did1
,
486 (int)((1 + ((stellaris_info
->dc0
>> 16) & 0xFFFF))/4),
487 (int)((1 + (stellaris_info
->dc0
& 0xFFFF))*2));
491 printed
= snprintf(buf
,
493 "master clock: %ikHz%s, "
494 "rcc is 0x%" PRIx32
", rcc2 is 0x%" PRIx32
"\n",
495 (int)(stellaris_info
->mck_freq
/ 1000),
496 stellaris_info
->mck_desc
,
498 stellaris_info
->rcc2
);
502 if (stellaris_info
->num_lockbits
> 0) {
505 "pagesize: %" PRIi32
", pages: %d, "
506 "lockbits: %i, pages per lockbit: %i\n",
507 stellaris_info
->pagesize
,
508 (unsigned) stellaris_info
->num_pages
,
509 stellaris_info
->num_lockbits
,
510 (unsigned) stellaris_info
->pages_in_lockregion
);
515 /***************************************************************************
516 * chip identification and status *
517 ***************************************************************************/
519 /* Set the flash timimg register to match current clocking */
520 static void stellaris_set_flash_timing(struct flash_bank
*bank
)
522 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
523 struct target
*target
= bank
->target
;
524 uint32_t usecrl
= (stellaris_info
->mck_freq
/1000000ul-1);
526 /* only valid for Sandstorm and Fury class devices */
527 if (stellaris_info
->target_class
> 1)
530 LOG_DEBUG("usecrl = %i", (int)(usecrl
));
531 target_write_u32(target
, SCB_BASE
| USECRL
, usecrl
);
534 static const unsigned rcc_xtal
[32] = {
535 [0x00] = 1000000, /* no pll */
536 [0x01] = 1843200, /* no pll */
537 [0x02] = 2000000, /* no pll */
538 [0x03] = 2457600, /* no pll */
542 [0x06] = 4000000, /* usb */
546 [0x09] = 5000000, /* usb */
548 [0x0b] = 6000000, /* (reset) usb */
552 [0x0e] = 8000000, /* usb */
555 /* parts before DustDevil use just 4 bits for xtal spec */
557 [0x10] = 10000000, /* usb */
558 [0x11] = 12000000, /* usb */
563 [0x15] = 16000000, /* usb */
567 /** Read clock configuration and set stellaris_info->usec_clocks. */
568 static void stellaris_read_clock_info(struct flash_bank
*bank
)
570 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
571 struct target
*target
= bank
->target
;
572 uint32_t rcc
, rcc2
, pllcfg
, sysdiv
, usesysdiv
, bypass
, oscsrc
;
574 unsigned long mainfreq
;
576 target_read_u32(target
, SCB_BASE
| RCC
, &rcc
);
577 LOG_DEBUG("Stellaris RCC %" PRIx32
"", rcc
);
579 target_read_u32(target
, SCB_BASE
| RCC2
, &rcc2
);
580 LOG_DEBUG("Stellaris RCC2 %" PRIx32
"", rcc
);
582 target_read_u32(target
, SCB_BASE
| PLLCFG
, &pllcfg
);
583 LOG_DEBUG("Stellaris PLLCFG %" PRIx32
"", pllcfg
);
585 stellaris_info
->rcc
= rcc
;
586 stellaris_info
->rcc
= rcc2
;
588 sysdiv
= (rcc
>> 23) & 0xF;
589 usesysdiv
= (rcc
>> 22) & 0x1;
590 bypass
= (rcc
>> 11) & 0x1;
591 oscsrc
= (rcc
>> 4) & 0x3;
592 xtal
= (rcc
>> 6) & stellaris_info
->xtal_mask
;
594 /* NOTE: post-Sandstorm parts have RCC2 which may override
595 * parts of RCC ... with more sysdiv options, option for
596 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
597 * as zero, so the "use RCC2" flag is always clear.
599 if (rcc2
& (1 << 31)) {
600 sysdiv
= (rcc2
>> 23) & 0x3F;
601 bypass
= (rcc2
>> 11) & 0x1;
602 oscsrc
= (rcc2
>> 4) & 0x7;
604 /* FIXME Tempest parts have an additional lsb for
605 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
609 stellaris_info
->mck_desc
= "";
613 mainfreq
= rcc_xtal
[xtal
];
616 mainfreq
= stellaris_info
->iosc_freq
;
617 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
620 mainfreq
= stellaris_info
->iosc_freq
/ 4;
621 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
623 case 3: /* lowspeed */
624 /* Sandstorm doesn't have this 30K +/- 30% osc */
626 stellaris_info
->mck_desc
= " (±30%)";
628 case 8: /* hibernation osc */
629 /* not all parts support hibernation */
633 default: /* NOTREACHED */
638 /* PLL is used if it's not bypassed; its output is 200 MHz
639 * even when it runs at 400 MHz (adds divide-by-two stage).
642 mainfreq
= 200000000;
645 stellaris_info
->mck_freq
= mainfreq
/(1 + sysdiv
);
647 stellaris_info
->mck_freq
= mainfreq
;
650 /* Read device id register, main clock frequency register and fill in driver info structure */
651 static int stellaris_read_part_info(struct flash_bank
*bank
)
653 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
654 struct target
*target
= bank
->target
;
655 uint32_t did0
, did1
, ver
, fam
;
658 /* Read and parse chip identification register */
659 target_read_u32(target
, SCB_BASE
| DID0
, &did0
);
660 target_read_u32(target
, SCB_BASE
| DID1
, &did1
);
661 target_read_u32(target
, SCB_BASE
| DC0
, &stellaris_info
->dc0
);
662 target_read_u32(target
, SCB_BASE
| DC1
, &stellaris_info
->dc1
);
663 LOG_DEBUG("did0 0x%" PRIx32
", did1 0x%" PRIx32
", dc0 0x%" PRIx32
", dc1 0x%" PRIx32
"",
664 did0
, did1
, stellaris_info
->dc0
, stellaris_info
->dc1
);
667 if ((ver
!= 0) && (ver
!= 1)) {
668 LOG_WARNING("Unknown did0 version, cannot identify target");
669 return ERROR_FLASH_OPERATION_FAILED
;
673 LOG_WARNING("Cannot identify target as a Stellaris");
674 return ERROR_FLASH_OPERATION_FAILED
;
678 fam
= (did1
>> 24) & 0xF;
679 if (((ver
!= 0) && (ver
!= 1)) || (fam
!= 0)) {
680 LOG_WARNING("Unknown did1 version/family.");
681 return ERROR_FLASH_OPERATION_FAILED
;
684 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
685 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
686 * even give _both_ numbers! We'll use current numbers; IOSC is
687 * always approximate.
689 * For Tempest: IOSC is calibrated, 16 MHz
690 * For Blizzard: IOSC is calibrated, 16 MHz
691 * For Firestorm: IOSC is calibrated, 16 MHz
693 stellaris_info
->iosc_freq
= 12000000;
694 stellaris_info
->iosc_desc
= " (±30%)";
695 stellaris_info
->xtal_mask
= 0x0f;
697 /* get device class */
698 if (DID0_VER(did0
) > 0) {
699 stellaris_info
->target_class
= (did0
>> 16) & 0xFF;
701 /* Sandstorm class */
702 stellaris_info
->target_class
= 0;
705 switch (stellaris_info
->target_class
) {
706 case 0: /* Sandstorm */
708 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
709 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
710 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
712 if (((did0
>> 8) & 0xff) < 2) {
713 stellaris_info
->iosc_freq
= 15000000;
714 stellaris_info
->iosc_desc
= " (±50%)";
721 case 4: /* Tempest */
722 case 5: /* Blizzard */
723 case 6: /* Firestorm */
724 stellaris_info
->iosc_freq
= 16000000; /* +/- 1% */
725 stellaris_info
->iosc_desc
= " (±1%)";
728 case 3: /* DustDevil */
729 stellaris_info
->xtal_mask
= 0x1f;
733 LOG_WARNING("Unknown did0 class");
736 for (i
= 0; StellarisParts
[i
].partno
; i
++) {
737 if ((StellarisParts
[i
].partno
== ((did1
>> 16) & 0xFF)) &&
738 (StellarisParts
[i
].class == stellaris_info
->target_class
))
742 stellaris_info
->target_name
= StellarisParts
[i
].partname
;
744 stellaris_info
->did0
= did0
;
745 stellaris_info
->did1
= did1
;
747 stellaris_info
->num_lockbits
= 1 + (stellaris_info
->dc0
& 0xFFFF);
748 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->dc0
& 0xFFFF));
749 stellaris_info
->pagesize
= 1024;
750 stellaris_info
->pages_in_lockregion
= 2;
752 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
753 * That exposes a 32-word Flash Write Buffer ... enabling
754 * writes of more than one word at a time.
760 /***************************************************************************
762 ***************************************************************************/
764 static int stellaris_protect_check(struct flash_bank
*bank
)
766 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
767 int status
= ERROR_OK
;
771 if (stellaris
->did1
== 0)
772 return ERROR_FLASH_BANK_NOT_PROBED
;
774 for (i
= 0; i
< (unsigned) bank
->num_sectors
; i
++)
775 bank
->sectors
[i
].is_protected
= -1;
777 /* Read each Flash Memory Protection Program Enable (FMPPE) register
778 * to report any pages that we can't write. Ignore the Read Enable
781 for (i
= 0, page
= 0;
782 i
< DIV_ROUND_UP(stellaris
->num_lockbits
, 32u);
786 status
= target_read_u32(bank
->target
,
787 SCB_BASE
+ (i
? (FMPPE0
+ 4 * i
) : FMPPE
),
789 LOG_DEBUG("FMPPE%d = %#8.8x (status %d)", i
,
790 (unsigned) lockbits
, status
);
791 if (status
!= ERROR_OK
)
794 for (unsigned j
= 0; j
< 32; j
++) {
797 for (k
= 0; k
< stellaris
->pages_in_lockregion
; k
++) {
798 if (page
>= (unsigned) bank
->num_sectors
)
800 bank
->sectors
[page
++].is_protected
=
801 !(lockbits
& (1 << j
));
810 static int stellaris_erase(struct flash_bank
*bank
, int first
, int last
)
813 uint32_t flash_fmc
, flash_cris
;
814 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
815 struct target
*target
= bank
->target
;
817 if (bank
->target
->state
!= TARGET_HALTED
) {
818 LOG_ERROR("Target not halted");
819 return ERROR_TARGET_NOT_HALTED
;
822 if (stellaris_info
->did1
== 0)
823 return ERROR_FLASH_BANK_NOT_PROBED
;
825 if ((first
< 0) || (last
< first
) || (last
>= (int)stellaris_info
->num_pages
))
826 return ERROR_FLASH_SECTOR_INVALID
;
828 if ((first
== 0) && (last
== ((int)stellaris_info
->num_pages
-1)))
829 return stellaris_mass_erase(bank
);
831 /* Refresh flash controller timing */
832 stellaris_read_clock_info(bank
);
833 stellaris_set_flash_timing(bank
);
835 /* Clear and disable flash programming interrupts */
836 target_write_u32(target
, FLASH_CIM
, 0);
837 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
839 /* REVISIT this clobbers state set by any halted firmware ...
840 * it might want to process those IRQs.
843 for (banknr
= first
; banknr
<= last
; banknr
++) {
844 /* Address is first word in page */
845 target_write_u32(target
, FLASH_FMA
, banknr
* stellaris_info
->pagesize
);
846 /* Write erase command */
847 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_ERASE
);
848 /* Wait until erase complete */
850 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
851 } while (flash_fmc
& FMC_ERASE
);
853 /* Check acess violations */
854 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
855 if (flash_cris
& (AMASK
)) {
856 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32
"",
858 target_write_u32(target
, FLASH_CRIS
, 0);
859 return ERROR_FLASH_OPERATION_FAILED
;
862 bank
->sectors
[banknr
].is_erased
= 1;
868 static int stellaris_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
870 uint32_t fmppe
, flash_fmc
, flash_cris
;
873 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
874 struct target
*target
= bank
->target
;
876 if (bank
->target
->state
!= TARGET_HALTED
) {
877 LOG_ERROR("Target not halted");
878 return ERROR_TARGET_NOT_HALTED
;
882 LOG_ERROR("Hardware doesn't support page-level unprotect. "
883 "Try the 'recover' command.");
884 return ERROR_COMMAND_SYNTAX_ERROR
;
887 if (stellaris_info
->did1
== 0)
888 return ERROR_FLASH_BANK_NOT_PROBED
;
890 /* lockregions are 2 pages ... must protect [even..odd] */
891 if ((first
< 0) || (first
& 1)
892 || (last
< first
) || !(last
& 1)
893 || (last
>= 2 * stellaris_info
->num_lockbits
)) {
894 LOG_ERROR("Can't protect unaligned or out-of-range pages.");
895 return ERROR_FLASH_SECTOR_INVALID
;
898 /* Refresh flash controller timing */
899 stellaris_read_clock_info(bank
);
900 stellaris_set_flash_timing(bank
);
902 /* convert from pages to lockregions */
906 /* FIXME this assumes single FMPPE, for a max of 64K of flash!!
907 * Current parts can be much bigger.
910 LOG_ERROR("No support yet for protection > 64K");
911 return ERROR_FLASH_OPERATION_FAILED
;
914 target_read_u32(target
, SCB_BASE
| FMPPE
, &fmppe
);
916 for (lockregion
= first
; lockregion
<= last
; lockregion
++)
917 fmppe
&= ~(1 << lockregion
);
919 /* Clear and disable flash programming interrupts */
920 target_write_u32(target
, FLASH_CIM
, 0);
921 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
923 /* REVISIT this clobbers state set by any halted firmware ...
924 * it might want to process those IRQs.
927 LOG_DEBUG("fmppe 0x%" PRIx32
"", fmppe
);
928 target_write_u32(target
, SCB_BASE
| FMPPE
, fmppe
);
931 target_write_u32(target
, FLASH_FMA
, 1);
933 /* Write commit command */
934 /* REVISIT safety check, since this cannot be undone
935 * except by the "Recover a locked device" procedure.
936 * REVISIT DustDevil-A0 parts have an erratum making FMPPE commits
937 * inadvisable ... it makes future mass erase operations fail.
939 LOG_WARNING("Flash protection cannot be removed once committed, commit is NOT executed !");
940 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
942 /* Wait until erase complete */
944 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
945 } while (flash_fmc
& FMC_COMT
);
947 /* Check acess violations */
948 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
949 if (flash_cris
& (AMASK
)) {
950 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32
"", flash_cris
);
951 target_write_u32(target
, FLASH_CRIS
, 0);
952 return ERROR_FLASH_OPERATION_FAILED
;
958 /* see contib/loaders/flash/stellaris.s for src */
960 static const uint8_t stellaris_write_code
[] = {
964 r1 = destination address
965 r2 = bytecount (in) - endaddr (work)
968 r3 = pFLASH_CTRL_BASE
974 0x07, 0x4B, /* ldr r3,pFLASH_CTRL_BASE */
975 0x08, 0x4C, /* ldr r4,FLASHWRITECMD */
976 0x01, 0x25, /* movs r5, 1 */
977 0x00, 0x26, /* movs r6, #0 */
979 0x19, 0x60, /* str r1, [r3, #0] */
980 0x87, 0x59, /* ldr r7, [r0, r6] */
981 0x5F, 0x60, /* str r7, [r3, #4] */
982 0x9C, 0x60, /* str r4, [r3, #8] */
984 0x9F, 0x68, /* ldr r7, [r3, #8] */
985 0x2F, 0x42, /* tst r7, r5 */
986 0xFC, 0xD1, /* bne waitloop */
987 0x04, 0x31, /* adds r1, r1, #4 */
988 0x04, 0x36, /* adds r6, r6, #4 */
989 0x96, 0x42, /* cmp r6, r2 */
990 0xF4, 0xD1, /* bne mainloop */
991 0x00, 0xBE, /* bkpt #0 */
992 /* pFLASH_CTRL_BASE: */
993 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
995 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
998 static int stellaris_write_block(struct flash_bank
*bank
,
999 uint8_t *buffer
, uint32_t offset
, uint32_t wcount
)
1001 struct target
*target
= bank
->target
;
1002 uint32_t buffer_size
= 16384;
1003 struct working_area
*source
;
1004 struct working_area
*write_algorithm
;
1005 uint32_t address
= bank
->base
+ offset
;
1006 struct reg_param reg_params
[3];
1007 struct armv7m_algorithm armv7m_info
;
1008 int retval
= ERROR_OK
;
1010 /* power of two, and multiple of word size */
1011 static const unsigned buf_min
= 128;
1013 /* for small buffers it's faster not to download an algorithm */
1014 if (wcount
* 4 < buf_min
)
1015 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1017 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" wcount=%08" PRIx32
"",
1018 bank
, buffer
, offset
, wcount
);
1020 /* flash write code */
1021 if (target_alloc_working_area(target
, sizeof(stellaris_write_code
),
1022 &write_algorithm
) != ERROR_OK
) {
1023 LOG_DEBUG("no working area for block memory writes");
1024 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1027 /* plus a buffer big enough for this data */
1028 if (wcount
* 4 < buffer_size
)
1029 buffer_size
= wcount
* 4;
1032 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
1034 if (buffer_size
<= buf_min
) {
1035 target_free_working_area(target
, write_algorithm
);
1036 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1038 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1039 target_name(target
), (unsigned) buffer_size
);
1042 retval
= target_write_buffer(target
, write_algorithm
->address
,
1043 sizeof(stellaris_write_code
),
1044 (uint8_t *) stellaris_write_code
);
1046 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
1047 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
1049 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1050 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1051 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
1053 while (wcount
> 0) {
1054 uint32_t thisrun_count
= (wcount
> (buffer_size
/ 4)) ? (buffer_size
/ 4) : wcount
;
1056 target_write_buffer(target
, source
->address
, thisrun_count
* 4, buffer
);
1058 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
1059 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
1060 buf_set_u32(reg_params
[2].value
, 0, 32, 4*thisrun_count
);
1061 LOG_DEBUG("Algorithm flash write %u words to 0x%" PRIx32
1063 (unsigned) thisrun_count
, address
,
1064 (unsigned) (wcount
- thisrun_count
));
1065 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
1066 write_algorithm
->address
,
1068 10000, &armv7m_info
);
1069 if (retval
!= ERROR_OK
) {
1070 LOG_ERROR("error %d executing stellaris "
1071 "flash write algorithm",
1073 retval
= ERROR_FLASH_OPERATION_FAILED
;
1077 buffer
+= thisrun_count
* 4;
1078 address
+= thisrun_count
* 4;
1079 wcount
-= thisrun_count
;
1082 /* REVISIT we could speed up writing multi-section images by
1083 * not freeing the initialized write_algorithm this way.
1086 target_free_working_area(target
, write_algorithm
);
1087 target_free_working_area(target
, source
);
1089 destroy_reg_param(®_params
[0]);
1090 destroy_reg_param(®_params
[1]);
1091 destroy_reg_param(®_params
[2]);
1096 static int stellaris_write(struct flash_bank
*bank
, uint8_t *buffer
,
1097 uint32_t offset
, uint32_t count
)
1099 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1100 struct target
*target
= bank
->target
;
1101 uint32_t address
= offset
;
1102 uint32_t flash_cris
, flash_fmc
;
1103 uint32_t words_remaining
= (count
/ 4);
1104 uint32_t bytes_remaining
= (count
& 0x00000003);
1105 uint32_t bytes_written
= 0;
1108 if (bank
->target
->state
!= TARGET_HALTED
) {
1109 LOG_ERROR("Target not halted");
1110 return ERROR_TARGET_NOT_HALTED
;
1113 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" count=%08" PRIx32
"",
1114 bank
, buffer
, offset
, count
);
1116 if (stellaris_info
->did1
== 0)
1117 return ERROR_FLASH_BANK_NOT_PROBED
;
1120 LOG_WARNING("offset size must be word aligned");
1121 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1124 if (offset
+ count
> bank
->size
)
1125 return ERROR_FLASH_DST_OUT_OF_BANK
;
1127 /* Refresh flash controller timing */
1128 stellaris_read_clock_info(bank
);
1129 stellaris_set_flash_timing(bank
);
1131 /* Clear and disable flash programming interrupts */
1132 target_write_u32(target
, FLASH_CIM
, 0);
1133 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1135 /* REVISIT this clobbers state set by any halted firmware ...
1136 * it might want to process those IRQs.
1139 /* multiple words to be programmed? */
1140 if (words_remaining
> 0) {
1141 /* try using a block write */
1142 retval
= stellaris_write_block(bank
, buffer
, offset
,
1144 if (retval
!= ERROR_OK
) {
1145 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
1146 LOG_DEBUG("writing flash word-at-a-time");
1147 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
1148 /* if an error occured, we examine the reason, and quit */
1149 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1151 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32
"", flash_cris
);
1152 return ERROR_FLASH_OPERATION_FAILED
;
1155 buffer
+= words_remaining
* 4;
1156 address
+= words_remaining
* 4;
1157 words_remaining
= 0;
1161 while (words_remaining
> 0) {
1162 if (!(address
& 0xff))
1163 LOG_DEBUG("0x%" PRIx32
"", address
);
1165 /* Program one word */
1166 target_write_u32(target
, FLASH_FMA
, address
);
1167 target_write_buffer(target
, FLASH_FMD
, 4, buffer
);
1168 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1169 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1170 /* Wait until write complete */
1172 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1173 } while (flash_fmc
& FMC_WRITE
);
1180 if (bytes_remaining
) {
1181 uint8_t last_word
[4] = {0xff, 0xff, 0xff, 0xff};
1183 /* copy the last remaining bytes into the write buffer */
1184 memcpy(last_word
, buffer
+bytes_written
, bytes_remaining
);
1186 if (!(address
& 0xff))
1187 LOG_DEBUG("0x%" PRIx32
"", address
);
1189 /* Program one word */
1190 target_write_u32(target
, FLASH_FMA
, address
);
1191 target_write_buffer(target
, FLASH_FMD
, 4, last_word
);
1192 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1193 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1194 /* Wait until write complete */
1196 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1197 } while (flash_fmc
& FMC_WRITE
);
1200 /* Check access violations */
1201 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1202 if (flash_cris
& (AMASK
)) {
1203 LOG_DEBUG("flash_cris 0x%" PRIx32
"", flash_cris
);
1204 return ERROR_FLASH_OPERATION_FAILED
;
1209 static int stellaris_probe(struct flash_bank
*bank
)
1211 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1214 /* If this is a stellaris chip, it has flash; probe() is just
1215 * to figure out how much is present. Only do it once.
1217 if (stellaris_info
->did1
!= 0)
1220 /* stellaris_read_part_info() already handled error checking and
1221 * reporting. Note that it doesn't write, so we don't care about
1222 * whether the target is halted or not.
1224 retval
= stellaris_read_part_info(bank
);
1225 if (retval
!= ERROR_OK
)
1228 if (bank
->sectors
) {
1229 free(bank
->sectors
);
1230 bank
->sectors
= NULL
;
1233 /* provide this for the benefit of the NOR flash framework */
1234 bank
->size
= 1024 * stellaris_info
->num_pages
;
1235 bank
->num_sectors
= stellaris_info
->num_pages
;
1236 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
1237 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
1238 bank
->sectors
[i
].offset
= i
* stellaris_info
->pagesize
;
1239 bank
->sectors
[i
].size
= stellaris_info
->pagesize
;
1240 bank
->sectors
[i
].is_erased
= -1;
1241 bank
->sectors
[i
].is_protected
= -1;
1247 static int stellaris_mass_erase(struct flash_bank
*bank
)
1249 struct target
*target
= NULL
;
1250 struct stellaris_flash_bank
*stellaris_info
= NULL
;
1253 stellaris_info
= bank
->driver_priv
;
1254 target
= bank
->target
;
1256 if (target
->state
!= TARGET_HALTED
) {
1257 LOG_ERROR("Target not halted");
1258 return ERROR_TARGET_NOT_HALTED
;
1261 if (stellaris_info
->did1
== 0)
1262 return ERROR_FLASH_BANK_NOT_PROBED
;
1264 /* Refresh flash controller timing */
1265 stellaris_read_clock_info(bank
);
1266 stellaris_set_flash_timing(bank
);
1268 /* Clear and disable flash programming interrupts */
1269 target_write_u32(target
, FLASH_CIM
, 0);
1270 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1272 /* REVISIT this clobbers state set by any halted firmware ...
1273 * it might want to process those IRQs.
1276 target_write_u32(target
, FLASH_FMA
, 0);
1277 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1278 /* Wait until erase complete */
1280 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1281 } while (flash_fmc
& FMC_MERASE
);
1283 /* if device has > 128k, then second erase cycle is needed
1284 * this is only valid for older devices, but will not hurt */
1285 if (stellaris_info
->num_pages
* stellaris_info
->pagesize
> 0x20000) {
1286 target_write_u32(target
, FLASH_FMA
, 0x20000);
1287 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1288 /* Wait until erase complete */
1290 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1291 } while (flash_fmc
& FMC_MERASE
);
1297 COMMAND_HANDLER(stellaris_handle_mass_erase_command
)
1302 return ERROR_COMMAND_SYNTAX_ERROR
;
1304 struct flash_bank
*bank
;
1305 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1306 if (ERROR_OK
!= retval
)
1309 if (stellaris_mass_erase(bank
) == ERROR_OK
) {
1310 /* set all sectors as erased */
1311 for (i
= 0; i
< bank
->num_sectors
; i
++)
1312 bank
->sectors
[i
].is_erased
= 1;
1314 command_print(CMD_CTX
, "stellaris mass erase complete");
1316 command_print(CMD_CTX
, "stellaris mass erase failed");
1322 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1323 * This performs a mass erase and then restores all nonvolatile registers
1324 * (including USER_* registers and flash lock bits) to their defaults.
1325 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1327 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1328 * can affect this operation if flash protection has been enabled.
1330 COMMAND_HANDLER(stellaris_handle_recover_command
)
1332 struct flash_bank
*bank
;
1335 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1336 if (retval
!= ERROR_OK
)
1339 /* REVISIT ... it may be worth sanity checking that the AP is
1340 * inactive before we start. ARM documents that switching a DP's
1341 * mode while it's active can cause fault modes that need a power
1346 if (!(jtag_get_reset_config() & RESET_HAS_SRST
)) {
1347 LOG_ERROR("Can't recover Stellaris flash without SRST");
1350 jtag_add_reset(0, 1);
1352 for (int i
= 0; i
< 5; i
++) {
1353 retval
= dap_to_swd(bank
->target
);
1354 if (retval
!= ERROR_OK
)
1357 retval
= dap_to_jtag(bank
->target
);
1358 if (retval
!= ERROR_OK
)
1362 /* de-assert SRST */
1363 jtag_add_reset(0, 0);
1364 retval
= jtag_execute_queue();
1366 /* wait 400+ msec ... OK, "1+ second" is simpler */
1369 /* USER INTERVENTION required for the power cycle
1370 * Restarting OpenOCD is likely needed because of mode switching.
1372 LOG_INFO("USER ACTION: "
1373 "power cycle Stellaris chip, then restart OpenOCD.");
1379 static const struct command_registration stellaris_exec_command_handlers
[] = {
1381 .name
= "mass_erase",
1383 .handler
= stellaris_handle_mass_erase_command
,
1384 .mode
= COMMAND_EXEC
,
1385 .help
= "erase entire device",
1389 .handler
= stellaris_handle_recover_command
,
1390 .mode
= COMMAND_EXEC
,
1392 .help
= "recover (and erase) locked device",
1394 COMMAND_REGISTRATION_DONE
1396 static const struct command_registration stellaris_command_handlers
[] = {
1398 .name
= "stellaris",
1399 .mode
= COMMAND_EXEC
,
1400 .help
= "Stellaris flash command group",
1402 .chain
= stellaris_exec_command_handlers
,
1404 COMMAND_REGISTRATION_DONE
1407 struct flash_driver stellaris_flash
= {
1408 .name
= "stellaris",
1409 .commands
= stellaris_command_handlers
,
1410 .flash_bank_command
= stellaris_flash_bank_command
,
1411 .erase
= stellaris_erase
,
1412 .protect
= stellaris_protect
,
1413 .write
= stellaris_write
,
1414 .read
= default_flash_read
,
1415 .probe
= stellaris_probe
,
1416 .auto_probe
= stellaris_probe
,
1417 .erase_check
= default_flash_mem_blank_check
,
1418 .protect_check
= stellaris_protect_check
,
1419 .info
= get_stellaris_info
,
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)