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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
24 /***************************************************************************
25 * STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more.
26 ***************************************************************************/
32 #include "jtag/interface.h"
34 #include <target/algorithm.h>
35 #include <target/armv7m.h>
37 #define DID0_VER(did0) ((did0 >> 28)&0x07)
39 /* STELLARIS control registers */
40 #define SCB_BASE 0x400FE000
55 /* "legacy" flash memory protection registers (64KB max) */
59 /* new flash memory protection registers (for more than 64KB) */
60 #define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */
61 #define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */
65 #define FLASH_CONTROL_BASE 0x400FD000
66 #define FLASH_FMA (FLASH_CONTROL_BASE | 0x000)
67 #define FLASH_FMD (FLASH_CONTROL_BASE | 0x004)
68 #define FLASH_FMC (FLASH_CONTROL_BASE | 0x008)
69 #define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C)
70 #define FLASH_CIM (FLASH_CONTROL_BASE | 0x010)
71 #define FLASH_MISC (FLASH_CONTROL_BASE | 0x014)
72 #define FLASH_FSIZE (FLASH_CONTROL_BASE | 0xFC0)
73 #define FLASH_SSIZE (FLASH_CONTROL_BASE | 0xFC4)
81 /* Flash Controller Command bits */
82 #define FMC_WRKEY (0xA442 << 16)
83 #define FMC_COMT (1 << 3)
84 #define FMC_MERASE (1 << 2)
85 #define FMC_ERASE (1 << 1)
86 #define FMC_WRITE (1 << 0)
88 /* STELLARIS constants */
90 /* values to write in FMA to commit write-"once" values */
91 #define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */
92 #define FLASH_FMA_PPE(x) (2 * (x) + 1) /* for FMPPPEx */
94 static void stellaris_read_clock_info(struct flash_bank
*bank
);
95 static int stellaris_mass_erase(struct flash_bank
*bank
);
97 struct stellaris_flash_bank
{
98 /* chip id register */
106 const char *target_name
;
107 uint8_t target_class
;
114 uint32_t pages_in_lockregion
;
117 uint16_t num_lockbits
;
119 /* main clock status */
126 const char *iosc_desc
;
127 const char *mck_desc
;
130 /* Autogenerated by contrib/gen-stellaris-part-header.pl */
131 /* From Stellaris Firmware Development Package revision 9453 */
132 static const struct {
135 const char *partname
;
136 } StellarisParts
[] = {
137 {0x00, 0x01, "LM3S101"},
138 {0x00, 0x02, "LM3S102"},
139 {0x01, 0xBF, "LM3S1110"},
140 {0x01, 0xC3, "LM3S1133"},
141 {0x01, 0xC5, "LM3S1138"},
142 {0x01, 0xC1, "LM3S1150"},
143 {0x01, 0xC4, "LM3S1162"},
144 {0x01, 0xC2, "LM3S1165"},
145 {0x01, 0xEC, "LM3S1166"},
146 {0x01, 0xC6, "LM3S1332"},
147 {0x01, 0xBC, "LM3S1435"},
148 {0x01, 0xBA, "LM3S1439"},
149 {0x01, 0xBB, "LM3S1512"},
150 {0x01, 0xC7, "LM3S1538"},
151 {0x01, 0xDB, "LM3S1601"},
152 {0x03, 0x06, "LM3S1607"},
153 {0x01, 0xDA, "LM3S1608"},
154 {0x01, 0xC0, "LM3S1620"},
155 {0x04, 0xCD, "LM3S1621"},
156 {0x03, 0x03, "LM3S1625"},
157 {0x03, 0x04, "LM3S1626"},
158 {0x03, 0x05, "LM3S1627"},
159 {0x01, 0xB3, "LM3S1635"},
160 {0x01, 0xEB, "LM3S1636"},
161 {0x01, 0xBD, "LM3S1637"},
162 {0x04, 0xB1, "LM3S1651"},
163 {0x01, 0xB9, "LM3S1751"},
164 {0x03, 0x10, "LM3S1776"},
165 {0x04, 0x16, "LM3S1811"},
166 {0x04, 0x3D, "LM3S1816"},
167 {0x01, 0xB4, "LM3S1850"},
168 {0x01, 0xDD, "LM3S1911"},
169 {0x01, 0xDC, "LM3S1918"},
170 {0x01, 0xB7, "LM3S1937"},
171 {0x01, 0xBE, "LM3S1958"},
172 {0x01, 0xB5, "LM3S1960"},
173 {0x01, 0xB8, "LM3S1968"},
174 {0x01, 0xEA, "LM3S1969"},
175 {0x04, 0xCE, "LM3S1B21"},
176 {0x06, 0xCA, "LM3S1C21"},
177 {0x06, 0xCB, "LM3S1C26"},
178 {0x06, 0x98, "LM3S1C58"},
179 {0x06, 0xB0, "LM3S1D21"},
180 {0x06, 0xCC, "LM3S1D26"},
181 {0x06, 0x1D, "LM3S1F11"},
182 {0x06, 0x1B, "LM3S1F16"},
183 {0x06, 0xAF, "LM3S1G21"},
184 {0x06, 0x95, "LM3S1G58"},
185 {0x06, 0x1E, "LM3S1H11"},
186 {0x06, 0x1C, "LM3S1H16"},
187 {0x04, 0x0F, "LM3S1J11"},
188 {0x04, 0x3C, "LM3S1J16"},
189 {0x04, 0x0E, "LM3S1N11"},
190 {0x04, 0x3B, "LM3S1N16"},
191 {0x04, 0xB2, "LM3S1P51"},
192 {0x04, 0x9E, "LM3S1R21"},
193 {0x04, 0xC9, "LM3S1R26"},
194 {0x04, 0x30, "LM3S1W16"},
195 {0x04, 0x2F, "LM3S1Z16"},
196 {0x01, 0x51, "LM3S2110"},
197 {0x01, 0x84, "LM3S2139"},
198 {0x03, 0x39, "LM3S2276"},
199 {0x01, 0xA2, "LM3S2410"},
200 {0x01, 0x59, "LM3S2412"},
201 {0x01, 0x56, "LM3S2432"},
202 {0x01, 0x5A, "LM3S2533"},
203 {0x01, 0xE1, "LM3S2601"},
204 {0x01, 0xE0, "LM3S2608"},
205 {0x03, 0x33, "LM3S2616"},
206 {0x01, 0x57, "LM3S2620"},
207 {0x01, 0x85, "LM3S2637"},
208 {0x01, 0x53, "LM3S2651"},
209 {0x03, 0x80, "LM3S2671"},
210 {0x03, 0x50, "LM3S2678"},
211 {0x01, 0xA4, "LM3S2730"},
212 {0x01, 0x52, "LM3S2739"},
213 {0x03, 0x3A, "LM3S2776"},
214 {0x04, 0x6D, "LM3S2793"},
215 {0x01, 0xE3, "LM3S2911"},
216 {0x01, 0xE2, "LM3S2918"},
217 {0x01, 0xED, "LM3S2919"},
218 {0x01, 0x54, "LM3S2939"},
219 {0x01, 0x8F, "LM3S2948"},
220 {0x01, 0x58, "LM3S2950"},
221 {0x01, 0x55, "LM3S2965"},
222 {0x04, 0x6C, "LM3S2B93"},
223 {0x06, 0x94, "LM3S2D93"},
224 {0x06, 0x93, "LM3S2U93"},
225 {0x00, 0x19, "LM3S300"},
226 {0x00, 0x11, "LM3S301"},
227 {0x00, 0x1A, "LM3S308"},
228 {0x00, 0x12, "LM3S310"},
229 {0x00, 0x13, "LM3S315"},
230 {0x00, 0x14, "LM3S316"},
231 {0x00, 0x17, "LM3S317"},
232 {0x00, 0x15, "LM3S328"},
233 {0x03, 0x08, "LM3S3634"},
234 {0x03, 0x43, "LM3S3651"},
235 {0x04, 0xC8, "LM3S3654"},
236 {0x03, 0x44, "LM3S3739"},
237 {0x03, 0x49, "LM3S3748"},
238 {0x03, 0x45, "LM3S3749"},
239 {0x04, 0x42, "LM3S3826"},
240 {0x04, 0x41, "LM3S3J26"},
241 {0x04, 0x40, "LM3S3N26"},
242 {0x04, 0x3F, "LM3S3W26"},
243 {0x04, 0x3E, "LM3S3Z26"},
244 {0x03, 0x81, "LM3S5632"},
245 {0x04, 0x0C, "LM3S5651"},
246 {0x03, 0x8A, "LM3S5652"},
247 {0x04, 0x4D, "LM3S5656"},
248 {0x03, 0x91, "LM3S5662"},
249 {0x03, 0x96, "LM3S5732"},
250 {0x03, 0x97, "LM3S5737"},
251 {0x03, 0xA0, "LM3S5739"},
252 {0x03, 0x99, "LM3S5747"},
253 {0x03, 0xA7, "LM3S5749"},
254 {0x03, 0x9A, "LM3S5752"},
255 {0x03, 0x9C, "LM3S5762"},
256 {0x04, 0x69, "LM3S5791"},
257 {0x04, 0x0B, "LM3S5951"},
258 {0x04, 0x4E, "LM3S5956"},
259 {0x04, 0x68, "LM3S5B91"},
260 {0x06, 0x2E, "LM3S5C31"},
261 {0x06, 0x2C, "LM3S5C36"},
262 {0x06, 0x5E, "LM3S5C51"},
263 {0x06, 0x5B, "LM3S5C56"},
264 {0x06, 0x5F, "LM3S5D51"},
265 {0x06, 0x5C, "LM3S5D56"},
266 {0x06, 0x87, "LM3S5D91"},
267 {0x06, 0x2D, "LM3S5G31"},
268 {0x06, 0x1F, "LM3S5G36"},
269 {0x06, 0x5D, "LM3S5G51"},
270 {0x06, 0x4F, "LM3S5G56"},
271 {0x04, 0x09, "LM3S5K31"},
272 {0x04, 0x4A, "LM3S5K36"},
273 {0x04, 0x0A, "LM3S5P31"},
274 {0x04, 0x48, "LM3S5P36"},
275 {0x04, 0xB6, "LM3S5P3B"},
276 {0x04, 0x0D, "LM3S5P51"},
277 {0x04, 0x4C, "LM3S5P56"},
278 {0x04, 0x07, "LM3S5R31"},
279 {0x04, 0x4B, "LM3S5R36"},
280 {0x04, 0x47, "LM3S5T36"},
281 {0x06, 0x7F, "LM3S5U91"},
282 {0x04, 0x46, "LM3S5Y36"},
283 {0x00, 0x2A, "LM3S600"},
284 {0x00, 0x21, "LM3S601"},
285 {0x00, 0x2B, "LM3S608"},
286 {0x00, 0x22, "LM3S610"},
287 {0x01, 0xA1, "LM3S6100"},
288 {0x00, 0x23, "LM3S611"},
289 {0x01, 0x74, "LM3S6110"},
290 {0x00, 0x24, "LM3S612"},
291 {0x00, 0x25, "LM3S613"},
292 {0x00, 0x26, "LM3S615"},
293 {0x00, 0x28, "LM3S617"},
294 {0x00, 0x29, "LM3S618"},
295 {0x00, 0x27, "LM3S628"},
296 {0x01, 0xA5, "LM3S6420"},
297 {0x01, 0x82, "LM3S6422"},
298 {0x01, 0x75, "LM3S6432"},
299 {0x01, 0x76, "LM3S6537"},
300 {0x01, 0x71, "LM3S6610"},
301 {0x01, 0xE7, "LM3S6611"},
302 {0x01, 0xE6, "LM3S6618"},
303 {0x01, 0x83, "LM3S6633"},
304 {0x01, 0x8B, "LM3S6637"},
305 {0x01, 0xA3, "LM3S6730"},
306 {0x01, 0x77, "LM3S6753"},
307 {0x01, 0xE9, "LM3S6911"},
308 {0x01, 0xE8, "LM3S6918"},
309 {0x01, 0x89, "LM3S6938"},
310 {0x01, 0x72, "LM3S6950"},
311 {0x01, 0x78, "LM3S6952"},
312 {0x01, 0x73, "LM3S6965"},
313 {0x06, 0xAA, "LM3S6C11"},
314 {0x06, 0xAC, "LM3S6C65"},
315 {0x06, 0x9F, "LM3S6G11"},
316 {0x06, 0xAB, "LM3S6G65"},
317 {0x00, 0x38, "LM3S800"},
318 {0x00, 0x31, "LM3S801"},
319 {0x00, 0x39, "LM3S808"},
320 {0x00, 0x32, "LM3S811"},
321 {0x00, 0x33, "LM3S812"},
322 {0x00, 0x34, "LM3S815"},
323 {0x00, 0x36, "LM3S817"},
324 {0x00, 0x37, "LM3S818"},
325 {0x00, 0x35, "LM3S828"},
326 {0x01, 0x64, "LM3S8530"},
327 {0x01, 0x8E, "LM3S8538"},
328 {0x01, 0x61, "LM3S8630"},
329 {0x01, 0x63, "LM3S8730"},
330 {0x01, 0x8D, "LM3S8733"},
331 {0x01, 0x86, "LM3S8738"},
332 {0x01, 0x65, "LM3S8930"},
333 {0x01, 0x8C, "LM3S8933"},
334 {0x01, 0x88, "LM3S8938"},
335 {0x01, 0xA6, "LM3S8962"},
336 {0x01, 0x62, "LM3S8970"},
337 {0x01, 0xD7, "LM3S8971"},
338 {0x06, 0xAE, "LM3S8C62"},
339 {0x06, 0xAD, "LM3S8G62"},
340 {0x04, 0xCF, "LM3S9781"},
341 {0x04, 0x67, "LM3S9790"},
342 {0x04, 0x6B, "LM3S9792"},
343 {0x04, 0x2D, "LM3S9971"},
344 {0x04, 0x20, "LM3S9997"},
345 {0x04, 0xD0, "LM3S9B81"},
346 {0x04, 0x66, "LM3S9B90"},
347 {0x04, 0x6A, "LM3S9B92"},
348 {0x04, 0x6E, "LM3S9B95"},
349 {0x04, 0x6F, "LM3S9B96"},
350 {0x04, 0x1D, "LM3S9BN2"},
351 {0x04, 0x1E, "LM3S9BN5"},
352 {0x04, 0x1F, "LM3S9BN6"},
353 {0x06, 0x70, "LM3S9C97"},
354 {0x06, 0xA9, "LM3S9D81"},
355 {0x06, 0x7E, "LM3S9D90"},
356 {0x06, 0x92, "LM3S9D92"},
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, 0x9B, "LM3S9U96"},
368 {0x05, 0x18, "LM4F110B2QR"},
369 {0x05, 0x19, "LM4F110C4QR"},
370 {0x05, 0x10, "LM4F110E5QR"},
371 {0x05, 0x11, "LM4F110H5QR"},
372 {0x05, 0x22, "LM4F111B2QR"},
373 {0x05, 0x23, "LM4F111C4QR"},
374 {0x05, 0x20, "LM4F111E5QR"},
375 {0x05, 0x21, "LM4F111H5QR"},
376 {0x05, 0x36, "LM4F112C4QC"},
377 {0x05, 0x30, "LM4F112E5QC"},
378 {0x05, 0x31, "LM4F112H5QC"},
379 {0x05, 0x35, "LM4F112H5QD"},
380 {0x05, 0x01, "LM4F120B2QR"},
381 {0x05, 0x02, "LM4F120C4QR"},
382 {0x05, 0x03, "LM4F120E5QR"},
383 {0x05, 0x04, "LM4F120H5QR"},
384 {0x05, 0x08, "LM4F121B2QR"},
385 {0x05, 0x09, "LM4F121C4QR"},
386 {0x05, 0x0A, "LM4F121E5QR"},
387 {0x05, 0x0B, "LM4F121H5QR"},
388 {0x05, 0xD0, "LM4F122C4QC"},
389 {0x05, 0xD1, "LM4F122E5QC"},
390 {0x05, 0xD2, "LM4F122H5QC"},
391 {0x05, 0xD6, "LM4F122H5QD"},
392 {0x05, 0x48, "LM4F130C4QR"},
393 {0x05, 0x40, "LM4F130E5QR"},
394 {0x05, 0x41, "LM4F130H5QR"},
395 {0x05, 0x52, "LM4F131C4QR"},
396 {0x05, 0x50, "LM4F131E5QR"},
397 {0x05, 0x51, "LM4F131H5QR"},
398 {0x05, 0x66, "LM4F132C4QC"},
399 {0x05, 0x60, "LM4F132E5QC"},
400 {0x05, 0x61, "LM4F132H5QC"},
401 {0x05, 0x65, "LM4F132H5QD"},
402 {0x05, 0x70, "LM4F210E5QR"},
403 {0x05, 0x73, "LM4F210H5QR"},
404 {0x05, 0x80, "LM4F211E5QR"},
405 {0x05, 0x83, "LM4F211H5QR"},
406 {0x05, 0xE9, "LM4F212H5BB"},
407 {0x05, 0xC4, "LM4F212H5QC"},
408 {0x05, 0xC6, "LM4F212H5QD"},
409 {0x05, 0xA0, "LM4F230E5QR"},
410 {0x05, 0xA1, "LM4F230H5QR/TM4C123GH6PM"},
411 {0x05, 0xB0, "LM4F231E5QR"},
412 {0x05, 0xB1, "LM4F231H5QR"},
413 {0x05, 0xC0, "LM4F232E5QC"},
414 {0x05, 0xE3, "LM4F232H5BB"},
415 {0x05, 0xC1, "LM4F232H5QC"},
416 {0x05, 0xC5, "LM4F232H5QD"},
417 {0x05, 0xE5, "LM4FS1AH5BB"},
418 {0x05, 0xEA, "LM4FS1GH5BB"},
419 {0x05, 0xE4, "LM4FS99H5BB"},
420 {0x05, 0xE1, "LM4FSXLH5BB"},
421 {0x0A, 0x1F, "TM4C1294NCPDT"},
422 {0xFF, 0x00, "Unknown Part"}
425 static const char * const StellarisClassname
[] = {
439 /***************************************************************************
440 * openocd command interface *
441 ***************************************************************************/
443 /* flash_bank stellaris <base> <size> 0 0 <target#>
445 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command
)
447 struct stellaris_flash_bank
*stellaris_info
;
450 return ERROR_COMMAND_SYNTAX_ERROR
;
452 stellaris_info
= calloc(sizeof(struct stellaris_flash_bank
), 1);
454 bank
->driver_priv
= stellaris_info
;
456 stellaris_info
->target_name
= "Unknown target";
458 /* part wasn't probed for info yet */
459 stellaris_info
->did1
= 0;
461 /* TODO Specify the main crystal speed in kHz using an optional
462 * argument; ditto, the speed of an external oscillator used
463 * instead of a crystal. Avoid programming flash using IOSC.
468 static int get_stellaris_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
471 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
473 if (stellaris_info
->did1
== 0)
474 return ERROR_FLASH_BANK_NOT_PROBED
;
476 /* Read main and master clock freqency register */
477 stellaris_read_clock_info(bank
);
479 printed
= snprintf(buf
,
481 "\nTI/LMI Stellaris information: Chip is "
482 "class %i (%s) %s rev %c%i\n",
483 stellaris_info
->target_class
,
484 StellarisClassname
[stellaris_info
->target_class
],
485 stellaris_info
->target_name
,
486 (int)('A' + ((stellaris_info
->did0
>> 8) & 0xFF)),
487 (int)((stellaris_info
->did0
) & 0xFF));
491 printed
= snprintf(buf
,
493 "did1: 0x%8.8" PRIx32
", arch: 0x%4.4" PRIx32
494 ", eproc: %s, ramsize: %ik, flashsize: %ik\n",
495 stellaris_info
->did1
,
496 stellaris_info
->did1
,
498 stellaris_info
->sramsiz
,
499 stellaris_info
->num_pages
* stellaris_info
->pagesize
/ 1024);
503 printed
= snprintf(buf
,
505 "master clock: %ikHz%s, "
506 "rcc is 0x%" PRIx32
", rcc2 is 0x%" PRIx32
"\n",
507 (int)(stellaris_info
->mck_freq
/ 1000),
508 stellaris_info
->mck_desc
,
510 stellaris_info
->rcc2
);
514 if (stellaris_info
->num_lockbits
> 0) {
517 "pagesize: %" PRIi32
", pages: %d, "
518 "lockbits: %i, pages per lockbit: %i\n",
519 stellaris_info
->pagesize
,
520 (unsigned) stellaris_info
->num_pages
,
521 stellaris_info
->num_lockbits
,
522 (unsigned) stellaris_info
->pages_in_lockregion
);
527 /***************************************************************************
528 * chip identification and status *
529 ***************************************************************************/
531 /* Set the flash timimg register to match current clocking */
532 static void stellaris_set_flash_timing(struct flash_bank
*bank
)
534 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
535 struct target
*target
= bank
->target
;
536 uint32_t usecrl
= (stellaris_info
->mck_freq
/1000000ul-1);
538 /* only valid for Sandstorm and Fury class devices */
539 if (stellaris_info
->target_class
> 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
= "";
625 mainfreq
= rcc_xtal
[xtal
];
628 mainfreq
= stellaris_info
->iosc_freq
;
629 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
632 mainfreq
= stellaris_info
->iosc_freq
/ 4;
633 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
635 case 3: /* lowspeed */
636 /* Sandstorm doesn't have this 30K +/- 30% osc */
638 stellaris_info
->mck_desc
= " (±30%)";
640 case 8: /* hibernation osc */
641 /* not all parts support hibernation */
645 default: /* NOTREACHED */
650 /* PLL is used if it's not bypassed; its output is 200 MHz
651 * even when it runs at 400 MHz (adds divide-by-two stage).
654 mainfreq
= 200000000;
657 stellaris_info
->mck_freq
= mainfreq
/(1 + sysdiv
);
659 stellaris_info
->mck_freq
= mainfreq
;
662 /* Read device id register, main clock frequency register and fill in driver info structure */
663 static int stellaris_read_part_info(struct flash_bank
*bank
)
665 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
666 struct target
*target
= bank
->target
;
667 uint32_t did0
, did1
, ver
, fam
;
670 /* Read and parse chip identification register */
671 target_read_u32(target
, SCB_BASE
| DID0
, &did0
);
672 target_read_u32(target
, SCB_BASE
| DID1
, &did1
);
673 target_read_u32(target
, SCB_BASE
| DC0
, &stellaris_info
->dc0
);
674 target_read_u32(target
, SCB_BASE
| DC1
, &stellaris_info
->dc1
);
675 LOG_DEBUG("did0 0x%" PRIx32
", did1 0x%" PRIx32
", dc0 0x%" PRIx32
", dc1 0x%" PRIx32
"",
676 did0
, did1
, stellaris_info
->dc0
, stellaris_info
->dc1
);
678 ver
= DID0_VER(did0
);
679 if ((ver
!= 0) && (ver
!= 1)) {
680 LOG_WARNING("Unknown did0 version, cannot identify target");
681 return ERROR_FLASH_OPERATION_FAILED
;
685 LOG_WARNING("Cannot identify target as a Stellaris");
686 return ERROR_FLASH_OPERATION_FAILED
;
690 fam
= (did1
>> 24) & 0xF;
691 if (((ver
!= 0) && (ver
!= 1)) || (fam
!= 0)) {
692 LOG_WARNING("Unknown did1 version/family.");
693 return ERROR_FLASH_OPERATION_FAILED
;
696 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
697 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
698 * even give _both_ numbers! We'll use current numbers; IOSC is
699 * always approximate.
701 * For Tempest: IOSC is calibrated, 16 MHz
702 * For Blizzard: IOSC is calibrated, 16 MHz
703 * For Firestorm: IOSC is calibrated, 16 MHz
705 stellaris_info
->iosc_freq
= 12000000;
706 stellaris_info
->iosc_desc
= " (±30%)";
707 stellaris_info
->xtal_mask
= 0x0f;
709 /* get device class */
710 if (DID0_VER(did0
) > 0) {
711 stellaris_info
->target_class
= (did0
>> 16) & 0xFF;
713 /* Sandstorm class */
714 stellaris_info
->target_class
= 0;
717 switch (stellaris_info
->target_class
) {
718 case 0: /* Sandstorm */
720 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
721 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
722 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
724 if (((did0
>> 8) & 0xff) < 2) {
725 stellaris_info
->iosc_freq
= 15000000;
726 stellaris_info
->iosc_desc
= " (±50%)";
733 case 4: /* Tempest */
734 case 5: /* Blizzard */
735 case 6: /* Firestorm */
736 case 0xa: /* Snowflake */
737 stellaris_info
->iosc_freq
= 16000000; /* +/- 1% */
738 stellaris_info
->iosc_desc
= " (±1%)";
741 case 3: /* DustDevil */
742 stellaris_info
->xtal_mask
= 0x1f;
746 LOG_WARNING("Unknown did0 class");
749 for (i
= 0; StellarisParts
[i
].partno
; i
++) {
750 if ((StellarisParts
[i
].partno
== ((did1
>> 16) & 0xFF)) &&
751 (StellarisParts
[i
].class == stellaris_info
->target_class
))
755 stellaris_info
->target_name
= StellarisParts
[i
].partname
;
757 stellaris_info
->did0
= did0
;
758 stellaris_info
->did1
= did1
;
760 if (stellaris_info
->target_class
== 5) { /* Blizzard */
761 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
762 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
764 stellaris_info
->num_lockbits
= 1 + (stellaris_info
->fsize
& 0xFFFF);
765 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->fsize
& 0xFFFF));
766 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
767 stellaris_info
->pagesize
= 1024;
768 stellaris_info
->pages_in_lockregion
= 2;
769 } else if (stellaris_info
->target_class
== 0xa) { /* Snowflake */
770 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
771 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
773 stellaris_info
->pagesize
= (1 << ((stellaris_info
->fsize
>> 16) & 7)) * 1024;
774 stellaris_info
->num_pages
= 2048 * (1 + (stellaris_info
->fsize
& 0xFFFF)) /
775 stellaris_info
->pagesize
;
776 stellaris_info
->pages_in_lockregion
= 1;
778 stellaris_info
->num_lockbits
= stellaris_info
->pagesize
* stellaris_info
->num_pages
/
780 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
782 stellaris_info
->num_lockbits
= 1 + (stellaris_info
->dc0
& 0xFFFF);
783 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->dc0
& 0xFFFF));
784 stellaris_info
->sramsiz
= (1 + ((stellaris_info
->dc0
>> 16) & 0xFFFF)) / 4;
785 stellaris_info
->pagesize
= 1024;
786 stellaris_info
->pages_in_lockregion
= 2;
789 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
790 * That exposes a 32-word Flash Write Buffer ... enabling
791 * writes of more than one word at a time.
797 /***************************************************************************
799 ***************************************************************************/
801 static int stellaris_protect_check(struct flash_bank
*bank
)
803 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
804 int status
= ERROR_OK
;
808 if (stellaris
->did1
== 0)
809 return ERROR_FLASH_BANK_NOT_PROBED
;
811 if (stellaris
->target_class
== 0xa) {
812 LOG_WARNING("Assuming flash to be unprotected on Snowflake");
816 for (i
= 0; i
< (unsigned) bank
->num_sectors
; i
++)
817 bank
->sectors
[i
].is_protected
= -1;
819 /* Read each Flash Memory Protection Program Enable (FMPPE) register
820 * to report any pages that we can't write. Ignore the Read Enable
823 for (i
= 0, page
= 0;
824 i
< DIV_ROUND_UP(stellaris
->num_lockbits
, 32u);
828 status
= target_read_u32(bank
->target
,
829 SCB_BASE
+ (i
? (FMPPE0
+ 4 * i
) : FMPPE
),
831 LOG_DEBUG("FMPPE%d = %#8.8x (status %d)", i
,
832 (unsigned) lockbits
, status
);
833 if (status
!= ERROR_OK
)
836 for (unsigned j
= 0; j
< 32; j
++) {
839 for (k
= 0; k
< stellaris
->pages_in_lockregion
; k
++) {
840 if (page
>= (unsigned) bank
->num_sectors
)
842 bank
->sectors
[page
++].is_protected
=
843 !(lockbits
& (1 << j
));
852 static int stellaris_erase(struct flash_bank
*bank
, int first
, int last
)
855 uint32_t flash_fmc
, flash_cris
;
856 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
857 struct target
*target
= bank
->target
;
859 if (bank
->target
->state
!= TARGET_HALTED
) {
860 LOG_ERROR("Target not halted");
861 return ERROR_TARGET_NOT_HALTED
;
864 if (stellaris_info
->did1
== 0)
865 return ERROR_FLASH_BANK_NOT_PROBED
;
867 if ((first
< 0) || (last
< first
) || (last
>= (int)stellaris_info
->num_pages
))
868 return ERROR_FLASH_SECTOR_INVALID
;
870 if ((first
== 0) && (last
== ((int)stellaris_info
->num_pages
-1)))
871 return stellaris_mass_erase(bank
);
873 /* Refresh flash controller timing */
874 stellaris_read_clock_info(bank
);
875 stellaris_set_flash_timing(bank
);
877 /* Clear and disable flash programming interrupts */
878 target_write_u32(target
, FLASH_CIM
, 0);
879 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
881 /* REVISIT this clobbers state set by any halted firmware ...
882 * it might want to process those IRQs.
885 for (banknr
= first
; banknr
<= last
; banknr
++) {
886 /* Address is first word in page */
887 target_write_u32(target
, FLASH_FMA
, banknr
* stellaris_info
->pagesize
);
888 /* Write erase command */
889 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_ERASE
);
890 /* Wait until erase complete */
892 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
893 } while (flash_fmc
& FMC_ERASE
);
895 /* Check acess violations */
896 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
897 if (flash_cris
& (AMASK
)) {
898 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32
"",
900 target_write_u32(target
, FLASH_CRIS
, 0);
901 return ERROR_FLASH_OPERATION_FAILED
;
904 bank
->sectors
[banknr
].is_erased
= 1;
910 static int stellaris_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
912 uint32_t fmppe
, flash_fmc
, flash_cris
;
915 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
916 struct target
*target
= bank
->target
;
918 if (bank
->target
->state
!= TARGET_HALTED
) {
919 LOG_ERROR("Target not halted");
920 return ERROR_TARGET_NOT_HALTED
;
924 LOG_ERROR("Hardware doesn't support page-level unprotect. "
925 "Try the 'recover' command.");
926 return ERROR_COMMAND_SYNTAX_ERROR
;
929 if (stellaris_info
->did1
== 0)
930 return ERROR_FLASH_BANK_NOT_PROBED
;
932 if (stellaris_info
->target_class
== 0xa) {
933 LOG_ERROR("Protection on Snowflake is not supported yet");
934 return ERROR_FLASH_OPERATION_FAILED
;
937 /* lockregions are 2 pages ... must protect [even..odd] */
938 if ((first
< 0) || (first
& 1)
939 || (last
< first
) || !(last
& 1)
940 || (last
>= 2 * stellaris_info
->num_lockbits
)) {
941 LOG_ERROR("Can't protect unaligned or out-of-range pages.");
942 return ERROR_FLASH_SECTOR_INVALID
;
945 /* Refresh flash controller timing */
946 stellaris_read_clock_info(bank
);
947 stellaris_set_flash_timing(bank
);
949 /* convert from pages to lockregions */
953 /* FIXME this assumes single FMPPE, for a max of 64K of flash!!
954 * Current parts can be much bigger.
957 LOG_ERROR("No support yet for protection > 64K");
958 return ERROR_FLASH_OPERATION_FAILED
;
961 target_read_u32(target
, SCB_BASE
| FMPPE
, &fmppe
);
963 for (lockregion
= first
; lockregion
<= last
; lockregion
++)
964 fmppe
&= ~(1 << lockregion
);
966 /* Clear and disable flash programming interrupts */
967 target_write_u32(target
, FLASH_CIM
, 0);
968 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
970 /* REVISIT this clobbers state set by any halted firmware ...
971 * it might want to process those IRQs.
974 LOG_DEBUG("fmppe 0x%" PRIx32
"", fmppe
);
975 target_write_u32(target
, SCB_BASE
| FMPPE
, fmppe
);
978 target_write_u32(target
, FLASH_FMA
, 1);
980 /* Write commit command */
981 /* REVISIT safety check, since this cannot be undone
982 * except by the "Recover a locked device" procedure.
983 * REVISIT DustDevil-A0 parts have an erratum making FMPPE commits
984 * inadvisable ... it makes future mass erase operations fail.
986 LOG_WARNING("Flash protection cannot be removed once committed, commit is NOT executed !");
987 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
989 /* Wait until erase complete */
991 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
992 } while (flash_fmc
& FMC_COMT
);
994 /* Check acess violations */
995 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
996 if (flash_cris
& (AMASK
)) {
997 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32
"", flash_cris
);
998 target_write_u32(target
, FLASH_CRIS
, 0);
999 return ERROR_FLASH_OPERATION_FAILED
;
1005 /* see contib/loaders/flash/stellaris.s for src */
1007 static const uint8_t stellaris_write_code
[] = {
1009 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */
1010 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */
1012 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
1013 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
1014 0x17, 0xD0, /* beq exit */
1015 0x47, 0x68, /* ldr r7, [r0, #4] */
1016 0x47, 0x45, /* cmp r7, r8 */
1017 0xF7, 0xD0, /* beq wait_fifo */
1019 0x22, 0x60, /* str r2, [r4, #0] */
1020 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */
1021 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */
1022 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */
1023 0xA5, 0x60, /* str r5, [r4, #8] */
1025 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */
1026 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */
1027 0xFA, 0xD1, /* bne busy */
1028 0x8F, 0x42, /* cmp r7, r1 */
1029 0x28, 0xBF, /* it cs */
1030 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
1031 0x47, 0x60, /* str r7, [r0, #4] */
1032 0x01, 0x3B, /* subs r3, r3, #1 */
1033 0x03, 0xB1, /* cbz r3, exit */
1034 0xE2, 0xE7, /* b wait_fifo */
1036 0x00, 0xBE, /* bkpt #0 */
1038 /* pFLASH_CTRL_BASE: */
1039 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
1040 /* FLASHWRITECMD: */
1041 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
1043 static int stellaris_write_block(struct flash_bank
*bank
,
1044 const uint8_t *buffer
, uint32_t offset
, uint32_t wcount
)
1046 struct target
*target
= bank
->target
;
1047 uint32_t buffer_size
= 16384;
1048 struct working_area
*source
;
1049 struct working_area
*write_algorithm
;
1050 uint32_t address
= bank
->base
+ offset
;
1051 struct reg_param reg_params
[4];
1052 struct armv7m_algorithm armv7m_info
;
1053 int retval
= ERROR_OK
;
1055 /* power of two, and multiple of word size */
1056 static const unsigned buf_min
= 128;
1058 /* for small buffers it's faster not to download an algorithm */
1059 if (wcount
* 4 < buf_min
)
1060 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1062 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" wcount=%08" PRIx32
"",
1063 bank
, buffer
, offset
, wcount
);
1065 /* flash write code */
1066 if (target_alloc_working_area(target
, sizeof(stellaris_write_code
),
1067 &write_algorithm
) != ERROR_OK
) {
1068 LOG_DEBUG("no working area for block memory writes");
1069 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1072 /* plus a buffer big enough for this data */
1073 if (wcount
* 4 < buffer_size
)
1074 buffer_size
= wcount
* 4;
1077 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
1079 if (buffer_size
<= buf_min
) {
1080 target_free_working_area(target
, write_algorithm
);
1081 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1083 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1084 target_name(target
), (unsigned) buffer_size
);
1087 target_write_buffer(target
, write_algorithm
->address
,
1088 sizeof(stellaris_write_code
),
1089 stellaris_write_code
);
1091 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
1092 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
1094 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1095 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1096 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
1097 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
1099 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
1100 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
1101 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
1102 buf_set_u32(reg_params
[3].value
, 0, 32, wcount
);
1104 retval
= target_run_flash_async_algorithm(target
, buffer
, wcount
, 4,
1107 source
->address
, source
->size
,
1108 write_algorithm
->address
, 0,
1111 if (retval
== ERROR_FLASH_OPERATION_FAILED
)
1112 LOG_ERROR("error %d executing stellaris flash write algorithm", retval
);
1114 target_free_working_area(target
, write_algorithm
);
1115 target_free_working_area(target
, source
);
1117 destroy_reg_param(®_params
[0]);
1118 destroy_reg_param(®_params
[1]);
1119 destroy_reg_param(®_params
[2]);
1120 destroy_reg_param(®_params
[3]);
1125 static int stellaris_write(struct flash_bank
*bank
, const uint8_t *buffer
,
1126 uint32_t offset
, uint32_t count
)
1128 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1129 struct target
*target
= bank
->target
;
1130 uint32_t address
= offset
;
1131 uint32_t flash_cris
, flash_fmc
;
1132 uint32_t words_remaining
= (count
/ 4);
1133 uint32_t bytes_remaining
= (count
& 0x00000003);
1134 uint32_t bytes_written
= 0;
1137 if (bank
->target
->state
!= TARGET_HALTED
) {
1138 LOG_ERROR("Target not halted");
1139 return ERROR_TARGET_NOT_HALTED
;
1142 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" count=%08" PRIx32
"",
1143 bank
, buffer
, offset
, count
);
1145 if (stellaris_info
->did1
== 0)
1146 return ERROR_FLASH_BANK_NOT_PROBED
;
1149 LOG_WARNING("offset size must be word aligned");
1150 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1153 if (offset
+ count
> bank
->size
)
1154 return ERROR_FLASH_DST_OUT_OF_BANK
;
1156 /* Refresh flash controller timing */
1157 stellaris_read_clock_info(bank
);
1158 stellaris_set_flash_timing(bank
);
1160 /* Clear and disable flash programming interrupts */
1161 target_write_u32(target
, FLASH_CIM
, 0);
1162 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1164 /* REVISIT this clobbers state set by any halted firmware ...
1165 * it might want to process those IRQs.
1168 /* multiple words to be programmed? */
1169 if (words_remaining
> 0) {
1170 /* try using a block write */
1171 retval
= stellaris_write_block(bank
, buffer
, offset
,
1173 if (retval
!= ERROR_OK
) {
1174 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
1175 LOG_DEBUG("writing flash word-at-a-time");
1176 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
1177 /* if an error occured, we examine the reason, and quit */
1178 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1180 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32
"", flash_cris
);
1181 return ERROR_FLASH_OPERATION_FAILED
;
1184 buffer
+= words_remaining
* 4;
1185 address
+= words_remaining
* 4;
1186 words_remaining
= 0;
1190 while (words_remaining
> 0) {
1191 if (!(address
& 0xff))
1192 LOG_DEBUG("0x%" PRIx32
"", address
);
1194 /* Program one word */
1195 target_write_u32(target
, FLASH_FMA
, address
);
1196 target_write_buffer(target
, FLASH_FMD
, 4, buffer
);
1197 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1198 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1199 /* Wait until write complete */
1201 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1202 } while (flash_fmc
& FMC_WRITE
);
1209 if (bytes_remaining
) {
1210 uint8_t last_word
[4] = {0xff, 0xff, 0xff, 0xff};
1212 /* copy the last remaining bytes into the write buffer */
1213 memcpy(last_word
, buffer
+bytes_written
, bytes_remaining
);
1215 if (!(address
& 0xff))
1216 LOG_DEBUG("0x%" PRIx32
"", address
);
1218 /* Program one word */
1219 target_write_u32(target
, FLASH_FMA
, address
);
1220 target_write_buffer(target
, FLASH_FMD
, 4, last_word
);
1221 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1222 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1223 /* Wait until write complete */
1225 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1226 } while (flash_fmc
& FMC_WRITE
);
1229 /* Check access violations */
1230 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1231 if (flash_cris
& (AMASK
)) {
1232 LOG_DEBUG("flash_cris 0x%" PRIx32
"", flash_cris
);
1233 return ERROR_FLASH_OPERATION_FAILED
;
1238 static int stellaris_probe(struct flash_bank
*bank
)
1240 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1243 /* If this is a stellaris chip, it has flash; probe() is just
1244 * to figure out how much is present. Only do it once.
1246 if (stellaris_info
->did1
!= 0)
1249 /* stellaris_read_part_info() already handled error checking and
1250 * reporting. Note that it doesn't write, so we don't care about
1251 * whether the target is halted or not.
1253 retval
= stellaris_read_part_info(bank
);
1254 if (retval
!= ERROR_OK
)
1257 if (bank
->sectors
) {
1258 free(bank
->sectors
);
1259 bank
->sectors
= NULL
;
1262 /* provide this for the benefit of the NOR flash framework */
1263 bank
->size
= stellaris_info
->num_pages
* stellaris_info
->pagesize
;
1264 bank
->num_sectors
= stellaris_info
->num_pages
;
1265 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
1266 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
1267 bank
->sectors
[i
].offset
= i
* stellaris_info
->pagesize
;
1268 bank
->sectors
[i
].size
= stellaris_info
->pagesize
;
1269 bank
->sectors
[i
].is_erased
= -1;
1270 bank
->sectors
[i
].is_protected
= -1;
1276 static int stellaris_mass_erase(struct flash_bank
*bank
)
1278 struct target
*target
= NULL
;
1279 struct stellaris_flash_bank
*stellaris_info
= NULL
;
1282 stellaris_info
= bank
->driver_priv
;
1283 target
= bank
->target
;
1285 if (target
->state
!= TARGET_HALTED
) {
1286 LOG_ERROR("Target not halted");
1287 return ERROR_TARGET_NOT_HALTED
;
1290 if (stellaris_info
->did1
== 0)
1291 return ERROR_FLASH_BANK_NOT_PROBED
;
1293 /* Refresh flash controller timing */
1294 stellaris_read_clock_info(bank
);
1295 stellaris_set_flash_timing(bank
);
1297 /* Clear and disable flash programming interrupts */
1298 target_write_u32(target
, FLASH_CIM
, 0);
1299 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1301 /* REVISIT this clobbers state set by any halted firmware ...
1302 * it might want to process those IRQs.
1305 target_write_u32(target
, FLASH_FMA
, 0);
1306 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1307 /* Wait until erase complete */
1309 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1310 } while (flash_fmc
& FMC_MERASE
);
1312 /* if device has > 128k, then second erase cycle is needed
1313 * this is only valid for older devices, but will not hurt */
1314 if (stellaris_info
->num_pages
* stellaris_info
->pagesize
> 0x20000) {
1315 target_write_u32(target
, FLASH_FMA
, 0x20000);
1316 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1317 /* Wait until erase complete */
1319 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1320 } while (flash_fmc
& FMC_MERASE
);
1326 COMMAND_HANDLER(stellaris_handle_mass_erase_command
)
1331 return ERROR_COMMAND_SYNTAX_ERROR
;
1333 struct flash_bank
*bank
;
1334 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1335 if (ERROR_OK
!= retval
)
1338 if (stellaris_mass_erase(bank
) == ERROR_OK
) {
1339 /* set all sectors as erased */
1340 for (i
= 0; i
< bank
->num_sectors
; i
++)
1341 bank
->sectors
[i
].is_erased
= 1;
1343 command_print(CMD_CTX
, "stellaris mass erase complete");
1345 command_print(CMD_CTX
, "stellaris mass erase failed");
1351 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1352 * This performs a mass erase and then restores all nonvolatile registers
1353 * (including USER_* registers and flash lock bits) to their defaults.
1354 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1356 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1357 * can affect this operation if flash protection has been enabled.
1359 COMMAND_HANDLER(stellaris_handle_recover_command
)
1361 struct flash_bank
*bank
;
1364 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1365 if (retval
!= ERROR_OK
)
1368 /* REVISIT ... it may be worth sanity checking that the AP is
1369 * inactive before we start. ARM documents that switching a DP's
1370 * mode while it's active can cause fault modes that need a power
1375 if (!(jtag_get_reset_config() & RESET_HAS_SRST
)) {
1376 LOG_ERROR("Can't recover Stellaris flash without SRST");
1379 adapter_assert_reset();
1381 for (int i
= 0; i
< 5; i
++) {
1382 retval
= dap_to_swd(bank
->target
);
1383 if (retval
!= ERROR_OK
)
1386 retval
= dap_to_jtag(bank
->target
);
1387 if (retval
!= ERROR_OK
)
1391 /* de-assert SRST */
1392 adapter_deassert_reset();
1393 retval
= jtag_execute_queue();
1395 /* wait 400+ msec ... OK, "1+ second" is simpler */
1398 /* USER INTERVENTION required for the power cycle
1399 * Restarting OpenOCD is likely needed because of mode switching.
1401 LOG_INFO("USER ACTION: "
1402 "power cycle Stellaris chip, then restart OpenOCD.");
1408 static const struct command_registration stellaris_exec_command_handlers
[] = {
1410 .name
= "mass_erase",
1412 .handler
= stellaris_handle_mass_erase_command
,
1413 .mode
= COMMAND_EXEC
,
1414 .help
= "erase entire device",
1418 .handler
= stellaris_handle_recover_command
,
1419 .mode
= COMMAND_EXEC
,
1421 .help
= "recover (and erase) locked device",
1423 COMMAND_REGISTRATION_DONE
1425 static const struct command_registration stellaris_command_handlers
[] = {
1427 .name
= "stellaris",
1428 .mode
= COMMAND_EXEC
,
1429 .help
= "Stellaris flash command group",
1431 .chain
= stellaris_exec_command_handlers
,
1433 COMMAND_REGISTRATION_DONE
1436 struct flash_driver stellaris_flash
= {
1437 .name
= "stellaris",
1438 .commands
= stellaris_command_handlers
,
1439 .flash_bank_command
= stellaris_flash_bank_command
,
1440 .erase
= stellaris_erase
,
1441 .protect
= stellaris_protect
,
1442 .write
= stellaris_write
,
1443 .read
= default_flash_read
,
1444 .probe
= stellaris_probe
,
1445 .auto_probe
= stellaris_probe
,
1446 .erase_check
= default_flash_blank_check
,
1447 .protect_check
= stellaris_protect_check
,
1448 .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)