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, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
22 /***************************************************************************
23 * STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more.
24 ***************************************************************************/
30 #include "jtag/interface.h"
32 #include <target/algorithm.h>
33 #include <target/armv7m.h>
35 #define DID0_VER(did0) ((did0 >> 28)&0x07)
37 /* STELLARIS control registers */
38 #define SCB_BASE 0x400FE000
53 /* "legacy" flash memory protection registers (64KB max) */
57 /* new flash memory protection registers (for more than 64KB) */
58 #define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */
59 #define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */
63 #define FLASH_CONTROL_BASE 0x400FD000
64 #define FLASH_FMA (FLASH_CONTROL_BASE | 0x000)
65 #define FLASH_FMD (FLASH_CONTROL_BASE | 0x004)
66 #define FLASH_FMC (FLASH_CONTROL_BASE | 0x008)
67 #define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C)
68 #define FLASH_CIM (FLASH_CONTROL_BASE | 0x010)
69 #define FLASH_MISC (FLASH_CONTROL_BASE | 0x014)
70 #define FLASH_FSIZE (FLASH_CONTROL_BASE | 0xFC0)
71 #define FLASH_SSIZE (FLASH_CONTROL_BASE | 0xFC4)
79 /* Flash Controller Command bits */
80 #define FMC_WRKEY (0xA442 << 16)
81 #define FMC_COMT (1 << 3)
82 #define FMC_MERASE (1 << 2)
83 #define FMC_ERASE (1 << 1)
84 #define FMC_WRITE (1 << 0)
86 /* STELLARIS constants */
88 /* values to write in FMA to commit write-"once" values */
89 #define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */
90 #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
{
96 /* chip id register */
104 const char *target_name
;
105 uint8_t target_class
;
112 /* main clock status */
119 const char *iosc_desc
;
120 const char *mck_desc
;
123 /* Autogenerated by contrib/gen-stellaris-part-header.pl */
124 /* From Stellaris Firmware Development Package revision 9453 */
125 static const struct {
128 const char *partname
;
129 } stellaris_parts
[] = {
130 {0x00, 0x01, "LM3S101"},
131 {0x00, 0x02, "LM3S102"},
132 {0x01, 0xBF, "LM3S1110"},
133 {0x01, 0xC3, "LM3S1133"},
134 {0x01, 0xC5, "LM3S1138"},
135 {0x01, 0xC1, "LM3S1150"},
136 {0x01, 0xC4, "LM3S1162"},
137 {0x01, 0xC2, "LM3S1165"},
138 {0x01, 0xEC, "LM3S1166"},
139 {0x01, 0xC6, "LM3S1332"},
140 {0x01, 0xBC, "LM3S1435"},
141 {0x01, 0xBA, "LM3S1439"},
142 {0x01, 0xBB, "LM3S1512"},
143 {0x01, 0xC7, "LM3S1538"},
144 {0x01, 0xDB, "LM3S1601"},
145 {0x03, 0x06, "LM3S1607"},
146 {0x01, 0xDA, "LM3S1608"},
147 {0x01, 0xC0, "LM3S1620"},
148 {0x04, 0xCD, "LM3S1621"},
149 {0x03, 0x03, "LM3S1625"},
150 {0x03, 0x04, "LM3S1626"},
151 {0x03, 0x05, "LM3S1627"},
152 {0x01, 0xB3, "LM3S1635"},
153 {0x01, 0xEB, "LM3S1636"},
154 {0x01, 0xBD, "LM3S1637"},
155 {0x04, 0xB1, "LM3S1651"},
156 {0x01, 0xB9, "LM3S1751"},
157 {0x03, 0x10, "LM3S1776"},
158 {0x04, 0x16, "LM3S1811"},
159 {0x04, 0x3D, "LM3S1816"},
160 {0x01, 0xB4, "LM3S1850"},
161 {0x01, 0xDD, "LM3S1911"},
162 {0x01, 0xDC, "LM3S1918"},
163 {0x01, 0xB7, "LM3S1937"},
164 {0x01, 0xBE, "LM3S1958"},
165 {0x01, 0xB5, "LM3S1960"},
166 {0x01, 0xB8, "LM3S1968"},
167 {0x01, 0xEA, "LM3S1969"},
168 {0x04, 0xCE, "LM3S1B21"},
169 {0x06, 0xCA, "LM3S1C21"},
170 {0x06, 0xCB, "LM3S1C26"},
171 {0x06, 0x98, "LM3S1C58"},
172 {0x06, 0xB0, "LM3S1D21"},
173 {0x06, 0xCC, "LM3S1D26"},
174 {0x06, 0x1D, "LM3S1F11"},
175 {0x06, 0x1B, "LM3S1F16"},
176 {0x06, 0xAF, "LM3S1G21"},
177 {0x06, 0x95, "LM3S1G58"},
178 {0x06, 0x1E, "LM3S1H11"},
179 {0x06, 0x1C, "LM3S1H16"},
180 {0x04, 0x0F, "LM3S1J11"},
181 {0x04, 0x3C, "LM3S1J16"},
182 {0x04, 0x0E, "LM3S1N11"},
183 {0x04, 0x3B, "LM3S1N16"},
184 {0x04, 0xB2, "LM3S1P51"},
185 {0x04, 0x9E, "LM3S1R21"},
186 {0x04, 0xC9, "LM3S1R26"},
187 {0x04, 0x30, "LM3S1W16"},
188 {0x04, 0x2F, "LM3S1Z16"},
189 {0x01, 0x51, "LM3S2110"},
190 {0x01, 0x84, "LM3S2139"},
191 {0x03, 0x39, "LM3S2276"},
192 {0x01, 0xA2, "LM3S2410"},
193 {0x01, 0x59, "LM3S2412"},
194 {0x01, 0x56, "LM3S2432"},
195 {0x01, 0x5A, "LM3S2533"},
196 {0x01, 0xE1, "LM3S2601"},
197 {0x01, 0xE0, "LM3S2608"},
198 {0x03, 0x33, "LM3S2616"},
199 {0x01, 0x57, "LM3S2620"},
200 {0x01, 0x85, "LM3S2637"},
201 {0x01, 0x53, "LM3S2651"},
202 {0x03, 0x80, "LM3S2671"},
203 {0x03, 0x50, "LM3S2678"},
204 {0x01, 0xA4, "LM3S2730"},
205 {0x01, 0x52, "LM3S2739"},
206 {0x03, 0x3A, "LM3S2776"},
207 {0x04, 0x6D, "LM3S2793"},
208 {0x01, 0xE3, "LM3S2911"},
209 {0x01, 0xE2, "LM3S2918"},
210 {0x01, 0xED, "LM3S2919"},
211 {0x01, 0x54, "LM3S2939"},
212 {0x01, 0x8F, "LM3S2948"},
213 {0x01, 0x58, "LM3S2950"},
214 {0x01, 0x55, "LM3S2965"},
215 {0x04, 0x6C, "LM3S2B93"},
216 {0x06, 0x94, "LM3S2D93"},
217 {0x06, 0x93, "LM3S2U93"},
218 {0x00, 0x19, "LM3S300"},
219 {0x00, 0x11, "LM3S301"},
220 {0x00, 0x1A, "LM3S308"},
221 {0x00, 0x12, "LM3S310"},
222 {0x00, 0x13, "LM3S315"},
223 {0x00, 0x14, "LM3S316"},
224 {0x00, 0x17, "LM3S317"},
225 {0x00, 0x15, "LM3S328"},
226 {0x03, 0x08, "LM3S3634"},
227 {0x03, 0x43, "LM3S3651"},
228 {0x04, 0xC8, "LM3S3654"},
229 {0x03, 0x44, "LM3S3739"},
230 {0x03, 0x49, "LM3S3748"},
231 {0x03, 0x45, "LM3S3749"},
232 {0x04, 0x42, "LM3S3826"},
233 {0x04, 0x41, "LM3S3J26"},
234 {0x04, 0x40, "LM3S3N26"},
235 {0x04, 0x3F, "LM3S3W26"},
236 {0x04, 0x3E, "LM3S3Z26"},
237 {0x03, 0x81, "LM3S5632"},
238 {0x04, 0x0C, "LM3S5651"},
239 {0x03, 0x8A, "LM3S5652"},
240 {0x04, 0x4D, "LM3S5656"},
241 {0x03, 0x91, "LM3S5662"},
242 {0x03, 0x96, "LM3S5732"},
243 {0x03, 0x97, "LM3S5737"},
244 {0x03, 0xA0, "LM3S5739"},
245 {0x03, 0x99, "LM3S5747"},
246 {0x03, 0xA7, "LM3S5749"},
247 {0x03, 0x9A, "LM3S5752"},
248 {0x03, 0x9C, "LM3S5762"},
249 {0x04, 0x69, "LM3S5791"},
250 {0x04, 0x0B, "LM3S5951"},
251 {0x04, 0x4E, "LM3S5956"},
252 {0x04, 0x68, "LM3S5B91"},
253 {0x06, 0x2E, "LM3S5C31"},
254 {0x06, 0x2C, "LM3S5C36"},
255 {0x06, 0x5E, "LM3S5C51"},
256 {0x06, 0x5B, "LM3S5C56"},
257 {0x06, 0x5F, "LM3S5D51"},
258 {0x06, 0x5C, "LM3S5D56"},
259 {0x06, 0x87, "LM3S5D91"},
260 {0x06, 0x2D, "LM3S5G31"},
261 {0x06, 0x1F, "LM3S5G36"},
262 {0x06, 0x5D, "LM3S5G51"},
263 {0x06, 0x4F, "LM3S5G56"},
264 {0x04, 0x09, "LM3S5K31"},
265 {0x04, 0x4A, "LM3S5K36"},
266 {0x04, 0x0A, "LM3S5P31"},
267 {0x04, 0x48, "LM3S5P36"},
268 {0x04, 0xB6, "LM3S5P3B"},
269 {0x04, 0x0D, "LM3S5P51"},
270 {0x04, 0x4C, "LM3S5P56"},
271 {0x04, 0x07, "LM3S5R31"},
272 {0x04, 0x4B, "LM3S5R36"},
273 {0x04, 0x47, "LM3S5T36"},
274 {0x06, 0x7F, "LM3S5U91"},
275 {0x04, 0x46, "LM3S5Y36"},
276 {0x00, 0x2A, "LM3S600"},
277 {0x00, 0x21, "LM3S601"},
278 {0x00, 0x2B, "LM3S608"},
279 {0x00, 0x22, "LM3S610"},
280 {0x01, 0xA1, "LM3S6100"},
281 {0x00, 0x23, "LM3S611"},
282 {0x01, 0x74, "LM3S6110"},
283 {0x00, 0x24, "LM3S612"},
284 {0x00, 0x25, "LM3S613"},
285 {0x00, 0x26, "LM3S615"},
286 {0x00, 0x28, "LM3S617"},
287 {0x00, 0x29, "LM3S618"},
288 {0x00, 0x27, "LM3S628"},
289 {0x01, 0xA5, "LM3S6420"},
290 {0x01, 0x82, "LM3S6422"},
291 {0x01, 0x75, "LM3S6432"},
292 {0x01, 0x76, "LM3S6537"},
293 {0x01, 0x71, "LM3S6610"},
294 {0x01, 0xE7, "LM3S6611"},
295 {0x01, 0xE6, "LM3S6618"},
296 {0x01, 0x83, "LM3S6633"},
297 {0x01, 0x8B, "LM3S6637"},
298 {0x01, 0xA3, "LM3S6730"},
299 {0x01, 0x77, "LM3S6753"},
300 {0x01, 0xE9, "LM3S6911"},
301 {0x01, 0xE8, "LM3S6918"},
302 {0x01, 0x89, "LM3S6938"},
303 {0x01, 0x72, "LM3S6950"},
304 {0x01, 0x78, "LM3S6952"},
305 {0x01, 0x73, "LM3S6965"},
306 {0x06, 0xAA, "LM3S6C11"},
307 {0x06, 0xAC, "LM3S6C65"},
308 {0x06, 0x9F, "LM3S6G11"},
309 {0x06, 0xAB, "LM3S6G65"},
310 {0x00, 0x38, "LM3S800"},
311 {0x00, 0x31, "LM3S801"},
312 {0x00, 0x39, "LM3S808"},
313 {0x00, 0x32, "LM3S811"},
314 {0x00, 0x33, "LM3S812"},
315 {0x00, 0x34, "LM3S815"},
316 {0x00, 0x36, "LM3S817"},
317 {0x00, 0x37, "LM3S818"},
318 {0x00, 0x35, "LM3S828"},
319 {0x01, 0x64, "LM3S8530"},
320 {0x01, 0x8E, "LM3S8538"},
321 {0x01, 0x61, "LM3S8630"},
322 {0x01, 0x63, "LM3S8730"},
323 {0x01, 0x8D, "LM3S8733"},
324 {0x01, 0x86, "LM3S8738"},
325 {0x01, 0x65, "LM3S8930"},
326 {0x01, 0x8C, "LM3S8933"},
327 {0x01, 0x88, "LM3S8938"},
328 {0x01, 0xA6, "LM3S8962"},
329 {0x01, 0x62, "LM3S8970"},
330 {0x01, 0xD7, "LM3S8971"},
331 {0x06, 0xAE, "LM3S8C62"},
332 {0x06, 0xAD, "LM3S8G62"},
333 {0x04, 0xCF, "LM3S9781"},
334 {0x04, 0x67, "LM3S9790"},
335 {0x04, 0x6B, "LM3S9792"},
336 {0x04, 0x2D, "LM3S9971"},
337 {0x04, 0x20, "LM3S9997"},
338 {0x04, 0xD0, "LM3S9B81"},
339 {0x04, 0x66, "LM3S9B90"},
340 {0x04, 0x6A, "LM3S9B92"},
341 {0x04, 0x6E, "LM3S9B95"},
342 {0x04, 0x6F, "LM3S9B96"},
343 {0x04, 0x1D, "LM3S9BN2"},
344 {0x04, 0x1E, "LM3S9BN5"},
345 {0x04, 0x1F, "LM3S9BN6"},
346 {0x06, 0x70, "LM3S9C97"},
347 {0x06, 0xA9, "LM3S9D81"},
348 {0x06, 0x7E, "LM3S9D90"},
349 {0x06, 0x92, "LM3S9D92"},
350 {0x06, 0x9D, "LM3S9D96"},
351 {0x06, 0x7B, "LM3S9DN5"},
352 {0x06, 0x7C, "LM3S9DN6"},
353 {0x06, 0x60, "LM3S9G97"},
354 {0x06, 0x79, "LM3S9GN5"},
355 {0x04, 0x1B, "LM3S9L71"},
356 {0x04, 0x18, "LM3S9L97"},
357 {0x06, 0xA8, "LM3S9U81"},
358 {0x06, 0x7D, "LM3S9U90"},
359 {0x06, 0x90, "LM3S9U92"},
360 {0x06, 0x9B, "LM3S9U96"},
361 {0x05, 0x01, "LM4F120B2QR/TM4C1233C3PM"},
362 {0x05, 0x02, "LM4F120C4QR/TM4C1233D5PM"},
363 {0x05, 0x03, "LM4F120E5QR/TM4C1233E6PM"},
364 {0x05, 0x04, "LM4F120H5QR/TM4C1233H6PM"},
365 {0x05, 0x08, "LM4F121B2QR/TM4C1232C3PM"},
366 {0x05, 0x09, "LM4F121C4QR/TM4C1232D5PM"},
367 {0x05, 0x0A, "LM4F121E5QR/TM4C1232E6PM"},
368 {0x05, 0x0B, "LM4F121H5QR/TM4C1232H6PM"},
369 {0x05, 0x10, "LM4F110E5QR/TM4C1231E6PM"},
370 {0x05, 0x11, "LM4F110H5QR/TM4C1231H6PM"},
371 {0x05, 0x18, "LM4F110B2QR/TM4C1231C3PM"},
372 {0x05, 0x19, "LM4F110C4QR/TM4C1231D5PM"},
373 {0x05, 0x20, "LM4F111E5QR/TM4C1230E6PM"},
374 {0x05, 0x21, "LM4F111H5QR/TM4C1230H6PM"},
375 {0x05, 0x22, "LM4F111B2QR/TM4C1230C3PM"},
376 {0x05, 0x23, "LM4F111C4QR/TM4C1230D5PM"},
377 {0x05, 0x30, "LM4F112E5QC/TM4C1231E6PZ"},
378 {0x05, 0x31, "LM4F112H5QC/TM4C1231H6PZ"},
379 {0x05, 0x35, "LM4F112H5QD/TM4C1231H6PGE"},
380 {0x05, 0x36, "LM4F112C4QC/TM4C1231D5PZ"},
381 {0x05, 0x40, "LM4F130E5QR/TM4C1237E6PM"},
382 {0x05, 0x41, "LM4F130H5QR/TM4C1237H6PM"},
383 {0x05, 0x48, "LM4F130C4QR/TM4C1237D5PM"},
384 {0x05, 0x50, "LM4F131E5QR/TM4C1236E6PM"},
385 {0x05, 0x51, "LM4F131H5QR/TM4C1236H6PM"},
386 {0x05, 0x52, "LM4F131C4QR/TM4C1236D5PM"},
387 {0x05, 0x60, "LM4F132E5QC/TM4C1237E6PZ"},
388 {0x05, 0x61, "LM4F132H5QC/TM4C1237H6PZ"},
389 {0x05, 0x65, "LM4F132H5QD/TM4C1237H6PGE"},
390 {0x05, 0x66, "LM4F132C4QC/TM4C1237D5PZ"},
391 {0x05, 0x70, "LM4F210E5QR/TM4C123BE6PM"},
392 {0x05, 0x73, "LM4F210H5QR/TM4C123BH6PM"},
393 {0x05, 0x80, "LM4F211E5QR/TM4C123AE6PM"},
394 {0x05, 0x83, "LM4F211H5QR/TM4C123AH6PM"},
395 {0x05, 0xA0, "LM4F230E5QR/TM4C123GE6PM"},
396 {0x05, 0xA1, "LM4F230H5QR/TM4C123GH6PM"},
397 {0x05, 0xB0, "LM4F231E5QR/TM4C123FE6PM"},
398 {0x05, 0xB1, "LM4F231H5QR/TM4C123FH6PM"},
399 {0x05, 0xC0, "LM4F232E5QC/TM4C123GE6PZ"},
400 {0x05, 0xC1, "LM4F232H5QC/TM4C123GH6PZ"},
401 {0x05, 0xC3, "LM4F212E5QC/TM4C123BE6PZ"},
402 {0x05, 0xC4, "LM4F212H5QC/TM4C123BH6PZ"},
403 {0x05, 0xC5, "LM4F232H5QD/TM4C123GH6PGE"},
404 {0x05, 0xC6, "LM4F212H5QD/TM4C123BH6PGE"},
405 {0x05, 0xD0, "LM4F122C4QC/TM4C1233D5PZ"},
406 {0x05, 0xD1, "LM4F122E5QC/TM4C1233E6PZ"},
407 {0x05, 0xD2, "LM4F122H5QC/TM4C1233H6PZ"},
408 {0x05, 0xD6, "LM4F122H5QD/TM4C1233H6PGE"},
409 {0x05, 0xE1, "LM4FSXLH5BB"},
410 {0x05, 0xE3, "LM4F232H5BB/TM4C123GH6ZRB"},
411 {0x05, 0xE4, "LM4FS99H5BB"},
412 {0x05, 0xE5, "LM4FS1AH5BB"},
413 {0x05, 0xE9, "LM4F212H5BB/TM4C123BH6ZRB"},
414 {0x05, 0xEA, "LM4FS1GH5BB"},
415 {0x05, 0xF0, "TM4C123GH6ZXR"},
416 {0x0A, 0x19, "TM4C1290NCPDT"},
417 {0x0A, 0x1B, "TM4C1290NCZAD"},
418 {0x0A, 0x1C, "TM4C1292NCPDT"},
419 {0x0A, 0x1E, "TM4C1292NCZAD"},
420 {0x0A, 0x1F, "TM4C1294NCPDT"},
421 {0x0A, 0x21, "TM4C1294NCZAD"},
422 {0x0A, 0x22, "TM4C1297NCZAD"},
423 {0x0A, 0x23, "TM4C1299NCZAD"},
424 {0x0A, 0x24, "TM4C129CNCPDT"},
425 {0x0A, 0x26, "TM4C129CNCZAD"},
426 {0x0A, 0x27, "TM4C129DNCPDT"},
427 {0x0A, 0x29, "TM4C129DNCZAD"},
428 {0x0A, 0x2D, "TM4C129ENCPDT"},
429 {0x0A, 0x2F, "TM4C129ENCZAD"},
430 {0x0A, 0x30, "TM4C129LNCZAD"},
431 {0x0A, 0x32, "TM4C129XNCZAD"},
432 {0x0A, 0x34, "TM4C1294KCPDT"},
433 {0x0A, 0x35, "TM4C129EKCPDT"},
434 {0x0A, 0x36, "TM4C1299KCZAD"},
435 {0x0A, 0x37, "TM4C129XKCZAD"},
436 {0xFF, 0x00, "Unknown Part"}
439 static const char * const stellaris_classname
[] = {
453 /***************************************************************************
454 * openocd command interface *
455 ***************************************************************************/
457 /* flash_bank stellaris <base> <size> 0 0 <target#>
459 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command
)
461 struct stellaris_flash_bank
*stellaris_info
;
464 return ERROR_COMMAND_SYNTAX_ERROR
;
466 stellaris_info
= calloc(sizeof(struct stellaris_flash_bank
), 1);
468 bank
->driver_priv
= stellaris_info
;
470 stellaris_info
->target_name
= "Unknown target";
472 /* part wasn't probed for info yet */
473 stellaris_info
->did1
= 0;
475 /* TODO Specify the main crystal speed in kHz using an optional
476 * argument; ditto, the speed of an external oscillator used
477 * instead of a crystal. Avoid programming flash using IOSC.
482 static int get_stellaris_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
484 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
486 if (stellaris_info
->did1
== 0)
487 return ERROR_FLASH_BANK_NOT_PROBED
;
489 /* Read main and master clock frequency register */
490 stellaris_read_clock_info(bank
);
492 command_print_sameline(cmd
,
493 "\nTI/LMI Stellaris information: Chip is "
494 "class %i (%s) %s rev %c%i\n",
495 stellaris_info
->target_class
,
496 stellaris_classname
[stellaris_info
->target_class
],
497 stellaris_info
->target_name
,
498 (int)('A' + ((stellaris_info
->did0
>> 8) & 0xFF)),
499 (int)((stellaris_info
->did0
) & 0xFF));
501 command_print_sameline(cmd
,
502 "did1: 0x%8.8" PRIx32
", arch: 0x%4.4" PRIx32
503 ", eproc: %s, ramsize: %" PRIu32
"k, flashsize: %" PRIu32
"k\n",
504 stellaris_info
->did1
,
505 stellaris_info
->did1
,
507 stellaris_info
->sramsiz
,
508 (uint32_t)(stellaris_info
->num_pages
* stellaris_info
->pagesize
/ 1024));
510 command_print_sameline(cmd
,
511 "master clock: %ikHz%s, "
512 "rcc is 0x%" PRIx32
", rcc2 is 0x%" PRIx32
", "
513 "pagesize: %" PRIu32
", pages: %" PRIu32
,
514 (int)(stellaris_info
->mck_freq
/ 1000),
515 stellaris_info
->mck_desc
,
517 stellaris_info
->rcc2
,
518 stellaris_info
->pagesize
,
519 stellaris_info
->num_pages
);
524 /***************************************************************************
525 * chip identification and status *
526 ***************************************************************************/
528 /* Set the flash timing register to match current clocking */
529 static void stellaris_set_flash_timing(struct flash_bank
*bank
)
531 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
532 struct target
*target
= bank
->target
;
533 uint32_t usecrl
= (stellaris_info
->mck_freq
/1000000ul-1);
535 /* only valid for Sandstorm and Fury class devices */
536 if (stellaris_info
->target_class
> 1)
539 LOG_DEBUG("usecrl = %i", (int)(usecrl
));
540 target_write_u32(target
, SCB_BASE
| USECRL
, usecrl
);
543 static const unsigned rcc_xtal
[32] = {
544 [0x00] = 1000000, /* no pll */
545 [0x01] = 1843200, /* no pll */
546 [0x02] = 2000000, /* no pll */
547 [0x03] = 2457600, /* no pll */
551 [0x06] = 4000000, /* usb */
555 [0x09] = 5000000, /* usb */
557 [0x0b] = 6000000, /* (reset) usb */
561 [0x0e] = 8000000, /* usb */
564 /* parts before DustDevil use just 4 bits for xtal spec */
566 [0x10] = 10000000, /* usb */
567 [0x11] = 12000000, /* usb */
572 [0x15] = 16000000, /* usb */
576 /** Read clock configuration and set stellaris_info->usec_clocks. */
577 static void stellaris_read_clock_info(struct flash_bank
*bank
)
579 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
580 struct target
*target
= bank
->target
;
581 uint32_t rcc
, rcc2
, pllcfg
, sysdiv
, usesysdiv
, bypass
, oscsrc
;
583 unsigned long mainfreq
;
585 target_read_u32(target
, SCB_BASE
| RCC
, &rcc
);
586 LOG_DEBUG("Stellaris RCC %" PRIx32
"", rcc
);
588 target_read_u32(target
, SCB_BASE
| RCC2
, &rcc2
);
589 LOG_DEBUG("Stellaris RCC2 %" PRIx32
"", rcc
);
591 target_read_u32(target
, SCB_BASE
| PLLCFG
, &pllcfg
);
592 LOG_DEBUG("Stellaris PLLCFG %" PRIx32
"", pllcfg
);
594 stellaris_info
->rcc
= rcc
;
595 stellaris_info
->rcc2
= rcc2
;
597 sysdiv
= (rcc
>> 23) & 0xF;
598 usesysdiv
= (rcc
>> 22) & 0x1;
599 bypass
= (rcc
>> 11) & 0x1;
600 oscsrc
= (rcc
>> 4) & 0x3;
601 xtal
= (rcc
>> 6) & stellaris_info
->xtal_mask
;
603 /* NOTE: post-Sandstorm parts have RCC2 which may override
604 * parts of RCC ... with more sysdiv options, option for
605 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
606 * as zero, so the "use RCC2" flag is always clear.
608 if (rcc2
& (1 << 31)) {
609 sysdiv
= (rcc2
>> 23) & 0x3F;
610 bypass
= (rcc2
>> 11) & 0x1;
611 oscsrc
= (rcc2
>> 4) & 0x7;
613 /* FIXME Tempest parts have an additional lsb for
614 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
618 stellaris_info
->mck_desc
= "";
622 mainfreq
= rcc_xtal
[xtal
];
625 mainfreq
= stellaris_info
->iosc_freq
;
626 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
629 mainfreq
= stellaris_info
->iosc_freq
/ 4;
630 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
632 case 3: /* lowspeed */
633 /* Sandstorm doesn't have this 30K +/- 30% osc */
635 stellaris_info
->mck_desc
= " (±30%)";
637 case 8: /* hibernation osc */
638 /* not all parts support hibernation */
642 default: /* NOTREACHED */
647 /* PLL is used if it's not bypassed; its output is 200 MHz
648 * even when it runs at 400 MHz (adds divide-by-two stage).
651 mainfreq
= 200000000;
654 stellaris_info
->mck_freq
= mainfreq
/(1 + sysdiv
);
656 stellaris_info
->mck_freq
= mainfreq
;
659 /* Read device id register, main clock frequency register and fill in driver info structure */
660 static int stellaris_read_part_info(struct flash_bank
*bank
)
662 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
663 struct target
*target
= bank
->target
;
664 uint32_t did0
, did1
, ver
, fam
;
667 /* Read and parse chip identification register */
668 target_read_u32(target
, SCB_BASE
| DID0
, &did0
);
669 target_read_u32(target
, SCB_BASE
| DID1
, &did1
);
670 target_read_u32(target
, SCB_BASE
| DC0
, &stellaris_info
->dc0
);
671 target_read_u32(target
, SCB_BASE
| DC1
, &stellaris_info
->dc1
);
672 LOG_DEBUG("did0 0x%" PRIx32
", did1 0x%" PRIx32
", dc0 0x%" PRIx32
", dc1 0x%" PRIx32
"",
673 did0
, did1
, stellaris_info
->dc0
, stellaris_info
->dc1
);
675 ver
= DID0_VER(did0
);
676 if ((ver
!= 0) && (ver
!= 1)) {
677 LOG_WARNING("Unknown did0 version, cannot identify target");
678 return ERROR_FLASH_OPERATION_FAILED
;
682 LOG_WARNING("Cannot identify target as a Stellaris");
683 return ERROR_FLASH_OPERATION_FAILED
;
687 fam
= (did1
>> 24) & 0xF;
688 if (((ver
!= 0) && (ver
!= 1)) || (fam
!= 0)) {
689 LOG_WARNING("Unknown did1 version/family.");
690 return ERROR_FLASH_OPERATION_FAILED
;
693 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
694 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
695 * even give _both_ numbers! We'll use current numbers; IOSC is
696 * always approximate.
698 * For Tempest: IOSC is calibrated, 16 MHz
699 * For Blizzard: IOSC is calibrated, 16 MHz
700 * For Firestorm: IOSC is calibrated, 16 MHz
702 stellaris_info
->iosc_freq
= 12000000;
703 stellaris_info
->iosc_desc
= " (±30%)";
704 stellaris_info
->xtal_mask
= 0x0f;
706 /* get device class */
707 if (DID0_VER(did0
) > 0) {
708 stellaris_info
->target_class
= (did0
>> 16) & 0xFF;
710 /* Sandstorm class */
711 stellaris_info
->target_class
= 0;
714 switch (stellaris_info
->target_class
) {
715 case 0: /* Sandstorm */
717 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
718 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
719 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
721 if (((did0
>> 8) & 0xff) < 2) {
722 stellaris_info
->iosc_freq
= 15000000;
723 stellaris_info
->iosc_desc
= " (±50%)";
730 case 4: /* Tempest */
731 case 5: /* Blizzard */
732 case 6: /* Firestorm */
733 case 0xa: /* Snowflake */
734 stellaris_info
->iosc_freq
= 16000000; /* +/- 1% */
735 stellaris_info
->iosc_desc
= " (±1%)";
738 case 3: /* DustDevil */
739 stellaris_info
->xtal_mask
= 0x1f;
743 LOG_WARNING("Unknown did0 class");
746 for (i
= 0; stellaris_parts
[i
].partno
; i
++) {
747 if ((stellaris_parts
[i
].partno
== ((did1
>> 16) & 0xFF)) &&
748 (stellaris_parts
[i
].class == stellaris_info
->target_class
))
752 stellaris_info
->target_name
= stellaris_parts
[i
].partname
;
754 stellaris_info
->did0
= did0
;
755 stellaris_info
->did1
= did1
;
757 if (stellaris_info
->target_class
== 5) { /* Blizzard */
758 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
759 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
761 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->fsize
& 0xFFFF));
762 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
763 stellaris_info
->pagesize
= 1024;
764 } else if (stellaris_info
->target_class
== 0xa) { /* Snowflake */
765 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
766 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
768 stellaris_info
->pagesize
= (1 << ((stellaris_info
->fsize
>> 16) & 7)) * 1024;
769 stellaris_info
->num_pages
= 2048 * (1 + (stellaris_info
->fsize
& 0xFFFF)) /
770 stellaris_info
->pagesize
;
771 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
773 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->dc0
& 0xFFFF));
774 stellaris_info
->sramsiz
= (1 + ((stellaris_info
->dc0
>> 16) & 0xFFFF)) / 4;
775 stellaris_info
->pagesize
= 1024;
778 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
779 * That exposes a 32-word Flash Write Buffer ... enabling
780 * writes of more than one word at a time.
786 /***************************************************************************
788 ***************************************************************************/
790 static int stellaris_protect_check(struct flash_bank
*bank
)
792 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
793 struct target
*target
= bank
->target
;
794 uint32_t flash_sizek
= stellaris
->pagesize
/ 1024 *
795 stellaris
->num_pages
;
797 int status
= ERROR_OK
;
799 if (stellaris
->did1
== 0)
800 return ERROR_FLASH_BANK_NOT_PROBED
;
802 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++)
803 bank
->sectors
[i
].is_protected
= -1;
805 /* Read each Flash Memory Protection Program Enable (FMPPE) register
806 * to report any pages that we can't write. Ignore the Read Enable
810 if (stellaris
->target_class
>= 0x0a || flash_sizek
> 64)
811 fmppe_addr
= SCB_BASE
| FMPPE0
;
813 fmppe_addr
= SCB_BASE
| FMPPE
;
815 unsigned int page
= 0, lockbitnum
, lockbitcnt
= flash_sizek
/ 2;
816 unsigned int bits_per_page
= stellaris
->pagesize
/ 2048;
817 /* Every lock bit always corresponds to a 2k region */
818 for (lockbitnum
= 0; lockbitnum
< lockbitcnt
; lockbitnum
+= 32) {
821 target_read_u32(target
, fmppe_addr
, &fmppe
);
822 for (unsigned int i
= 0; i
< 32 && lockbitnum
+ i
< lockbitcnt
; i
++) {
823 bool protect
= !(fmppe
& (1 << i
));
825 bank
->sectors
[page
++].is_protected
= protect
;
826 i
+= bits_per_page
- 1;
827 } else { /* 1024k pages, every lockbit covers 2 pages */
828 bank
->sectors
[page
++].is_protected
= protect
;
829 bank
->sectors
[page
++].is_protected
= protect
;
838 static int stellaris_erase(struct flash_bank
*bank
, unsigned int first
,
841 uint32_t flash_fmc
, flash_cris
;
842 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
843 struct target
*target
= bank
->target
;
845 if (bank
->target
->state
!= TARGET_HALTED
) {
846 LOG_ERROR("Target not halted");
847 return ERROR_TARGET_NOT_HALTED
;
850 if (stellaris_info
->did1
== 0)
851 return ERROR_FLASH_BANK_NOT_PROBED
;
853 if ((last
< first
) || (last
>= stellaris_info
->num_pages
))
854 return ERROR_FLASH_SECTOR_INVALID
;
856 if ((first
== 0) && (last
== (stellaris_info
->num_pages
- 1)))
857 return stellaris_mass_erase(bank
);
859 /* Refresh flash controller timing */
860 stellaris_read_clock_info(bank
);
861 stellaris_set_flash_timing(bank
);
863 /* Clear and disable flash programming interrupts */
864 target_write_u32(target
, FLASH_CIM
, 0);
865 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
867 /* REVISIT this clobbers state set by any halted firmware ...
868 * it might want to process those IRQs.
871 for (unsigned int banknr
= first
; banknr
<= last
; banknr
++) {
872 /* Address is first word in page */
873 target_write_u32(target
, FLASH_FMA
, banknr
* stellaris_info
->pagesize
);
874 /* Write erase command */
875 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_ERASE
);
876 /* Wait until erase complete */
878 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
879 } while (flash_fmc
& FMC_ERASE
);
881 /* Check access violations */
882 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
883 if (flash_cris
& (AMASK
)) {
884 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32
"",
886 target_write_u32(target
, FLASH_CRIS
, 0);
887 return ERROR_FLASH_OPERATION_FAILED
;
894 static int stellaris_protect(struct flash_bank
*bank
, int set
,
895 unsigned int first
, unsigned int last
)
897 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
898 struct target
*target
= bank
->target
;
899 uint32_t flash_fmc
, flash_cris
;
900 unsigned int bits_per_page
= stellaris
->pagesize
/ 2048;
902 if (target
->state
!= TARGET_HALTED
) {
903 LOG_ERROR("Target not halted");
904 return ERROR_TARGET_NOT_HALTED
;
908 LOG_ERROR("Hardware doesn't support page-level unprotect. "
909 "Try the 'recover' command.");
910 return ERROR_COMMAND_SYNTAX_ERROR
;
913 if (stellaris
->did1
== 0)
914 return ERROR_FLASH_BANK_NOT_PROBED
;
916 if (stellaris
->target_class
== 0x03 &&
917 !((stellaris
->did0
>> 8) & 0xFF) &&
918 !((stellaris
->did0
) & 0xFF)) {
919 LOG_ERROR("DustDevil A0 parts can't be unprotected, see errata; refusing to proceed");
920 return ERROR_FLASH_OPERATION_FAILED
;
923 if (!bits_per_page
&& (first
% 2 || !(last
% 2))) {
924 LOG_ERROR("Can't protect unaligned pages");
925 return ERROR_FLASH_SECTOR_INVALID
;
928 /* Refresh flash controller timing */
929 stellaris_read_clock_info(bank
);
930 stellaris_set_flash_timing(bank
);
932 /* Clear and disable flash programming interrupts */
933 target_write_u32(target
, FLASH_CIM
, 0);
934 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
936 uint32_t flash_sizek
= stellaris
->pagesize
/ 1024 *
937 stellaris
->num_pages
;
940 if (stellaris
->target_class
>= 0x0a || flash_sizek
> 64)
941 fmppe_addr
= SCB_BASE
| FMPPE0
;
943 fmppe_addr
= SCB_BASE
| FMPPE
;
945 unsigned int page
= 0;
946 unsigned int lockbitnum
, lockbitcnt
= flash_sizek
/ 2;
947 /* Every lock bit always corresponds to a 2k region */
948 for (lockbitnum
= 0; lockbitnum
< lockbitcnt
; lockbitnum
+= 32) {
951 target_read_u32(target
, fmppe_addr
, &fmppe
);
952 for (unsigned int i
= 0;
953 i
< 32 && lockbitnum
+ i
< lockbitcnt
;
955 if (page
>= first
&& page
<= last
)
959 if (!((i
+ 1) % bits_per_page
))
961 } else { /* 1024k pages, every lockbit covers 2 pages */
965 target_write_u32(target
, fmppe_addr
, fmppe
);
968 target_write_u32(target
, FLASH_FMA
, 1 + lockbitnum
/ 16);
969 /* Write commit command */
970 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_COMT
);
972 /* Wait until commit complete */
974 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
975 } while (flash_fmc
& FMC_COMT
);
977 /* Check access violations */
978 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
979 if (flash_cris
& (AMASK
)) {
980 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32
"", flash_cris
);
981 target_write_u32(target
, FLASH_CRIS
, 0);
982 return ERROR_FLASH_OPERATION_FAILED
;
991 /* see contrib/loaders/flash/stellaris.s for src */
993 static const uint8_t stellaris_write_code
[] = {
995 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */
996 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */
998 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
999 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
1000 0x17, 0xD0, /* beq exit */
1001 0x47, 0x68, /* ldr r7, [r0, #4] */
1002 0x47, 0x45, /* cmp r7, r8 */
1003 0xF7, 0xD0, /* beq wait_fifo */
1005 0x22, 0x60, /* str r2, [r4, #0] */
1006 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */
1007 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */
1008 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */
1009 0xA5, 0x60, /* str r5, [r4, #8] */
1011 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */
1012 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */
1013 0xFA, 0xD1, /* bne busy */
1014 0x8F, 0x42, /* cmp r7, r1 */
1015 0x28, 0xBF, /* it cs */
1016 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
1017 0x47, 0x60, /* str r7, [r0, #4] */
1018 0x01, 0x3B, /* subs r3, r3, #1 */
1019 0x03, 0xB1, /* cbz r3, exit */
1020 0xE2, 0xE7, /* b wait_fifo */
1022 0x00, 0xBE, /* bkpt #0 */
1024 /* pFLASH_CTRL_BASE: */
1025 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
1026 /* FLASHWRITECMD: */
1027 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
1029 static int stellaris_write_block(struct flash_bank
*bank
,
1030 const uint8_t *buffer
, uint32_t offset
, uint32_t wcount
)
1032 struct target
*target
= bank
->target
;
1033 uint32_t buffer_size
= 16384;
1034 struct working_area
*source
;
1035 struct working_area
*write_algorithm
;
1036 uint32_t address
= bank
->base
+ offset
;
1037 struct reg_param reg_params
[4];
1038 struct armv7m_algorithm armv7m_info
;
1039 int retval
= ERROR_OK
;
1041 /* power of two, and multiple of word size */
1042 static const unsigned buf_min
= 128;
1044 /* for small buffers it's faster not to download an algorithm */
1045 if (wcount
* 4 < buf_min
)
1046 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1048 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" wcount=%08" PRIx32
"",
1049 bank
, buffer
, offset
, wcount
);
1051 /* flash write code */
1052 if (target_alloc_working_area(target
, sizeof(stellaris_write_code
),
1053 &write_algorithm
) != ERROR_OK
) {
1054 LOG_DEBUG("no working area for block memory writes");
1055 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1058 /* plus a buffer big enough for this data */
1059 if (wcount
* 4 < buffer_size
)
1060 buffer_size
= wcount
* 4;
1063 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
1065 if (buffer_size
<= buf_min
) {
1066 target_free_working_area(target
, write_algorithm
);
1067 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1069 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1070 target_name(target
), (unsigned) buffer_size
);
1073 target_write_buffer(target
, write_algorithm
->address
,
1074 sizeof(stellaris_write_code
),
1075 stellaris_write_code
);
1077 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
1078 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
1080 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1081 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1082 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
1083 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
1085 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
1086 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
1087 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
1088 buf_set_u32(reg_params
[3].value
, 0, 32, wcount
);
1090 retval
= target_run_flash_async_algorithm(target
, buffer
, wcount
, 4,
1093 source
->address
, source
->size
,
1094 write_algorithm
->address
, 0,
1097 if (retval
== ERROR_FLASH_OPERATION_FAILED
)
1098 LOG_ERROR("error %d executing stellaris flash write algorithm", retval
);
1100 target_free_working_area(target
, write_algorithm
);
1101 target_free_working_area(target
, source
);
1103 destroy_reg_param(®_params
[0]);
1104 destroy_reg_param(®_params
[1]);
1105 destroy_reg_param(®_params
[2]);
1106 destroy_reg_param(®_params
[3]);
1111 static int stellaris_write(struct flash_bank
*bank
, const uint8_t *buffer
,
1112 uint32_t offset
, uint32_t count
)
1114 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1115 struct target
*target
= bank
->target
;
1116 uint32_t address
= offset
;
1117 uint32_t flash_cris
, flash_fmc
;
1118 uint32_t words_remaining
= (count
/ 4);
1119 uint32_t bytes_remaining
= (count
& 0x00000003);
1120 uint32_t bytes_written
= 0;
1123 if (bank
->target
->state
!= TARGET_HALTED
) {
1124 LOG_ERROR("Target not halted");
1125 return ERROR_TARGET_NOT_HALTED
;
1128 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" count=%08" PRIx32
"",
1129 bank
, buffer
, offset
, count
);
1131 if (stellaris_info
->did1
== 0)
1132 return ERROR_FLASH_BANK_NOT_PROBED
;
1135 LOG_WARNING("offset size must be word aligned");
1136 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1139 if (offset
+ count
> bank
->size
)
1140 return ERROR_FLASH_DST_OUT_OF_BANK
;
1142 /* Refresh flash controller timing */
1143 stellaris_read_clock_info(bank
);
1144 stellaris_set_flash_timing(bank
);
1146 /* Clear and disable flash programming interrupts */
1147 target_write_u32(target
, FLASH_CIM
, 0);
1148 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1150 /* REVISIT this clobbers state set by any halted firmware ...
1151 * it might want to process those IRQs.
1154 /* multiple words to be programmed? */
1155 if (words_remaining
> 0) {
1156 /* try using a block write */
1157 retval
= stellaris_write_block(bank
, buffer
, offset
,
1159 if (retval
!= ERROR_OK
) {
1160 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
1161 LOG_DEBUG("writing flash word-at-a-time");
1162 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
1163 /* if an error occurred, we examine the reason, and quit */
1164 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1166 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32
"", flash_cris
);
1167 return ERROR_FLASH_OPERATION_FAILED
;
1170 buffer
+= words_remaining
* 4;
1171 address
+= words_remaining
* 4;
1172 words_remaining
= 0;
1176 while (words_remaining
> 0) {
1177 if (!(address
& 0xff))
1178 LOG_DEBUG("0x%" PRIx32
"", address
);
1180 /* Program one word */
1181 target_write_u32(target
, FLASH_FMA
, address
);
1182 target_write_buffer(target
, FLASH_FMD
, 4, buffer
);
1183 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1184 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1185 /* Wait until write complete */
1187 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1188 } while (flash_fmc
& FMC_WRITE
);
1195 if (bytes_remaining
) {
1196 uint8_t last_word
[4] = {0xff, 0xff, 0xff, 0xff};
1198 /* copy the last remaining bytes into the write buffer */
1199 memcpy(last_word
, buffer
+bytes_written
, bytes_remaining
);
1201 if (!(address
& 0xff))
1202 LOG_DEBUG("0x%" PRIx32
"", address
);
1204 /* Program one word */
1205 target_write_u32(target
, FLASH_FMA
, address
);
1206 target_write_buffer(target
, FLASH_FMD
, 4, last_word
);
1207 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1208 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1209 /* Wait until write complete */
1211 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1212 } while (flash_fmc
& FMC_WRITE
);
1215 /* Check access violations */
1216 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1217 if (flash_cris
& (AMASK
)) {
1218 LOG_DEBUG("flash_cris 0x%" PRIx32
"", flash_cris
);
1219 return ERROR_FLASH_OPERATION_FAILED
;
1224 static int stellaris_probe(struct flash_bank
*bank
)
1226 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1229 /* If this is a stellaris chip, it has flash; probe() is just
1230 * to figure out how much is present. Only do it once.
1232 if (stellaris_info
->did1
!= 0)
1235 /* stellaris_read_part_info() already handled error checking and
1236 * reporting. Note that it doesn't write, so we don't care about
1237 * whether the target is halted or not.
1239 retval
= stellaris_read_part_info(bank
);
1240 if (retval
!= ERROR_OK
)
1243 free(bank
->sectors
);
1245 /* provide this for the benefit of the NOR flash framework */
1246 bank
->size
= stellaris_info
->num_pages
* stellaris_info
->pagesize
;
1247 bank
->num_sectors
= stellaris_info
->num_pages
;
1248 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
1249 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
1250 bank
->sectors
[i
].offset
= i
* stellaris_info
->pagesize
;
1251 bank
->sectors
[i
].size
= stellaris_info
->pagesize
;
1252 bank
->sectors
[i
].is_erased
= -1;
1253 bank
->sectors
[i
].is_protected
= -1;
1259 static int stellaris_mass_erase(struct flash_bank
*bank
)
1261 struct target
*target
= NULL
;
1262 struct stellaris_flash_bank
*stellaris_info
= NULL
;
1265 stellaris_info
= bank
->driver_priv
;
1266 target
= bank
->target
;
1268 if (target
->state
!= TARGET_HALTED
) {
1269 LOG_ERROR("Target not halted");
1270 return ERROR_TARGET_NOT_HALTED
;
1273 if (stellaris_info
->did1
== 0)
1274 return ERROR_FLASH_BANK_NOT_PROBED
;
1276 /* Refresh flash controller timing */
1277 stellaris_read_clock_info(bank
);
1278 stellaris_set_flash_timing(bank
);
1280 /* Clear and disable flash programming interrupts */
1281 target_write_u32(target
, FLASH_CIM
, 0);
1282 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1284 /* REVISIT this clobbers state set by any halted firmware ...
1285 * it might want to process those IRQs.
1288 target_write_u32(target
, FLASH_FMA
, 0);
1289 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1290 /* Wait until erase complete */
1292 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1293 } while (flash_fmc
& FMC_MERASE
);
1295 /* if device has > 128k, then second erase cycle is needed
1296 * this is only valid for older devices, but will not hurt */
1297 if (stellaris_info
->num_pages
* stellaris_info
->pagesize
> 0x20000) {
1298 target_write_u32(target
, FLASH_FMA
, 0x20000);
1299 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1300 /* Wait until erase complete */
1302 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1303 } while (flash_fmc
& FMC_MERASE
);
1309 COMMAND_HANDLER(stellaris_handle_mass_erase_command
)
1312 return ERROR_COMMAND_SYNTAX_ERROR
;
1314 struct flash_bank
*bank
;
1315 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1316 if (retval
!= ERROR_OK
)
1319 if (stellaris_mass_erase(bank
) == ERROR_OK
)
1320 command_print(CMD
, "stellaris mass erase complete");
1322 command_print(CMD
, "stellaris mass erase failed");
1328 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1329 * This performs a mass erase and then restores all nonvolatile registers
1330 * (including USER_* registers and flash lock bits) to their defaults.
1331 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1333 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1334 * can affect this operation if flash protection has been enabled.
1336 COMMAND_HANDLER(stellaris_handle_recover_command
)
1338 struct flash_bank
*bank
;
1343 return ERROR_COMMAND_SYNTAX_ERROR
;
1345 bank
= get_flash_bank_by_num_noprobe(0);
1349 /* REVISIT ... it may be worth sanity checking that the AP is
1350 * inactive before we start. ARM documents that switching a DP's
1351 * mode while it's active can cause fault modes that need a power
1355 Jim_Eval_Named(CMD_CTX
->interp
, "catch { hla_command \"debug unlock\" }", 0, 0);
1356 if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX
->interp
), NULL
), "0")) {
1362 if (!(jtag_get_reset_config() & RESET_HAS_SRST
)) {
1363 LOG_ERROR("Can't recover Stellaris flash without SRST");
1366 adapter_assert_reset();
1368 arm
= target_to_arm(bank
->target
);
1369 for (int i
= 0; i
< 5; i
++) {
1370 retval
= dap_to_swd(arm
->dap
);
1371 if (retval
!= ERROR_OK
)
1374 retval
= dap_to_jtag(arm
->dap
);
1375 if (retval
!= ERROR_OK
)
1379 /* de-assert SRST */
1380 adapter_deassert_reset();
1381 retval
= jtag_execute_queue();
1383 /* wait 400+ msec ... OK, "1+ second" is simpler */
1387 /* USER INTERVENTION required for the power cycle
1388 * Restarting OpenOCD is likely needed because of mode switching.
1390 LOG_INFO("USER ACTION: "
1391 "power cycle Stellaris chip, then restart OpenOCD.");
1397 static const struct command_registration stellaris_exec_command_handlers
[] = {
1399 .name
= "mass_erase",
1401 .handler
= stellaris_handle_mass_erase_command
,
1402 .mode
= COMMAND_EXEC
,
1403 .help
= "erase entire device",
1407 .handler
= stellaris_handle_recover_command
,
1408 .mode
= COMMAND_EXEC
,
1410 .help
= "recover (and erase) locked device",
1412 COMMAND_REGISTRATION_DONE
1414 static const struct command_registration stellaris_command_handlers
[] = {
1416 .name
= "stellaris",
1417 .mode
= COMMAND_EXEC
,
1418 .help
= "Stellaris flash command group",
1420 .chain
= stellaris_exec_command_handlers
,
1422 COMMAND_REGISTRATION_DONE
1425 const struct flash_driver stellaris_flash
= {
1426 .name
= "stellaris",
1427 .commands
= stellaris_command_handlers
,
1428 .flash_bank_command
= stellaris_flash_bank_command
,
1429 .erase
= stellaris_erase
,
1430 .protect
= stellaris_protect
,
1431 .write
= stellaris_write
,
1432 .read
= default_flash_read
,
1433 .probe
= stellaris_probe
,
1434 .auto_probe
= stellaris_probe
,
1435 .erase_check
= default_flash_blank_check
,
1436 .protect_check
= stellaris_protect_check
,
1437 .info
= get_stellaris_info
,
1438 .free_driver_priv
= default_flash_free_driver_priv
,
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)