1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2006 by Magnus Lundin *
7 * Copyright (C) 2008 by Spencer Oliver *
8 * spen@spen-soft.co.uk *
9 ***************************************************************************/
11 /***************************************************************************
12 * STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more.
13 ***************************************************************************/
19 #include "jtag/interface.h"
21 #include <target/algorithm.h>
22 #include <target/arm_adi_v5.h>
23 #include <target/armv7m.h>
25 #define DID0_VER(did0) ((did0 >> 28)&0x07)
27 /* STELLARIS control registers */
28 #define SCB_BASE 0x400FE000
43 /* "legacy" flash memory protection registers (64KB max) */
47 /* new flash memory protection registers (for more than 64KB) */
48 #define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */
49 #define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */
53 #define FLASH_CONTROL_BASE 0x400FD000
54 #define FLASH_FMA (FLASH_CONTROL_BASE | 0x000)
55 #define FLASH_FMD (FLASH_CONTROL_BASE | 0x004)
56 #define FLASH_FMC (FLASH_CONTROL_BASE | 0x008)
57 #define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C)
58 #define FLASH_CIM (FLASH_CONTROL_BASE | 0x010)
59 #define FLASH_MISC (FLASH_CONTROL_BASE | 0x014)
60 #define FLASH_FSIZE (FLASH_CONTROL_BASE | 0xFC0)
61 #define FLASH_SSIZE (FLASH_CONTROL_BASE | 0xFC4)
69 /* Flash Controller Command bits */
70 #define FMC_WRKEY (0xA442 << 16)
71 #define FMC_COMT (1 << 3)
72 #define FMC_MERASE (1 << 2)
73 #define FMC_ERASE (1 << 1)
74 #define FMC_WRITE (1 << 0)
76 /* STELLARIS constants */
78 /* values to write in FMA to commit write-"once" values */
79 #define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */
80 #define FLASH_FMA_PPE(x) (2 * (x) + 1) /* for FMPPPEx */
82 static void stellaris_read_clock_info(struct flash_bank
*bank
);
83 static int stellaris_mass_erase(struct flash_bank
*bank
);
85 struct stellaris_flash_bank
{
86 /* chip id register */
94 const char *target_name
;
102 /* main clock status */
109 const char *iosc_desc
;
110 const char *mck_desc
;
113 /* Autogenerated by contrib/gen-stellaris-part-header.pl */
114 /* From Stellaris Firmware Development Package revision 9453 */
115 static const struct {
118 const char *partname
;
119 } stellaris_parts
[] = {
120 {0x00, 0x01, "LM3S101"},
121 {0x00, 0x02, "LM3S102"},
122 {0x01, 0xBF, "LM3S1110"},
123 {0x01, 0xC3, "LM3S1133"},
124 {0x01, 0xC5, "LM3S1138"},
125 {0x01, 0xC1, "LM3S1150"},
126 {0x01, 0xC4, "LM3S1162"},
127 {0x01, 0xC2, "LM3S1165"},
128 {0x01, 0xEC, "LM3S1166"},
129 {0x01, 0xC6, "LM3S1332"},
130 {0x01, 0xBC, "LM3S1435"},
131 {0x01, 0xBA, "LM3S1439"},
132 {0x01, 0xBB, "LM3S1512"},
133 {0x01, 0xC7, "LM3S1538"},
134 {0x01, 0xDB, "LM3S1601"},
135 {0x03, 0x06, "LM3S1607"},
136 {0x01, 0xDA, "LM3S1608"},
137 {0x01, 0xC0, "LM3S1620"},
138 {0x04, 0xCD, "LM3S1621"},
139 {0x03, 0x03, "LM3S1625"},
140 {0x03, 0x04, "LM3S1626"},
141 {0x03, 0x05, "LM3S1627"},
142 {0x01, 0xB3, "LM3S1635"},
143 {0x01, 0xEB, "LM3S1636"},
144 {0x01, 0xBD, "LM3S1637"},
145 {0x04, 0xB1, "LM3S1651"},
146 {0x01, 0xB9, "LM3S1751"},
147 {0x03, 0x10, "LM3S1776"},
148 {0x04, 0x16, "LM3S1811"},
149 {0x04, 0x3D, "LM3S1816"},
150 {0x01, 0xB4, "LM3S1850"},
151 {0x01, 0xDD, "LM3S1911"},
152 {0x01, 0xDC, "LM3S1918"},
153 {0x01, 0xB7, "LM3S1937"},
154 {0x01, 0xBE, "LM3S1958"},
155 {0x01, 0xB5, "LM3S1960"},
156 {0x01, 0xB8, "LM3S1968"},
157 {0x01, 0xEA, "LM3S1969"},
158 {0x04, 0xCE, "LM3S1B21"},
159 {0x06, 0xCA, "LM3S1C21"},
160 {0x06, 0xCB, "LM3S1C26"},
161 {0x06, 0x98, "LM3S1C58"},
162 {0x06, 0xB0, "LM3S1D21"},
163 {0x06, 0xCC, "LM3S1D26"},
164 {0x06, 0x1D, "LM3S1F11"},
165 {0x06, 0x1B, "LM3S1F16"},
166 {0x06, 0xAF, "LM3S1G21"},
167 {0x06, 0x95, "LM3S1G58"},
168 {0x06, 0x1E, "LM3S1H11"},
169 {0x06, 0x1C, "LM3S1H16"},
170 {0x04, 0x0F, "LM3S1J11"},
171 {0x04, 0x3C, "LM3S1J16"},
172 {0x04, 0x0E, "LM3S1N11"},
173 {0x04, 0x3B, "LM3S1N16"},
174 {0x04, 0xB2, "LM3S1P51"},
175 {0x04, 0x9E, "LM3S1R21"},
176 {0x04, 0xC9, "LM3S1R26"},
177 {0x04, 0x30, "LM3S1W16"},
178 {0x04, 0x2F, "LM3S1Z16"},
179 {0x01, 0x51, "LM3S2110"},
180 {0x01, 0x84, "LM3S2139"},
181 {0x03, 0x39, "LM3S2276"},
182 {0x01, 0xA2, "LM3S2410"},
183 {0x01, 0x59, "LM3S2412"},
184 {0x01, 0x56, "LM3S2432"},
185 {0x01, 0x5A, "LM3S2533"},
186 {0x01, 0xE1, "LM3S2601"},
187 {0x01, 0xE0, "LM3S2608"},
188 {0x03, 0x33, "LM3S2616"},
189 {0x01, 0x57, "LM3S2620"},
190 {0x01, 0x85, "LM3S2637"},
191 {0x01, 0x53, "LM3S2651"},
192 {0x03, 0x80, "LM3S2671"},
193 {0x03, 0x50, "LM3S2678"},
194 {0x01, 0xA4, "LM3S2730"},
195 {0x01, 0x52, "LM3S2739"},
196 {0x03, 0x3A, "LM3S2776"},
197 {0x04, 0x6D, "LM3S2793"},
198 {0x01, 0xE3, "LM3S2911"},
199 {0x01, 0xE2, "LM3S2918"},
200 {0x01, 0xED, "LM3S2919"},
201 {0x01, 0x54, "LM3S2939"},
202 {0x01, 0x8F, "LM3S2948"},
203 {0x01, 0x58, "LM3S2950"},
204 {0x01, 0x55, "LM3S2965"},
205 {0x04, 0x6C, "LM3S2B93"},
206 {0x06, 0x94, "LM3S2D93"},
207 {0x06, 0x93, "LM3S2U93"},
208 {0x00, 0x19, "LM3S300"},
209 {0x00, 0x11, "LM3S301"},
210 {0x00, 0x1A, "LM3S308"},
211 {0x00, 0x12, "LM3S310"},
212 {0x00, 0x13, "LM3S315"},
213 {0x00, 0x14, "LM3S316"},
214 {0x00, 0x17, "LM3S317"},
215 {0x00, 0x15, "LM3S328"},
216 {0x03, 0x08, "LM3S3634"},
217 {0x03, 0x43, "LM3S3651"},
218 {0x04, 0xC8, "LM3S3654"},
219 {0x03, 0x44, "LM3S3739"},
220 {0x03, 0x49, "LM3S3748"},
221 {0x03, 0x45, "LM3S3749"},
222 {0x04, 0x42, "LM3S3826"},
223 {0x04, 0x41, "LM3S3J26"},
224 {0x04, 0x40, "LM3S3N26"},
225 {0x04, 0x3F, "LM3S3W26"},
226 {0x04, 0x3E, "LM3S3Z26"},
227 {0x03, 0x81, "LM3S5632"},
228 {0x04, 0x0C, "LM3S5651"},
229 {0x03, 0x8A, "LM3S5652"},
230 {0x04, 0x4D, "LM3S5656"},
231 {0x03, 0x91, "LM3S5662"},
232 {0x03, 0x96, "LM3S5732"},
233 {0x03, 0x97, "LM3S5737"},
234 {0x03, 0xA0, "LM3S5739"},
235 {0x03, 0x99, "LM3S5747"},
236 {0x03, 0xA7, "LM3S5749"},
237 {0x03, 0x9A, "LM3S5752"},
238 {0x03, 0x9C, "LM3S5762"},
239 {0x04, 0x69, "LM3S5791"},
240 {0x04, 0x0B, "LM3S5951"},
241 {0x04, 0x4E, "LM3S5956"},
242 {0x04, 0x68, "LM3S5B91"},
243 {0x06, 0x2E, "LM3S5C31"},
244 {0x06, 0x2C, "LM3S5C36"},
245 {0x06, 0x5E, "LM3S5C51"},
246 {0x06, 0x5B, "LM3S5C56"},
247 {0x06, 0x5F, "LM3S5D51"},
248 {0x06, 0x5C, "LM3S5D56"},
249 {0x06, 0x87, "LM3S5D91"},
250 {0x06, 0x2D, "LM3S5G31"},
251 {0x06, 0x1F, "LM3S5G36"},
252 {0x06, 0x5D, "LM3S5G51"},
253 {0x06, 0x4F, "LM3S5G56"},
254 {0x04, 0x09, "LM3S5K31"},
255 {0x04, 0x4A, "LM3S5K36"},
256 {0x04, 0x0A, "LM3S5P31"},
257 {0x04, 0x48, "LM3S5P36"},
258 {0x04, 0xB6, "LM3S5P3B"},
259 {0x04, 0x0D, "LM3S5P51"},
260 {0x04, 0x4C, "LM3S5P56"},
261 {0x04, 0x07, "LM3S5R31"},
262 {0x04, 0x4B, "LM3S5R36"},
263 {0x04, 0x47, "LM3S5T36"},
264 {0x06, 0x7F, "LM3S5U91"},
265 {0x04, 0x46, "LM3S5Y36"},
266 {0x00, 0x2A, "LM3S600"},
267 {0x00, 0x21, "LM3S601"},
268 {0x00, 0x2B, "LM3S608"},
269 {0x00, 0x22, "LM3S610"},
270 {0x01, 0xA1, "LM3S6100"},
271 {0x00, 0x23, "LM3S611"},
272 {0x01, 0x74, "LM3S6110"},
273 {0x00, 0x24, "LM3S612"},
274 {0x00, 0x25, "LM3S613"},
275 {0x00, 0x26, "LM3S615"},
276 {0x00, 0x28, "LM3S617"},
277 {0x00, 0x29, "LM3S618"},
278 {0x00, 0x27, "LM3S628"},
279 {0x01, 0xA5, "LM3S6420"},
280 {0x01, 0x82, "LM3S6422"},
281 {0x01, 0x75, "LM3S6432"},
282 {0x01, 0x76, "LM3S6537"},
283 {0x01, 0x71, "LM3S6610"},
284 {0x01, 0xE7, "LM3S6611"},
285 {0x01, 0xE6, "LM3S6618"},
286 {0x01, 0x83, "LM3S6633"},
287 {0x01, 0x8B, "LM3S6637"},
288 {0x01, 0xA3, "LM3S6730"},
289 {0x01, 0x77, "LM3S6753"},
290 {0x01, 0xE9, "LM3S6911"},
291 {0x01, 0xE8, "LM3S6918"},
292 {0x01, 0x89, "LM3S6938"},
293 {0x01, 0x72, "LM3S6950"},
294 {0x01, 0x78, "LM3S6952"},
295 {0x01, 0x73, "LM3S6965"},
296 {0x06, 0xAA, "LM3S6C11"},
297 {0x06, 0xAC, "LM3S6C65"},
298 {0x06, 0x9F, "LM3S6G11"},
299 {0x06, 0xAB, "LM3S6G65"},
300 {0x00, 0x38, "LM3S800"},
301 {0x00, 0x31, "LM3S801"},
302 {0x00, 0x39, "LM3S808"},
303 {0x00, 0x32, "LM3S811"},
304 {0x00, 0x33, "LM3S812"},
305 {0x00, 0x34, "LM3S815"},
306 {0x00, 0x36, "LM3S817"},
307 {0x00, 0x37, "LM3S818"},
308 {0x00, 0x35, "LM3S828"},
309 {0x01, 0x64, "LM3S8530"},
310 {0x01, 0x8E, "LM3S8538"},
311 {0x01, 0x61, "LM3S8630"},
312 {0x01, 0x63, "LM3S8730"},
313 {0x01, 0x8D, "LM3S8733"},
314 {0x01, 0x86, "LM3S8738"},
315 {0x01, 0x65, "LM3S8930"},
316 {0x01, 0x8C, "LM3S8933"},
317 {0x01, 0x88, "LM3S8938"},
318 {0x01, 0xA6, "LM3S8962"},
319 {0x01, 0x62, "LM3S8970"},
320 {0x01, 0xD7, "LM3S8971"},
321 {0x06, 0xAE, "LM3S8C62"},
322 {0x06, 0xAD, "LM3S8G62"},
323 {0x04, 0xCF, "LM3S9781"},
324 {0x04, 0x67, "LM3S9790"},
325 {0x04, 0x6B, "LM3S9792"},
326 {0x04, 0x2D, "LM3S9971"},
327 {0x04, 0x20, "LM3S9997"},
328 {0x04, 0xD0, "LM3S9B81"},
329 {0x04, 0x66, "LM3S9B90"},
330 {0x04, 0x6A, "LM3S9B92"},
331 {0x04, 0x6E, "LM3S9B95"},
332 {0x04, 0x6F, "LM3S9B96"},
333 {0x04, 0x1D, "LM3S9BN2"},
334 {0x04, 0x1E, "LM3S9BN5"},
335 {0x04, 0x1F, "LM3S9BN6"},
336 {0x06, 0x70, "LM3S9C97"},
337 {0x06, 0xA9, "LM3S9D81"},
338 {0x06, 0x7E, "LM3S9D90"},
339 {0x06, 0x92, "LM3S9D92"},
340 {0x06, 0x9D, "LM3S9D96"},
341 {0x06, 0x7B, "LM3S9DN5"},
342 {0x06, 0x7C, "LM3S9DN6"},
343 {0x06, 0x60, "LM3S9G97"},
344 {0x06, 0x79, "LM3S9GN5"},
345 {0x04, 0x1B, "LM3S9L71"},
346 {0x04, 0x18, "LM3S9L97"},
347 {0x06, 0xA8, "LM3S9U81"},
348 {0x06, 0x7D, "LM3S9U90"},
349 {0x06, 0x90, "LM3S9U92"},
350 {0x06, 0x9B, "LM3S9U96"},
351 {0x05, 0x01, "LM4F120B2QR/TM4C1233C3PM"},
352 {0x05, 0x02, "LM4F120C4QR/TM4C1233D5PM"},
353 {0x05, 0x03, "LM4F120E5QR/TM4C1233E6PM"},
354 {0x05, 0x04, "LM4F120H5QR/TM4C1233H6PM"},
355 {0x05, 0x08, "LM4F121B2QR/TM4C1232C3PM"},
356 {0x05, 0x09, "LM4F121C4QR/TM4C1232D5PM"},
357 {0x05, 0x0A, "LM4F121E5QR/TM4C1232E6PM"},
358 {0x05, 0x0B, "LM4F121H5QR/TM4C1232H6PM"},
359 {0x05, 0x10, "LM4F110E5QR/TM4C1231E6PM"},
360 {0x05, 0x11, "LM4F110H5QR/TM4C1231H6PM"},
361 {0x05, 0x18, "LM4F110B2QR/TM4C1231C3PM"},
362 {0x05, 0x19, "LM4F110C4QR/TM4C1231D5PM"},
363 {0x05, 0x20, "LM4F111E5QR/TM4C1230E6PM"},
364 {0x05, 0x21, "LM4F111H5QR/TM4C1230H6PM"},
365 {0x05, 0x22, "LM4F111B2QR/TM4C1230C3PM"},
366 {0x05, 0x23, "LM4F111C4QR/TM4C1230D5PM"},
367 {0x05, 0x30, "LM4F112E5QC/TM4C1231E6PZ"},
368 {0x05, 0x31, "LM4F112H5QC/TM4C1231H6PZ"},
369 {0x05, 0x35, "LM4F112H5QD/TM4C1231H6PGE"},
370 {0x05, 0x36, "LM4F112C4QC/TM4C1231D5PZ"},
371 {0x05, 0x40, "LM4F130E5QR/TM4C1237E6PM"},
372 {0x05, 0x41, "LM4F130H5QR/TM4C1237H6PM"},
373 {0x05, 0x48, "LM4F130C4QR/TM4C1237D5PM"},
374 {0x05, 0x50, "LM4F131E5QR/TM4C1236E6PM"},
375 {0x05, 0x51, "LM4F131H5QR/TM4C1236H6PM"},
376 {0x05, 0x52, "LM4F131C4QR/TM4C1236D5PM"},
377 {0x05, 0x60, "LM4F132E5QC/TM4C1237E6PZ"},
378 {0x05, 0x61, "LM4F132H5QC/TM4C1237H6PZ"},
379 {0x05, 0x65, "LM4F132H5QD/TM4C1237H6PGE"},
380 {0x05, 0x66, "LM4F132C4QC/TM4C1237D5PZ"},
381 {0x05, 0x70, "LM4F210E5QR/TM4C123BE6PM"},
382 {0x05, 0x73, "LM4F210H5QR/TM4C123BH6PM"},
383 {0x05, 0x80, "LM4F211E5QR/TM4C123AE6PM"},
384 {0x05, 0x83, "LM4F211H5QR/TM4C123AH6PM"},
385 {0x05, 0xA0, "LM4F230E5QR/TM4C123GE6PM"},
386 {0x05, 0xA1, "LM4F230H5QR/TM4C123GH6PM"},
387 {0x05, 0xB0, "LM4F231E5QR/TM4C123FE6PM"},
388 {0x05, 0xB1, "LM4F231H5QR/TM4C123FH6PM"},
389 {0x05, 0xC0, "LM4F232E5QC/TM4C123GE6PZ"},
390 {0x05, 0xC1, "LM4F232H5QC/TM4C123GH6PZ"},
391 {0x05, 0xC3, "LM4F212E5QC/TM4C123BE6PZ"},
392 {0x05, 0xC4, "LM4F212H5QC/TM4C123BH6PZ"},
393 {0x05, 0xC5, "LM4F232H5QD/TM4C123GH6PGE"},
394 {0x05, 0xC6, "LM4F212H5QD/TM4C123BH6PGE"},
395 {0x05, 0xD0, "LM4F122C4QC/TM4C1233D5PZ"},
396 {0x05, 0xD1, "LM4F122E5QC/TM4C1233E6PZ"},
397 {0x05, 0xD2, "LM4F122H5QC/TM4C1233H6PZ"},
398 {0x05, 0xD6, "LM4F122H5QD/TM4C1233H6PGE"},
399 {0x05, 0xE1, "LM4FSXLH5BB"},
400 {0x05, 0xE3, "LM4F232H5BB/TM4C123GH6ZRB"},
401 {0x05, 0xE4, "LM4FS99H5BB"},
402 {0x05, 0xE5, "LM4FS1AH5BB"},
403 {0x05, 0xE9, "LM4F212H5BB/TM4C123BH6ZRB"},
404 {0x05, 0xEA, "LM4FS1GH5BB"},
405 {0x05, 0xF0, "TM4C123GH6ZXR"},
406 {0x0A, 0x19, "TM4C1290NCPDT"},
407 {0x0A, 0x1B, "TM4C1290NCZAD"},
408 {0x0A, 0x1C, "TM4C1292NCPDT"},
409 {0x0A, 0x1E, "TM4C1292NCZAD"},
410 {0x0A, 0x1F, "TM4C1294NCPDT"},
411 {0x0A, 0x21, "TM4C1294NCZAD"},
412 {0x0A, 0x22, "TM4C1297NCZAD"},
413 {0x0A, 0x23, "TM4C1299NCZAD"},
414 {0x0A, 0x24, "TM4C129CNCPDT"},
415 {0x0A, 0x26, "TM4C129CNCZAD"},
416 {0x0A, 0x27, "TM4C129DNCPDT"},
417 {0x0A, 0x29, "TM4C129DNCZAD"},
418 {0x0A, 0x2D, "TM4C129ENCPDT"},
419 {0x0A, 0x2F, "TM4C129ENCZAD"},
420 {0x0A, 0x30, "TM4C129LNCZAD"},
421 {0x0A, 0x32, "TM4C129XNCZAD"},
422 {0x0A, 0x34, "TM4C1294KCPDT"},
423 {0x0A, 0x35, "TM4C129EKCPDT"},
424 {0x0A, 0x36, "TM4C1299KCZAD"},
425 {0x0A, 0x37, "TM4C129XKCZAD"},
426 {0xFF, 0x00, "Unknown Part"}
429 static const char * const stellaris_classname
[] = {
443 /***************************************************************************
444 * openocd command interface *
445 ***************************************************************************/
447 /* flash_bank stellaris <base> <size> 0 0 <target#>
449 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command
)
451 struct stellaris_flash_bank
*stellaris_info
;
454 return ERROR_COMMAND_SYNTAX_ERROR
;
456 stellaris_info
= calloc(sizeof(struct stellaris_flash_bank
), 1);
458 bank
->driver_priv
= stellaris_info
;
460 stellaris_info
->target_name
= "Unknown target";
462 /* part wasn't probed for info yet */
463 stellaris_info
->did1
= 0;
465 /* TODO Specify the main crystal speed in kHz using an optional
466 * argument; ditto, the speed of an external oscillator used
467 * instead of a crystal. Avoid programming flash using IOSC.
472 static int get_stellaris_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
474 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
476 if (stellaris_info
->did1
== 0)
477 return ERROR_FLASH_BANK_NOT_PROBED
;
479 /* Read main and master clock frequency register */
480 stellaris_read_clock_info(bank
);
482 command_print_sameline(cmd
,
483 "\nTI/LMI Stellaris information: Chip is "
484 "class %i (%s) %s rev %c%i\n",
485 stellaris_info
->target_class
,
486 stellaris_classname
[stellaris_info
->target_class
],
487 stellaris_info
->target_name
,
488 (int)('A' + ((stellaris_info
->did0
>> 8) & 0xFF)),
489 (int)((stellaris_info
->did0
) & 0xFF));
491 command_print_sameline(cmd
,
492 "did1: 0x%8.8" PRIx32
", arch: 0x%4.4" PRIx32
493 ", eproc: %s, ramsize: %" PRIu32
"k, flashsize: %" PRIu32
"k\n",
494 stellaris_info
->did1
,
495 stellaris_info
->did1
,
497 stellaris_info
->sramsiz
,
498 (uint32_t)(stellaris_info
->num_pages
* stellaris_info
->pagesize
/ 1024));
500 command_print_sameline(cmd
,
501 "master clock: %ikHz%s, "
502 "rcc is 0x%" PRIx32
", rcc2 is 0x%" PRIx32
", "
503 "pagesize: %" PRIu32
", pages: %" PRIu32
,
504 (int)(stellaris_info
->mck_freq
/ 1000),
505 stellaris_info
->mck_desc
,
507 stellaris_info
->rcc2
,
508 stellaris_info
->pagesize
,
509 stellaris_info
->num_pages
);
514 /***************************************************************************
515 * chip identification and status *
516 ***************************************************************************/
518 /* Set the flash timing register to match current clocking */
519 static void stellaris_set_flash_timing(struct flash_bank
*bank
)
521 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
522 struct target
*target
= bank
->target
;
523 uint32_t usecrl
= (stellaris_info
->mck_freq
/1000000ul-1);
525 /* only valid for Sandstorm and Fury class devices */
526 if (stellaris_info
->target_class
> 1)
529 LOG_DEBUG("usecrl = %i", (int)(usecrl
));
530 target_write_u32(target
, SCB_BASE
| USECRL
, usecrl
);
533 static const unsigned rcc_xtal
[32] = {
534 [0x00] = 1000000, /* no pll */
535 [0x01] = 1843200, /* no pll */
536 [0x02] = 2000000, /* no pll */
537 [0x03] = 2457600, /* no pll */
541 [0x06] = 4000000, /* usb */
545 [0x09] = 5000000, /* usb */
547 [0x0b] = 6000000, /* (reset) usb */
551 [0x0e] = 8000000, /* usb */
554 /* parts before DustDevil use just 4 bits for xtal spec */
556 [0x10] = 10000000, /* usb */
557 [0x11] = 12000000, /* usb */
562 [0x15] = 16000000, /* usb */
566 /** Read clock configuration and set stellaris_info->usec_clocks. */
567 static void stellaris_read_clock_info(struct flash_bank
*bank
)
569 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
570 struct target
*target
= bank
->target
;
571 uint32_t rcc
, rcc2
, pllcfg
, sysdiv
, usesysdiv
, bypass
, oscsrc
;
573 unsigned long mainfreq
;
575 target_read_u32(target
, SCB_BASE
| RCC
, &rcc
);
576 LOG_DEBUG("Stellaris RCC %" PRIx32
"", rcc
);
578 target_read_u32(target
, SCB_BASE
| RCC2
, &rcc2
);
579 LOG_DEBUG("Stellaris RCC2 %" PRIx32
"", rcc
);
581 target_read_u32(target
, SCB_BASE
| PLLCFG
, &pllcfg
);
582 LOG_DEBUG("Stellaris PLLCFG %" PRIx32
"", pllcfg
);
584 stellaris_info
->rcc
= rcc
;
585 stellaris_info
->rcc2
= rcc2
;
587 sysdiv
= (rcc
>> 23) & 0xF;
588 usesysdiv
= (rcc
>> 22) & 0x1;
589 bypass
= (rcc
>> 11) & 0x1;
590 oscsrc
= (rcc
>> 4) & 0x3;
591 xtal
= (rcc
>> 6) & stellaris_info
->xtal_mask
;
593 /* NOTE: post-Sandstorm parts have RCC2 which may override
594 * parts of RCC ... with more sysdiv options, option for
595 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
596 * as zero, so the "use RCC2" flag is always clear.
598 if (rcc2
& (1 << 31)) {
599 sysdiv
= (rcc2
>> 23) & 0x3F;
600 bypass
= (rcc2
>> 11) & 0x1;
601 oscsrc
= (rcc2
>> 4) & 0x7;
603 /* FIXME Tempest parts have an additional lsb for
604 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
608 stellaris_info
->mck_desc
= "";
612 mainfreq
= rcc_xtal
[xtal
];
615 mainfreq
= stellaris_info
->iosc_freq
;
616 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
619 mainfreq
= stellaris_info
->iosc_freq
/ 4;
620 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
622 case 3: /* lowspeed */
623 /* Sandstorm doesn't have this 30K +/- 30% osc */
625 stellaris_info
->mck_desc
= " (±30%)";
627 case 8: /* hibernation osc */
628 /* not all parts support hibernation */
632 default: /* NOTREACHED */
637 /* PLL is used if it's not bypassed; its output is 200 MHz
638 * even when it runs at 400 MHz (adds divide-by-two stage).
641 mainfreq
= 200000000;
644 stellaris_info
->mck_freq
= mainfreq
/(1 + sysdiv
);
646 stellaris_info
->mck_freq
= mainfreq
;
649 /* Read device id register, main clock frequency register and fill in driver info structure */
650 static int stellaris_read_part_info(struct flash_bank
*bank
)
652 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
653 struct target
*target
= bank
->target
;
654 uint32_t did0
, did1
, ver
, fam
;
657 /* Read and parse chip identification register */
658 target_read_u32(target
, SCB_BASE
| DID0
, &did0
);
659 target_read_u32(target
, SCB_BASE
| DID1
, &did1
);
660 target_read_u32(target
, SCB_BASE
| DC0
, &stellaris_info
->dc0
);
661 target_read_u32(target
, SCB_BASE
| DC1
, &stellaris_info
->dc1
);
662 LOG_DEBUG("did0 0x%" PRIx32
", did1 0x%" PRIx32
", dc0 0x%" PRIx32
", dc1 0x%" PRIx32
"",
663 did0
, did1
, stellaris_info
->dc0
, stellaris_info
->dc1
);
665 ver
= DID0_VER(did0
);
666 if ((ver
!= 0) && (ver
!= 1)) {
667 LOG_WARNING("Unknown did0 version, cannot identify target");
668 return ERROR_FLASH_OPERATION_FAILED
;
672 LOG_WARNING("Cannot identify target as a Stellaris");
673 return ERROR_FLASH_OPERATION_FAILED
;
677 fam
= (did1
>> 24) & 0xF;
678 if (((ver
!= 0) && (ver
!= 1)) || (fam
!= 0)) {
679 LOG_WARNING("Unknown did1 version/family.");
680 return ERROR_FLASH_OPERATION_FAILED
;
683 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
684 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
685 * even give _both_ numbers! We'll use current numbers; IOSC is
686 * always approximate.
688 * For Tempest: IOSC is calibrated, 16 MHz
689 * For Blizzard: IOSC is calibrated, 16 MHz
690 * For Firestorm: IOSC is calibrated, 16 MHz
692 stellaris_info
->iosc_freq
= 12000000;
693 stellaris_info
->iosc_desc
= " (±30%)";
694 stellaris_info
->xtal_mask
= 0x0f;
696 /* get device class */
697 if (DID0_VER(did0
) > 0) {
698 stellaris_info
->target_class
= (did0
>> 16) & 0xFF;
700 /* Sandstorm class */
701 stellaris_info
->target_class
= 0;
704 switch (stellaris_info
->target_class
) {
705 case 0: /* Sandstorm */
707 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
708 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
709 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
711 if (((did0
>> 8) & 0xff) < 2) {
712 stellaris_info
->iosc_freq
= 15000000;
713 stellaris_info
->iosc_desc
= " (±50%)";
720 case 4: /* Tempest */
721 case 5: /* Blizzard */
722 case 6: /* Firestorm */
723 case 0xa: /* Snowflake */
724 stellaris_info
->iosc_freq
= 16000000; /* +/- 1% */
725 stellaris_info
->iosc_desc
= " (±1%)";
728 case 3: /* DustDevil */
729 stellaris_info
->xtal_mask
= 0x1f;
733 LOG_WARNING("Unknown did0 class");
736 for (i
= 0; stellaris_parts
[i
].partno
; i
++) {
737 if ((stellaris_parts
[i
].partno
== ((did1
>> 16) & 0xFF)) &&
738 (stellaris_parts
[i
].class == stellaris_info
->target_class
))
742 stellaris_info
->target_name
= stellaris_parts
[i
].partname
;
744 stellaris_info
->did0
= did0
;
745 stellaris_info
->did1
= did1
;
747 if (stellaris_info
->target_class
== 5) { /* Blizzard */
748 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
749 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
751 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->fsize
& 0xFFFF));
752 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
753 stellaris_info
->pagesize
= 1024;
754 } else if (stellaris_info
->target_class
== 0xa) { /* Snowflake */
755 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
756 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
758 stellaris_info
->pagesize
= (1 << ((stellaris_info
->fsize
>> 16) & 7)) * 1024;
759 stellaris_info
->num_pages
= 2048 * (1 + (stellaris_info
->fsize
& 0xFFFF)) /
760 stellaris_info
->pagesize
;
761 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
763 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->dc0
& 0xFFFF));
764 stellaris_info
->sramsiz
= (1 + ((stellaris_info
->dc0
>> 16) & 0xFFFF)) / 4;
765 stellaris_info
->pagesize
= 1024;
768 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
769 * That exposes a 32-word Flash Write Buffer ... enabling
770 * writes of more than one word at a time.
776 /***************************************************************************
778 ***************************************************************************/
780 static int stellaris_protect_check(struct flash_bank
*bank
)
782 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
783 struct target
*target
= bank
->target
;
784 uint32_t flash_sizek
= stellaris
->pagesize
/ 1024 *
785 stellaris
->num_pages
;
787 int status
= ERROR_OK
;
789 if (stellaris
->did1
== 0)
790 return ERROR_FLASH_BANK_NOT_PROBED
;
792 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++)
793 bank
->sectors
[i
].is_protected
= -1;
795 /* Read each Flash Memory Protection Program Enable (FMPPE) register
796 * to report any pages that we can't write. Ignore the Read Enable
800 if (stellaris
->target_class
>= 0x0a || flash_sizek
> 64)
801 fmppe_addr
= SCB_BASE
| FMPPE0
;
803 fmppe_addr
= SCB_BASE
| FMPPE
;
805 unsigned int page
= 0, lockbitnum
, lockbitcnt
= flash_sizek
/ 2;
806 unsigned int bits_per_page
= stellaris
->pagesize
/ 2048;
807 /* Every lock bit always corresponds to a 2k region */
808 for (lockbitnum
= 0; lockbitnum
< lockbitcnt
; lockbitnum
+= 32) {
811 target_read_u32(target
, fmppe_addr
, &fmppe
);
812 for (unsigned int i
= 0; i
< 32 && lockbitnum
+ i
< lockbitcnt
; i
++) {
813 bool protect
= !(fmppe
& (1 << i
));
815 bank
->sectors
[page
++].is_protected
= protect
;
816 i
+= bits_per_page
- 1;
817 } else { /* 1024k pages, every lockbit covers 2 pages */
818 bank
->sectors
[page
++].is_protected
= protect
;
819 bank
->sectors
[page
++].is_protected
= protect
;
828 static int stellaris_erase(struct flash_bank
*bank
, unsigned int first
,
831 uint32_t flash_fmc
, flash_cris
;
832 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
833 struct target
*target
= bank
->target
;
835 if (bank
->target
->state
!= TARGET_HALTED
) {
836 LOG_ERROR("Target not halted");
837 return ERROR_TARGET_NOT_HALTED
;
840 if (stellaris_info
->did1
== 0)
841 return ERROR_FLASH_BANK_NOT_PROBED
;
843 if ((last
< first
) || (last
>= stellaris_info
->num_pages
))
844 return ERROR_FLASH_SECTOR_INVALID
;
846 if ((first
== 0) && (last
== (stellaris_info
->num_pages
- 1)))
847 return stellaris_mass_erase(bank
);
849 /* Refresh flash controller timing */
850 stellaris_read_clock_info(bank
);
851 stellaris_set_flash_timing(bank
);
853 /* Clear and disable flash programming interrupts */
854 target_write_u32(target
, FLASH_CIM
, 0);
855 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
857 /* REVISIT this clobbers state set by any halted firmware ...
858 * it might want to process those IRQs.
861 for (unsigned int banknr
= first
; banknr
<= last
; banknr
++) {
862 /* Address is first word in page */
863 target_write_u32(target
, FLASH_FMA
, banknr
* stellaris_info
->pagesize
);
864 /* Write erase command */
865 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_ERASE
);
866 /* Wait until erase complete */
868 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
869 } while (flash_fmc
& FMC_ERASE
);
871 /* Check access violations */
872 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
873 if (flash_cris
& (AMASK
)) {
874 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32
"",
876 target_write_u32(target
, FLASH_CRIS
, 0);
877 return ERROR_FLASH_OPERATION_FAILED
;
884 static int stellaris_protect(struct flash_bank
*bank
, int set
,
885 unsigned int first
, unsigned int last
)
887 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
888 struct target
*target
= bank
->target
;
889 uint32_t flash_fmc
, flash_cris
;
890 unsigned int bits_per_page
= stellaris
->pagesize
/ 2048;
892 if (target
->state
!= TARGET_HALTED
) {
893 LOG_ERROR("Target not halted");
894 return ERROR_TARGET_NOT_HALTED
;
898 LOG_ERROR("Hardware doesn't support page-level unprotect. "
899 "Try the 'recover' command.");
900 return ERROR_COMMAND_SYNTAX_ERROR
;
903 if (stellaris
->did1
== 0)
904 return ERROR_FLASH_BANK_NOT_PROBED
;
906 if (stellaris
->target_class
== 0x03 &&
907 !((stellaris
->did0
>> 8) & 0xFF) &&
908 !((stellaris
->did0
) & 0xFF)) {
909 LOG_ERROR("DustDevil A0 parts can't be unprotected, see errata; refusing to proceed");
910 return ERROR_FLASH_OPERATION_FAILED
;
913 if (!bits_per_page
&& (first
% 2 || !(last
% 2))) {
914 LOG_ERROR("Can't protect unaligned pages");
915 return ERROR_FLASH_SECTOR_INVALID
;
918 /* Refresh flash controller timing */
919 stellaris_read_clock_info(bank
);
920 stellaris_set_flash_timing(bank
);
922 /* Clear and disable flash programming interrupts */
923 target_write_u32(target
, FLASH_CIM
, 0);
924 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
926 uint32_t flash_sizek
= stellaris
->pagesize
/ 1024 *
927 stellaris
->num_pages
;
930 if (stellaris
->target_class
>= 0x0a || flash_sizek
> 64)
931 fmppe_addr
= SCB_BASE
| FMPPE0
;
933 fmppe_addr
= SCB_BASE
| FMPPE
;
935 unsigned int page
= 0;
936 unsigned int lockbitnum
, lockbitcnt
= flash_sizek
/ 2;
937 /* Every lock bit always corresponds to a 2k region */
938 for (lockbitnum
= 0; lockbitnum
< lockbitcnt
; lockbitnum
+= 32) {
941 target_read_u32(target
, fmppe_addr
, &fmppe
);
942 for (unsigned int i
= 0;
943 i
< 32 && lockbitnum
+ i
< lockbitcnt
;
945 if (page
>= first
&& page
<= last
)
949 if (!((i
+ 1) % bits_per_page
))
951 } else { /* 1024k pages, every lockbit covers 2 pages */
955 target_write_u32(target
, fmppe_addr
, fmppe
);
958 target_write_u32(target
, FLASH_FMA
, 1 + lockbitnum
/ 16);
959 /* Write commit command */
960 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_COMT
);
962 /* Wait until commit complete */
964 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
965 } while (flash_fmc
& FMC_COMT
);
967 /* Check access violations */
968 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
969 if (flash_cris
& (AMASK
)) {
970 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32
"", flash_cris
);
971 target_write_u32(target
, FLASH_CRIS
, 0);
972 return ERROR_FLASH_OPERATION_FAILED
;
981 /* see contrib/loaders/flash/stellaris.s for src */
983 static const uint8_t stellaris_write_code
[] = {
985 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */
986 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */
988 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
989 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
990 0x17, 0xD0, /* beq exit */
991 0x47, 0x68, /* ldr r7, [r0, #4] */
992 0x47, 0x45, /* cmp r7, r8 */
993 0xF7, 0xD0, /* beq wait_fifo */
995 0x22, 0x60, /* str r2, [r4, #0] */
996 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */
997 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */
998 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */
999 0xA5, 0x60, /* str r5, [r4, #8] */
1001 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */
1002 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */
1003 0xFA, 0xD1, /* bne busy */
1004 0x8F, 0x42, /* cmp r7, r1 */
1005 0x28, 0xBF, /* it cs */
1006 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
1007 0x47, 0x60, /* str r7, [r0, #4] */
1008 0x01, 0x3B, /* subs r3, r3, #1 */
1009 0x03, 0xB1, /* cbz r3, exit */
1010 0xE2, 0xE7, /* b wait_fifo */
1012 0x00, 0xBE, /* bkpt #0 */
1014 /* pFLASH_CTRL_BASE: */
1015 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
1016 /* FLASHWRITECMD: */
1017 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
1019 static int stellaris_write_block(struct flash_bank
*bank
,
1020 const uint8_t *buffer
, uint32_t offset
, uint32_t wcount
)
1022 struct target
*target
= bank
->target
;
1023 uint32_t buffer_size
= 16384;
1024 struct working_area
*source
;
1025 struct working_area
*write_algorithm
;
1026 uint32_t address
= bank
->base
+ offset
;
1027 struct reg_param reg_params
[4];
1028 struct armv7m_algorithm armv7m_info
;
1029 int retval
= ERROR_OK
;
1031 /* power of two, and multiple of word size */
1032 static const unsigned buf_min
= 128;
1034 /* for small buffers it's faster not to download an algorithm */
1035 if (wcount
* 4 < buf_min
)
1036 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1038 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" wcount=%08" PRIx32
"",
1039 bank
, buffer
, offset
, wcount
);
1041 /* flash write code */
1042 if (target_alloc_working_area(target
, sizeof(stellaris_write_code
),
1043 &write_algorithm
) != ERROR_OK
) {
1044 LOG_DEBUG("no working area for block memory writes");
1045 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1048 /* plus a buffer big enough for this data */
1049 if (wcount
* 4 < buffer_size
)
1050 buffer_size
= wcount
* 4;
1053 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
1055 if (buffer_size
<= buf_min
) {
1056 target_free_working_area(target
, write_algorithm
);
1057 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1059 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1060 target_name(target
), (unsigned) buffer_size
);
1063 target_write_buffer(target
, write_algorithm
->address
,
1064 sizeof(stellaris_write_code
),
1065 stellaris_write_code
);
1067 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
1068 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
1070 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1071 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1072 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
1073 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
1075 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
1076 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
1077 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
1078 buf_set_u32(reg_params
[3].value
, 0, 32, wcount
);
1080 retval
= target_run_flash_async_algorithm(target
, buffer
, wcount
, 4,
1083 source
->address
, source
->size
,
1084 write_algorithm
->address
, 0,
1087 if (retval
== ERROR_FLASH_OPERATION_FAILED
)
1088 LOG_ERROR("error %d executing stellaris flash write algorithm", retval
);
1090 target_free_working_area(target
, write_algorithm
);
1091 target_free_working_area(target
, source
);
1093 destroy_reg_param(®_params
[0]);
1094 destroy_reg_param(®_params
[1]);
1095 destroy_reg_param(®_params
[2]);
1096 destroy_reg_param(®_params
[3]);
1101 static int stellaris_write(struct flash_bank
*bank
, const uint8_t *buffer
,
1102 uint32_t offset
, uint32_t count
)
1104 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1105 struct target
*target
= bank
->target
;
1106 uint32_t address
= offset
;
1107 uint32_t flash_cris
, flash_fmc
;
1108 uint32_t words_remaining
= (count
/ 4);
1109 uint32_t bytes_remaining
= (count
& 0x00000003);
1110 uint32_t bytes_written
= 0;
1113 if (bank
->target
->state
!= TARGET_HALTED
) {
1114 LOG_ERROR("Target not halted");
1115 return ERROR_TARGET_NOT_HALTED
;
1118 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" count=%08" PRIx32
"",
1119 bank
, buffer
, offset
, count
);
1121 if (stellaris_info
->did1
== 0)
1122 return ERROR_FLASH_BANK_NOT_PROBED
;
1125 LOG_WARNING("offset size must be word aligned");
1126 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1129 if (offset
+ count
> bank
->size
)
1130 return ERROR_FLASH_DST_OUT_OF_BANK
;
1132 /* Refresh flash controller timing */
1133 stellaris_read_clock_info(bank
);
1134 stellaris_set_flash_timing(bank
);
1136 /* Clear and disable flash programming interrupts */
1137 target_write_u32(target
, FLASH_CIM
, 0);
1138 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1140 /* REVISIT this clobbers state set by any halted firmware ...
1141 * it might want to process those IRQs.
1144 /* multiple words to be programmed? */
1145 if (words_remaining
> 0) {
1146 /* try using a block write */
1147 retval
= stellaris_write_block(bank
, buffer
, offset
,
1149 if (retval
!= ERROR_OK
) {
1150 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
1151 LOG_DEBUG("writing flash word-at-a-time");
1152 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
1153 /* if an error occurred, we examine the reason, and quit */
1154 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1156 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32
"", flash_cris
);
1157 return ERROR_FLASH_OPERATION_FAILED
;
1160 buffer
+= words_remaining
* 4;
1161 address
+= words_remaining
* 4;
1162 words_remaining
= 0;
1166 while (words_remaining
> 0) {
1167 if (!(address
& 0xff))
1168 LOG_DEBUG("0x%" PRIx32
"", address
);
1170 /* Program one word */
1171 target_write_u32(target
, FLASH_FMA
, address
);
1172 target_write_buffer(target
, FLASH_FMD
, 4, buffer
);
1173 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1174 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1175 /* Wait until write complete */
1177 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1178 } while (flash_fmc
& FMC_WRITE
);
1185 if (bytes_remaining
) {
1186 uint8_t last_word
[4] = {0xff, 0xff, 0xff, 0xff};
1188 /* copy the last remaining bytes into the write buffer */
1189 memcpy(last_word
, buffer
+bytes_written
, bytes_remaining
);
1191 if (!(address
& 0xff))
1192 LOG_DEBUG("0x%" PRIx32
"", address
);
1194 /* Program one word */
1195 target_write_u32(target
, FLASH_FMA
, address
);
1196 target_write_buffer(target
, FLASH_FMD
, 4, last_word
);
1197 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1198 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1199 /* Wait until write complete */
1201 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1202 } while (flash_fmc
& FMC_WRITE
);
1205 /* Check access violations */
1206 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1207 if (flash_cris
& (AMASK
)) {
1208 LOG_DEBUG("flash_cris 0x%" PRIx32
"", flash_cris
);
1209 return ERROR_FLASH_OPERATION_FAILED
;
1214 static int stellaris_probe(struct flash_bank
*bank
)
1216 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1219 /* If this is a stellaris chip, it has flash; probe() is just
1220 * to figure out how much is present. Only do it once.
1222 if (stellaris_info
->did1
!= 0)
1225 /* stellaris_read_part_info() already handled error checking and
1226 * reporting. Note that it doesn't write, so we don't care about
1227 * whether the target is halted or not.
1229 retval
= stellaris_read_part_info(bank
);
1230 if (retval
!= ERROR_OK
)
1233 free(bank
->sectors
);
1235 /* provide this for the benefit of the NOR flash framework */
1236 bank
->size
= stellaris_info
->num_pages
* stellaris_info
->pagesize
;
1237 bank
->num_sectors
= stellaris_info
->num_pages
;
1238 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
1239 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
1240 bank
->sectors
[i
].offset
= i
* stellaris_info
->pagesize
;
1241 bank
->sectors
[i
].size
= stellaris_info
->pagesize
;
1242 bank
->sectors
[i
].is_erased
= -1;
1243 bank
->sectors
[i
].is_protected
= -1;
1249 static int stellaris_mass_erase(struct flash_bank
*bank
)
1251 struct target
*target
= NULL
;
1252 struct stellaris_flash_bank
*stellaris_info
= NULL
;
1255 stellaris_info
= bank
->driver_priv
;
1256 target
= bank
->target
;
1258 if (target
->state
!= TARGET_HALTED
) {
1259 LOG_ERROR("Target not halted");
1260 return ERROR_TARGET_NOT_HALTED
;
1263 if (stellaris_info
->did1
== 0)
1264 return ERROR_FLASH_BANK_NOT_PROBED
;
1266 /* Refresh flash controller timing */
1267 stellaris_read_clock_info(bank
);
1268 stellaris_set_flash_timing(bank
);
1270 /* Clear and disable flash programming interrupts */
1271 target_write_u32(target
, FLASH_CIM
, 0);
1272 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1274 /* REVISIT this clobbers state set by any halted firmware ...
1275 * it might want to process those IRQs.
1278 target_write_u32(target
, FLASH_FMA
, 0);
1279 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1280 /* Wait until erase complete */
1282 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1283 } while (flash_fmc
& FMC_MERASE
);
1285 /* if device has > 128k, then second erase cycle is needed
1286 * this is only valid for older devices, but will not hurt */
1287 if (stellaris_info
->num_pages
* stellaris_info
->pagesize
> 0x20000) {
1288 target_write_u32(target
, FLASH_FMA
, 0x20000);
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
);
1299 COMMAND_HANDLER(stellaris_handle_mass_erase_command
)
1302 return ERROR_COMMAND_SYNTAX_ERROR
;
1304 struct flash_bank
*bank
;
1305 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1306 if (retval
!= ERROR_OK
)
1309 if (stellaris_mass_erase(bank
) == ERROR_OK
)
1310 command_print(CMD
, "stellaris mass erase complete");
1312 command_print(CMD
, "stellaris mass erase failed");
1318 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1319 * This performs a mass erase and then restores all nonvolatile registers
1320 * (including USER_* registers and flash lock bits) to their defaults.
1321 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1323 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1324 * can affect this operation if flash protection has been enabled.
1326 COMMAND_HANDLER(stellaris_handle_recover_command
)
1328 struct flash_bank
*bank
;
1333 return ERROR_COMMAND_SYNTAX_ERROR
;
1335 bank
= get_flash_bank_by_num_noprobe(0);
1339 /* REVISIT ... it may be worth sanity checking that the AP is
1340 * inactive before we start. ARM documents that switching a DP's
1341 * mode while it's active can cause fault modes that need a power
1345 Jim_Eval_Named(CMD_CTX
->interp
, "catch { hla_command \"debug unlock\" }", 0, 0);
1346 if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX
->interp
), NULL
), "0")) {
1352 if (!(jtag_get_reset_config() & RESET_HAS_SRST
)) {
1353 LOG_ERROR("Can't recover Stellaris flash without SRST");
1356 adapter_assert_reset();
1358 arm
= target_to_arm(bank
->target
);
1359 for (int i
= 0; i
< 5; i
++) {
1360 retval
= dap_to_swd(arm
->dap
);
1361 if (retval
!= ERROR_OK
)
1364 retval
= dap_to_jtag(arm
->dap
);
1365 if (retval
!= ERROR_OK
)
1369 /* de-assert SRST */
1370 adapter_deassert_reset();
1371 retval
= jtag_execute_queue();
1373 /* wait 400+ msec ... OK, "1+ second" is simpler */
1377 /* USER INTERVENTION required for the power cycle
1378 * Restarting OpenOCD is likely needed because of mode switching.
1380 LOG_INFO("USER ACTION: "
1381 "power cycle Stellaris chip, then restart OpenOCD.");
1387 static const struct command_registration stellaris_exec_command_handlers
[] = {
1389 .name
= "mass_erase",
1391 .handler
= stellaris_handle_mass_erase_command
,
1392 .mode
= COMMAND_EXEC
,
1393 .help
= "erase entire device",
1397 .handler
= stellaris_handle_recover_command
,
1398 .mode
= COMMAND_EXEC
,
1400 .help
= "recover (and erase) locked device",
1402 COMMAND_REGISTRATION_DONE
1404 static const struct command_registration stellaris_command_handlers
[] = {
1406 .name
= "stellaris",
1407 .mode
= COMMAND_EXEC
,
1408 .help
= "Stellaris flash command group",
1410 .chain
= stellaris_exec_command_handlers
,
1412 COMMAND_REGISTRATION_DONE
1415 const struct flash_driver stellaris_flash
= {
1416 .name
= "stellaris",
1417 .commands
= stellaris_command_handlers
,
1418 .flash_bank_command
= stellaris_flash_bank_command
,
1419 .erase
= stellaris_erase
,
1420 .protect
= stellaris_protect
,
1421 .write
= stellaris_write
,
1422 .read
= default_flash_read
,
1423 .probe
= stellaris_probe
,
1424 .auto_probe
= stellaris_probe
,
1425 .erase_check
= default_flash_blank_check
,
1426 .protect_check
= stellaris_protect_check
,
1427 .info
= get_stellaris_info
,
1428 .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)