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, 0x01, "LM4F120B2QR/TM4C1233C3PM"},
369 {0x05, 0x02, "LM4F120C4QR/TM4C1233D5PM"},
370 {0x05, 0x03, "LM4F120E5QR/TM4C1233E6PM"},
371 {0x05, 0x04, "LM4F120H5QR/TM4C1233H6PM"},
372 {0x05, 0x08, "LM4F121B2QR/TM4C1232C3PM"},
373 {0x05, 0x09, "LM4F121C4QR/TM4C1232D5PM"},
374 {0x05, 0x0A, "LM4F121E5QR/TM4C1232E6PM"},
375 {0x05, 0x0B, "LM4F121H5QR/TM4C1232H6PM"},
376 {0x05, 0x10, "LM4F110E5QR/TM4C1231E6PM"},
377 {0x05, 0x11, "LM4F110H5QR/TM4C1231H6PM"},
378 {0x05, 0x18, "LM4F110B2QR/TM4C1231C3PM"},
379 {0x05, 0x19, "LM4F110C4QR/TM4C1231D5PM"},
380 {0x05, 0x20, "LM4F111E5QR/TM4C1230E6PM"},
381 {0x05, 0x21, "LM4F111H5QR/TM4C1230H6PM"},
382 {0x05, 0x22, "LM4F111B2QR/TM4C1230C3PM"},
383 {0x05, 0x23, "LM4F111C4QR/TM4C1230D5PM"},
384 {0x05, 0x30, "LM4F112E5QC/TM4C1231E6PZ"},
385 {0x05, 0x31, "LM4F112H5QC/TM4C1231H6PZ"},
386 {0x05, 0x35, "LM4F112H5QD/TM4C1231H6PGE"},
387 {0x05, 0x36, "LM4F112C4QC/TM4C1231D5PZ"},
388 {0x05, 0x40, "LM4F130E5QR/TM4C1237E6PM"},
389 {0x05, 0x41, "LM4F130H5QR/TM4C1237H6PM"},
390 {0x05, 0x48, "LM4F130C4QR/TM4C1237D5PM"},
391 {0x05, 0x50, "LM4F131E5QR/TM4C1236E6PM"},
392 {0x05, 0x51, "LM4F131H5QR/TM4C1236H6PM"},
393 {0x05, 0x52, "LM4F131C4QR/TM4C1236D5PM"},
394 {0x05, 0x60, "LM4F132E5QC/TM4C1237E6PZ"},
395 {0x05, 0x61, "LM4F132H5QC/TM4C1237H6PZ"},
396 {0x05, 0x65, "LM4F132H5QD/TM4C1237H6PGE"},
397 {0x05, 0x66, "LM4F132C4QC/TM4C1237D5PZ"},
398 {0x05, 0x70, "LM4F210E5QR/TM4C123BE6PM"},
399 {0x05, 0x73, "LM4F210H5QR/TM4C123BH6PM"},
400 {0x05, 0x80, "LM4F211E5QR/TM4C123AE6PM"},
401 {0x05, 0x83, "LM4F211H5QR/TM4C123AH6PM"},
402 {0x05, 0xA0, "LM4F230E5QR/TM4C123GE6PM"},
403 {0x05, 0xA1, "LM4F230H5QR/TM4C123GH6PM"},
404 {0x05, 0xB0, "LM4F231E5QR/TM4C123FE6PM"},
405 {0x05, 0xB1, "LM4F231H5QR/TM4C123FH6PM"},
406 {0x05, 0xC0, "LM4F232E5QC/TM4C123GE6PZ"},
407 {0x05, 0xC1, "LM4F232H5QC/TM4C123GH6PZ"},
408 {0x05, 0xC3, "LM4F212E5QC/TM4C123BE6PZ"},
409 {0x05, 0xC4, "LM4F212H5QC/TM4C123BH6PZ"},
410 {0x05, 0xC5, "LM4F232H5QD/TM4C123GH6PGE"},
411 {0x05, 0xC6, "LM4F212H5QD/TM4C123BH6PGE"},
412 {0x05, 0xD0, "LM4F122C4QC/TM4C1233D5PZ"},
413 {0x05, 0xD1, "LM4F122E5QC/TM4C1233E6PZ"},
414 {0x05, 0xD2, "LM4F122H5QC/TM4C1233H6PZ"},
415 {0x05, 0xD6, "LM4F122H5QD/TM4C1233H6PGE"},
416 {0x05, 0xE1, "LM4FSXLH5BB"},
417 {0x05, 0xE3, "LM4F232H5BB/TM4C123GH6ZRB"},
418 {0x05, 0xE4, "LM4FS99H5BB"},
419 {0x05, 0xE5, "LM4FS1AH5BB"},
420 {0x05, 0xE9, "LM4F212H5BB/TM4C123BH6ZRB"},
421 {0x05, 0xEA, "LM4FS1GH5BB"},
422 {0x05, 0xF0, "TM4C123GH6ZXR"},
423 {0x0A, 0x19, "TM4C1290NCPDT"},
424 {0x0A, 0x1B, "TM4C1290NCZAD"},
425 {0x0A, 0x1C, "TM4C1292NCPDT"},
426 {0x0A, 0x1E, "TM4C1292NCZAD"},
427 {0x0A, 0x1F, "TM4C1294NCPDT"},
428 {0x0A, 0x21, "TM4C1294NCZAD"},
429 {0x0A, 0x22, "TM4C1297NCZAD"},
430 {0x0A, 0x23, "TM4C1299NCZAD"},
431 {0x0A, 0x24, "TM4C129CNCPDT"},
432 {0x0A, 0x26, "TM4C129CNCZAD"},
433 {0x0A, 0x27, "TM4C129DNCPDT"},
434 {0x0A, 0x29, "TM4C129DNCZAD"},
435 {0x0A, 0x2D, "TM4C129ENCPDT"},
436 {0x0A, 0x2F, "TM4C129ENCZAD"},
437 {0x0A, 0x30, "TM4C129LNCZAD"},
438 {0x0A, 0x32, "TM4C129XNCZAD"},
439 {0x0A, 0x34, "TM4C1294KCPDT"},
440 {0x0A, 0x35, "TM4C129EKCPDT"},
441 {0x0A, 0x36, "TM4C1299KCZAD"},
442 {0x0A, 0x37, "TM4C129XKCZAD"},
443 {0xFF, 0x00, "Unknown Part"}
446 static const char * const StellarisClassname
[] = {
460 /***************************************************************************
461 * openocd command interface *
462 ***************************************************************************/
464 /* flash_bank stellaris <base> <size> 0 0 <target#>
466 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command
)
468 struct stellaris_flash_bank
*stellaris_info
;
471 return ERROR_COMMAND_SYNTAX_ERROR
;
473 stellaris_info
= calloc(sizeof(struct stellaris_flash_bank
), 1);
475 bank
->driver_priv
= stellaris_info
;
477 stellaris_info
->target_name
= "Unknown target";
479 /* part wasn't probed for info yet */
480 stellaris_info
->did1
= 0;
482 /* TODO Specify the main crystal speed in kHz using an optional
483 * argument; ditto, the speed of an external oscillator used
484 * instead of a crystal. Avoid programming flash using IOSC.
489 static int get_stellaris_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
492 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
494 if (stellaris_info
->did1
== 0)
495 return ERROR_FLASH_BANK_NOT_PROBED
;
497 /* Read main and master clock freqency register */
498 stellaris_read_clock_info(bank
);
500 printed
= snprintf(buf
,
502 "\nTI/LMI Stellaris information: Chip is "
503 "class %i (%s) %s rev %c%i\n",
504 stellaris_info
->target_class
,
505 StellarisClassname
[stellaris_info
->target_class
],
506 stellaris_info
->target_name
,
507 (int)('A' + ((stellaris_info
->did0
>> 8) & 0xFF)),
508 (int)((stellaris_info
->did0
) & 0xFF));
512 printed
= snprintf(buf
,
514 "did1: 0x%8.8" PRIx32
", arch: 0x%4.4" PRIx32
515 ", eproc: %s, ramsize: %ik, flashsize: %ik\n",
516 stellaris_info
->did1
,
517 stellaris_info
->did1
,
519 stellaris_info
->sramsiz
,
520 stellaris_info
->num_pages
* stellaris_info
->pagesize
/ 1024);
524 printed
= snprintf(buf
,
526 "master clock: %ikHz%s, "
527 "rcc is 0x%" PRIx32
", rcc2 is 0x%" PRIx32
"\n",
528 (int)(stellaris_info
->mck_freq
/ 1000),
529 stellaris_info
->mck_desc
,
531 stellaris_info
->rcc2
);
535 if (stellaris_info
->num_lockbits
> 0) {
538 "pagesize: %" PRIi32
", pages: %d, "
539 "lockbits: %i, pages per lockbit: %i\n",
540 stellaris_info
->pagesize
,
541 (unsigned) stellaris_info
->num_pages
,
542 stellaris_info
->num_lockbits
,
543 (unsigned) stellaris_info
->pages_in_lockregion
);
548 /***************************************************************************
549 * chip identification and status *
550 ***************************************************************************/
552 /* Set the flash timimg register to match current clocking */
553 static void stellaris_set_flash_timing(struct flash_bank
*bank
)
555 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
556 struct target
*target
= bank
->target
;
557 uint32_t usecrl
= (stellaris_info
->mck_freq
/1000000ul-1);
559 /* only valid for Sandstorm and Fury class devices */
560 if (stellaris_info
->target_class
> 1)
563 LOG_DEBUG("usecrl = %i", (int)(usecrl
));
564 target_write_u32(target
, SCB_BASE
| USECRL
, usecrl
);
567 static const unsigned rcc_xtal
[32] = {
568 [0x00] = 1000000, /* no pll */
569 [0x01] = 1843200, /* no pll */
570 [0x02] = 2000000, /* no pll */
571 [0x03] = 2457600, /* no pll */
575 [0x06] = 4000000, /* usb */
579 [0x09] = 5000000, /* usb */
581 [0x0b] = 6000000, /* (reset) usb */
585 [0x0e] = 8000000, /* usb */
588 /* parts before DustDevil use just 4 bits for xtal spec */
590 [0x10] = 10000000, /* usb */
591 [0x11] = 12000000, /* usb */
596 [0x15] = 16000000, /* usb */
600 /** Read clock configuration and set stellaris_info->usec_clocks. */
601 static void stellaris_read_clock_info(struct flash_bank
*bank
)
603 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
604 struct target
*target
= bank
->target
;
605 uint32_t rcc
, rcc2
, pllcfg
, sysdiv
, usesysdiv
, bypass
, oscsrc
;
607 unsigned long mainfreq
;
609 target_read_u32(target
, SCB_BASE
| RCC
, &rcc
);
610 LOG_DEBUG("Stellaris RCC %" PRIx32
"", rcc
);
612 target_read_u32(target
, SCB_BASE
| RCC2
, &rcc2
);
613 LOG_DEBUG("Stellaris RCC2 %" PRIx32
"", rcc
);
615 target_read_u32(target
, SCB_BASE
| PLLCFG
, &pllcfg
);
616 LOG_DEBUG("Stellaris PLLCFG %" PRIx32
"", pllcfg
);
618 stellaris_info
->rcc
= rcc
;
619 stellaris_info
->rcc
= rcc2
;
621 sysdiv
= (rcc
>> 23) & 0xF;
622 usesysdiv
= (rcc
>> 22) & 0x1;
623 bypass
= (rcc
>> 11) & 0x1;
624 oscsrc
= (rcc
>> 4) & 0x3;
625 xtal
= (rcc
>> 6) & stellaris_info
->xtal_mask
;
627 /* NOTE: post-Sandstorm parts have RCC2 which may override
628 * parts of RCC ... with more sysdiv options, option for
629 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
630 * as zero, so the "use RCC2" flag is always clear.
632 if (rcc2
& (1 << 31)) {
633 sysdiv
= (rcc2
>> 23) & 0x3F;
634 bypass
= (rcc2
>> 11) & 0x1;
635 oscsrc
= (rcc2
>> 4) & 0x7;
637 /* FIXME Tempest parts have an additional lsb for
638 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
642 stellaris_info
->mck_desc
= "";
646 mainfreq
= rcc_xtal
[xtal
];
649 mainfreq
= stellaris_info
->iosc_freq
;
650 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
653 mainfreq
= stellaris_info
->iosc_freq
/ 4;
654 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
656 case 3: /* lowspeed */
657 /* Sandstorm doesn't have this 30K +/- 30% osc */
659 stellaris_info
->mck_desc
= " (±30%)";
661 case 8: /* hibernation osc */
662 /* not all parts support hibernation */
666 default: /* NOTREACHED */
671 /* PLL is used if it's not bypassed; its output is 200 MHz
672 * even when it runs at 400 MHz (adds divide-by-two stage).
675 mainfreq
= 200000000;
678 stellaris_info
->mck_freq
= mainfreq
/(1 + sysdiv
);
680 stellaris_info
->mck_freq
= mainfreq
;
683 /* Read device id register, main clock frequency register and fill in driver info structure */
684 static int stellaris_read_part_info(struct flash_bank
*bank
)
686 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
687 struct target
*target
= bank
->target
;
688 uint32_t did0
, did1
, ver
, fam
;
691 /* Read and parse chip identification register */
692 target_read_u32(target
, SCB_BASE
| DID0
, &did0
);
693 target_read_u32(target
, SCB_BASE
| DID1
, &did1
);
694 target_read_u32(target
, SCB_BASE
| DC0
, &stellaris_info
->dc0
);
695 target_read_u32(target
, SCB_BASE
| DC1
, &stellaris_info
->dc1
);
696 LOG_DEBUG("did0 0x%" PRIx32
", did1 0x%" PRIx32
", dc0 0x%" PRIx32
", dc1 0x%" PRIx32
"",
697 did0
, did1
, stellaris_info
->dc0
, stellaris_info
->dc1
);
699 ver
= DID0_VER(did0
);
700 if ((ver
!= 0) && (ver
!= 1)) {
701 LOG_WARNING("Unknown did0 version, cannot identify target");
702 return ERROR_FLASH_OPERATION_FAILED
;
706 LOG_WARNING("Cannot identify target as a Stellaris");
707 return ERROR_FLASH_OPERATION_FAILED
;
711 fam
= (did1
>> 24) & 0xF;
712 if (((ver
!= 0) && (ver
!= 1)) || (fam
!= 0)) {
713 LOG_WARNING("Unknown did1 version/family.");
714 return ERROR_FLASH_OPERATION_FAILED
;
717 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
718 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
719 * even give _both_ numbers! We'll use current numbers; IOSC is
720 * always approximate.
722 * For Tempest: IOSC is calibrated, 16 MHz
723 * For Blizzard: IOSC is calibrated, 16 MHz
724 * For Firestorm: IOSC is calibrated, 16 MHz
726 stellaris_info
->iosc_freq
= 12000000;
727 stellaris_info
->iosc_desc
= " (±30%)";
728 stellaris_info
->xtal_mask
= 0x0f;
730 /* get device class */
731 if (DID0_VER(did0
) > 0) {
732 stellaris_info
->target_class
= (did0
>> 16) & 0xFF;
734 /* Sandstorm class */
735 stellaris_info
->target_class
= 0;
738 switch (stellaris_info
->target_class
) {
739 case 0: /* Sandstorm */
741 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
742 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
743 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
745 if (((did0
>> 8) & 0xff) < 2) {
746 stellaris_info
->iosc_freq
= 15000000;
747 stellaris_info
->iosc_desc
= " (±50%)";
754 case 4: /* Tempest */
755 case 5: /* Blizzard */
756 case 6: /* Firestorm */
757 case 0xa: /* Snowflake */
758 stellaris_info
->iosc_freq
= 16000000; /* +/- 1% */
759 stellaris_info
->iosc_desc
= " (±1%)";
762 case 3: /* DustDevil */
763 stellaris_info
->xtal_mask
= 0x1f;
767 LOG_WARNING("Unknown did0 class");
770 for (i
= 0; StellarisParts
[i
].partno
; i
++) {
771 if ((StellarisParts
[i
].partno
== ((did1
>> 16) & 0xFF)) &&
772 (StellarisParts
[i
].class == stellaris_info
->target_class
))
776 stellaris_info
->target_name
= StellarisParts
[i
].partname
;
778 stellaris_info
->did0
= did0
;
779 stellaris_info
->did1
= did1
;
781 if (stellaris_info
->target_class
== 5) { /* Blizzard */
782 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
783 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
785 stellaris_info
->num_lockbits
= 1 + (stellaris_info
->fsize
& 0xFFFF);
786 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->fsize
& 0xFFFF));
787 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
788 stellaris_info
->pagesize
= 1024;
789 stellaris_info
->pages_in_lockregion
= 2;
790 } else if (stellaris_info
->target_class
== 0xa) { /* Snowflake */
791 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
792 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
794 stellaris_info
->pagesize
= (1 << ((stellaris_info
->fsize
>> 16) & 7)) * 1024;
795 stellaris_info
->num_pages
= 2048 * (1 + (stellaris_info
->fsize
& 0xFFFF)) /
796 stellaris_info
->pagesize
;
797 stellaris_info
->pages_in_lockregion
= 1;
799 stellaris_info
->num_lockbits
= stellaris_info
->pagesize
* stellaris_info
->num_pages
/
801 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
803 stellaris_info
->num_lockbits
= 1 + (stellaris_info
->dc0
& 0xFFFF);
804 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->dc0
& 0xFFFF));
805 stellaris_info
->sramsiz
= (1 + ((stellaris_info
->dc0
>> 16) & 0xFFFF)) / 4;
806 stellaris_info
->pagesize
= 1024;
807 stellaris_info
->pages_in_lockregion
= 2;
810 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
811 * That exposes a 32-word Flash Write Buffer ... enabling
812 * writes of more than one word at a time.
818 /***************************************************************************
820 ***************************************************************************/
822 static int stellaris_protect_check(struct flash_bank
*bank
)
824 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
825 int status
= ERROR_OK
;
829 if (stellaris
->did1
== 0)
830 return ERROR_FLASH_BANK_NOT_PROBED
;
832 if (stellaris
->target_class
== 0xa) {
833 LOG_WARNING("Assuming flash to be unprotected on Snowflake");
837 for (i
= 0; i
< (unsigned) bank
->num_sectors
; i
++)
838 bank
->sectors
[i
].is_protected
= -1;
840 /* Read each Flash Memory Protection Program Enable (FMPPE) register
841 * to report any pages that we can't write. Ignore the Read Enable
844 for (i
= 0, page
= 0;
845 i
< DIV_ROUND_UP(stellaris
->num_lockbits
, 32u);
849 status
= target_read_u32(bank
->target
,
850 SCB_BASE
+ (i
? (FMPPE0
+ 4 * i
) : FMPPE
),
852 LOG_DEBUG("FMPPE%d = %#8.8x (status %d)", i
,
853 (unsigned) lockbits
, status
);
854 if (status
!= ERROR_OK
)
857 for (unsigned j
= 0; j
< 32; j
++) {
860 for (k
= 0; k
< stellaris
->pages_in_lockregion
; k
++) {
861 if (page
>= (unsigned) bank
->num_sectors
)
863 bank
->sectors
[page
++].is_protected
=
864 !(lockbits
& (1 << j
));
873 static int stellaris_erase(struct flash_bank
*bank
, int first
, int last
)
876 uint32_t flash_fmc
, flash_cris
;
877 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
878 struct target
*target
= bank
->target
;
880 if (bank
->target
->state
!= TARGET_HALTED
) {
881 LOG_ERROR("Target not halted");
882 return ERROR_TARGET_NOT_HALTED
;
885 if (stellaris_info
->did1
== 0)
886 return ERROR_FLASH_BANK_NOT_PROBED
;
888 if ((first
< 0) || (last
< first
) || (last
>= (int)stellaris_info
->num_pages
))
889 return ERROR_FLASH_SECTOR_INVALID
;
891 if ((first
== 0) && (last
== ((int)stellaris_info
->num_pages
-1)))
892 return stellaris_mass_erase(bank
);
894 /* Refresh flash controller timing */
895 stellaris_read_clock_info(bank
);
896 stellaris_set_flash_timing(bank
);
898 /* Clear and disable flash programming interrupts */
899 target_write_u32(target
, FLASH_CIM
, 0);
900 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
902 /* REVISIT this clobbers state set by any halted firmware ...
903 * it might want to process those IRQs.
906 for (banknr
= first
; banknr
<= last
; banknr
++) {
907 /* Address is first word in page */
908 target_write_u32(target
, FLASH_FMA
, banknr
* stellaris_info
->pagesize
);
909 /* Write erase command */
910 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_ERASE
);
911 /* Wait until erase complete */
913 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
914 } while (flash_fmc
& FMC_ERASE
);
916 /* Check acess violations */
917 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
918 if (flash_cris
& (AMASK
)) {
919 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32
"",
921 target_write_u32(target
, FLASH_CRIS
, 0);
922 return ERROR_FLASH_OPERATION_FAILED
;
925 bank
->sectors
[banknr
].is_erased
= 1;
931 static int stellaris_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
933 uint32_t fmppe
, flash_fmc
, flash_cris
;
936 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
937 struct target
*target
= bank
->target
;
939 if (bank
->target
->state
!= TARGET_HALTED
) {
940 LOG_ERROR("Target not halted");
941 return ERROR_TARGET_NOT_HALTED
;
945 LOG_ERROR("Hardware doesn't support page-level unprotect. "
946 "Try the 'recover' command.");
947 return ERROR_COMMAND_SYNTAX_ERROR
;
950 if (stellaris_info
->did1
== 0)
951 return ERROR_FLASH_BANK_NOT_PROBED
;
953 if (stellaris_info
->target_class
== 0xa) {
954 LOG_ERROR("Protection on Snowflake is not supported yet");
955 return ERROR_FLASH_OPERATION_FAILED
;
958 /* lockregions are 2 pages ... must protect [even..odd] */
959 if ((first
< 0) || (first
& 1)
960 || (last
< first
) || !(last
& 1)
961 || (last
>= 2 * stellaris_info
->num_lockbits
)) {
962 LOG_ERROR("Can't protect unaligned or out-of-range pages.");
963 return ERROR_FLASH_SECTOR_INVALID
;
966 /* Refresh flash controller timing */
967 stellaris_read_clock_info(bank
);
968 stellaris_set_flash_timing(bank
);
970 /* convert from pages to lockregions */
974 /* FIXME this assumes single FMPPE, for a max of 64K of flash!!
975 * Current parts can be much bigger.
978 LOG_ERROR("No support yet for protection > 64K");
979 return ERROR_FLASH_OPERATION_FAILED
;
982 target_read_u32(target
, SCB_BASE
| FMPPE
, &fmppe
);
984 for (lockregion
= first
; lockregion
<= last
; lockregion
++)
985 fmppe
&= ~(1 << lockregion
);
987 /* Clear and disable flash programming interrupts */
988 target_write_u32(target
, FLASH_CIM
, 0);
989 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
991 /* REVISIT this clobbers state set by any halted firmware ...
992 * it might want to process those IRQs.
995 LOG_DEBUG("fmppe 0x%" PRIx32
"", fmppe
);
996 target_write_u32(target
, SCB_BASE
| FMPPE
, fmppe
);
999 target_write_u32(target
, FLASH_FMA
, 1);
1001 /* Write commit command */
1002 /* REVISIT safety check, since this cannot be undone
1003 * except by the "Recover a locked device" procedure.
1004 * REVISIT DustDevil-A0 parts have an erratum making FMPPE commits
1005 * inadvisable ... it makes future mass erase operations fail.
1007 LOG_WARNING("Flash protection cannot be removed once committed, commit is NOT executed !");
1008 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
1010 /* Wait until erase complete */
1012 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1013 } while (flash_fmc
& FMC_COMT
);
1015 /* Check acess violations */
1016 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1017 if (flash_cris
& (AMASK
)) {
1018 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32
"", flash_cris
);
1019 target_write_u32(target
, FLASH_CRIS
, 0);
1020 return ERROR_FLASH_OPERATION_FAILED
;
1026 /* see contib/loaders/flash/stellaris.s for src */
1028 static const uint8_t stellaris_write_code
[] = {
1030 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */
1031 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */
1033 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
1034 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
1035 0x17, 0xD0, /* beq exit */
1036 0x47, 0x68, /* ldr r7, [r0, #4] */
1037 0x47, 0x45, /* cmp r7, r8 */
1038 0xF7, 0xD0, /* beq wait_fifo */
1040 0x22, 0x60, /* str r2, [r4, #0] */
1041 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */
1042 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */
1043 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */
1044 0xA5, 0x60, /* str r5, [r4, #8] */
1046 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */
1047 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */
1048 0xFA, 0xD1, /* bne busy */
1049 0x8F, 0x42, /* cmp r7, r1 */
1050 0x28, 0xBF, /* it cs */
1051 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
1052 0x47, 0x60, /* str r7, [r0, #4] */
1053 0x01, 0x3B, /* subs r3, r3, #1 */
1054 0x03, 0xB1, /* cbz r3, exit */
1055 0xE2, 0xE7, /* b wait_fifo */
1057 0x00, 0xBE, /* bkpt #0 */
1059 /* pFLASH_CTRL_BASE: */
1060 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
1061 /* FLASHWRITECMD: */
1062 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
1064 static int stellaris_write_block(struct flash_bank
*bank
,
1065 const uint8_t *buffer
, uint32_t offset
, uint32_t wcount
)
1067 struct target
*target
= bank
->target
;
1068 uint32_t buffer_size
= 16384;
1069 struct working_area
*source
;
1070 struct working_area
*write_algorithm
;
1071 uint32_t address
= bank
->base
+ offset
;
1072 struct reg_param reg_params
[4];
1073 struct armv7m_algorithm armv7m_info
;
1074 int retval
= ERROR_OK
;
1076 /* power of two, and multiple of word size */
1077 static const unsigned buf_min
= 128;
1079 /* for small buffers it's faster not to download an algorithm */
1080 if (wcount
* 4 < buf_min
)
1081 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1083 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" wcount=%08" PRIx32
"",
1084 bank
, buffer
, offset
, wcount
);
1086 /* flash write code */
1087 if (target_alloc_working_area(target
, sizeof(stellaris_write_code
),
1088 &write_algorithm
) != ERROR_OK
) {
1089 LOG_DEBUG("no working area for block memory writes");
1090 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1093 /* plus a buffer big enough for this data */
1094 if (wcount
* 4 < buffer_size
)
1095 buffer_size
= wcount
* 4;
1098 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
1100 if (buffer_size
<= buf_min
) {
1101 target_free_working_area(target
, write_algorithm
);
1102 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1104 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1105 target_name(target
), (unsigned) buffer_size
);
1108 target_write_buffer(target
, write_algorithm
->address
,
1109 sizeof(stellaris_write_code
),
1110 stellaris_write_code
);
1112 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
1113 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
1115 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1116 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1117 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
1118 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
1120 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
1121 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
1122 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
1123 buf_set_u32(reg_params
[3].value
, 0, 32, wcount
);
1125 retval
= target_run_flash_async_algorithm(target
, buffer
, wcount
, 4,
1128 source
->address
, source
->size
,
1129 write_algorithm
->address
, 0,
1132 if (retval
== ERROR_FLASH_OPERATION_FAILED
)
1133 LOG_ERROR("error %d executing stellaris flash write algorithm", retval
);
1135 target_free_working_area(target
, write_algorithm
);
1136 target_free_working_area(target
, source
);
1138 destroy_reg_param(®_params
[0]);
1139 destroy_reg_param(®_params
[1]);
1140 destroy_reg_param(®_params
[2]);
1141 destroy_reg_param(®_params
[3]);
1146 static int stellaris_write(struct flash_bank
*bank
, const uint8_t *buffer
,
1147 uint32_t offset
, uint32_t count
)
1149 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1150 struct target
*target
= bank
->target
;
1151 uint32_t address
= offset
;
1152 uint32_t flash_cris
, flash_fmc
;
1153 uint32_t words_remaining
= (count
/ 4);
1154 uint32_t bytes_remaining
= (count
& 0x00000003);
1155 uint32_t bytes_written
= 0;
1158 if (bank
->target
->state
!= TARGET_HALTED
) {
1159 LOG_ERROR("Target not halted");
1160 return ERROR_TARGET_NOT_HALTED
;
1163 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" count=%08" PRIx32
"",
1164 bank
, buffer
, offset
, count
);
1166 if (stellaris_info
->did1
== 0)
1167 return ERROR_FLASH_BANK_NOT_PROBED
;
1170 LOG_WARNING("offset size must be word aligned");
1171 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1174 if (offset
+ count
> bank
->size
)
1175 return ERROR_FLASH_DST_OUT_OF_BANK
;
1177 /* Refresh flash controller timing */
1178 stellaris_read_clock_info(bank
);
1179 stellaris_set_flash_timing(bank
);
1181 /* Clear and disable flash programming interrupts */
1182 target_write_u32(target
, FLASH_CIM
, 0);
1183 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1185 /* REVISIT this clobbers state set by any halted firmware ...
1186 * it might want to process those IRQs.
1189 /* multiple words to be programmed? */
1190 if (words_remaining
> 0) {
1191 /* try using a block write */
1192 retval
= stellaris_write_block(bank
, buffer
, offset
,
1194 if (retval
!= ERROR_OK
) {
1195 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
1196 LOG_DEBUG("writing flash word-at-a-time");
1197 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
1198 /* if an error occured, we examine the reason, and quit */
1199 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1201 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32
"", flash_cris
);
1202 return ERROR_FLASH_OPERATION_FAILED
;
1205 buffer
+= words_remaining
* 4;
1206 address
+= words_remaining
* 4;
1207 words_remaining
= 0;
1211 while (words_remaining
> 0) {
1212 if (!(address
& 0xff))
1213 LOG_DEBUG("0x%" PRIx32
"", address
);
1215 /* Program one word */
1216 target_write_u32(target
, FLASH_FMA
, address
);
1217 target_write_buffer(target
, FLASH_FMD
, 4, buffer
);
1218 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1219 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1220 /* Wait until write complete */
1222 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1223 } while (flash_fmc
& FMC_WRITE
);
1230 if (bytes_remaining
) {
1231 uint8_t last_word
[4] = {0xff, 0xff, 0xff, 0xff};
1233 /* copy the last remaining bytes into the write buffer */
1234 memcpy(last_word
, buffer
+bytes_written
, bytes_remaining
);
1236 if (!(address
& 0xff))
1237 LOG_DEBUG("0x%" PRIx32
"", address
);
1239 /* Program one word */
1240 target_write_u32(target
, FLASH_FMA
, address
);
1241 target_write_buffer(target
, FLASH_FMD
, 4, last_word
);
1242 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1243 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1244 /* Wait until write complete */
1246 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1247 } while (flash_fmc
& FMC_WRITE
);
1250 /* Check access violations */
1251 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1252 if (flash_cris
& (AMASK
)) {
1253 LOG_DEBUG("flash_cris 0x%" PRIx32
"", flash_cris
);
1254 return ERROR_FLASH_OPERATION_FAILED
;
1259 static int stellaris_probe(struct flash_bank
*bank
)
1261 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1264 /* If this is a stellaris chip, it has flash; probe() is just
1265 * to figure out how much is present. Only do it once.
1267 if (stellaris_info
->did1
!= 0)
1270 /* stellaris_read_part_info() already handled error checking and
1271 * reporting. Note that it doesn't write, so we don't care about
1272 * whether the target is halted or not.
1274 retval
= stellaris_read_part_info(bank
);
1275 if (retval
!= ERROR_OK
)
1278 if (bank
->sectors
) {
1279 free(bank
->sectors
);
1280 bank
->sectors
= NULL
;
1283 /* provide this for the benefit of the NOR flash framework */
1284 bank
->size
= stellaris_info
->num_pages
* stellaris_info
->pagesize
;
1285 bank
->num_sectors
= stellaris_info
->num_pages
;
1286 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
1287 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
1288 bank
->sectors
[i
].offset
= i
* stellaris_info
->pagesize
;
1289 bank
->sectors
[i
].size
= stellaris_info
->pagesize
;
1290 bank
->sectors
[i
].is_erased
= -1;
1291 bank
->sectors
[i
].is_protected
= -1;
1297 static int stellaris_mass_erase(struct flash_bank
*bank
)
1299 struct target
*target
= NULL
;
1300 struct stellaris_flash_bank
*stellaris_info
= NULL
;
1303 stellaris_info
= bank
->driver_priv
;
1304 target
= bank
->target
;
1306 if (target
->state
!= TARGET_HALTED
) {
1307 LOG_ERROR("Target not halted");
1308 return ERROR_TARGET_NOT_HALTED
;
1311 if (stellaris_info
->did1
== 0)
1312 return ERROR_FLASH_BANK_NOT_PROBED
;
1314 /* Refresh flash controller timing */
1315 stellaris_read_clock_info(bank
);
1316 stellaris_set_flash_timing(bank
);
1318 /* Clear and disable flash programming interrupts */
1319 target_write_u32(target
, FLASH_CIM
, 0);
1320 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1322 /* REVISIT this clobbers state set by any halted firmware ...
1323 * it might want to process those IRQs.
1326 target_write_u32(target
, FLASH_FMA
, 0);
1327 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1328 /* Wait until erase complete */
1330 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) {
1336 target_write_u32(target
, FLASH_FMA
, 0x20000);
1337 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1338 /* Wait until erase complete */
1340 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1341 } while (flash_fmc
& FMC_MERASE
);
1347 COMMAND_HANDLER(stellaris_handle_mass_erase_command
)
1352 return ERROR_COMMAND_SYNTAX_ERROR
;
1354 struct flash_bank
*bank
;
1355 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1356 if (ERROR_OK
!= retval
)
1359 if (stellaris_mass_erase(bank
) == ERROR_OK
) {
1360 /* set all sectors as erased */
1361 for (i
= 0; i
< bank
->num_sectors
; i
++)
1362 bank
->sectors
[i
].is_erased
= 1;
1364 command_print(CMD_CTX
, "stellaris mass erase complete");
1366 command_print(CMD_CTX
, "stellaris mass erase failed");
1372 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1373 * This performs a mass erase and then restores all nonvolatile registers
1374 * (including USER_* registers and flash lock bits) to their defaults.
1375 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1377 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1378 * can affect this operation if flash protection has been enabled.
1380 COMMAND_HANDLER(stellaris_handle_recover_command
)
1382 struct flash_bank
*bank
;
1385 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1386 if (retval
!= ERROR_OK
)
1389 /* REVISIT ... it may be worth sanity checking that the AP is
1390 * inactive before we start. ARM documents that switching a DP's
1391 * mode while it's active can cause fault modes that need a power
1396 if (!(jtag_get_reset_config() & RESET_HAS_SRST
)) {
1397 LOG_ERROR("Can't recover Stellaris flash without SRST");
1400 adapter_assert_reset();
1402 for (int i
= 0; i
< 5; i
++) {
1403 retval
= dap_to_swd(bank
->target
);
1404 if (retval
!= ERROR_OK
)
1407 retval
= dap_to_jtag(bank
->target
);
1408 if (retval
!= ERROR_OK
)
1412 /* de-assert SRST */
1413 adapter_deassert_reset();
1414 retval
= jtag_execute_queue();
1416 /* wait 400+ msec ... OK, "1+ second" is simpler */
1419 /* USER INTERVENTION required for the power cycle
1420 * Restarting OpenOCD is likely needed because of mode switching.
1422 LOG_INFO("USER ACTION: "
1423 "power cycle Stellaris chip, then restart OpenOCD.");
1429 static const struct command_registration stellaris_exec_command_handlers
[] = {
1431 .name
= "mass_erase",
1433 .handler
= stellaris_handle_mass_erase_command
,
1434 .mode
= COMMAND_EXEC
,
1435 .help
= "erase entire device",
1439 .handler
= stellaris_handle_recover_command
,
1440 .mode
= COMMAND_EXEC
,
1442 .help
= "recover (and erase) locked device",
1444 COMMAND_REGISTRATION_DONE
1446 static const struct command_registration stellaris_command_handlers
[] = {
1448 .name
= "stellaris",
1449 .mode
= COMMAND_EXEC
,
1450 .help
= "Stellaris flash command group",
1452 .chain
= stellaris_exec_command_handlers
,
1454 COMMAND_REGISTRATION_DONE
1457 struct flash_driver stellaris_flash
= {
1458 .name
= "stellaris",
1459 .commands
= stellaris_command_handlers
,
1460 .flash_bank_command
= stellaris_flash_bank_command
,
1461 .erase
= stellaris_erase
,
1462 .protect
= stellaris_protect
,
1463 .write
= stellaris_write
,
1464 .read
= default_flash_read
,
1465 .probe
= stellaris_probe
,
1466 .auto_probe
= stellaris_probe
,
1467 .erase_check
= default_flash_blank_check
,
1468 .protect_check
= stellaris_protect_check
,
1469 .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)