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
, char *buf
, int buf_size
)
485 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
487 if (stellaris_info
->did1
== 0)
488 return ERROR_FLASH_BANK_NOT_PROBED
;
490 /* Read main and master clock freqency register */
491 stellaris_read_clock_info(bank
);
493 printed
= snprintf(buf
,
495 "\nTI/LMI Stellaris information: Chip is "
496 "class %i (%s) %s rev %c%i\n",
497 stellaris_info
->target_class
,
498 StellarisClassname
[stellaris_info
->target_class
],
499 stellaris_info
->target_name
,
500 (int)('A' + ((stellaris_info
->did0
>> 8) & 0xFF)),
501 (int)((stellaris_info
->did0
) & 0xFF));
505 printed
= snprintf(buf
,
507 "did1: 0x%8.8" PRIx32
", arch: 0x%4.4" PRIx32
508 ", eproc: %s, ramsize: %" PRIu32
"k, flashsize: %" PRIu32
"k\n",
509 stellaris_info
->did1
,
510 stellaris_info
->did1
,
512 stellaris_info
->sramsiz
,
513 (uint32_t)(stellaris_info
->num_pages
* stellaris_info
->pagesize
/ 1024));
519 "master clock: %ikHz%s, "
520 "rcc is 0x%" PRIx32
", rcc2 is 0x%" PRIx32
", "
521 "pagesize: %" PRIu32
", pages: %" PRIu32
,
522 (int)(stellaris_info
->mck_freq
/ 1000),
523 stellaris_info
->mck_desc
,
525 stellaris_info
->rcc2
,
526 stellaris_info
->pagesize
,
527 stellaris_info
->num_pages
);
532 /***************************************************************************
533 * chip identification and status *
534 ***************************************************************************/
536 /* Set the flash timimg register to match current clocking */
537 static void stellaris_set_flash_timing(struct flash_bank
*bank
)
539 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
540 struct target
*target
= bank
->target
;
541 uint32_t usecrl
= (stellaris_info
->mck_freq
/1000000ul-1);
543 /* only valid for Sandstorm and Fury class devices */
544 if (stellaris_info
->target_class
> 1)
547 LOG_DEBUG("usecrl = %i", (int)(usecrl
));
548 target_write_u32(target
, SCB_BASE
| USECRL
, usecrl
);
551 static const unsigned rcc_xtal
[32] = {
552 [0x00] = 1000000, /* no pll */
553 [0x01] = 1843200, /* no pll */
554 [0x02] = 2000000, /* no pll */
555 [0x03] = 2457600, /* no pll */
559 [0x06] = 4000000, /* usb */
563 [0x09] = 5000000, /* usb */
565 [0x0b] = 6000000, /* (reset) usb */
569 [0x0e] = 8000000, /* usb */
572 /* parts before DustDevil use just 4 bits for xtal spec */
574 [0x10] = 10000000, /* usb */
575 [0x11] = 12000000, /* usb */
580 [0x15] = 16000000, /* usb */
584 /** Read clock configuration and set stellaris_info->usec_clocks. */
585 static void stellaris_read_clock_info(struct flash_bank
*bank
)
587 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
588 struct target
*target
= bank
->target
;
589 uint32_t rcc
, rcc2
, pllcfg
, sysdiv
, usesysdiv
, bypass
, oscsrc
;
591 unsigned long mainfreq
;
593 target_read_u32(target
, SCB_BASE
| RCC
, &rcc
);
594 LOG_DEBUG("Stellaris RCC %" PRIx32
"", rcc
);
596 target_read_u32(target
, SCB_BASE
| RCC2
, &rcc2
);
597 LOG_DEBUG("Stellaris RCC2 %" PRIx32
"", rcc
);
599 target_read_u32(target
, SCB_BASE
| PLLCFG
, &pllcfg
);
600 LOG_DEBUG("Stellaris PLLCFG %" PRIx32
"", pllcfg
);
602 stellaris_info
->rcc
= rcc
;
603 stellaris_info
->rcc2
= rcc2
;
605 sysdiv
= (rcc
>> 23) & 0xF;
606 usesysdiv
= (rcc
>> 22) & 0x1;
607 bypass
= (rcc
>> 11) & 0x1;
608 oscsrc
= (rcc
>> 4) & 0x3;
609 xtal
= (rcc
>> 6) & stellaris_info
->xtal_mask
;
611 /* NOTE: post-Sandstorm parts have RCC2 which may override
612 * parts of RCC ... with more sysdiv options, option for
613 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
614 * as zero, so the "use RCC2" flag is always clear.
616 if (rcc2
& (1 << 31)) {
617 sysdiv
= (rcc2
>> 23) & 0x3F;
618 bypass
= (rcc2
>> 11) & 0x1;
619 oscsrc
= (rcc2
>> 4) & 0x7;
621 /* FIXME Tempest parts have an additional lsb for
622 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
626 stellaris_info
->mck_desc
= "";
630 mainfreq
= rcc_xtal
[xtal
];
633 mainfreq
= stellaris_info
->iosc_freq
;
634 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
637 mainfreq
= stellaris_info
->iosc_freq
/ 4;
638 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
640 case 3: /* lowspeed */
641 /* Sandstorm doesn't have this 30K +/- 30% osc */
643 stellaris_info
->mck_desc
= " (±30%)";
645 case 8: /* hibernation osc */
646 /* not all parts support hibernation */
650 default: /* NOTREACHED */
655 /* PLL is used if it's not bypassed; its output is 200 MHz
656 * even when it runs at 400 MHz (adds divide-by-two stage).
659 mainfreq
= 200000000;
662 stellaris_info
->mck_freq
= mainfreq
/(1 + sysdiv
);
664 stellaris_info
->mck_freq
= mainfreq
;
667 /* Read device id register, main clock frequency register and fill in driver info structure */
668 static int stellaris_read_part_info(struct flash_bank
*bank
)
670 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
671 struct target
*target
= bank
->target
;
672 uint32_t did0
, did1
, ver
, fam
;
675 /* Read and parse chip identification register */
676 target_read_u32(target
, SCB_BASE
| DID0
, &did0
);
677 target_read_u32(target
, SCB_BASE
| DID1
, &did1
);
678 target_read_u32(target
, SCB_BASE
| DC0
, &stellaris_info
->dc0
);
679 target_read_u32(target
, SCB_BASE
| DC1
, &stellaris_info
->dc1
);
680 LOG_DEBUG("did0 0x%" PRIx32
", did1 0x%" PRIx32
", dc0 0x%" PRIx32
", dc1 0x%" PRIx32
"",
681 did0
, did1
, stellaris_info
->dc0
, stellaris_info
->dc1
);
683 ver
= DID0_VER(did0
);
684 if ((ver
!= 0) && (ver
!= 1)) {
685 LOG_WARNING("Unknown did0 version, cannot identify target");
686 return ERROR_FLASH_OPERATION_FAILED
;
690 LOG_WARNING("Cannot identify target as a Stellaris");
691 return ERROR_FLASH_OPERATION_FAILED
;
695 fam
= (did1
>> 24) & 0xF;
696 if (((ver
!= 0) && (ver
!= 1)) || (fam
!= 0)) {
697 LOG_WARNING("Unknown did1 version/family.");
698 return ERROR_FLASH_OPERATION_FAILED
;
701 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
702 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
703 * even give _both_ numbers! We'll use current numbers; IOSC is
704 * always approximate.
706 * For Tempest: IOSC is calibrated, 16 MHz
707 * For Blizzard: IOSC is calibrated, 16 MHz
708 * For Firestorm: IOSC is calibrated, 16 MHz
710 stellaris_info
->iosc_freq
= 12000000;
711 stellaris_info
->iosc_desc
= " (±30%)";
712 stellaris_info
->xtal_mask
= 0x0f;
714 /* get device class */
715 if (DID0_VER(did0
) > 0) {
716 stellaris_info
->target_class
= (did0
>> 16) & 0xFF;
718 /* Sandstorm class */
719 stellaris_info
->target_class
= 0;
722 switch (stellaris_info
->target_class
) {
723 case 0: /* Sandstorm */
725 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
726 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
727 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
729 if (((did0
>> 8) & 0xff) < 2) {
730 stellaris_info
->iosc_freq
= 15000000;
731 stellaris_info
->iosc_desc
= " (±50%)";
738 case 4: /* Tempest */
739 case 5: /* Blizzard */
740 case 6: /* Firestorm */
741 case 0xa: /* Snowflake */
742 stellaris_info
->iosc_freq
= 16000000; /* +/- 1% */
743 stellaris_info
->iosc_desc
= " (±1%)";
746 case 3: /* DustDevil */
747 stellaris_info
->xtal_mask
= 0x1f;
751 LOG_WARNING("Unknown did0 class");
754 for (i
= 0; StellarisParts
[i
].partno
; i
++) {
755 if ((StellarisParts
[i
].partno
== ((did1
>> 16) & 0xFF)) &&
756 (StellarisParts
[i
].class == stellaris_info
->target_class
))
760 stellaris_info
->target_name
= StellarisParts
[i
].partname
;
762 stellaris_info
->did0
= did0
;
763 stellaris_info
->did1
= did1
;
765 if (stellaris_info
->target_class
== 5) { /* Blizzard */
766 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
767 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
769 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->fsize
& 0xFFFF));
770 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
771 stellaris_info
->pagesize
= 1024;
772 } else if (stellaris_info
->target_class
== 0xa) { /* Snowflake */
773 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
774 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
776 stellaris_info
->pagesize
= (1 << ((stellaris_info
->fsize
>> 16) & 7)) * 1024;
777 stellaris_info
->num_pages
= 2048 * (1 + (stellaris_info
->fsize
& 0xFFFF)) /
778 stellaris_info
->pagesize
;
779 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
781 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->dc0
& 0xFFFF));
782 stellaris_info
->sramsiz
= (1 + ((stellaris_info
->dc0
>> 16) & 0xFFFF)) / 4;
783 stellaris_info
->pagesize
= 1024;
786 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
787 * That exposes a 32-word Flash Write Buffer ... enabling
788 * writes of more than one word at a time.
794 /***************************************************************************
796 ***************************************************************************/
798 static int stellaris_protect_check(struct flash_bank
*bank
)
800 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
801 struct target
*target
= bank
->target
;
802 uint32_t flash_sizek
= stellaris
->pagesize
/ 1024 *
803 stellaris
->num_pages
;
805 int status
= ERROR_OK
;
808 if (stellaris
->did1
== 0)
809 return ERROR_FLASH_BANK_NOT_PROBED
;
811 for (i
= 0; i
< (unsigned) bank
->num_sectors
; i
++)
812 bank
->sectors
[i
].is_protected
= -1;
814 /* Read each Flash Memory Protection Program Enable (FMPPE) register
815 * to report any pages that we can't write. Ignore the Read Enable
819 if (stellaris
->target_class
>= 0x0a || flash_sizek
> 64)
820 fmppe_addr
= SCB_BASE
| FMPPE0
;
822 fmppe_addr
= SCB_BASE
| FMPPE
;
824 unsigned int page
= 0, lockbitnum
, lockbitcnt
= flash_sizek
/ 2;
825 unsigned int bits_per_page
= stellaris
->pagesize
/ 2048;
826 /* Every lock bit always corresponds to a 2k region */
827 for (lockbitnum
= 0; lockbitnum
< lockbitcnt
; lockbitnum
+= 32) {
830 target_read_u32(target
, fmppe_addr
, &fmppe
);
831 for (i
= 0; i
< 32 && lockbitnum
+ i
< lockbitcnt
; i
++) {
832 bool protect
= !(fmppe
& (1 << i
));
834 bank
->sectors
[page
++].is_protected
= protect
;
835 i
+= bits_per_page
- 1;
836 } else { /* 1024k pages, every lockbit covers 2 pages */
837 bank
->sectors
[page
++].is_protected
= protect
;
838 bank
->sectors
[page
++].is_protected
= protect
;
847 static int stellaris_erase(struct flash_bank
*bank
, int first
, int last
)
850 uint32_t flash_fmc
, flash_cris
;
851 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
852 struct target
*target
= bank
->target
;
854 if (bank
->target
->state
!= TARGET_HALTED
) {
855 LOG_ERROR("Target not halted");
856 return ERROR_TARGET_NOT_HALTED
;
859 if (stellaris_info
->did1
== 0)
860 return ERROR_FLASH_BANK_NOT_PROBED
;
862 if ((first
< 0) || (last
< first
) || (last
>= (int)stellaris_info
->num_pages
))
863 return ERROR_FLASH_SECTOR_INVALID
;
865 if ((first
== 0) && (last
== ((int)stellaris_info
->num_pages
-1)))
866 return stellaris_mass_erase(bank
);
868 /* Refresh flash controller timing */
869 stellaris_read_clock_info(bank
);
870 stellaris_set_flash_timing(bank
);
872 /* Clear and disable flash programming interrupts */
873 target_write_u32(target
, FLASH_CIM
, 0);
874 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
876 /* REVISIT this clobbers state set by any halted firmware ...
877 * it might want to process those IRQs.
880 for (banknr
= first
; banknr
<= last
; banknr
++) {
881 /* Address is first word in page */
882 target_write_u32(target
, FLASH_FMA
, banknr
* stellaris_info
->pagesize
);
883 /* Write erase command */
884 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_ERASE
);
885 /* Wait until erase complete */
887 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
888 } while (flash_fmc
& FMC_ERASE
);
890 /* Check acess violations */
891 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
892 if (flash_cris
& (AMASK
)) {
893 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32
"",
895 target_write_u32(target
, FLASH_CRIS
, 0);
896 return ERROR_FLASH_OPERATION_FAILED
;
899 bank
->sectors
[banknr
].is_erased
= 1;
905 static int stellaris_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
907 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
908 struct target
*target
= bank
->target
;
909 uint32_t flash_fmc
, flash_cris
;
910 unsigned int bits_per_page
= stellaris
->pagesize
/ 2048;
912 if (target
->state
!= TARGET_HALTED
) {
913 LOG_ERROR("Target not halted");
914 return ERROR_TARGET_NOT_HALTED
;
918 LOG_ERROR("Hardware doesn't support page-level unprotect. "
919 "Try the 'recover' command.");
920 return ERROR_COMMAND_SYNTAX_ERROR
;
923 if (stellaris
->did1
== 0)
924 return ERROR_FLASH_BANK_NOT_PROBED
;
926 if (stellaris
->target_class
== 0x03 &&
927 !((stellaris
->did0
>> 8) & 0xFF) &&
928 !((stellaris
->did0
) & 0xFF)) {
929 LOG_ERROR("DustDevil A0 parts can't be unprotected, see errata; refusing to proceed");
930 return ERROR_FLASH_OPERATION_FAILED
;
933 if (!bits_per_page
&& (first
% 2 || !(last
% 2))) {
934 LOG_ERROR("Can't protect unaligned pages");
935 return ERROR_FLASH_SECTOR_INVALID
;
938 /* Refresh flash controller timing */
939 stellaris_read_clock_info(bank
);
940 stellaris_set_flash_timing(bank
);
942 /* Clear and disable flash programming interrupts */
943 target_write_u32(target
, FLASH_CIM
, 0);
944 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
946 uint32_t flash_sizek
= stellaris
->pagesize
/ 1024 *
947 stellaris
->num_pages
;
950 if (stellaris
->target_class
>= 0x0a || flash_sizek
> 64)
951 fmppe_addr
= SCB_BASE
| FMPPE0
;
953 fmppe_addr
= SCB_BASE
| FMPPE
;
956 unsigned int lockbitnum
, lockbitcnt
= flash_sizek
/ 2;
957 /* Every lock bit always corresponds to a 2k region */
958 for (lockbitnum
= 0; lockbitnum
< lockbitcnt
; lockbitnum
+= 32) {
961 target_read_u32(target
, fmppe_addr
, &fmppe
);
962 for (unsigned int i
= 0;
963 i
< 32 && lockbitnum
+ i
< lockbitcnt
;
965 if (page
>= first
&& page
<= last
)
969 if (!((i
+ 1) % bits_per_page
))
971 } else { /* 1024k pages, every lockbit covers 2 pages */
975 target_write_u32(target
, fmppe_addr
, fmppe
);
978 target_write_u32(target
, FLASH_FMA
, 1 + lockbitnum
/ 16);
979 /* Write commit command */
980 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_COMT
);
982 /* Wait until commit complete */
984 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
985 } while (flash_fmc
& FMC_COMT
);
987 /* Check access violations */
988 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
989 if (flash_cris
& (AMASK
)) {
990 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32
"", flash_cris
);
991 target_write_u32(target
, FLASH_CRIS
, 0);
992 return ERROR_FLASH_OPERATION_FAILED
;
1001 /* see contib/loaders/flash/stellaris.s for src */
1003 static const uint8_t stellaris_write_code
[] = {
1005 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */
1006 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */
1008 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
1009 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
1010 0x17, 0xD0, /* beq exit */
1011 0x47, 0x68, /* ldr r7, [r0, #4] */
1012 0x47, 0x45, /* cmp r7, r8 */
1013 0xF7, 0xD0, /* beq wait_fifo */
1015 0x22, 0x60, /* str r2, [r4, #0] */
1016 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */
1017 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */
1018 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */
1019 0xA5, 0x60, /* str r5, [r4, #8] */
1021 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */
1022 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */
1023 0xFA, 0xD1, /* bne busy */
1024 0x8F, 0x42, /* cmp r7, r1 */
1025 0x28, 0xBF, /* it cs */
1026 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
1027 0x47, 0x60, /* str r7, [r0, #4] */
1028 0x01, 0x3B, /* subs r3, r3, #1 */
1029 0x03, 0xB1, /* cbz r3, exit */
1030 0xE2, 0xE7, /* b wait_fifo */
1032 0x00, 0xBE, /* bkpt #0 */
1034 /* pFLASH_CTRL_BASE: */
1035 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
1036 /* FLASHWRITECMD: */
1037 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
1039 static int stellaris_write_block(struct flash_bank
*bank
,
1040 const uint8_t *buffer
, uint32_t offset
, uint32_t wcount
)
1042 struct target
*target
= bank
->target
;
1043 uint32_t buffer_size
= 16384;
1044 struct working_area
*source
;
1045 struct working_area
*write_algorithm
;
1046 uint32_t address
= bank
->base
+ offset
;
1047 struct reg_param reg_params
[4];
1048 struct armv7m_algorithm armv7m_info
;
1049 int retval
= ERROR_OK
;
1051 /* power of two, and multiple of word size */
1052 static const unsigned buf_min
= 128;
1054 /* for small buffers it's faster not to download an algorithm */
1055 if (wcount
* 4 < buf_min
)
1056 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1058 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" wcount=%08" PRIx32
"",
1059 bank
, buffer
, offset
, wcount
);
1061 /* flash write code */
1062 if (target_alloc_working_area(target
, sizeof(stellaris_write_code
),
1063 &write_algorithm
) != ERROR_OK
) {
1064 LOG_DEBUG("no working area for block memory writes");
1065 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1068 /* plus a buffer big enough for this data */
1069 if (wcount
* 4 < buffer_size
)
1070 buffer_size
= wcount
* 4;
1073 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
1075 if (buffer_size
<= buf_min
) {
1076 target_free_working_area(target
, write_algorithm
);
1077 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1079 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1080 target_name(target
), (unsigned) buffer_size
);
1083 target_write_buffer(target
, write_algorithm
->address
,
1084 sizeof(stellaris_write_code
),
1085 stellaris_write_code
);
1087 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
1088 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
1090 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1091 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1092 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
1093 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
1095 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
1096 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
1097 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
1098 buf_set_u32(reg_params
[3].value
, 0, 32, wcount
);
1100 retval
= target_run_flash_async_algorithm(target
, buffer
, wcount
, 4,
1103 source
->address
, source
->size
,
1104 write_algorithm
->address
, 0,
1107 if (retval
== ERROR_FLASH_OPERATION_FAILED
)
1108 LOG_ERROR("error %d executing stellaris flash write algorithm", retval
);
1110 target_free_working_area(target
, write_algorithm
);
1111 target_free_working_area(target
, source
);
1113 destroy_reg_param(®_params
[0]);
1114 destroy_reg_param(®_params
[1]);
1115 destroy_reg_param(®_params
[2]);
1116 destroy_reg_param(®_params
[3]);
1121 static int stellaris_write(struct flash_bank
*bank
, const uint8_t *buffer
,
1122 uint32_t offset
, uint32_t count
)
1124 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1125 struct target
*target
= bank
->target
;
1126 uint32_t address
= offset
;
1127 uint32_t flash_cris
, flash_fmc
;
1128 uint32_t words_remaining
= (count
/ 4);
1129 uint32_t bytes_remaining
= (count
& 0x00000003);
1130 uint32_t bytes_written
= 0;
1133 if (bank
->target
->state
!= TARGET_HALTED
) {
1134 LOG_ERROR("Target not halted");
1135 return ERROR_TARGET_NOT_HALTED
;
1138 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" count=%08" PRIx32
"",
1139 bank
, buffer
, offset
, count
);
1141 if (stellaris_info
->did1
== 0)
1142 return ERROR_FLASH_BANK_NOT_PROBED
;
1145 LOG_WARNING("offset size must be word aligned");
1146 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1149 if (offset
+ count
> bank
->size
)
1150 return ERROR_FLASH_DST_OUT_OF_BANK
;
1152 /* Refresh flash controller timing */
1153 stellaris_read_clock_info(bank
);
1154 stellaris_set_flash_timing(bank
);
1156 /* Clear and disable flash programming interrupts */
1157 target_write_u32(target
, FLASH_CIM
, 0);
1158 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1160 /* REVISIT this clobbers state set by any halted firmware ...
1161 * it might want to process those IRQs.
1164 /* multiple words to be programmed? */
1165 if (words_remaining
> 0) {
1166 /* try using a block write */
1167 retval
= stellaris_write_block(bank
, buffer
, offset
,
1169 if (retval
!= ERROR_OK
) {
1170 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
1171 LOG_DEBUG("writing flash word-at-a-time");
1172 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
1173 /* if an error occured, we examine the reason, and quit */
1174 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1176 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32
"", flash_cris
);
1177 return ERROR_FLASH_OPERATION_FAILED
;
1180 buffer
+= words_remaining
* 4;
1181 address
+= words_remaining
* 4;
1182 words_remaining
= 0;
1186 while (words_remaining
> 0) {
1187 if (!(address
& 0xff))
1188 LOG_DEBUG("0x%" PRIx32
"", address
);
1190 /* Program one word */
1191 target_write_u32(target
, FLASH_FMA
, address
);
1192 target_write_buffer(target
, FLASH_FMD
, 4, buffer
);
1193 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1194 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1195 /* Wait until write complete */
1197 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1198 } while (flash_fmc
& FMC_WRITE
);
1205 if (bytes_remaining
) {
1206 uint8_t last_word
[4] = {0xff, 0xff, 0xff, 0xff};
1208 /* copy the last remaining bytes into the write buffer */
1209 memcpy(last_word
, buffer
+bytes_written
, bytes_remaining
);
1211 if (!(address
& 0xff))
1212 LOG_DEBUG("0x%" PRIx32
"", address
);
1214 /* Program one word */
1215 target_write_u32(target
, FLASH_FMA
, address
);
1216 target_write_buffer(target
, FLASH_FMD
, 4, last_word
);
1217 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1218 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1219 /* Wait until write complete */
1221 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1222 } while (flash_fmc
& FMC_WRITE
);
1225 /* Check access violations */
1226 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1227 if (flash_cris
& (AMASK
)) {
1228 LOG_DEBUG("flash_cris 0x%" PRIx32
"", flash_cris
);
1229 return ERROR_FLASH_OPERATION_FAILED
;
1234 static int stellaris_probe(struct flash_bank
*bank
)
1236 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1239 /* If this is a stellaris chip, it has flash; probe() is just
1240 * to figure out how much is present. Only do it once.
1242 if (stellaris_info
->did1
!= 0)
1245 /* stellaris_read_part_info() already handled error checking and
1246 * reporting. Note that it doesn't write, so we don't care about
1247 * whether the target is halted or not.
1249 retval
= stellaris_read_part_info(bank
);
1250 if (retval
!= ERROR_OK
)
1253 if (bank
->sectors
) {
1254 free(bank
->sectors
);
1255 bank
->sectors
= NULL
;
1258 /* provide this for the benefit of the NOR flash framework */
1259 bank
->size
= stellaris_info
->num_pages
* stellaris_info
->pagesize
;
1260 bank
->num_sectors
= stellaris_info
->num_pages
;
1261 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
1262 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
1263 bank
->sectors
[i
].offset
= i
* stellaris_info
->pagesize
;
1264 bank
->sectors
[i
].size
= stellaris_info
->pagesize
;
1265 bank
->sectors
[i
].is_erased
= -1;
1266 bank
->sectors
[i
].is_protected
= -1;
1272 static int stellaris_mass_erase(struct flash_bank
*bank
)
1274 struct target
*target
= NULL
;
1275 struct stellaris_flash_bank
*stellaris_info
= NULL
;
1278 stellaris_info
= bank
->driver_priv
;
1279 target
= bank
->target
;
1281 if (target
->state
!= TARGET_HALTED
) {
1282 LOG_ERROR("Target not halted");
1283 return ERROR_TARGET_NOT_HALTED
;
1286 if (stellaris_info
->did1
== 0)
1287 return ERROR_FLASH_BANK_NOT_PROBED
;
1289 /* Refresh flash controller timing */
1290 stellaris_read_clock_info(bank
);
1291 stellaris_set_flash_timing(bank
);
1293 /* Clear and disable flash programming interrupts */
1294 target_write_u32(target
, FLASH_CIM
, 0);
1295 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1297 /* REVISIT this clobbers state set by any halted firmware ...
1298 * it might want to process those IRQs.
1301 target_write_u32(target
, FLASH_FMA
, 0);
1302 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1303 /* Wait until erase complete */
1305 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1306 } while (flash_fmc
& FMC_MERASE
);
1308 /* if device has > 128k, then second erase cycle is needed
1309 * this is only valid for older devices, but will not hurt */
1310 if (stellaris_info
->num_pages
* stellaris_info
->pagesize
> 0x20000) {
1311 target_write_u32(target
, FLASH_FMA
, 0x20000);
1312 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1313 /* Wait until erase complete */
1315 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1316 } while (flash_fmc
& FMC_MERASE
);
1322 COMMAND_HANDLER(stellaris_handle_mass_erase_command
)
1327 return ERROR_COMMAND_SYNTAX_ERROR
;
1329 struct flash_bank
*bank
;
1330 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1331 if (ERROR_OK
!= retval
)
1334 if (stellaris_mass_erase(bank
) == ERROR_OK
) {
1335 /* set all sectors as erased */
1336 for (i
= 0; i
< bank
->num_sectors
; i
++)
1337 bank
->sectors
[i
].is_erased
= 1;
1339 command_print(CMD
, "stellaris mass erase complete");
1341 command_print(CMD
, "stellaris mass erase failed");
1347 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1348 * This performs a mass erase and then restores all nonvolatile registers
1349 * (including USER_* registers and flash lock bits) to their defaults.
1350 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1352 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1353 * can affect this operation if flash protection has been enabled.
1355 COMMAND_HANDLER(stellaris_handle_recover_command
)
1357 struct flash_bank
*bank
;
1362 return ERROR_COMMAND_SYNTAX_ERROR
;
1364 bank
= get_flash_bank_by_num_noprobe(0);
1368 /* REVISIT ... it may be worth sanity checking that the AP is
1369 * inactive before we start. ARM documents that switching a DP's
1370 * mode while it's active can cause fault modes that need a power
1374 Jim_Eval_Named(CMD_CTX
->interp
, "catch { hla_command \"debug unlock\" }", 0, 0);
1375 if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX
->interp
), NULL
), "0")) {
1381 if (!(jtag_get_reset_config() & RESET_HAS_SRST
)) {
1382 LOG_ERROR("Can't recover Stellaris flash without SRST");
1385 adapter_assert_reset();
1387 arm
= target_to_arm(bank
->target
);
1388 for (int i
= 0; i
< 5; i
++) {
1389 retval
= dap_to_swd(arm
->dap
);
1390 if (retval
!= ERROR_OK
)
1393 retval
= dap_to_jtag(arm
->dap
);
1394 if (retval
!= ERROR_OK
)
1398 /* de-assert SRST */
1399 adapter_deassert_reset();
1400 retval
= jtag_execute_queue();
1402 /* wait 400+ msec ... OK, "1+ second" is simpler */
1406 /* USER INTERVENTION required for the power cycle
1407 * Restarting OpenOCD is likely needed because of mode switching.
1409 LOG_INFO("USER ACTION: "
1410 "power cycle Stellaris chip, then restart OpenOCD.");
1416 static const struct command_registration stellaris_exec_command_handlers
[] = {
1418 .name
= "mass_erase",
1420 .handler
= stellaris_handle_mass_erase_command
,
1421 .mode
= COMMAND_EXEC
,
1422 .help
= "erase entire device",
1426 .handler
= stellaris_handle_recover_command
,
1427 .mode
= COMMAND_EXEC
,
1429 .help
= "recover (and erase) locked device",
1431 COMMAND_REGISTRATION_DONE
1433 static const struct command_registration stellaris_command_handlers
[] = {
1435 .name
= "stellaris",
1436 .mode
= COMMAND_EXEC
,
1437 .help
= "Stellaris flash command group",
1439 .chain
= stellaris_exec_command_handlers
,
1441 COMMAND_REGISTRATION_DONE
1444 const struct flash_driver stellaris_flash
= {
1445 .name
= "stellaris",
1446 .commands
= stellaris_command_handlers
,
1447 .flash_bank_command
= stellaris_flash_bank_command
,
1448 .erase
= stellaris_erase
,
1449 .protect
= stellaris_protect
,
1450 .write
= stellaris_write
,
1451 .read
= default_flash_read
,
1452 .probe
= stellaris_probe
,
1453 .auto_probe
= stellaris_probe
,
1454 .erase_check
= default_flash_blank_check
,
1455 .protect_check
= stellaris_protect_check
,
1456 .info
= get_stellaris_info
,
1457 .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)