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 ***************************************************************************/
32 #include <target/algorithm.h>
33 #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 */
92 static void stellaris_read_clock_info(struct flash_bank
*bank
);
93 static int stellaris_mass_erase(struct flash_bank
*bank
);
95 struct stellaris_flash_bank
97 /* chip id register */
103 const char * target_name
;
110 uint32_t pages_in_lockregion
;
113 uint16_t num_lockbits
;
115 /* main clock status */
122 const char *iosc_desc
;
123 const char *mck_desc
;
126 // Autogenerated by contrib/gen-stellaris-part-header.pl
127 // From Stellaris Firmware Development Package revision 8049
131 const char *partname
;
132 } StellarisParts
[] = {
133 {0x00, 0x01, "LM3S101"},
134 {0x00, 0x02, "LM3S102"},
135 {0x01, 0xBF, "LM3S1110"},
136 {0x01, 0xC3, "LM3S1133"},
137 {0x01, 0xC5, "LM3S1138"},
138 {0x01, 0xC1, "LM3S1150"},
139 {0x01, 0xC4, "LM3S1162"},
140 {0x01, 0xC2, "LM3S1165"},
141 {0x01, 0xEC, "LM3S1166"},
142 {0x01, 0xC6, "LM3S1332"},
143 {0x01, 0xBC, "LM3S1435"},
144 {0x01, 0xBA, "LM3S1439"},
145 {0x01, 0xBB, "LM3S1512"},
146 {0x01, 0xC7, "LM3S1538"},
147 {0x01, 0xDB, "LM3S1601"},
148 {0x03, 0x06, "LM3S1607"},
149 {0x01, 0xDA, "LM3S1608"},
150 {0x01, 0xC0, "LM3S1620"},
151 {0x04, 0xCD, "LM3S1621"},
152 {0x03, 0x03, "LM3S1625"},
153 {0x03, 0x04, "LM3S1626"},
154 {0x03, 0x05, "LM3S1627"},
155 {0x01, 0xB3, "LM3S1635"},
156 {0x01, 0xEB, "LM3S1636"},
157 {0x01, 0xBD, "LM3S1637"},
158 {0x04, 0xB1, "LM3S1651"},
159 {0x01, 0xB9, "LM3S1751"},
160 {0x03, 0x10, "LM3S1776"},
161 {0x04, 0x16, "LM3S1811"},
162 {0x04, 0x3D, "LM3S1816"},
163 {0x01, 0xB4, "LM3S1850"},
164 {0x01, 0xDD, "LM3S1911"},
165 {0x01, 0xDC, "LM3S1918"},
166 {0x01, 0xB7, "LM3S1937"},
167 {0x01, 0xBE, "LM3S1958"},
168 {0x01, 0xB5, "LM3S1960"},
169 {0x01, 0xB8, "LM3S1968"},
170 {0x01, 0xEA, "LM3S1969"},
171 {0x04, 0xCE, "LM3S1B21"},
172 {0x06, 0xCA, "LM3S1C21"},
173 {0x06, 0xCB, "LM3S1C26"},
174 {0x06, 0x98, "LM3S1C58"},
175 {0x06, 0xB0, "LM3S1D21"},
176 {0x06, 0xCC, "LM3S1D26"},
177 {0x06, 0x1D, "LM3S1F11"},
178 {0x06, 0x1B, "LM3S1F16"},
179 {0x06, 0xAF, "LM3S1G21"},
180 {0x06, 0x95, "LM3S1G58"},
181 {0x06, 0x1E, "LM3S1H11"},
182 {0x06, 0x1C, "LM3S1H16"},
183 {0x04, 0x0F, "LM3S1J11"},
184 {0x04, 0x3C, "LM3S1J16"},
185 {0x04, 0x0E, "LM3S1N11"},
186 {0x04, 0x3B, "LM3S1N16"},
187 {0x04, 0xB2, "LM3S1P51"},
188 {0x04, 0x9E, "LM3S1R21"},
189 {0x04, 0xC9, "LM3S1R26"},
190 {0x04, 0x30, "LM3S1W16"},
191 {0x04, 0x2F, "LM3S1Z16"},
192 {0x01, 0xD4, "LM3S2016"},
193 {0x01, 0x51, "LM3S2110"},
194 {0x01, 0x84, "LM3S2139"},
195 {0x03, 0x39, "LM3S2276"},
196 {0x01, 0xA2, "LM3S2410"},
197 {0x01, 0x59, "LM3S2412"},
198 {0x01, 0x56, "LM3S2432"},
199 {0x01, 0x5A, "LM3S2533"},
200 {0x01, 0xE1, "LM3S2601"},
201 {0x01, 0xE0, "LM3S2608"},
202 {0x03, 0x33, "LM3S2616"},
203 {0x01, 0x57, "LM3S2620"},
204 {0x01, 0x85, "LM3S2637"},
205 {0x01, 0x53, "LM3S2651"},
206 {0x03, 0x80, "LM3S2671"},
207 {0x03, 0x50, "LM3S2678"},
208 {0x01, 0xA4, "LM3S2730"},
209 {0x01, 0x52, "LM3S2739"},
210 {0x03, 0x3A, "LM3S2776"},
211 {0x04, 0x6D, "LM3S2793"},
212 {0x01, 0xE3, "LM3S2911"},
213 {0x01, 0xE2, "LM3S2918"},
214 {0x01, 0xED, "LM3S2919"},
215 {0x01, 0x54, "LM3S2939"},
216 {0x01, 0x8F, "LM3S2948"},
217 {0x01, 0x58, "LM3S2950"},
218 {0x01, 0x55, "LM3S2965"},
219 {0x04, 0x6C, "LM3S2B93"},
220 {0x06, 0x94, "LM3S2D93"},
221 {0x06, 0x93, "LM3S2U93"},
222 {0x00, 0x19, "LM3S300"},
223 {0x00, 0x11, "LM3S301"},
224 {0x00, 0x1A, "LM3S308"},
225 {0x00, 0x12, "LM3S310"},
226 {0x00, 0x13, "LM3S315"},
227 {0x00, 0x14, "LM3S316"},
228 {0x00, 0x17, "LM3S317"},
229 {0x00, 0x15, "LM3S328"},
230 {0x03, 0x08, "LM3S3634"},
231 {0x03, 0x43, "LM3S3651"},
232 {0x04, 0xC8, "LM3S3654"},
233 {0x03, 0x44, "LM3S3739"},
234 {0x03, 0x49, "LM3S3748"},
235 {0x03, 0x45, "LM3S3749"},
236 {0x04, 0x42, "LM3S3826"},
237 {0x04, 0x41, "LM3S3J26"},
238 {0x04, 0x40, "LM3S3N26"},
239 {0x04, 0x3F, "LM3S3W26"},
240 {0x04, 0x3E, "LM3S3Z26"},
241 {0x03, 0x81, "LM3S5632"},
242 {0x04, 0x0C, "LM3S5651"},
243 {0x03, 0x8A, "LM3S5652"},
244 {0x04, 0x4D, "LM3S5656"},
245 {0x03, 0x91, "LM3S5662"},
246 {0x03, 0x96, "LM3S5732"},
247 {0x03, 0x97, "LM3S5737"},
248 {0x03, 0xA0, "LM3S5739"},
249 {0x03, 0x99, "LM3S5747"},
250 {0x03, 0xA7, "LM3S5749"},
251 {0x03, 0x9A, "LM3S5752"},
252 {0x03, 0x9C, "LM3S5762"},
253 {0x04, 0x69, "LM3S5791"},
254 {0x04, 0x0B, "LM3S5951"},
255 {0x04, 0x4E, "LM3S5956"},
256 {0x04, 0x68, "LM3S5B91"},
257 {0x06, 0x2E, "LM3S5C31"},
258 {0x06, 0x2C, "LM3S5C36"},
259 {0x06, 0x5E, "LM3S5C51"},
260 {0x06, 0x5B, "LM3S5C56"},
261 {0x06, 0x5F, "LM3S5D51"},
262 {0x06, 0x5C, "LM3S5D56"},
263 {0x06, 0x87, "LM3S5D91"},
264 {0x06, 0x2D, "LM3S5G31"},
265 {0x06, 0x1F, "LM3S5G36"},
266 {0x06, 0x5D, "LM3S5G51"},
267 {0x06, 0x4F, "LM3S5G56"},
268 {0x04, 0x09, "LM3S5K31"},
269 {0x04, 0x4A, "LM3S5K36"},
270 {0x04, 0x0A, "LM3S5P31"},
271 {0x04, 0x48, "LM3S5P36"},
272 {0x04, 0xB6, "LM3S5P3B"},
273 {0x04, 0x0D, "LM3S5P51"},
274 {0x04, 0x4C, "LM3S5P56"},
275 {0x04, 0x07, "LM3S5R31"},
276 {0x04, 0x4B, "LM3S5R36"},
277 {0x04, 0x47, "LM3S5T36"},
278 {0x06, 0x7F, "LM3S5U91"},
279 {0x04, 0x46, "LM3S5Y36"},
280 {0x00, 0x2A, "LM3S600"},
281 {0x00, 0x21, "LM3S601"},
282 {0x00, 0x2B, "LM3S608"},
283 {0x00, 0x22, "LM3S610"},
284 {0x01, 0xA1, "LM3S6100"},
285 {0x00, 0x23, "LM3S611"},
286 {0x01, 0x74, "LM3S6110"},
287 {0x00, 0x24, "LM3S612"},
288 {0x00, 0x25, "LM3S613"},
289 {0x00, 0x26, "LM3S615"},
290 {0x00, 0x28, "LM3S617"},
291 {0x00, 0x29, "LM3S618"},
292 {0x00, 0x27, "LM3S628"},
293 {0x01, 0xA5, "LM3S6420"},
294 {0x01, 0x82, "LM3S6422"},
295 {0x01, 0x75, "LM3S6432"},
296 {0x01, 0x76, "LM3S6537"},
297 {0x01, 0x71, "LM3S6610"},
298 {0x01, 0xE7, "LM3S6611"},
299 {0x01, 0xE6, "LM3S6618"},
300 {0x01, 0x83, "LM3S6633"},
301 {0x01, 0x8B, "LM3S6637"},
302 {0x01, 0xA3, "LM3S6730"},
303 {0x01, 0x77, "LM3S6753"},
304 {0x01, 0xD1, "LM3S6816"},
305 {0x01, 0xE9, "LM3S6911"},
306 {0x01, 0xD3, "LM3S6916"},
307 {0x01, 0xE8, "LM3S6918"},
308 {0x01, 0x89, "LM3S6938"},
309 {0x01, 0x72, "LM3S6950"},
310 {0x01, 0x78, "LM3S6952"},
311 {0x01, 0x73, "LM3S6965"},
312 {0x06, 0xAA, "LM3S6C11"},
313 {0x06, 0xAC, "LM3S6C65"},
314 {0x06, 0x9F, "LM3S6G11"},
315 {0x06, 0xAB, "LM3S6G65"},
316 {0x00, 0x38, "LM3S800"},
317 {0x00, 0x31, "LM3S801"},
318 {0x00, 0x39, "LM3S808"},
319 {0x00, 0x32, "LM3S811"},
320 {0x00, 0x33, "LM3S812"},
321 {0x00, 0x34, "LM3S815"},
322 {0x00, 0x36, "LM3S817"},
323 {0x00, 0x37, "LM3S818"},
324 {0x00, 0x35, "LM3S828"},
325 {0x01, 0x64, "LM3S8530"},
326 {0x01, 0x8E, "LM3S8538"},
327 {0x01, 0x61, "LM3S8630"},
328 {0x01, 0x63, "LM3S8730"},
329 {0x01, 0x8D, "LM3S8733"},
330 {0x01, 0x86, "LM3S8738"},
331 {0x01, 0x65, "LM3S8930"},
332 {0x01, 0x8C, "LM3S8933"},
333 {0x01, 0x88, "LM3S8938"},
334 {0x01, 0xA6, "LM3S8962"},
335 {0x01, 0x62, "LM3S8970"},
336 {0x01, 0xD7, "LM3S8971"},
337 {0x06, 0xAE, "LM3S8C62"},
338 {0x06, 0xAD, "LM3S8G62"},
339 {0x04, 0xCF, "LM3S9781"},
340 {0x04, 0x67, "LM3S9790"},
341 {0x04, 0x6B, "LM3S9792"},
342 {0x04, 0x2D, "LM3S9971"},
343 {0x04, 0x20, "LM3S9997"},
344 {0x04, 0xD0, "LM3S9B81"},
345 {0x04, 0x66, "LM3S9B90"},
346 {0x04, 0x6A, "LM3S9B92"},
347 {0x04, 0x6E, "LM3S9B95"},
348 {0x04, 0x6F, "LM3S9B96"},
349 {0x04, 0x1D, "LM3S9BN2"},
350 {0x04, 0x1E, "LM3S9BN5"},
351 {0x04, 0x1F, "LM3S9BN6"},
352 {0x06, 0x70, "LM3S9C97"},
353 {0x06, 0x7A, "LM3S9CN5"},
354 {0x06, 0xA9, "LM3S9D81"},
355 {0x06, 0x7E, "LM3S9D90"},
356 {0x06, 0x92, "LM3S9D92"},
357 {0x06, 0xC8, "LM3S9D95"},
358 {0x06, 0x9D, "LM3S9D96"},
359 {0x06, 0x7B, "LM3S9DN5"},
360 {0x06, 0x7C, "LM3S9DN6"},
361 {0x06, 0x60, "LM3S9G97"},
362 {0x06, 0x79, "LM3S9GN5"},
363 {0x04, 0x1B, "LM3S9L71"},
364 {0x04, 0x18, "LM3S9L97"},
365 {0x06, 0xA8, "LM3S9U81"},
366 {0x06, 0x7D, "LM3S9U90"},
367 {0x06, 0x90, "LM3S9U92"},
368 {0x06, 0xB7, "LM3S9U95"},
369 {0x06, 0x9B, "LM3S9U96"},
370 {0x05, 0x18, "LM4F110B2QR"},
371 {0x05, 0x19, "LM4F110C4QR"},
372 {0x05, 0x10, "LM4F110E5QR"},
373 {0x05, 0x11, "LM4F110H5QR"},
374 {0x05, 0x22, "LM4F111B2QR"},
375 {0x05, 0x23, "LM4F111C4QR"},
376 {0x05, 0x20, "LM4F111E5QR"},
377 {0x05, 0x21, "LM4F111H5QR"},
378 {0x05, 0x36, "LM4F112C4QC"},
379 {0x05, 0x30, "LM4F112E5QC"},
380 {0x05, 0x31, "LM4F112H5QC"},
381 {0x05, 0x35, "LM4F112H5QD"},
382 {0x05, 0x01, "LM4F120B2QR"},
383 {0x05, 0x02, "LM4F120C4QR"},
384 {0x05, 0x03, "LM4F120E5QR"},
385 {0x05, 0x04, "LM4F120H5QR"},
386 {0x05, 0x08, "LM4F121B2QR"},
387 {0x05, 0x09, "LM4F121C4QR"},
388 {0x05, 0x0A, "LM4F121E5QR"},
389 {0x05, 0x0B, "LM4F121H5QR"},
390 {0x05, 0xD0, "LM4F122C4QC"},
391 {0x05, 0xD1, "LM4F122E5QC"},
392 {0x05, 0xD2, "LM4F122H5QC"},
393 {0x05, 0xD6, "LM4F122H5QD"},
394 {0x05, 0x48, "LM4F130C4QR"},
395 {0x05, 0x40, "LM4F130E5QR"},
396 {0x05, 0x41, "LM4F130H5QR"},
397 {0x05, 0x52, "LM4F131C4QR"},
398 {0x05, 0x50, "LM4F131E5QR"},
399 {0x05, 0x51, "LM4F131H5QR"},
400 {0x05, 0x66, "LM4F132C4QC"},
401 {0x05, 0x60, "LM4F132E5QC"},
402 {0x05, 0x61, "LM4F132H5QC"},
403 {0x05, 0x65, "LM4F132H5QD"},
404 {0x05, 0xA0, "LM4F230E5QR"},
405 {0x05, 0xA1, "LM4F230H5QR"},
406 {0x05, 0xB0, "LM4F231E5QR"},
407 {0x05, 0xB1, "LM4F231H5QR"},
408 {0x05, 0xC0, "LM4F232E5QC"},
409 {0x05, 0xE3, "LM4F232H5BB"},
410 {0x05, 0xC1, "LM4F232H5QC"},
411 {0x05, 0xC5, "LM4F232H5QD"},
412 {0x05, 0xE5, "LM4FS1AH5BB"},
413 {0x05, 0xE4, "LM4FS99H5BB"},
414 {0x05, 0xE0, "LM4FSXAH5BB"},
415 {0xFF, 0x00, "Unknown Part"}
418 static char * StellarisClassname
[7] =
429 /***************************************************************************
430 * openocd command interface *
431 ***************************************************************************/
433 /* flash_bank stellaris <base> <size> 0 0 <target#>
435 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command
)
437 struct stellaris_flash_bank
*stellaris_info
;
441 LOG_WARNING("incomplete flash_bank stellaris configuration");
442 return ERROR_FLASH_BANK_INVALID
;
445 stellaris_info
= calloc(sizeof(struct stellaris_flash_bank
), 1);
447 bank
->driver_priv
= stellaris_info
;
449 stellaris_info
->target_name
= "Unknown target";
451 /* part wasn't probed for info yet */
452 stellaris_info
->did1
= 0;
454 /* TODO Specify the main crystal speed in kHz using an optional
455 * argument; ditto, the speed of an external oscillator used
456 * instead of a crystal. Avoid programming flash using IOSC.
461 static int get_stellaris_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
463 int printed
, device_class
;
464 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
466 if (stellaris_info
->did1
== 0)
467 return ERROR_FLASH_BANK_NOT_PROBED
;
469 /* Read main and master clock freqency register */
470 stellaris_read_clock_info(bank
);
472 if (DID0_VER(stellaris_info
->did0
) > 0)
474 device_class
= (stellaris_info
->did0
>> 16) & 0xFF;
480 printed
= snprintf(buf
,
482 "\nTI/LMI Stellaris information: Chip is "
483 "class %i (%s) %s rev %c%i\n",
485 StellarisClassname
[device_class
],
486 stellaris_info
->target_name
,
487 (int)('A' + ((stellaris_info
->did0
>> 8) & 0xFF)),
488 (int)((stellaris_info
->did0
) & 0xFF));
492 printed
= snprintf(buf
,
494 "did1: 0x%8.8" PRIx32
", arch: 0x%4.4" PRIx32
495 ", eproc: %s, ramsize: %ik, flashsize: %ik\n",
496 stellaris_info
->did1
,
497 stellaris_info
->did1
,
499 (int)((1 + ((stellaris_info
->dc0
>> 16) & 0xFFFF))/4),
500 (int)((1 + (stellaris_info
->dc0
& 0xFFFF))*2));
504 printed
= snprintf(buf
,
506 "master clock: %ikHz%s, "
507 "rcc is 0x%" PRIx32
", rcc2 is 0x%" PRIx32
"\n",
508 (int)(stellaris_info
->mck_freq
/ 1000),
509 stellaris_info
->mck_desc
,
511 stellaris_info
->rcc2
);
515 if (stellaris_info
->num_lockbits
> 0)
517 printed
= snprintf(buf
,
519 "pagesize: %" PRIi32
", pages: %d, "
520 "lockbits: %i, pages per lockbit: %i\n",
521 stellaris_info
->pagesize
,
522 (unsigned) stellaris_info
->num_pages
,
523 stellaris_info
->num_lockbits
,
524 (unsigned) stellaris_info
->pages_in_lockregion
);
531 /***************************************************************************
532 * chip identification and status *
533 ***************************************************************************/
535 /* Set the flash timimg register to match current clocking */
536 static void stellaris_set_flash_timing(struct flash_bank
*bank
)
538 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
539 struct target
*target
= bank
->target
;
540 uint32_t usecrl
= (stellaris_info
->mck_freq
/1000000ul-1);
542 LOG_DEBUG("usecrl = %i",(int)(usecrl
));
543 target_write_u32(target
, SCB_BASE
| USECRL
, usecrl
);
546 static const unsigned rcc_xtal
[32] = {
547 [0x00] = 1000000, /* no pll */
548 [0x01] = 1843200, /* no pll */
549 [0x02] = 2000000, /* no pll */
550 [0x03] = 2457600, /* no pll */
554 [0x06] = 4000000, /* usb */
558 [0x09] = 5000000, /* usb */
560 [0x0b] = 6000000, /* (reset) usb */
564 [0x0e] = 8000000, /* usb */
567 /* parts before DustDevil use just 4 bits for xtal spec */
569 [0x10] = 10000000, /* usb */
570 [0x11] = 12000000, /* usb */
575 [0x15] = 16000000, /* usb */
579 /** Read clock configuration and set stellaris_info->usec_clocks. */
580 static void stellaris_read_clock_info(struct flash_bank
*bank
)
582 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
583 struct target
*target
= bank
->target
;
584 uint32_t rcc
, rcc2
, pllcfg
, sysdiv
, usesysdiv
, bypass
, oscsrc
;
586 unsigned long mainfreq
;
588 target_read_u32(target
, SCB_BASE
| RCC
, &rcc
);
589 LOG_DEBUG("Stellaris RCC %" PRIx32
"", rcc
);
591 target_read_u32(target
, SCB_BASE
| RCC2
, &rcc2
);
592 LOG_DEBUG("Stellaris RCC2 %" PRIx32
"", rcc
);
594 target_read_u32(target
, SCB_BASE
| PLLCFG
, &pllcfg
);
595 LOG_DEBUG("Stellaris PLLCFG %" PRIx32
"", pllcfg
);
597 stellaris_info
->rcc
= rcc
;
598 stellaris_info
->rcc
= rcc2
;
600 sysdiv
= (rcc
>> 23) & 0xF;
601 usesysdiv
= (rcc
>> 22) & 0x1;
602 bypass
= (rcc
>> 11) & 0x1;
603 oscsrc
= (rcc
>> 4) & 0x3;
604 xtal
= (rcc
>> 6) & stellaris_info
->xtal_mask
;
606 /* NOTE: post-Sandstorm parts have RCC2 which may override
607 * parts of RCC ... with more sysdiv options, option for
608 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
609 * as zero, so the "use RCC2" flag is always clear.
611 if (rcc2
& (1 << 31)) {
612 sysdiv
= (rcc2
>> 23) & 0x3F;
613 bypass
= (rcc2
>> 11) & 0x1;
614 oscsrc
= (rcc2
>> 4) & 0x7;
616 /* FIXME Tempest parts have an additional lsb for
617 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
621 stellaris_info
->mck_desc
= "";
626 mainfreq
= rcc_xtal
[xtal
];
629 mainfreq
= stellaris_info
->iosc_freq
;
630 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
633 mainfreq
= stellaris_info
->iosc_freq
/ 4;
634 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
636 case 3: /* lowspeed */
637 /* Sandstorm doesn't have this 30K +/- 30% osc */
639 stellaris_info
->mck_desc
= " (±30%)";
641 case 8: /* hibernation osc */
642 /* not all parts support hibernation */
646 default: /* NOTREACHED */
651 /* PLL is used if it's not bypassed; its output is 200 MHz
652 * even when it runs at 400 MHz (adds divide-by-two stage).
655 mainfreq
= 200000000;
658 stellaris_info
->mck_freq
= mainfreq
/(1 + sysdiv
);
660 stellaris_info
->mck_freq
= mainfreq
;
663 /* Read device id register, main clock frequency register and fill in driver info structure */
664 static int stellaris_read_part_info(struct flash_bank
*bank
)
666 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
667 struct target
*target
= bank
->target
;
668 uint32_t did0
, did1
, ver
, fam
;
671 /* Read and parse chip identification register */
672 target_read_u32(target
, SCB_BASE
| DID0
, &did0
);
673 target_read_u32(target
, SCB_BASE
| DID1
, &did1
);
674 target_read_u32(target
, SCB_BASE
| DC0
, &stellaris_info
->dc0
);
675 target_read_u32(target
, SCB_BASE
| DC1
, &stellaris_info
->dc1
);
676 LOG_DEBUG("did0 0x%" PRIx32
", did1 0x%" PRIx32
", dc0 0x%" PRIx32
", dc1 0x%" PRIx32
"",
677 did0
, did1
, stellaris_info
->dc0
, stellaris_info
->dc1
);
680 if ((ver
!= 0) && (ver
!= 1))
682 LOG_WARNING("Unknown did0 version, cannot identify target");
683 return ERROR_FLASH_OPERATION_FAILED
;
688 LOG_WARNING("Cannot identify target as a Stellaris");
689 return ERROR_FLASH_OPERATION_FAILED
;
693 fam
= (did1
>> 24) & 0xF;
694 if (((ver
!= 0) && (ver
!= 1)) || (fam
!= 0))
696 LOG_WARNING("Unknown did1 version/family.");
697 return ERROR_FLASH_OPERATION_FAILED
;
700 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
701 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
702 * even give _both_ numbers! We'll use current numbers; IOSC is
703 * always approximate.
705 * For Tempest: IOSC is calibrated, 16 MHz
707 stellaris_info
->iosc_freq
= 12000000;
708 stellaris_info
->iosc_desc
= " (±30%)";
709 stellaris_info
->xtal_mask
= 0x0f;
711 switch ((did0
>> 28) & 0x7) {
712 case 0: /* Sandstorm */
714 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
715 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
716 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
718 if (((did0
>> 8) & 0xff) < 2) {
719 stellaris_info
->iosc_freq
= 15000000;
720 stellaris_info
->iosc_desc
= " (±50%)";
724 switch ((did0
>> 16) & 0xff) {
727 case 4: /* Tempest */
728 stellaris_info
->iosc_freq
= 16000000; /* +/- 1% */
729 stellaris_info
->iosc_desc
= " (±1%)";
731 case 3: /* DustDevil */
732 stellaris_info
->xtal_mask
= 0x1f;
735 LOG_WARNING("Unknown did0 class");
739 LOG_WARNING("Unknown did0 version");
743 for (i
= 0; StellarisParts
[i
].partno
; i
++)
745 if ((StellarisParts
[i
].partno
== ((did1
>> 16) & 0xFF)) &&
746 (StellarisParts
[i
].class == ((did0
>> 16) & 0xFF)))
750 stellaris_info
->target_name
= StellarisParts
[i
].partname
;
752 stellaris_info
->did0
= did0
;
753 stellaris_info
->did1
= did1
;
755 stellaris_info
->num_lockbits
= 1 + (stellaris_info
->dc0
& 0xFFFF);
756 stellaris_info
->num_pages
= 2 *(1 + (stellaris_info
->dc0
& 0xFFFF));
757 stellaris_info
->pagesize
= 1024;
758 stellaris_info
->pages_in_lockregion
= 2;
760 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
761 * That exposes a 32-word Flash Write Buffer ... enabling
762 * writes of more than one word at a time.
768 /***************************************************************************
770 ***************************************************************************/
772 static int stellaris_protect_check(struct flash_bank
*bank
)
774 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
775 int status
= ERROR_OK
;
779 if (stellaris
->did1
== 0)
780 return ERROR_FLASH_BANK_NOT_PROBED
;
782 for (i
= 0; i
< (unsigned) bank
->num_sectors
; i
++)
783 bank
->sectors
[i
].is_protected
= -1;
785 /* Read each Flash Memory Protection Program Enable (FMPPE) register
786 * to report any pages that we can't write. Ignore the Read Enable
789 for (i
= 0, page
= 0;
790 i
< DIV_ROUND_UP(stellaris
->num_lockbits
, 32u);
794 status
= target_read_u32(bank
->target
,
795 SCB_BASE
+ (i
? (FMPPE0
+ 4 * i
) : FMPPE
),
797 LOG_DEBUG("FMPPE%d = %#8.8x (status %d)", i
,
798 (unsigned) lockbits
, status
);
799 if (status
!= ERROR_OK
)
802 for (unsigned j
= 0; j
< 32; j
++) {
805 for (k
= 0; k
< stellaris
->pages_in_lockregion
; k
++) {
806 if (page
>= (unsigned) bank
->num_sectors
)
808 bank
->sectors
[page
++].is_protected
=
809 !(lockbits
& (1 << j
));
818 static int stellaris_erase(struct flash_bank
*bank
, int first
, int last
)
821 uint32_t flash_fmc
, flash_cris
;
822 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
823 struct target
*target
= bank
->target
;
825 if (bank
->target
->state
!= TARGET_HALTED
)
827 LOG_ERROR("Target not halted");
828 return ERROR_TARGET_NOT_HALTED
;
831 if (stellaris_info
->did1
== 0)
832 return ERROR_FLASH_BANK_NOT_PROBED
;
834 if ((first
< 0) || (last
< first
) || (last
>= (int)stellaris_info
->num_pages
))
836 return ERROR_FLASH_SECTOR_INVALID
;
839 if ((first
== 0) && (last
== ((int)stellaris_info
->num_pages
-1)))
841 return stellaris_mass_erase(bank
);
844 /* Refresh flash controller timing */
845 stellaris_read_clock_info(bank
);
846 stellaris_set_flash_timing(bank
);
848 /* Clear and disable flash programming interrupts */
849 target_write_u32(target
, FLASH_CIM
, 0);
850 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
852 /* REVISIT this clobbers state set by any halted firmware ...
853 * it might want to process those IRQs.
856 for (banknr
= first
; banknr
<= last
; banknr
++)
858 /* Address is first word in page */
859 target_write_u32(target
, FLASH_FMA
, banknr
* stellaris_info
->pagesize
);
860 /* Write erase command */
861 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_ERASE
);
862 /* Wait until erase complete */
865 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
867 while (flash_fmc
& FMC_ERASE
);
869 /* Check acess violations */
870 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
871 if (flash_cris
& (AMASK
))
873 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32
"", banknr
, flash_cris
);
874 target_write_u32(target
, FLASH_CRIS
, 0);
875 return ERROR_FLASH_OPERATION_FAILED
;
878 bank
->sectors
[banknr
].is_erased
= 1;
884 static int stellaris_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
886 uint32_t fmppe
, flash_fmc
, flash_cris
;
889 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
890 struct target
*target
= bank
->target
;
892 if (bank
->target
->state
!= TARGET_HALTED
)
894 LOG_ERROR("Target not halted");
895 return ERROR_TARGET_NOT_HALTED
;
900 LOG_ERROR("Hardware doesn't support page-level unprotect. "
901 "Try the 'recover' command.");
902 return ERROR_INVALID_ARGUMENTS
;
905 if (stellaris_info
->did1
== 0)
906 return ERROR_FLASH_BANK_NOT_PROBED
;
908 /* lockregions are 2 pages ... must protect [even..odd] */
909 if ((first
< 0) || (first
& 1)
910 || (last
< first
) || !(last
& 1)
911 || (last
>= 2 * stellaris_info
->num_lockbits
))
913 LOG_ERROR("Can't protect unaligned or out-of-range pages.");
914 return ERROR_FLASH_SECTOR_INVALID
;
917 /* Refresh flash controller timing */
918 stellaris_read_clock_info(bank
);
919 stellaris_set_flash_timing(bank
);
921 /* convert from pages to lockregions */
925 /* FIXME this assumes single FMPPE, for a max of 64K of flash!!
926 * Current parts can be much bigger.
929 LOG_ERROR("No support yet for protection > 64K");
930 return ERROR_FLASH_OPERATION_FAILED
;
933 target_read_u32(target
, SCB_BASE
| FMPPE
, &fmppe
);
935 for (lockregion
= first
; lockregion
<= last
; lockregion
++)
936 fmppe
&= ~(1 << lockregion
);
938 /* Clear and disable flash programming interrupts */
939 target_write_u32(target
, FLASH_CIM
, 0);
940 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
942 /* REVISIT this clobbers state set by any halted firmware ...
943 * it might want to process those IRQs.
946 LOG_DEBUG("fmppe 0x%" PRIx32
"",fmppe
);
947 target_write_u32(target
, SCB_BASE
| FMPPE
, fmppe
);
950 target_write_u32(target
, FLASH_FMA
, 1);
952 /* Write commit command */
953 /* REVISIT safety check, since this cannot be undone
954 * except by the "Recover a locked device" procedure.
955 * REVISIT DustDevil-A0 parts have an erratum making FMPPE commits
956 * inadvisable ... it makes future mass erase operations fail.
958 LOG_WARNING("Flash protection cannot be removed once committed, commit is NOT executed !");
959 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
961 /* Wait until erase complete */
964 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
966 while (flash_fmc
& FMC_COMT
);
968 /* Check acess violations */
969 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
970 if (flash_cris
& (AMASK
))
972 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32
"", flash_cris
);
973 target_write_u32(target
, FLASH_CRIS
, 0);
974 return ERROR_FLASH_OPERATION_FAILED
;
980 /* see contib/loaders/flash/stellaris.s for src */
982 static const uint8_t stellaris_write_code
[] =
987 r1 = destination address
988 r2 = bytecount (in) - endaddr (work)
991 r3 = pFLASH_CTRL_BASE
997 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
998 0x08,0x4C, /* ldr r4,FLASHWRITECMD */
999 0x01,0x25, /* movs r5, 1 */
1000 0x00,0x26, /* movs r6, #0 */
1002 0x19,0x60, /* str r1, [r3, #0] */
1003 0x87,0x59, /* ldr r7, [r0, r6] */
1004 0x5F,0x60, /* str r7, [r3, #4] */
1005 0x9C,0x60, /* str r4, [r3, #8] */
1007 0x9F,0x68, /* ldr r7, [r3, #8] */
1008 0x2F,0x42, /* tst r7, r5 */
1009 0xFC,0xD1, /* bne waitloop */
1010 0x04,0x31, /* adds r1, r1, #4 */
1011 0x04,0x36, /* adds r6, r6, #4 */
1012 0x96,0x42, /* cmp r6, r2 */
1013 0xF4,0xD1, /* bne mainloop */
1014 0x00,0xBE, /* bkpt #0 */
1015 /* pFLASH_CTRL_BASE: */
1016 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
1017 /* FLASHWRITECMD: */
1018 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
1021 static int stellaris_write_block(struct flash_bank
*bank
,
1022 uint8_t *buffer
, uint32_t offset
, uint32_t wcount
)
1024 struct target
*target
= bank
->target
;
1025 uint32_t buffer_size
= 16384;
1026 struct working_area
*source
;
1027 struct working_area
*write_algorithm
;
1028 uint32_t address
= bank
->base
+ offset
;
1029 struct reg_param reg_params
[3];
1030 struct armv7m_algorithm armv7m_info
;
1031 int retval
= ERROR_OK
;
1033 /* power of two, and multiple of word size */
1034 static const unsigned buf_min
= 128;
1036 /* for small buffers it's faster not to download an algorithm */
1037 if (wcount
* 4 < buf_min
)
1038 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1040 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" wcount=%08" PRIx32
"",
1041 bank
, buffer
, offset
, wcount
);
1043 /* flash write code */
1044 if (target_alloc_working_area(target
, sizeof(stellaris_write_code
), &write_algorithm
) != ERROR_OK
)
1046 LOG_DEBUG("no working area for block memory writes");
1047 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1050 /* plus a buffer big enough for this data */
1051 if (wcount
* 4 < buffer_size
)
1052 buffer_size
= wcount
* 4;
1055 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
)
1058 if (buffer_size
<= buf_min
)
1060 target_free_working_area(target
, write_algorithm
);
1061 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1063 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1064 target_name(target
), (unsigned) buffer_size
);
1067 retval
= target_write_buffer(target
, write_algorithm
->address
,
1068 sizeof(stellaris_write_code
),
1069 (uint8_t *) stellaris_write_code
);
1071 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
1072 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
1074 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1075 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1076 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
1080 uint32_t thisrun_count
= (wcount
> (buffer_size
/ 4)) ? (buffer_size
/ 4) : wcount
;
1082 target_write_buffer(target
, source
->address
, thisrun_count
* 4, buffer
);
1084 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
1085 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
1086 buf_set_u32(reg_params
[2].value
, 0, 32, 4*thisrun_count
);
1087 LOG_DEBUG("Algorithm flash write %u words to 0x%" PRIx32
1089 (unsigned) thisrun_count
, address
,
1090 (unsigned) (wcount
- thisrun_count
));
1091 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
1092 write_algorithm
->address
,
1094 10000, &armv7m_info
);
1095 if (retval
!= ERROR_OK
)
1097 LOG_ERROR("error %d executing stellaris "
1098 "flash write algorithm",
1100 retval
= ERROR_FLASH_OPERATION_FAILED
;
1104 buffer
+= thisrun_count
* 4;
1105 address
+= thisrun_count
* 4;
1106 wcount
-= thisrun_count
;
1109 /* REVISIT we could speed up writing multi-section images by
1110 * not freeing the initialized write_algorithm this way.
1113 target_free_working_area(target
, write_algorithm
);
1114 target_free_working_area(target
, source
);
1116 destroy_reg_param(®_params
[0]);
1117 destroy_reg_param(®_params
[1]);
1118 destroy_reg_param(®_params
[2]);
1123 static int stellaris_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
1125 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1126 struct target
*target
= bank
->target
;
1127 uint32_t address
= offset
;
1128 uint32_t flash_cris
, flash_fmc
;
1129 uint32_t words_remaining
= (count
/ 4);
1130 uint32_t bytes_remaining
= (count
& 0x00000003);
1131 uint32_t bytes_written
= 0;
1134 if (bank
->target
->state
!= TARGET_HALTED
)
1136 LOG_ERROR("Target not halted");
1137 return ERROR_TARGET_NOT_HALTED
;
1140 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" count=%08" PRIx32
"",
1141 bank
, buffer
, offset
, count
);
1143 if (stellaris_info
->did1
== 0)
1144 return ERROR_FLASH_BANK_NOT_PROBED
;
1148 LOG_WARNING("offset size must be word aligned");
1149 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1152 if (offset
+ count
> bank
->size
)
1153 return ERROR_FLASH_DST_OUT_OF_BANK
;
1155 /* Refresh flash controller timing */
1156 stellaris_read_clock_info(bank
);
1157 stellaris_set_flash_timing(bank
);
1159 /* Clear and disable flash programming interrupts */
1160 target_write_u32(target
, FLASH_CIM
, 0);
1161 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1163 /* REVISIT this clobbers state set by any halted firmware ...
1164 * it might want to process those IRQs.
1167 /* multiple words to be programmed? */
1168 if (words_remaining
> 0)
1170 /* try using a block write */
1171 retval
= stellaris_write_block(bank
, buffer
, offset
,
1173 if (retval
!= ERROR_OK
)
1175 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
1177 LOG_DEBUG("writing flash word-at-a-time");
1179 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
1181 /* if an error occured, we examine the reason, and quit */
1182 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1184 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32
"", flash_cris
);
1185 return ERROR_FLASH_OPERATION_FAILED
;
1190 buffer
+= words_remaining
* 4;
1191 address
+= words_remaining
* 4;
1192 words_remaining
= 0;
1196 while (words_remaining
> 0)
1198 if (!(address
& 0xff))
1199 LOG_DEBUG("0x%" PRIx32
"", address
);
1201 /* Program one word */
1202 target_write_u32(target
, FLASH_FMA
, address
);
1203 target_write_buffer(target
, FLASH_FMD
, 4, buffer
);
1204 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1205 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1206 /* Wait until write complete */
1209 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1210 } while (flash_fmc
& FMC_WRITE
);
1217 if (bytes_remaining
)
1219 uint8_t last_word
[4] = {0xff, 0xff, 0xff, 0xff};
1222 while (bytes_remaining
> 0)
1224 last_word
[i
++] = *(buffer
+ bytes_written
);
1229 if (!(address
& 0xff))
1230 LOG_DEBUG("0x%" PRIx32
"", address
);
1232 /* Program one word */
1233 target_write_u32(target
, FLASH_FMA
, address
);
1234 target_write_buffer(target
, FLASH_FMD
, 4, last_word
);
1235 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1236 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1237 /* Wait until write complete */
1240 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1241 } while (flash_fmc
& FMC_WRITE
);
1244 /* Check access violations */
1245 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1246 if (flash_cris
& (AMASK
))
1248 LOG_DEBUG("flash_cris 0x%" PRIx32
"", flash_cris
);
1249 return ERROR_FLASH_OPERATION_FAILED
;
1254 static int stellaris_probe(struct flash_bank
*bank
)
1256 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1259 /* If this is a stellaris chip, it has flash; probe() is just
1260 * to figure out how much is present. Only do it once.
1262 if (stellaris_info
->did1
!= 0)
1265 /* stellaris_read_part_info() already handled error checking and
1266 * reporting. Note that it doesn't write, so we don't care about
1267 * whether the target is halted or not.
1269 retval
= stellaris_read_part_info(bank
);
1270 if (retval
!= ERROR_OK
)
1275 free(bank
->sectors
);
1276 bank
->sectors
= NULL
;
1279 /* provide this for the benefit of the NOR flash framework */
1280 bank
->size
= 1024 * stellaris_info
->num_pages
;
1281 bank
->num_sectors
= stellaris_info
->num_pages
;
1282 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
1283 for (int i
= 0; i
< bank
->num_sectors
; i
++)
1285 bank
->sectors
[i
].offset
= i
* stellaris_info
->pagesize
;
1286 bank
->sectors
[i
].size
= stellaris_info
->pagesize
;
1287 bank
->sectors
[i
].is_erased
= -1;
1288 bank
->sectors
[i
].is_protected
= -1;
1294 static int stellaris_mass_erase(struct flash_bank
*bank
)
1296 struct target
*target
= NULL
;
1297 struct stellaris_flash_bank
*stellaris_info
= NULL
;
1300 stellaris_info
= bank
->driver_priv
;
1301 target
= bank
->target
;
1303 if (target
->state
!= TARGET_HALTED
)
1305 LOG_ERROR("Target not halted");
1306 return ERROR_TARGET_NOT_HALTED
;
1309 if (stellaris_info
->did1
== 0)
1310 return ERROR_FLASH_BANK_NOT_PROBED
;
1312 /* Refresh flash controller timing */
1313 stellaris_read_clock_info(bank
);
1314 stellaris_set_flash_timing(bank
);
1316 /* Clear and disable flash programming interrupts */
1317 target_write_u32(target
, FLASH_CIM
, 0);
1318 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1320 /* REVISIT this clobbers state set by any halted firmware ...
1321 * it might want to process those IRQs.
1324 target_write_u32(target
, FLASH_FMA
, 0);
1325 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1326 /* Wait until erase complete */
1329 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1331 while (flash_fmc
& FMC_MERASE
);
1333 /* if device has > 128k, then second erase cycle is needed
1334 * this is only valid for older devices, but will not hurt */
1335 if (stellaris_info
->num_pages
* stellaris_info
->pagesize
> 0x20000)
1337 target_write_u32(target
, FLASH_FMA
, 0x20000);
1338 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1339 /* Wait until erase complete */
1342 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1344 while (flash_fmc
& FMC_MERASE
);
1350 COMMAND_HANDLER(stellaris_handle_mass_erase_command
)
1356 command_print(CMD_CTX
, "stellaris mass_erase <bank>");
1360 struct flash_bank
*bank
;
1361 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1362 if (ERROR_OK
!= retval
)
1365 if (stellaris_mass_erase(bank
) == ERROR_OK
)
1367 /* set all sectors as erased */
1368 for (i
= 0; i
< bank
->num_sectors
; i
++)
1370 bank
->sectors
[i
].is_erased
= 1;
1373 command_print(CMD_CTX
, "stellaris mass erase complete");
1377 command_print(CMD_CTX
, "stellaris mass erase failed");
1384 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1385 * This performs a mass erase and then restores all nonvolatile registers
1386 * (including USER_* registers and flash lock bits) to their defaults.
1387 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1389 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1390 * can affect this operation if flash protection has been enabled.
1392 COMMAND_HANDLER(stellaris_handle_recover_command
)
1394 struct flash_bank
*bank
;
1397 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1398 if (retval
!= ERROR_OK
)
1401 /* REVISIT ... it may be worth sanity checking that the AP is
1402 * inactive before we start. ARM documents that switching a DP's
1403 * mode while it's active can cause fault modes that need a power
1408 if (!(jtag_get_reset_config() & RESET_HAS_SRST
)) {
1409 LOG_ERROR("Can't recover Stellaris flash without SRST");
1412 jtag_add_reset(0, 1);
1414 for (int i
= 0; i
< 5; i
++) {
1415 retval
= dap_to_swd(bank
->target
);
1416 if (retval
!= ERROR_OK
)
1419 retval
= dap_to_jtag(bank
->target
);
1420 if (retval
!= ERROR_OK
)
1424 /* de-assert SRST */
1425 jtag_add_reset(0, 0);
1426 retval
= jtag_execute_queue();
1428 /* wait 400+ msec ... OK, "1+ second" is simpler */
1431 /* USER INTERVENTION required for the power cycle
1432 * Restarting OpenOCD is likely needed because of mode switching.
1434 LOG_INFO("USER ACTION: "
1435 "power cycle Stellaris chip, then restart OpenOCD.");
1441 static const struct command_registration stellaris_exec_command_handlers
[] = {
1443 .name
= "mass_erase",
1444 .handler
= stellaris_handle_mass_erase_command
,
1445 .mode
= COMMAND_EXEC
,
1447 .help
= "erase entire device",
1451 .handler
= stellaris_handle_recover_command
,
1452 .mode
= COMMAND_EXEC
,
1454 .help
= "recover (and erase) locked device",
1456 COMMAND_REGISTRATION_DONE
1458 static const struct command_registration stellaris_command_handlers
[] = {
1460 .name
= "stellaris",
1461 .mode
= COMMAND_EXEC
,
1462 .help
= "Stellaris flash command group",
1463 .chain
= stellaris_exec_command_handlers
,
1465 COMMAND_REGISTRATION_DONE
1468 struct flash_driver stellaris_flash
= {
1469 .name
= "stellaris",
1470 .commands
= stellaris_command_handlers
,
1471 .flash_bank_command
= stellaris_flash_bank_command
,
1472 .erase
= stellaris_erase
,
1473 .protect
= stellaris_protect
,
1474 .write
= stellaris_write
,
1475 .read
= default_flash_read
,
1476 .probe
= stellaris_probe
,
1477 .auto_probe
= stellaris_probe
,
1478 .erase_check
= default_flash_mem_blank_check
,
1479 .protect_check
= stellaris_protect_check
,
1480 .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)