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)
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
);
529 /***************************************************************************
530 * chip identification and status *
531 ***************************************************************************/
533 /* Set the flash timimg register to match current clocking */
534 static void stellaris_set_flash_timing(struct flash_bank
*bank
)
536 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
537 struct target
*target
= bank
->target
;
538 uint32_t usecrl
= (stellaris_info
->mck_freq
/1000000ul-1);
540 LOG_DEBUG("usecrl = %i",(int)(usecrl
));
541 target_write_u32(target
, SCB_BASE
| USECRL
, usecrl
);
544 static const unsigned rcc_xtal
[32] = {
545 [0x00] = 1000000, /* no pll */
546 [0x01] = 1843200, /* no pll */
547 [0x02] = 2000000, /* no pll */
548 [0x03] = 2457600, /* no pll */
552 [0x06] = 4000000, /* usb */
556 [0x09] = 5000000, /* usb */
558 [0x0b] = 6000000, /* (reset) usb */
562 [0x0e] = 8000000, /* usb */
565 /* parts before DustDevil use just 4 bits for xtal spec */
567 [0x10] = 10000000, /* usb */
568 [0x11] = 12000000, /* usb */
573 [0x15] = 16000000, /* usb */
577 /** Read clock configuration and set stellaris_info->usec_clocks. */
578 static void stellaris_read_clock_info(struct flash_bank
*bank
)
580 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
581 struct target
*target
= bank
->target
;
582 uint32_t rcc
, rcc2
, pllcfg
, sysdiv
, usesysdiv
, bypass
, oscsrc
;
584 unsigned long mainfreq
;
586 target_read_u32(target
, SCB_BASE
| RCC
, &rcc
);
587 LOG_DEBUG("Stellaris RCC %" PRIx32
"", rcc
);
589 target_read_u32(target
, SCB_BASE
| RCC2
, &rcc2
);
590 LOG_DEBUG("Stellaris RCC2 %" PRIx32
"", rcc
);
592 target_read_u32(target
, SCB_BASE
| PLLCFG
, &pllcfg
);
593 LOG_DEBUG("Stellaris PLLCFG %" PRIx32
"", pllcfg
);
595 stellaris_info
->rcc
= rcc
;
596 stellaris_info
->rcc
= rcc2
;
598 sysdiv
= (rcc
>> 23) & 0xF;
599 usesysdiv
= (rcc
>> 22) & 0x1;
600 bypass
= (rcc
>> 11) & 0x1;
601 oscsrc
= (rcc
>> 4) & 0x3;
602 xtal
= (rcc
>> 6) & stellaris_info
->xtal_mask
;
604 /* NOTE: post-Sandstorm parts have RCC2 which may override
605 * parts of RCC ... with more sysdiv options, option for
606 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
607 * as zero, so the "use RCC2" flag is always clear.
609 if (rcc2
& (1 << 31)) {
610 sysdiv
= (rcc2
>> 23) & 0x3F;
611 bypass
= (rcc2
>> 11) & 0x1;
612 oscsrc
= (rcc2
>> 4) & 0x7;
614 /* FIXME Tempest parts have an additional lsb for
615 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
619 stellaris_info
->mck_desc
= "";
624 mainfreq
= rcc_xtal
[xtal
];
627 mainfreq
= stellaris_info
->iosc_freq
;
628 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
631 mainfreq
= stellaris_info
->iosc_freq
/ 4;
632 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
634 case 3: /* lowspeed */
635 /* Sandstorm doesn't have this 30K +/- 30% osc */
637 stellaris_info
->mck_desc
= " (±30%)";
639 case 8: /* hibernation osc */
640 /* not all parts support hibernation */
644 default: /* NOTREACHED */
649 /* PLL is used if it's not bypassed; its output is 200 MHz
650 * even when it runs at 400 MHz (adds divide-by-two stage).
653 mainfreq
= 200000000;
656 stellaris_info
->mck_freq
= mainfreq
/(1 + sysdiv
);
658 stellaris_info
->mck_freq
= mainfreq
;
661 /* Read device id register, main clock frequency register and fill in driver info structure */
662 static int stellaris_read_part_info(struct flash_bank
*bank
)
664 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
665 struct target
*target
= bank
->target
;
666 uint32_t did0
, did1
, ver
, fam
;
669 /* Read and parse chip identification register */
670 target_read_u32(target
, SCB_BASE
| DID0
, &did0
);
671 target_read_u32(target
, SCB_BASE
| DID1
, &did1
);
672 target_read_u32(target
, SCB_BASE
| DC0
, &stellaris_info
->dc0
);
673 target_read_u32(target
, SCB_BASE
| DC1
, &stellaris_info
->dc1
);
674 LOG_DEBUG("did0 0x%" PRIx32
", did1 0x%" PRIx32
", dc0 0x%" PRIx32
", dc1 0x%" PRIx32
"",
675 did0
, did1
, stellaris_info
->dc0
, stellaris_info
->dc1
);
678 if ((ver
!= 0) && (ver
!= 1))
680 LOG_WARNING("Unknown did0 version, cannot identify target");
681 return ERROR_FLASH_OPERATION_FAILED
;
686 LOG_WARNING("Cannot identify target as a Stellaris");
687 return ERROR_FLASH_OPERATION_FAILED
;
691 fam
= (did1
>> 24) & 0xF;
692 if (((ver
!= 0) && (ver
!= 1)) || (fam
!= 0))
694 LOG_WARNING("Unknown did1 version/family.");
695 return ERROR_FLASH_OPERATION_FAILED
;
698 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
699 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
700 * even give _both_ numbers! We'll use current numbers; IOSC is
701 * always approximate.
703 * For Tempest: IOSC is calibrated, 16 MHz
705 stellaris_info
->iosc_freq
= 12000000;
706 stellaris_info
->iosc_desc
= " (±30%)";
707 stellaris_info
->xtal_mask
= 0x0f;
709 switch ((did0
>> 28) & 0x7) {
710 case 0: /* Sandstorm */
712 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
713 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
714 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
716 if (((did0
>> 8) & 0xff) < 2) {
717 stellaris_info
->iosc_freq
= 15000000;
718 stellaris_info
->iosc_desc
= " (±50%)";
722 switch ((did0
>> 16) & 0xff) {
725 case 4: /* Tempest */
726 stellaris_info
->iosc_freq
= 16000000; /* +/- 1% */
727 stellaris_info
->iosc_desc
= " (±1%)";
729 case 3: /* DustDevil */
730 stellaris_info
->xtal_mask
= 0x1f;
733 LOG_WARNING("Unknown did0 class");
737 LOG_WARNING("Unknown did0 version");
741 for (i
= 0; StellarisParts
[i
].partno
; i
++)
743 if ((StellarisParts
[i
].partno
== ((did1
>> 16) & 0xFF)) &&
744 (StellarisParts
[i
].class == ((did0
>> 16) & 0xFF)))
748 stellaris_info
->target_name
= StellarisParts
[i
].partname
;
750 stellaris_info
->did0
= did0
;
751 stellaris_info
->did1
= did1
;
753 stellaris_info
->num_lockbits
= 1 + (stellaris_info
->dc0
& 0xFFFF);
754 stellaris_info
->num_pages
= 2 *(1 + (stellaris_info
->dc0
& 0xFFFF));
755 stellaris_info
->pagesize
= 1024;
756 stellaris_info
->pages_in_lockregion
= 2;
758 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
759 * That exposes a 32-word Flash Write Buffer ... enabling
760 * writes of more than one word at a time.
766 /***************************************************************************
768 ***************************************************************************/
770 static int stellaris_protect_check(struct flash_bank
*bank
)
772 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
773 int status
= ERROR_OK
;
777 if (stellaris
->did1
== 0)
778 return ERROR_FLASH_BANK_NOT_PROBED
;
780 for (i
= 0; i
< (unsigned) bank
->num_sectors
; i
++)
781 bank
->sectors
[i
].is_protected
= -1;
783 /* Read each Flash Memory Protection Program Enable (FMPPE) register
784 * to report any pages that we can't write. Ignore the Read Enable
787 for (i
= 0, page
= 0;
788 i
< DIV_ROUND_UP(stellaris
->num_lockbits
, 32u);
792 status
= target_read_u32(bank
->target
,
793 SCB_BASE
+ (i
? (FMPPE0
+ 4 * i
) : FMPPE
),
795 LOG_DEBUG("FMPPE%d = %#8.8x (status %d)", i
,
796 (unsigned) lockbits
, status
);
797 if (status
!= ERROR_OK
)
800 for (unsigned j
= 0; j
< 32; j
++) {
803 for (k
= 0; k
< stellaris
->pages_in_lockregion
; k
++) {
804 if (page
>= (unsigned) bank
->num_sectors
)
806 bank
->sectors
[page
++].is_protected
=
807 !(lockbits
& (1 << j
));
816 static int stellaris_erase(struct flash_bank
*bank
, int first
, int last
)
819 uint32_t flash_fmc
, flash_cris
;
820 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
821 struct target
*target
= bank
->target
;
823 if (bank
->target
->state
!= TARGET_HALTED
)
825 LOG_ERROR("Target not halted");
826 return ERROR_TARGET_NOT_HALTED
;
829 if (stellaris_info
->did1
== 0)
830 return ERROR_FLASH_BANK_NOT_PROBED
;
832 if ((first
< 0) || (last
< first
) || (last
>= (int)stellaris_info
->num_pages
))
834 return ERROR_FLASH_SECTOR_INVALID
;
837 if ((first
== 0) && (last
== ((int)stellaris_info
->num_pages
-1)))
839 return stellaris_mass_erase(bank
);
842 /* Refresh flash controller timing */
843 stellaris_read_clock_info(bank
);
844 stellaris_set_flash_timing(bank
);
846 /* Clear and disable flash programming interrupts */
847 target_write_u32(target
, FLASH_CIM
, 0);
848 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
850 /* REVISIT this clobbers state set by any halted firmware ...
851 * it might want to process those IRQs.
854 for (banknr
= first
; banknr
<= last
; banknr
++)
856 /* Address is first word in page */
857 target_write_u32(target
, FLASH_FMA
, banknr
* stellaris_info
->pagesize
);
858 /* Write erase command */
859 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_ERASE
);
860 /* Wait until erase complete */
863 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
865 while (flash_fmc
& FMC_ERASE
);
867 /* Check acess violations */
868 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
869 if (flash_cris
& (AMASK
))
871 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32
"", banknr
, flash_cris
);
872 target_write_u32(target
, FLASH_CRIS
, 0);
873 return ERROR_FLASH_OPERATION_FAILED
;
876 bank
->sectors
[banknr
].is_erased
= 1;
882 static int stellaris_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
884 uint32_t fmppe
, flash_fmc
, flash_cris
;
887 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
888 struct target
*target
= bank
->target
;
890 if (bank
->target
->state
!= TARGET_HALTED
)
892 LOG_ERROR("Target not halted");
893 return ERROR_TARGET_NOT_HALTED
;
898 LOG_ERROR("Hardware doesn't support page-level unprotect. "
899 "Try the 'recover' command.");
900 return ERROR_INVALID_ARGUMENTS
;
903 if (stellaris_info
->did1
== 0)
904 return ERROR_FLASH_BANK_NOT_PROBED
;
906 /* lockregions are 2 pages ... must protect [even..odd] */
907 if ((first
< 0) || (first
& 1)
908 || (last
< first
) || !(last
& 1)
909 || (last
>= 2 * stellaris_info
->num_lockbits
))
911 LOG_ERROR("Can't protect unaligned or out-of-range pages.");
912 return ERROR_FLASH_SECTOR_INVALID
;
915 /* Refresh flash controller timing */
916 stellaris_read_clock_info(bank
);
917 stellaris_set_flash_timing(bank
);
919 /* convert from pages to lockregions */
923 /* FIXME this assumes single FMPPE, for a max of 64K of flash!!
924 * Current parts can be much bigger.
927 LOG_ERROR("No support yet for protection > 64K");
928 return ERROR_FLASH_OPERATION_FAILED
;
931 target_read_u32(target
, SCB_BASE
| FMPPE
, &fmppe
);
933 for (lockregion
= first
; lockregion
<= last
; lockregion
++)
934 fmppe
&= ~(1 << lockregion
);
936 /* Clear and disable flash programming interrupts */
937 target_write_u32(target
, FLASH_CIM
, 0);
938 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
940 /* REVISIT this clobbers state set by any halted firmware ...
941 * it might want to process those IRQs.
944 LOG_DEBUG("fmppe 0x%" PRIx32
"",fmppe
);
945 target_write_u32(target
, SCB_BASE
| FMPPE
, fmppe
);
948 target_write_u32(target
, FLASH_FMA
, 1);
950 /* Write commit command */
951 /* REVISIT safety check, since this cannot be undone
952 * except by the "Recover a locked device" procedure.
953 * REVISIT DustDevil-A0 parts have an erratum making FMPPE commits
954 * inadvisable ... it makes future mass erase operations fail.
956 LOG_WARNING("Flash protection cannot be removed once committed, commit is NOT executed !");
957 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
959 /* Wait until erase complete */
962 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
964 while (flash_fmc
& FMC_COMT
);
966 /* Check acess violations */
967 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
968 if (flash_cris
& (AMASK
))
970 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32
"", flash_cris
);
971 target_write_u32(target
, FLASH_CRIS
, 0);
972 return ERROR_FLASH_OPERATION_FAILED
;
978 /* see contib/loaders/flash/stellaris.s for src */
980 static const uint8_t stellaris_write_code
[] =
985 r1 = destination address
986 r2 = bytecount (in) - endaddr (work)
989 r3 = pFLASH_CTRL_BASE
995 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
996 0x08,0x4C, /* ldr r4,FLASHWRITECMD */
997 0x01,0x25, /* movs r5, 1 */
998 0x00,0x26, /* movs r6, #0 */
1000 0x19,0x60, /* str r1, [r3, #0] */
1001 0x87,0x59, /* ldr r7, [r0, r6] */
1002 0x5F,0x60, /* str r7, [r3, #4] */
1003 0x9C,0x60, /* str r4, [r3, #8] */
1005 0x9F,0x68, /* ldr r7, [r3, #8] */
1006 0x2F,0x42, /* tst r7, r5 */
1007 0xFC,0xD1, /* bne waitloop */
1008 0x04,0x31, /* adds r1, r1, #4 */
1009 0x04,0x36, /* adds r6, r6, #4 */
1010 0x96,0x42, /* cmp r6, r2 */
1011 0xF4,0xD1, /* bne mainloop */
1012 0x00,0xBE, /* bkpt #0 */
1013 /* pFLASH_CTRL_BASE: */
1014 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
1015 /* FLASHWRITECMD: */
1016 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
1019 static int stellaris_write_block(struct flash_bank
*bank
,
1020 uint8_t *buffer
, uint32_t offset
, uint32_t wcount
)
1022 struct target
*target
= bank
->target
;
1023 uint32_t buffer_size
= 16384;
1024 struct working_area
*source
;
1025 struct working_area
*write_algorithm
;
1026 uint32_t address
= bank
->base
+ offset
;
1027 struct reg_param reg_params
[3];
1028 struct armv7m_algorithm armv7m_info
;
1029 int retval
= ERROR_OK
;
1031 /* power of two, and multiple of word size */
1032 static const unsigned buf_min
= 128;
1034 /* for small buffers it's faster not to download an algorithm */
1035 if (wcount
* 4 < buf_min
)
1036 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1038 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" wcount=%08" PRIx32
"",
1039 bank
, buffer
, offset
, wcount
);
1041 /* flash write code */
1042 if (target_alloc_working_area(target
, sizeof(stellaris_write_code
), &write_algorithm
) != ERROR_OK
)
1044 LOG_DEBUG("no working area for block memory writes");
1045 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1048 /* plus a buffer big enough for this data */
1049 if (wcount
* 4 < buffer_size
)
1050 buffer_size
= wcount
* 4;
1053 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
)
1056 if (buffer_size
<= buf_min
)
1058 target_free_working_area(target
, write_algorithm
);
1059 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1061 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1062 target_name(target
), (unsigned) buffer_size
);
1065 retval
= target_write_buffer(target
, write_algorithm
->address
,
1066 sizeof(stellaris_write_code
),
1067 (uint8_t *) stellaris_write_code
);
1069 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
1070 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
1072 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1073 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1074 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
1078 uint32_t thisrun_count
= (wcount
> (buffer_size
/ 4)) ? (buffer_size
/ 4) : wcount
;
1080 target_write_buffer(target
, source
->address
, thisrun_count
* 4, buffer
);
1082 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
1083 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
1084 buf_set_u32(reg_params
[2].value
, 0, 32, 4*thisrun_count
);
1085 LOG_DEBUG("Algorithm flash write %u words to 0x%" PRIx32
1087 (unsigned) thisrun_count
, address
,
1088 (unsigned) (wcount
- thisrun_count
));
1089 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
1090 write_algorithm
->address
,
1092 10000, &armv7m_info
);
1093 if (retval
!= ERROR_OK
)
1095 LOG_ERROR("error %d executing stellaris "
1096 "flash write algorithm",
1098 retval
= ERROR_FLASH_OPERATION_FAILED
;
1102 buffer
+= thisrun_count
* 4;
1103 address
+= thisrun_count
* 4;
1104 wcount
-= thisrun_count
;
1107 /* REVISIT we could speed up writing multi-section images by
1108 * not freeing the initialized write_algorithm this way.
1111 target_free_working_area(target
, write_algorithm
);
1112 target_free_working_area(target
, source
);
1114 destroy_reg_param(®_params
[0]);
1115 destroy_reg_param(®_params
[1]);
1116 destroy_reg_param(®_params
[2]);
1121 static int stellaris_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
1123 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1124 struct target
*target
= bank
->target
;
1125 uint32_t address
= offset
;
1126 uint32_t flash_cris
, flash_fmc
;
1127 uint32_t words_remaining
= (count
/ 4);
1128 uint32_t bytes_remaining
= (count
& 0x00000003);
1129 uint32_t bytes_written
= 0;
1132 if (bank
->target
->state
!= TARGET_HALTED
)
1134 LOG_ERROR("Target not halted");
1135 return ERROR_TARGET_NOT_HALTED
;
1138 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" count=%08" PRIx32
"",
1139 bank
, buffer
, offset
, count
);
1141 if (stellaris_info
->did1
== 0)
1142 return ERROR_FLASH_BANK_NOT_PROBED
;
1146 LOG_WARNING("offset size must be word aligned");
1147 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1150 if (offset
+ count
> bank
->size
)
1151 return ERROR_FLASH_DST_OUT_OF_BANK
;
1153 /* Refresh flash controller timing */
1154 stellaris_read_clock_info(bank
);
1155 stellaris_set_flash_timing(bank
);
1157 /* Clear and disable flash programming interrupts */
1158 target_write_u32(target
, FLASH_CIM
, 0);
1159 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1161 /* REVISIT this clobbers state set by any halted firmware ...
1162 * it might want to process those IRQs.
1165 /* multiple words to be programmed? */
1166 if (words_remaining
> 0)
1168 /* try using a block write */
1169 retval
= stellaris_write_block(bank
, buffer
, offset
,
1171 if (retval
!= ERROR_OK
)
1173 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
1175 LOG_DEBUG("writing flash word-at-a-time");
1177 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
1179 /* if an error occured, we examine the reason, and quit */
1180 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1182 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32
"", flash_cris
);
1183 return ERROR_FLASH_OPERATION_FAILED
;
1188 buffer
+= words_remaining
* 4;
1189 address
+= words_remaining
* 4;
1190 words_remaining
= 0;
1194 while (words_remaining
> 0)
1196 if (!(address
& 0xff))
1197 LOG_DEBUG("0x%" PRIx32
"", address
);
1199 /* Program one word */
1200 target_write_u32(target
, FLASH_FMA
, address
);
1201 target_write_buffer(target
, FLASH_FMD
, 4, buffer
);
1202 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1203 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1204 /* Wait until write complete */
1207 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1208 } while (flash_fmc
& FMC_WRITE
);
1215 if (bytes_remaining
)
1217 uint8_t last_word
[4] = {0xff, 0xff, 0xff, 0xff};
1220 while (bytes_remaining
> 0)
1222 last_word
[i
++] = *(buffer
+ bytes_written
);
1227 if (!(address
& 0xff))
1228 LOG_DEBUG("0x%" PRIx32
"", address
);
1230 /* Program one word */
1231 target_write_u32(target
, FLASH_FMA
, address
);
1232 target_write_buffer(target
, FLASH_FMD
, 4, last_word
);
1233 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1234 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1235 /* Wait until write complete */
1238 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1239 } while (flash_fmc
& FMC_WRITE
);
1242 /* Check access violations */
1243 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1244 if (flash_cris
& (AMASK
))
1246 LOG_DEBUG("flash_cris 0x%" PRIx32
"", flash_cris
);
1247 return ERROR_FLASH_OPERATION_FAILED
;
1252 static int stellaris_probe(struct flash_bank
*bank
)
1254 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1257 /* If this is a stellaris chip, it has flash; probe() is just
1258 * to figure out how much is present. Only do it once.
1260 if (stellaris_info
->did1
!= 0)
1263 /* stellaris_read_part_info() already handled error checking and
1264 * reporting. Note that it doesn't write, so we don't care about
1265 * whether the target is halted or not.
1267 retval
= stellaris_read_part_info(bank
);
1268 if (retval
!= ERROR_OK
)
1273 free(bank
->sectors
);
1274 bank
->sectors
= NULL
;
1277 /* provide this for the benefit of the NOR flash framework */
1278 bank
->size
= 1024 * stellaris_info
->num_pages
;
1279 bank
->num_sectors
= stellaris_info
->num_pages
;
1280 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
1281 for (int i
= 0; i
< bank
->num_sectors
; i
++)
1283 bank
->sectors
[i
].offset
= i
* stellaris_info
->pagesize
;
1284 bank
->sectors
[i
].size
= stellaris_info
->pagesize
;
1285 bank
->sectors
[i
].is_erased
= -1;
1286 bank
->sectors
[i
].is_protected
= -1;
1292 static int stellaris_mass_erase(struct flash_bank
*bank
)
1294 struct target
*target
= NULL
;
1295 struct stellaris_flash_bank
*stellaris_info
= NULL
;
1298 stellaris_info
= bank
->driver_priv
;
1299 target
= bank
->target
;
1301 if (target
->state
!= TARGET_HALTED
)
1303 LOG_ERROR("Target not halted");
1304 return ERROR_TARGET_NOT_HALTED
;
1307 if (stellaris_info
->did1
== 0)
1308 return ERROR_FLASH_BANK_NOT_PROBED
;
1310 /* Refresh flash controller timing */
1311 stellaris_read_clock_info(bank
);
1312 stellaris_set_flash_timing(bank
);
1314 /* Clear and disable flash programming interrupts */
1315 target_write_u32(target
, FLASH_CIM
, 0);
1316 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1318 /* REVISIT this clobbers state set by any halted firmware ...
1319 * it might want to process those IRQs.
1322 target_write_u32(target
, FLASH_FMA
, 0);
1323 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1324 /* Wait until erase complete */
1327 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1329 while (flash_fmc
& FMC_MERASE
);
1331 /* if device has > 128k, then second erase cycle is needed
1332 * this is only valid for older devices, but will not hurt */
1333 if (stellaris_info
->num_pages
* stellaris_info
->pagesize
> 0x20000)
1335 target_write_u32(target
, FLASH_FMA
, 0x20000);
1336 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1337 /* Wait until erase complete */
1340 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1342 while (flash_fmc
& FMC_MERASE
);
1348 COMMAND_HANDLER(stellaris_handle_mass_erase_command
)
1354 command_print(CMD_CTX
, "stellaris mass_erase <bank>");
1358 struct flash_bank
*bank
;
1359 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1360 if (ERROR_OK
!= retval
)
1363 if (stellaris_mass_erase(bank
) == ERROR_OK
)
1365 /* set all sectors as erased */
1366 for (i
= 0; i
< bank
->num_sectors
; i
++)
1368 bank
->sectors
[i
].is_erased
= 1;
1371 command_print(CMD_CTX
, "stellaris mass erase complete");
1375 command_print(CMD_CTX
, "stellaris mass erase failed");
1382 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1383 * This performs a mass erase and then restores all nonvolatile registers
1384 * (including USER_* registers and flash lock bits) to their defaults.
1385 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1387 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1388 * can affect this operation if flash protection has been enabled.
1390 COMMAND_HANDLER(stellaris_handle_recover_command
)
1392 struct flash_bank
*bank
;
1395 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1396 if (retval
!= ERROR_OK
)
1399 /* REVISIT ... it may be worth sanity checking that the AP is
1400 * inactive before we start. ARM documents that switching a DP's
1401 * mode while it's active can cause fault modes that need a power
1406 if (!(jtag_get_reset_config() & RESET_HAS_SRST
)) {
1407 LOG_ERROR("Can't recover Stellaris flash without SRST");
1410 jtag_add_reset(0, 1);
1412 for (int i
= 0; i
< 5; i
++) {
1413 retval
= dap_to_swd(bank
->target
);
1414 if (retval
!= ERROR_OK
)
1417 retval
= dap_to_jtag(bank
->target
);
1418 if (retval
!= ERROR_OK
)
1422 /* de-assert SRST */
1423 jtag_add_reset(0, 0);
1424 retval
= jtag_execute_queue();
1426 /* wait 400+ msec ... OK, "1+ second" is simpler */
1429 /* USER INTERVENTION required for the power cycle
1430 * Restarting OpenOCD is likely needed because of mode switching.
1432 LOG_INFO("USER ACTION: "
1433 "power cycle Stellaris chip, then restart OpenOCD.");
1439 static const struct command_registration stellaris_exec_command_handlers
[] = {
1441 .name
= "mass_erase",
1442 .handler
= stellaris_handle_mass_erase_command
,
1443 .mode
= COMMAND_EXEC
,
1445 .help
= "erase entire device",
1449 .handler
= stellaris_handle_recover_command
,
1450 .mode
= COMMAND_EXEC
,
1452 .help
= "recover (and erase) locked device",
1454 COMMAND_REGISTRATION_DONE
1456 static const struct command_registration stellaris_command_handlers
[] = {
1458 .name
= "stellaris",
1459 .mode
= COMMAND_EXEC
,
1460 .help
= "Stellaris flash command group",
1461 .chain
= stellaris_exec_command_handlers
,
1463 COMMAND_REGISTRATION_DONE
1466 struct flash_driver stellaris_flash
= {
1467 .name
= "stellaris",
1468 .commands
= stellaris_command_handlers
,
1469 .flash_bank_command
= stellaris_flash_bank_command
,
1470 .erase
= stellaris_erase
,
1471 .protect
= stellaris_protect
,
1472 .write
= stellaris_write
,
1473 .read
= default_flash_read
,
1474 .probe
= stellaris_probe
,
1475 .auto_probe
= stellaris_probe
,
1476 .erase_check
= default_flash_mem_blank_check
,
1477 .protect_check
= stellaris_protect_check
,
1478 .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)