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 } StellarisParts
[] = {
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 StellarisClassname
[] = {
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 StellarisClassname
[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; StellarisParts
[i
].partno
; i
++) {
747 if ((StellarisParts
[i
].partno
== ((did1
>> 16) & 0xFF)) &&
748 (StellarisParts
[i
].class == stellaris_info
->target_class
))
752 stellaris_info
->target_name
= StellarisParts
[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
;
890 bank
->sectors
[banknr
].is_erased
= 1;
896 static int stellaris_protect(struct flash_bank
*bank
, int set
,
897 unsigned int first
, unsigned int last
)
899 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
900 struct target
*target
= bank
->target
;
901 uint32_t flash_fmc
, flash_cris
;
902 unsigned int bits_per_page
= stellaris
->pagesize
/ 2048;
904 if (target
->state
!= TARGET_HALTED
) {
905 LOG_ERROR("Target not halted");
906 return ERROR_TARGET_NOT_HALTED
;
910 LOG_ERROR("Hardware doesn't support page-level unprotect. "
911 "Try the 'recover' command.");
912 return ERROR_COMMAND_SYNTAX_ERROR
;
915 if (stellaris
->did1
== 0)
916 return ERROR_FLASH_BANK_NOT_PROBED
;
918 if (stellaris
->target_class
== 0x03 &&
919 !((stellaris
->did0
>> 8) & 0xFF) &&
920 !((stellaris
->did0
) & 0xFF)) {
921 LOG_ERROR("DustDevil A0 parts can't be unprotected, see errata; refusing to proceed");
922 return ERROR_FLASH_OPERATION_FAILED
;
925 if (!bits_per_page
&& (first
% 2 || !(last
% 2))) {
926 LOG_ERROR("Can't protect unaligned pages");
927 return ERROR_FLASH_SECTOR_INVALID
;
930 /* Refresh flash controller timing */
931 stellaris_read_clock_info(bank
);
932 stellaris_set_flash_timing(bank
);
934 /* Clear and disable flash programming interrupts */
935 target_write_u32(target
, FLASH_CIM
, 0);
936 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
938 uint32_t flash_sizek
= stellaris
->pagesize
/ 1024 *
939 stellaris
->num_pages
;
942 if (stellaris
->target_class
>= 0x0a || flash_sizek
> 64)
943 fmppe_addr
= SCB_BASE
| FMPPE0
;
945 fmppe_addr
= SCB_BASE
| FMPPE
;
947 unsigned int page
= 0;
948 unsigned int lockbitnum
, lockbitcnt
= flash_sizek
/ 2;
949 /* Every lock bit always corresponds to a 2k region */
950 for (lockbitnum
= 0; lockbitnum
< lockbitcnt
; lockbitnum
+= 32) {
953 target_read_u32(target
, fmppe_addr
, &fmppe
);
954 for (unsigned int i
= 0;
955 i
< 32 && lockbitnum
+ i
< lockbitcnt
;
957 if (page
>= first
&& page
<= last
)
961 if (!((i
+ 1) % bits_per_page
))
963 } else { /* 1024k pages, every lockbit covers 2 pages */
967 target_write_u32(target
, fmppe_addr
, fmppe
);
970 target_write_u32(target
, FLASH_FMA
, 1 + lockbitnum
/ 16);
971 /* Write commit command */
972 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_COMT
);
974 /* Wait until commit complete */
976 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
977 } while (flash_fmc
& FMC_COMT
);
979 /* Check access violations */
980 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
981 if (flash_cris
& (AMASK
)) {
982 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32
"", flash_cris
);
983 target_write_u32(target
, FLASH_CRIS
, 0);
984 return ERROR_FLASH_OPERATION_FAILED
;
993 /* see contrib/loaders/flash/stellaris.s for src */
995 static const uint8_t stellaris_write_code
[] = {
997 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */
998 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */
1000 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
1001 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
1002 0x17, 0xD0, /* beq exit */
1003 0x47, 0x68, /* ldr r7, [r0, #4] */
1004 0x47, 0x45, /* cmp r7, r8 */
1005 0xF7, 0xD0, /* beq wait_fifo */
1007 0x22, 0x60, /* str r2, [r4, #0] */
1008 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */
1009 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */
1010 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */
1011 0xA5, 0x60, /* str r5, [r4, #8] */
1013 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */
1014 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */
1015 0xFA, 0xD1, /* bne busy */
1016 0x8F, 0x42, /* cmp r7, r1 */
1017 0x28, 0xBF, /* it cs */
1018 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
1019 0x47, 0x60, /* str r7, [r0, #4] */
1020 0x01, 0x3B, /* subs r3, r3, #1 */
1021 0x03, 0xB1, /* cbz r3, exit */
1022 0xE2, 0xE7, /* b wait_fifo */
1024 0x00, 0xBE, /* bkpt #0 */
1026 /* pFLASH_CTRL_BASE: */
1027 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
1028 /* FLASHWRITECMD: */
1029 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
1031 static int stellaris_write_block(struct flash_bank
*bank
,
1032 const uint8_t *buffer
, uint32_t offset
, uint32_t wcount
)
1034 struct target
*target
= bank
->target
;
1035 uint32_t buffer_size
= 16384;
1036 struct working_area
*source
;
1037 struct working_area
*write_algorithm
;
1038 uint32_t address
= bank
->base
+ offset
;
1039 struct reg_param reg_params
[4];
1040 struct armv7m_algorithm armv7m_info
;
1041 int retval
= ERROR_OK
;
1043 /* power of two, and multiple of word size */
1044 static const unsigned buf_min
= 128;
1046 /* for small buffers it's faster not to download an algorithm */
1047 if (wcount
* 4 < buf_min
)
1048 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1050 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" wcount=%08" PRIx32
"",
1051 bank
, buffer
, offset
, wcount
);
1053 /* flash write code */
1054 if (target_alloc_working_area(target
, sizeof(stellaris_write_code
),
1055 &write_algorithm
) != ERROR_OK
) {
1056 LOG_DEBUG("no working area for block memory writes");
1057 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1060 /* plus a buffer big enough for this data */
1061 if (wcount
* 4 < buffer_size
)
1062 buffer_size
= wcount
* 4;
1065 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
1067 if (buffer_size
<= buf_min
) {
1068 target_free_working_area(target
, write_algorithm
);
1069 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1071 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1072 target_name(target
), (unsigned) buffer_size
);
1075 target_write_buffer(target
, write_algorithm
->address
,
1076 sizeof(stellaris_write_code
),
1077 stellaris_write_code
);
1079 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
1080 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
1082 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1083 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1084 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
1085 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
1087 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
1088 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
1089 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
1090 buf_set_u32(reg_params
[3].value
, 0, 32, wcount
);
1092 retval
= target_run_flash_async_algorithm(target
, buffer
, wcount
, 4,
1095 source
->address
, source
->size
,
1096 write_algorithm
->address
, 0,
1099 if (retval
== ERROR_FLASH_OPERATION_FAILED
)
1100 LOG_ERROR("error %d executing stellaris flash write algorithm", retval
);
1102 target_free_working_area(target
, write_algorithm
);
1103 target_free_working_area(target
, source
);
1105 destroy_reg_param(®_params
[0]);
1106 destroy_reg_param(®_params
[1]);
1107 destroy_reg_param(®_params
[2]);
1108 destroy_reg_param(®_params
[3]);
1113 static int stellaris_write(struct flash_bank
*bank
, const uint8_t *buffer
,
1114 uint32_t offset
, uint32_t count
)
1116 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1117 struct target
*target
= bank
->target
;
1118 uint32_t address
= offset
;
1119 uint32_t flash_cris
, flash_fmc
;
1120 uint32_t words_remaining
= (count
/ 4);
1121 uint32_t bytes_remaining
= (count
& 0x00000003);
1122 uint32_t bytes_written
= 0;
1125 if (bank
->target
->state
!= TARGET_HALTED
) {
1126 LOG_ERROR("Target not halted");
1127 return ERROR_TARGET_NOT_HALTED
;
1130 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" count=%08" PRIx32
"",
1131 bank
, buffer
, offset
, count
);
1133 if (stellaris_info
->did1
== 0)
1134 return ERROR_FLASH_BANK_NOT_PROBED
;
1137 LOG_WARNING("offset size must be word aligned");
1138 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1141 if (offset
+ count
> bank
->size
)
1142 return ERROR_FLASH_DST_OUT_OF_BANK
;
1144 /* Refresh flash controller timing */
1145 stellaris_read_clock_info(bank
);
1146 stellaris_set_flash_timing(bank
);
1148 /* Clear and disable flash programming interrupts */
1149 target_write_u32(target
, FLASH_CIM
, 0);
1150 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1152 /* REVISIT this clobbers state set by any halted firmware ...
1153 * it might want to process those IRQs.
1156 /* multiple words to be programmed? */
1157 if (words_remaining
> 0) {
1158 /* try using a block write */
1159 retval
= stellaris_write_block(bank
, buffer
, offset
,
1161 if (retval
!= ERROR_OK
) {
1162 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
1163 LOG_DEBUG("writing flash word-at-a-time");
1164 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
1165 /* if an error occurred, we examine the reason, and quit */
1166 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1168 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32
"", flash_cris
);
1169 return ERROR_FLASH_OPERATION_FAILED
;
1172 buffer
+= words_remaining
* 4;
1173 address
+= words_remaining
* 4;
1174 words_remaining
= 0;
1178 while (words_remaining
> 0) {
1179 if (!(address
& 0xff))
1180 LOG_DEBUG("0x%" PRIx32
"", address
);
1182 /* Program one word */
1183 target_write_u32(target
, FLASH_FMA
, address
);
1184 target_write_buffer(target
, FLASH_FMD
, 4, buffer
);
1185 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1186 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1187 /* Wait until write complete */
1189 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1190 } while (flash_fmc
& FMC_WRITE
);
1197 if (bytes_remaining
) {
1198 uint8_t last_word
[4] = {0xff, 0xff, 0xff, 0xff};
1200 /* copy the last remaining bytes into the write buffer */
1201 memcpy(last_word
, buffer
+bytes_written
, bytes_remaining
);
1203 if (!(address
& 0xff))
1204 LOG_DEBUG("0x%" PRIx32
"", address
);
1206 /* Program one word */
1207 target_write_u32(target
, FLASH_FMA
, address
);
1208 target_write_buffer(target
, FLASH_FMD
, 4, last_word
);
1209 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1210 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1211 /* Wait until write complete */
1213 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1214 } while (flash_fmc
& FMC_WRITE
);
1217 /* Check access violations */
1218 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1219 if (flash_cris
& (AMASK
)) {
1220 LOG_DEBUG("flash_cris 0x%" PRIx32
"", flash_cris
);
1221 return ERROR_FLASH_OPERATION_FAILED
;
1226 static int stellaris_probe(struct flash_bank
*bank
)
1228 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1231 /* If this is a stellaris chip, it has flash; probe() is just
1232 * to figure out how much is present. Only do it once.
1234 if (stellaris_info
->did1
!= 0)
1237 /* stellaris_read_part_info() already handled error checking and
1238 * reporting. Note that it doesn't write, so we don't care about
1239 * whether the target is halted or not.
1241 retval
= stellaris_read_part_info(bank
);
1242 if (retval
!= ERROR_OK
)
1245 free(bank
->sectors
);
1247 /* provide this for the benefit of the NOR flash framework */
1248 bank
->size
= stellaris_info
->num_pages
* stellaris_info
->pagesize
;
1249 bank
->num_sectors
= stellaris_info
->num_pages
;
1250 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
1251 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
1252 bank
->sectors
[i
].offset
= i
* stellaris_info
->pagesize
;
1253 bank
->sectors
[i
].size
= stellaris_info
->pagesize
;
1254 bank
->sectors
[i
].is_erased
= -1;
1255 bank
->sectors
[i
].is_protected
= -1;
1261 static int stellaris_mass_erase(struct flash_bank
*bank
)
1263 struct target
*target
= NULL
;
1264 struct stellaris_flash_bank
*stellaris_info
= NULL
;
1267 stellaris_info
= bank
->driver_priv
;
1268 target
= bank
->target
;
1270 if (target
->state
!= TARGET_HALTED
) {
1271 LOG_ERROR("Target not halted");
1272 return ERROR_TARGET_NOT_HALTED
;
1275 if (stellaris_info
->did1
== 0)
1276 return ERROR_FLASH_BANK_NOT_PROBED
;
1278 /* Refresh flash controller timing */
1279 stellaris_read_clock_info(bank
);
1280 stellaris_set_flash_timing(bank
);
1282 /* Clear and disable flash programming interrupts */
1283 target_write_u32(target
, FLASH_CIM
, 0);
1284 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1286 /* REVISIT this clobbers state set by any halted firmware ...
1287 * it might want to process those IRQs.
1290 target_write_u32(target
, FLASH_FMA
, 0);
1291 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1292 /* Wait until erase complete */
1294 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1295 } while (flash_fmc
& FMC_MERASE
);
1297 /* if device has > 128k, then second erase cycle is needed
1298 * this is only valid for older devices, but will not hurt */
1299 if (stellaris_info
->num_pages
* stellaris_info
->pagesize
> 0x20000) {
1300 target_write_u32(target
, FLASH_FMA
, 0x20000);
1301 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1302 /* Wait until erase complete */
1304 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1305 } while (flash_fmc
& FMC_MERASE
);
1311 COMMAND_HANDLER(stellaris_handle_mass_erase_command
)
1314 return ERROR_COMMAND_SYNTAX_ERROR
;
1316 struct flash_bank
*bank
;
1317 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1318 if (ERROR_OK
!= retval
)
1321 if (stellaris_mass_erase(bank
) == ERROR_OK
) {
1322 /* set all sectors as erased */
1323 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++)
1324 bank
->sectors
[i
].is_erased
= 1;
1326 command_print(CMD
, "stellaris mass erase complete");
1328 command_print(CMD
, "stellaris mass erase failed");
1334 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1335 * This performs a mass erase and then restores all nonvolatile registers
1336 * (including USER_* registers and flash lock bits) to their defaults.
1337 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1339 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1340 * can affect this operation if flash protection has been enabled.
1342 COMMAND_HANDLER(stellaris_handle_recover_command
)
1344 struct flash_bank
*bank
;
1349 return ERROR_COMMAND_SYNTAX_ERROR
;
1351 bank
= get_flash_bank_by_num_noprobe(0);
1355 /* REVISIT ... it may be worth sanity checking that the AP is
1356 * inactive before we start. ARM documents that switching a DP's
1357 * mode while it's active can cause fault modes that need a power
1361 Jim_Eval_Named(CMD_CTX
->interp
, "catch { hla_command \"debug unlock\" }", 0, 0);
1362 if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX
->interp
), NULL
), "0")) {
1368 if (!(jtag_get_reset_config() & RESET_HAS_SRST
)) {
1369 LOG_ERROR("Can't recover Stellaris flash without SRST");
1372 adapter_assert_reset();
1374 arm
= target_to_arm(bank
->target
);
1375 for (int i
= 0; i
< 5; i
++) {
1376 retval
= dap_to_swd(arm
->dap
);
1377 if (retval
!= ERROR_OK
)
1380 retval
= dap_to_jtag(arm
->dap
);
1381 if (retval
!= ERROR_OK
)
1385 /* de-assert SRST */
1386 adapter_deassert_reset();
1387 retval
= jtag_execute_queue();
1389 /* wait 400+ msec ... OK, "1+ second" is simpler */
1393 /* USER INTERVENTION required for the power cycle
1394 * Restarting OpenOCD is likely needed because of mode switching.
1396 LOG_INFO("USER ACTION: "
1397 "power cycle Stellaris chip, then restart OpenOCD.");
1403 static const struct command_registration stellaris_exec_command_handlers
[] = {
1405 .name
= "mass_erase",
1407 .handler
= stellaris_handle_mass_erase_command
,
1408 .mode
= COMMAND_EXEC
,
1409 .help
= "erase entire device",
1413 .handler
= stellaris_handle_recover_command
,
1414 .mode
= COMMAND_EXEC
,
1416 .help
= "recover (and erase) locked device",
1418 COMMAND_REGISTRATION_DONE
1420 static const struct command_registration stellaris_command_handlers
[] = {
1422 .name
= "stellaris",
1423 .mode
= COMMAND_EXEC
,
1424 .help
= "Stellaris flash command group",
1426 .chain
= stellaris_exec_command_handlers
,
1428 COMMAND_REGISTRATION_DONE
1431 const struct flash_driver stellaris_flash
= {
1432 .name
= "stellaris",
1433 .commands
= stellaris_command_handlers
,
1434 .flash_bank_command
= stellaris_flash_bank_command
,
1435 .erase
= stellaris_erase
,
1436 .protect
= stellaris_protect
,
1437 .write
= stellaris_write
,
1438 .read
= default_flash_read
,
1439 .probe
= stellaris_probe
,
1440 .auto_probe
= stellaris_probe
,
1441 .erase_check
= default_flash_blank_check
,
1442 .protect_check
= stellaris_protect_check
,
1443 .info
= get_stellaris_info
,
1444 .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)