1 /***************************************************************************
2 * Copyright (C) 2006 by Magnus Lundin *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
24 /***************************************************************************
25 * STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more.
26 ***************************************************************************/
32 #include "jtag/interface.h"
34 #include <target/algorithm.h>
35 #include <target/armv7m.h>
37 #define DID0_VER(did0) ((did0 >> 28)&0x07)
39 /* STELLARIS control registers */
40 #define SCB_BASE 0x400FE000
55 /* "legacy" flash memory protection registers (64KB max) */
59 /* new flash memory protection registers (for more than 64KB) */
60 #define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */
61 #define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */
65 #define FLASH_CONTROL_BASE 0x400FD000
66 #define FLASH_FMA (FLASH_CONTROL_BASE | 0x000)
67 #define FLASH_FMD (FLASH_CONTROL_BASE | 0x004)
68 #define FLASH_FMC (FLASH_CONTROL_BASE | 0x008)
69 #define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C)
70 #define FLASH_CIM (FLASH_CONTROL_BASE | 0x010)
71 #define FLASH_MISC (FLASH_CONTROL_BASE | 0x014)
72 #define FLASH_FSIZE (FLASH_CONTROL_BASE | 0xFC0)
73 #define FLASH_SSIZE (FLASH_CONTROL_BASE | 0xFC4)
81 /* Flash Controller Command bits */
82 #define FMC_WRKEY (0xA442 << 16)
83 #define FMC_COMT (1 << 3)
84 #define FMC_MERASE (1 << 2)
85 #define FMC_ERASE (1 << 1)
86 #define FMC_WRITE (1 << 0)
88 /* STELLARIS constants */
90 /* values to write in FMA to commit write-"once" values */
91 #define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */
92 #define FLASH_FMA_PPE(x) (2 * (x) + 1) /* for FMPPPEx */
94 static void stellaris_read_clock_info(struct flash_bank
*bank
);
95 static int stellaris_mass_erase(struct flash_bank
*bank
);
97 struct stellaris_flash_bank
{
98 /* chip id register */
106 const char *target_name
;
107 uint8_t target_class
;
114 /* main clock status */
121 const char *iosc_desc
;
122 const char *mck_desc
;
125 /* Autogenerated by contrib/gen-stellaris-part-header.pl */
126 /* From Stellaris Firmware Development Package revision 9453 */
127 static const struct {
130 const char *partname
;
131 } StellarisParts
[] = {
132 {0x00, 0x01, "LM3S101"},
133 {0x00, 0x02, "LM3S102"},
134 {0x01, 0xBF, "LM3S1110"},
135 {0x01, 0xC3, "LM3S1133"},
136 {0x01, 0xC5, "LM3S1138"},
137 {0x01, 0xC1, "LM3S1150"},
138 {0x01, 0xC4, "LM3S1162"},
139 {0x01, 0xC2, "LM3S1165"},
140 {0x01, 0xEC, "LM3S1166"},
141 {0x01, 0xC6, "LM3S1332"},
142 {0x01, 0xBC, "LM3S1435"},
143 {0x01, 0xBA, "LM3S1439"},
144 {0x01, 0xBB, "LM3S1512"},
145 {0x01, 0xC7, "LM3S1538"},
146 {0x01, 0xDB, "LM3S1601"},
147 {0x03, 0x06, "LM3S1607"},
148 {0x01, 0xDA, "LM3S1608"},
149 {0x01, 0xC0, "LM3S1620"},
150 {0x04, 0xCD, "LM3S1621"},
151 {0x03, 0x03, "LM3S1625"},
152 {0x03, 0x04, "LM3S1626"},
153 {0x03, 0x05, "LM3S1627"},
154 {0x01, 0xB3, "LM3S1635"},
155 {0x01, 0xEB, "LM3S1636"},
156 {0x01, 0xBD, "LM3S1637"},
157 {0x04, 0xB1, "LM3S1651"},
158 {0x01, 0xB9, "LM3S1751"},
159 {0x03, 0x10, "LM3S1776"},
160 {0x04, 0x16, "LM3S1811"},
161 {0x04, 0x3D, "LM3S1816"},
162 {0x01, 0xB4, "LM3S1850"},
163 {0x01, 0xDD, "LM3S1911"},
164 {0x01, 0xDC, "LM3S1918"},
165 {0x01, 0xB7, "LM3S1937"},
166 {0x01, 0xBE, "LM3S1958"},
167 {0x01, 0xB5, "LM3S1960"},
168 {0x01, 0xB8, "LM3S1968"},
169 {0x01, 0xEA, "LM3S1969"},
170 {0x04, 0xCE, "LM3S1B21"},
171 {0x06, 0xCA, "LM3S1C21"},
172 {0x06, 0xCB, "LM3S1C26"},
173 {0x06, 0x98, "LM3S1C58"},
174 {0x06, 0xB0, "LM3S1D21"},
175 {0x06, 0xCC, "LM3S1D26"},
176 {0x06, 0x1D, "LM3S1F11"},
177 {0x06, 0x1B, "LM3S1F16"},
178 {0x06, 0xAF, "LM3S1G21"},
179 {0x06, 0x95, "LM3S1G58"},
180 {0x06, 0x1E, "LM3S1H11"},
181 {0x06, 0x1C, "LM3S1H16"},
182 {0x04, 0x0F, "LM3S1J11"},
183 {0x04, 0x3C, "LM3S1J16"},
184 {0x04, 0x0E, "LM3S1N11"},
185 {0x04, 0x3B, "LM3S1N16"},
186 {0x04, 0xB2, "LM3S1P51"},
187 {0x04, 0x9E, "LM3S1R21"},
188 {0x04, 0xC9, "LM3S1R26"},
189 {0x04, 0x30, "LM3S1W16"},
190 {0x04, 0x2F, "LM3S1Z16"},
191 {0x01, 0x51, "LM3S2110"},
192 {0x01, 0x84, "LM3S2139"},
193 {0x03, 0x39, "LM3S2276"},
194 {0x01, 0xA2, "LM3S2410"},
195 {0x01, 0x59, "LM3S2412"},
196 {0x01, 0x56, "LM3S2432"},
197 {0x01, 0x5A, "LM3S2533"},
198 {0x01, 0xE1, "LM3S2601"},
199 {0x01, 0xE0, "LM3S2608"},
200 {0x03, 0x33, "LM3S2616"},
201 {0x01, 0x57, "LM3S2620"},
202 {0x01, 0x85, "LM3S2637"},
203 {0x01, 0x53, "LM3S2651"},
204 {0x03, 0x80, "LM3S2671"},
205 {0x03, 0x50, "LM3S2678"},
206 {0x01, 0xA4, "LM3S2730"},
207 {0x01, 0x52, "LM3S2739"},
208 {0x03, 0x3A, "LM3S2776"},
209 {0x04, 0x6D, "LM3S2793"},
210 {0x01, 0xE3, "LM3S2911"},
211 {0x01, 0xE2, "LM3S2918"},
212 {0x01, 0xED, "LM3S2919"},
213 {0x01, 0x54, "LM3S2939"},
214 {0x01, 0x8F, "LM3S2948"},
215 {0x01, 0x58, "LM3S2950"},
216 {0x01, 0x55, "LM3S2965"},
217 {0x04, 0x6C, "LM3S2B93"},
218 {0x06, 0x94, "LM3S2D93"},
219 {0x06, 0x93, "LM3S2U93"},
220 {0x00, 0x19, "LM3S300"},
221 {0x00, 0x11, "LM3S301"},
222 {0x00, 0x1A, "LM3S308"},
223 {0x00, 0x12, "LM3S310"},
224 {0x00, 0x13, "LM3S315"},
225 {0x00, 0x14, "LM3S316"},
226 {0x00, 0x17, "LM3S317"},
227 {0x00, 0x15, "LM3S328"},
228 {0x03, 0x08, "LM3S3634"},
229 {0x03, 0x43, "LM3S3651"},
230 {0x04, 0xC8, "LM3S3654"},
231 {0x03, 0x44, "LM3S3739"},
232 {0x03, 0x49, "LM3S3748"},
233 {0x03, 0x45, "LM3S3749"},
234 {0x04, 0x42, "LM3S3826"},
235 {0x04, 0x41, "LM3S3J26"},
236 {0x04, 0x40, "LM3S3N26"},
237 {0x04, 0x3F, "LM3S3W26"},
238 {0x04, 0x3E, "LM3S3Z26"},
239 {0x03, 0x81, "LM3S5632"},
240 {0x04, 0x0C, "LM3S5651"},
241 {0x03, 0x8A, "LM3S5652"},
242 {0x04, 0x4D, "LM3S5656"},
243 {0x03, 0x91, "LM3S5662"},
244 {0x03, 0x96, "LM3S5732"},
245 {0x03, 0x97, "LM3S5737"},
246 {0x03, 0xA0, "LM3S5739"},
247 {0x03, 0x99, "LM3S5747"},
248 {0x03, 0xA7, "LM3S5749"},
249 {0x03, 0x9A, "LM3S5752"},
250 {0x03, 0x9C, "LM3S5762"},
251 {0x04, 0x69, "LM3S5791"},
252 {0x04, 0x0B, "LM3S5951"},
253 {0x04, 0x4E, "LM3S5956"},
254 {0x04, 0x68, "LM3S5B91"},
255 {0x06, 0x2E, "LM3S5C31"},
256 {0x06, 0x2C, "LM3S5C36"},
257 {0x06, 0x5E, "LM3S5C51"},
258 {0x06, 0x5B, "LM3S5C56"},
259 {0x06, 0x5F, "LM3S5D51"},
260 {0x06, 0x5C, "LM3S5D56"},
261 {0x06, 0x87, "LM3S5D91"},
262 {0x06, 0x2D, "LM3S5G31"},
263 {0x06, 0x1F, "LM3S5G36"},
264 {0x06, 0x5D, "LM3S5G51"},
265 {0x06, 0x4F, "LM3S5G56"},
266 {0x04, 0x09, "LM3S5K31"},
267 {0x04, 0x4A, "LM3S5K36"},
268 {0x04, 0x0A, "LM3S5P31"},
269 {0x04, 0x48, "LM3S5P36"},
270 {0x04, 0xB6, "LM3S5P3B"},
271 {0x04, 0x0D, "LM3S5P51"},
272 {0x04, 0x4C, "LM3S5P56"},
273 {0x04, 0x07, "LM3S5R31"},
274 {0x04, 0x4B, "LM3S5R36"},
275 {0x04, 0x47, "LM3S5T36"},
276 {0x06, 0x7F, "LM3S5U91"},
277 {0x04, 0x46, "LM3S5Y36"},
278 {0x00, 0x2A, "LM3S600"},
279 {0x00, 0x21, "LM3S601"},
280 {0x00, 0x2B, "LM3S608"},
281 {0x00, 0x22, "LM3S610"},
282 {0x01, 0xA1, "LM3S6100"},
283 {0x00, 0x23, "LM3S611"},
284 {0x01, 0x74, "LM3S6110"},
285 {0x00, 0x24, "LM3S612"},
286 {0x00, 0x25, "LM3S613"},
287 {0x00, 0x26, "LM3S615"},
288 {0x00, 0x28, "LM3S617"},
289 {0x00, 0x29, "LM3S618"},
290 {0x00, 0x27, "LM3S628"},
291 {0x01, 0xA5, "LM3S6420"},
292 {0x01, 0x82, "LM3S6422"},
293 {0x01, 0x75, "LM3S6432"},
294 {0x01, 0x76, "LM3S6537"},
295 {0x01, 0x71, "LM3S6610"},
296 {0x01, 0xE7, "LM3S6611"},
297 {0x01, 0xE6, "LM3S6618"},
298 {0x01, 0x83, "LM3S6633"},
299 {0x01, 0x8B, "LM3S6637"},
300 {0x01, 0xA3, "LM3S6730"},
301 {0x01, 0x77, "LM3S6753"},
302 {0x01, 0xE9, "LM3S6911"},
303 {0x01, 0xE8, "LM3S6918"},
304 {0x01, 0x89, "LM3S6938"},
305 {0x01, 0x72, "LM3S6950"},
306 {0x01, 0x78, "LM3S6952"},
307 {0x01, 0x73, "LM3S6965"},
308 {0x06, 0xAA, "LM3S6C11"},
309 {0x06, 0xAC, "LM3S6C65"},
310 {0x06, 0x9F, "LM3S6G11"},
311 {0x06, 0xAB, "LM3S6G65"},
312 {0x00, 0x38, "LM3S800"},
313 {0x00, 0x31, "LM3S801"},
314 {0x00, 0x39, "LM3S808"},
315 {0x00, 0x32, "LM3S811"},
316 {0x00, 0x33, "LM3S812"},
317 {0x00, 0x34, "LM3S815"},
318 {0x00, 0x36, "LM3S817"},
319 {0x00, 0x37, "LM3S818"},
320 {0x00, 0x35, "LM3S828"},
321 {0x01, 0x64, "LM3S8530"},
322 {0x01, 0x8E, "LM3S8538"},
323 {0x01, 0x61, "LM3S8630"},
324 {0x01, 0x63, "LM3S8730"},
325 {0x01, 0x8D, "LM3S8733"},
326 {0x01, 0x86, "LM3S8738"},
327 {0x01, 0x65, "LM3S8930"},
328 {0x01, 0x8C, "LM3S8933"},
329 {0x01, 0x88, "LM3S8938"},
330 {0x01, 0xA6, "LM3S8962"},
331 {0x01, 0x62, "LM3S8970"},
332 {0x01, 0xD7, "LM3S8971"},
333 {0x06, 0xAE, "LM3S8C62"},
334 {0x06, 0xAD, "LM3S8G62"},
335 {0x04, 0xCF, "LM3S9781"},
336 {0x04, 0x67, "LM3S9790"},
337 {0x04, 0x6B, "LM3S9792"},
338 {0x04, 0x2D, "LM3S9971"},
339 {0x04, 0x20, "LM3S9997"},
340 {0x04, 0xD0, "LM3S9B81"},
341 {0x04, 0x66, "LM3S9B90"},
342 {0x04, 0x6A, "LM3S9B92"},
343 {0x04, 0x6E, "LM3S9B95"},
344 {0x04, 0x6F, "LM3S9B96"},
345 {0x04, 0x1D, "LM3S9BN2"},
346 {0x04, 0x1E, "LM3S9BN5"},
347 {0x04, 0x1F, "LM3S9BN6"},
348 {0x06, 0x70, "LM3S9C97"},
349 {0x06, 0xA9, "LM3S9D81"},
350 {0x06, 0x7E, "LM3S9D90"},
351 {0x06, 0x92, "LM3S9D92"},
352 {0x06, 0x9D, "LM3S9D96"},
353 {0x06, 0x7B, "LM3S9DN5"},
354 {0x06, 0x7C, "LM3S9DN6"},
355 {0x06, 0x60, "LM3S9G97"},
356 {0x06, 0x79, "LM3S9GN5"},
357 {0x04, 0x1B, "LM3S9L71"},
358 {0x04, 0x18, "LM3S9L97"},
359 {0x06, 0xA8, "LM3S9U81"},
360 {0x06, 0x7D, "LM3S9U90"},
361 {0x06, 0x90, "LM3S9U92"},
362 {0x06, 0x9B, "LM3S9U96"},
363 {0x05, 0x01, "LM4F120B2QR/TM4C1233C3PM"},
364 {0x05, 0x02, "LM4F120C4QR/TM4C1233D5PM"},
365 {0x05, 0x03, "LM4F120E5QR/TM4C1233E6PM"},
366 {0x05, 0x04, "LM4F120H5QR/TM4C1233H6PM"},
367 {0x05, 0x08, "LM4F121B2QR/TM4C1232C3PM"},
368 {0x05, 0x09, "LM4F121C4QR/TM4C1232D5PM"},
369 {0x05, 0x0A, "LM4F121E5QR/TM4C1232E6PM"},
370 {0x05, 0x0B, "LM4F121H5QR/TM4C1232H6PM"},
371 {0x05, 0x10, "LM4F110E5QR/TM4C1231E6PM"},
372 {0x05, 0x11, "LM4F110H5QR/TM4C1231H6PM"},
373 {0x05, 0x18, "LM4F110B2QR/TM4C1231C3PM"},
374 {0x05, 0x19, "LM4F110C4QR/TM4C1231D5PM"},
375 {0x05, 0x20, "LM4F111E5QR/TM4C1230E6PM"},
376 {0x05, 0x21, "LM4F111H5QR/TM4C1230H6PM"},
377 {0x05, 0x22, "LM4F111B2QR/TM4C1230C3PM"},
378 {0x05, 0x23, "LM4F111C4QR/TM4C1230D5PM"},
379 {0x05, 0x30, "LM4F112E5QC/TM4C1231E6PZ"},
380 {0x05, 0x31, "LM4F112H5QC/TM4C1231H6PZ"},
381 {0x05, 0x35, "LM4F112H5QD/TM4C1231H6PGE"},
382 {0x05, 0x36, "LM4F112C4QC/TM4C1231D5PZ"},
383 {0x05, 0x40, "LM4F130E5QR/TM4C1237E6PM"},
384 {0x05, 0x41, "LM4F130H5QR/TM4C1237H6PM"},
385 {0x05, 0x48, "LM4F130C4QR/TM4C1237D5PM"},
386 {0x05, 0x50, "LM4F131E5QR/TM4C1236E6PM"},
387 {0x05, 0x51, "LM4F131H5QR/TM4C1236H6PM"},
388 {0x05, 0x52, "LM4F131C4QR/TM4C1236D5PM"},
389 {0x05, 0x60, "LM4F132E5QC/TM4C1237E6PZ"},
390 {0x05, 0x61, "LM4F132H5QC/TM4C1237H6PZ"},
391 {0x05, 0x65, "LM4F132H5QD/TM4C1237H6PGE"},
392 {0x05, 0x66, "LM4F132C4QC/TM4C1237D5PZ"},
393 {0x05, 0x70, "LM4F210E5QR/TM4C123BE6PM"},
394 {0x05, 0x73, "LM4F210H5QR/TM4C123BH6PM"},
395 {0x05, 0x80, "LM4F211E5QR/TM4C123AE6PM"},
396 {0x05, 0x83, "LM4F211H5QR/TM4C123AH6PM"},
397 {0x05, 0xA0, "LM4F230E5QR/TM4C123GE6PM"},
398 {0x05, 0xA1, "LM4F230H5QR/TM4C123GH6PM"},
399 {0x05, 0xB0, "LM4F231E5QR/TM4C123FE6PM"},
400 {0x05, 0xB1, "LM4F231H5QR/TM4C123FH6PM"},
401 {0x05, 0xC0, "LM4F232E5QC/TM4C123GE6PZ"},
402 {0x05, 0xC1, "LM4F232H5QC/TM4C123GH6PZ"},
403 {0x05, 0xC3, "LM4F212E5QC/TM4C123BE6PZ"},
404 {0x05, 0xC4, "LM4F212H5QC/TM4C123BH6PZ"},
405 {0x05, 0xC5, "LM4F232H5QD/TM4C123GH6PGE"},
406 {0x05, 0xC6, "LM4F212H5QD/TM4C123BH6PGE"},
407 {0x05, 0xD0, "LM4F122C4QC/TM4C1233D5PZ"},
408 {0x05, 0xD1, "LM4F122E5QC/TM4C1233E6PZ"},
409 {0x05, 0xD2, "LM4F122H5QC/TM4C1233H6PZ"},
410 {0x05, 0xD6, "LM4F122H5QD/TM4C1233H6PGE"},
411 {0x05, 0xE1, "LM4FSXLH5BB"},
412 {0x05, 0xE3, "LM4F232H5BB/TM4C123GH6ZRB"},
413 {0x05, 0xE4, "LM4FS99H5BB"},
414 {0x05, 0xE5, "LM4FS1AH5BB"},
415 {0x05, 0xE9, "LM4F212H5BB/TM4C123BH6ZRB"},
416 {0x05, 0xEA, "LM4FS1GH5BB"},
417 {0x05, 0xF0, "TM4C123GH6ZXR"},
418 {0x0A, 0x19, "TM4C1290NCPDT"},
419 {0x0A, 0x1B, "TM4C1290NCZAD"},
420 {0x0A, 0x1C, "TM4C1292NCPDT"},
421 {0x0A, 0x1E, "TM4C1292NCZAD"},
422 {0x0A, 0x1F, "TM4C1294NCPDT"},
423 {0x0A, 0x21, "TM4C1294NCZAD"},
424 {0x0A, 0x22, "TM4C1297NCZAD"},
425 {0x0A, 0x23, "TM4C1299NCZAD"},
426 {0x0A, 0x24, "TM4C129CNCPDT"},
427 {0x0A, 0x26, "TM4C129CNCZAD"},
428 {0x0A, 0x27, "TM4C129DNCPDT"},
429 {0x0A, 0x29, "TM4C129DNCZAD"},
430 {0x0A, 0x2D, "TM4C129ENCPDT"},
431 {0x0A, 0x2F, "TM4C129ENCZAD"},
432 {0x0A, 0x30, "TM4C129LNCZAD"},
433 {0x0A, 0x32, "TM4C129XNCZAD"},
434 {0x0A, 0x34, "TM4C1294KCPDT"},
435 {0x0A, 0x35, "TM4C129EKCPDT"},
436 {0x0A, 0x36, "TM4C1299KCZAD"},
437 {0x0A, 0x37, "TM4C129XKCZAD"},
438 {0xFF, 0x00, "Unknown Part"}
441 static const char * const StellarisClassname
[] = {
455 /***************************************************************************
456 * openocd command interface *
457 ***************************************************************************/
459 /* flash_bank stellaris <base> <size> 0 0 <target#>
461 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command
)
463 struct stellaris_flash_bank
*stellaris_info
;
466 return ERROR_COMMAND_SYNTAX_ERROR
;
468 stellaris_info
= calloc(sizeof(struct stellaris_flash_bank
), 1);
470 bank
->driver_priv
= stellaris_info
;
472 stellaris_info
->target_name
= "Unknown target";
474 /* part wasn't probed for info yet */
475 stellaris_info
->did1
= 0;
477 /* TODO Specify the main crystal speed in kHz using an optional
478 * argument; ditto, the speed of an external oscillator used
479 * instead of a crystal. Avoid programming flash using IOSC.
484 static int get_stellaris_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
487 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
489 if (stellaris_info
->did1
== 0)
490 return ERROR_FLASH_BANK_NOT_PROBED
;
492 /* Read main and master clock freqency register */
493 stellaris_read_clock_info(bank
);
495 printed
= snprintf(buf
,
497 "\nTI/LMI Stellaris information: Chip is "
498 "class %i (%s) %s rev %c%i\n",
499 stellaris_info
->target_class
,
500 StellarisClassname
[stellaris_info
->target_class
],
501 stellaris_info
->target_name
,
502 (int)('A' + ((stellaris_info
->did0
>> 8) & 0xFF)),
503 (int)((stellaris_info
->did0
) & 0xFF));
507 printed
= snprintf(buf
,
509 "did1: 0x%8.8" PRIx32
", arch: 0x%4.4" PRIx32
510 ", eproc: %s, ramsize: %" PRIu32
"k, flashsize: %" PRIu32
"k\n",
511 stellaris_info
->did1
,
512 stellaris_info
->did1
,
514 stellaris_info
->sramsiz
,
515 (uint32_t)(stellaris_info
->num_pages
* stellaris_info
->pagesize
/ 1024));
521 "master clock: %ikHz%s, "
522 "rcc is 0x%" PRIx32
", rcc2 is 0x%" PRIx32
", "
523 "pagesize: %" PRIu32
", pages: %" PRIu32
,
524 (int)(stellaris_info
->mck_freq
/ 1000),
525 stellaris_info
->mck_desc
,
527 stellaris_info
->rcc2
,
528 stellaris_info
->pagesize
,
529 stellaris_info
->num_pages
);
534 /***************************************************************************
535 * chip identification and status *
536 ***************************************************************************/
538 /* Set the flash timimg register to match current clocking */
539 static void stellaris_set_flash_timing(struct flash_bank
*bank
)
541 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
542 struct target
*target
= bank
->target
;
543 uint32_t usecrl
= (stellaris_info
->mck_freq
/1000000ul-1);
545 /* only valid for Sandstorm and Fury class devices */
546 if (stellaris_info
->target_class
> 1)
549 LOG_DEBUG("usecrl = %i", (int)(usecrl
));
550 target_write_u32(target
, SCB_BASE
| USECRL
, usecrl
);
553 static const unsigned rcc_xtal
[32] = {
554 [0x00] = 1000000, /* no pll */
555 [0x01] = 1843200, /* no pll */
556 [0x02] = 2000000, /* no pll */
557 [0x03] = 2457600, /* no pll */
561 [0x06] = 4000000, /* usb */
565 [0x09] = 5000000, /* usb */
567 [0x0b] = 6000000, /* (reset) usb */
571 [0x0e] = 8000000, /* usb */
574 /* parts before DustDevil use just 4 bits for xtal spec */
576 [0x10] = 10000000, /* usb */
577 [0x11] = 12000000, /* usb */
582 [0x15] = 16000000, /* usb */
586 /** Read clock configuration and set stellaris_info->usec_clocks. */
587 static void stellaris_read_clock_info(struct flash_bank
*bank
)
589 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
590 struct target
*target
= bank
->target
;
591 uint32_t rcc
, rcc2
, pllcfg
, sysdiv
, usesysdiv
, bypass
, oscsrc
;
593 unsigned long mainfreq
;
595 target_read_u32(target
, SCB_BASE
| RCC
, &rcc
);
596 LOG_DEBUG("Stellaris RCC %" PRIx32
"", rcc
);
598 target_read_u32(target
, SCB_BASE
| RCC2
, &rcc2
);
599 LOG_DEBUG("Stellaris RCC2 %" PRIx32
"", rcc
);
601 target_read_u32(target
, SCB_BASE
| PLLCFG
, &pllcfg
);
602 LOG_DEBUG("Stellaris PLLCFG %" PRIx32
"", pllcfg
);
604 stellaris_info
->rcc
= rcc
;
605 stellaris_info
->rcc2
= rcc2
;
607 sysdiv
= (rcc
>> 23) & 0xF;
608 usesysdiv
= (rcc
>> 22) & 0x1;
609 bypass
= (rcc
>> 11) & 0x1;
610 oscsrc
= (rcc
>> 4) & 0x3;
611 xtal
= (rcc
>> 6) & stellaris_info
->xtal_mask
;
613 /* NOTE: post-Sandstorm parts have RCC2 which may override
614 * parts of RCC ... with more sysdiv options, option for
615 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
616 * as zero, so the "use RCC2" flag is always clear.
618 if (rcc2
& (1 << 31)) {
619 sysdiv
= (rcc2
>> 23) & 0x3F;
620 bypass
= (rcc2
>> 11) & 0x1;
621 oscsrc
= (rcc2
>> 4) & 0x7;
623 /* FIXME Tempest parts have an additional lsb for
624 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
628 stellaris_info
->mck_desc
= "";
632 mainfreq
= rcc_xtal
[xtal
];
635 mainfreq
= stellaris_info
->iosc_freq
;
636 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
639 mainfreq
= stellaris_info
->iosc_freq
/ 4;
640 stellaris_info
->mck_desc
= stellaris_info
->iosc_desc
;
642 case 3: /* lowspeed */
643 /* Sandstorm doesn't have this 30K +/- 30% osc */
645 stellaris_info
->mck_desc
= " (±30%)";
647 case 8: /* hibernation osc */
648 /* not all parts support hibernation */
652 default: /* NOTREACHED */
657 /* PLL is used if it's not bypassed; its output is 200 MHz
658 * even when it runs at 400 MHz (adds divide-by-two stage).
661 mainfreq
= 200000000;
664 stellaris_info
->mck_freq
= mainfreq
/(1 + sysdiv
);
666 stellaris_info
->mck_freq
= mainfreq
;
669 /* Read device id register, main clock frequency register and fill in driver info structure */
670 static int stellaris_read_part_info(struct flash_bank
*bank
)
672 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
673 struct target
*target
= bank
->target
;
674 uint32_t did0
, did1
, ver
, fam
;
677 /* Read and parse chip identification register */
678 target_read_u32(target
, SCB_BASE
| DID0
, &did0
);
679 target_read_u32(target
, SCB_BASE
| DID1
, &did1
);
680 target_read_u32(target
, SCB_BASE
| DC0
, &stellaris_info
->dc0
);
681 target_read_u32(target
, SCB_BASE
| DC1
, &stellaris_info
->dc1
);
682 LOG_DEBUG("did0 0x%" PRIx32
", did1 0x%" PRIx32
", dc0 0x%" PRIx32
", dc1 0x%" PRIx32
"",
683 did0
, did1
, stellaris_info
->dc0
, stellaris_info
->dc1
);
685 ver
= DID0_VER(did0
);
686 if ((ver
!= 0) && (ver
!= 1)) {
687 LOG_WARNING("Unknown did0 version, cannot identify target");
688 return ERROR_FLASH_OPERATION_FAILED
;
692 LOG_WARNING("Cannot identify target as a Stellaris");
693 return ERROR_FLASH_OPERATION_FAILED
;
697 fam
= (did1
>> 24) & 0xF;
698 if (((ver
!= 0) && (ver
!= 1)) || (fam
!= 0)) {
699 LOG_WARNING("Unknown did1 version/family.");
700 return ERROR_FLASH_OPERATION_FAILED
;
703 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
704 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
705 * even give _both_ numbers! We'll use current numbers; IOSC is
706 * always approximate.
708 * For Tempest: IOSC is calibrated, 16 MHz
709 * For Blizzard: IOSC is calibrated, 16 MHz
710 * For Firestorm: IOSC is calibrated, 16 MHz
712 stellaris_info
->iosc_freq
= 12000000;
713 stellaris_info
->iosc_desc
= " (±30%)";
714 stellaris_info
->xtal_mask
= 0x0f;
716 /* get device class */
717 if (DID0_VER(did0
) > 0) {
718 stellaris_info
->target_class
= (did0
>> 16) & 0xFF;
720 /* Sandstorm class */
721 stellaris_info
->target_class
= 0;
724 switch (stellaris_info
->target_class
) {
725 case 0: /* Sandstorm */
727 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
728 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
729 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
731 if (((did0
>> 8) & 0xff) < 2) {
732 stellaris_info
->iosc_freq
= 15000000;
733 stellaris_info
->iosc_desc
= " (±50%)";
740 case 4: /* Tempest */
741 case 5: /* Blizzard */
742 case 6: /* Firestorm */
743 case 0xa: /* Snowflake */
744 stellaris_info
->iosc_freq
= 16000000; /* +/- 1% */
745 stellaris_info
->iosc_desc
= " (±1%)";
748 case 3: /* DustDevil */
749 stellaris_info
->xtal_mask
= 0x1f;
753 LOG_WARNING("Unknown did0 class");
756 for (i
= 0; StellarisParts
[i
].partno
; i
++) {
757 if ((StellarisParts
[i
].partno
== ((did1
>> 16) & 0xFF)) &&
758 (StellarisParts
[i
].class == stellaris_info
->target_class
))
762 stellaris_info
->target_name
= StellarisParts
[i
].partname
;
764 stellaris_info
->did0
= did0
;
765 stellaris_info
->did1
= did1
;
767 if (stellaris_info
->target_class
== 5) { /* Blizzard */
768 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
769 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
771 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->fsize
& 0xFFFF));
772 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
773 stellaris_info
->pagesize
= 1024;
774 } else if (stellaris_info
->target_class
== 0xa) { /* Snowflake */
775 target_read_u32(target
, FLASH_FSIZE
, &stellaris_info
->fsize
);
776 target_read_u32(target
, FLASH_SSIZE
, &stellaris_info
->ssize
);
778 stellaris_info
->pagesize
= (1 << ((stellaris_info
->fsize
>> 16) & 7)) * 1024;
779 stellaris_info
->num_pages
= 2048 * (1 + (stellaris_info
->fsize
& 0xFFFF)) /
780 stellaris_info
->pagesize
;
781 stellaris_info
->sramsiz
= (1 + (stellaris_info
->ssize
& 0xFFFF)) / 4;
783 stellaris_info
->num_pages
= 2 * (1 + (stellaris_info
->dc0
& 0xFFFF));
784 stellaris_info
->sramsiz
= (1 + ((stellaris_info
->dc0
>> 16) & 0xFFFF)) / 4;
785 stellaris_info
->pagesize
= 1024;
788 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
789 * That exposes a 32-word Flash Write Buffer ... enabling
790 * writes of more than one word at a time.
796 /***************************************************************************
798 ***************************************************************************/
800 static int stellaris_protect_check(struct flash_bank
*bank
)
802 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
803 struct target
*target
= bank
->target
;
804 uint32_t flash_sizek
= stellaris
->pagesize
/ 1024 *
805 stellaris
->num_pages
;
807 int status
= ERROR_OK
;
810 if (stellaris
->did1
== 0)
811 return ERROR_FLASH_BANK_NOT_PROBED
;
813 for (i
= 0; i
< (unsigned) bank
->num_sectors
; i
++)
814 bank
->sectors
[i
].is_protected
= -1;
816 /* Read each Flash Memory Protection Program Enable (FMPPE) register
817 * to report any pages that we can't write. Ignore the Read Enable
821 if (stellaris
->target_class
>= 0x0a || flash_sizek
> 64)
822 fmppe_addr
= SCB_BASE
| FMPPE0
;
824 fmppe_addr
= SCB_BASE
| FMPPE
;
826 unsigned int page
= 0, lockbitnum
, lockbitcnt
= flash_sizek
/ 2;
827 unsigned int bits_per_page
= stellaris
->pagesize
/ 2048;
828 /* Every lock bit always corresponds to a 2k region */
829 for (lockbitnum
= 0; lockbitnum
< lockbitcnt
; lockbitnum
+= 32) {
832 target_read_u32(target
, fmppe_addr
, &fmppe
);
833 for (i
= 0; i
< 32 && lockbitnum
+ i
< lockbitcnt
; i
++) {
834 bool protect
= !(fmppe
& (1 << i
));
836 bank
->sectors
[page
++].is_protected
= protect
;
837 i
+= bits_per_page
- 1;
838 } else { /* 1024k pages, every lockbit covers 2 pages */
839 bank
->sectors
[page
++].is_protected
= protect
;
840 bank
->sectors
[page
++].is_protected
= protect
;
849 static int stellaris_erase(struct flash_bank
*bank
, int first
, int last
)
852 uint32_t flash_fmc
, flash_cris
;
853 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
854 struct target
*target
= bank
->target
;
856 if (bank
->target
->state
!= TARGET_HALTED
) {
857 LOG_ERROR("Target not halted");
858 return ERROR_TARGET_NOT_HALTED
;
861 if (stellaris_info
->did1
== 0)
862 return ERROR_FLASH_BANK_NOT_PROBED
;
864 if ((first
< 0) || (last
< first
) || (last
>= (int)stellaris_info
->num_pages
))
865 return ERROR_FLASH_SECTOR_INVALID
;
867 if ((first
== 0) && (last
== ((int)stellaris_info
->num_pages
-1)))
868 return stellaris_mass_erase(bank
);
870 /* Refresh flash controller timing */
871 stellaris_read_clock_info(bank
);
872 stellaris_set_flash_timing(bank
);
874 /* Clear and disable flash programming interrupts */
875 target_write_u32(target
, FLASH_CIM
, 0);
876 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
878 /* REVISIT this clobbers state set by any halted firmware ...
879 * it might want to process those IRQs.
882 for (banknr
= first
; banknr
<= last
; banknr
++) {
883 /* Address is first word in page */
884 target_write_u32(target
, FLASH_FMA
, banknr
* stellaris_info
->pagesize
);
885 /* Write erase command */
886 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_ERASE
);
887 /* Wait until erase complete */
889 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
890 } while (flash_fmc
& FMC_ERASE
);
892 /* Check acess violations */
893 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
894 if (flash_cris
& (AMASK
)) {
895 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32
"",
897 target_write_u32(target
, FLASH_CRIS
, 0);
898 return ERROR_FLASH_OPERATION_FAILED
;
901 bank
->sectors
[banknr
].is_erased
= 1;
907 static int stellaris_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
909 struct stellaris_flash_bank
*stellaris
= bank
->driver_priv
;
910 struct target
*target
= bank
->target
;
911 uint32_t flash_fmc
, flash_cris
;
912 unsigned int bits_per_page
= stellaris
->pagesize
/ 2048;
914 if (target
->state
!= TARGET_HALTED
) {
915 LOG_ERROR("Target not halted");
916 return ERROR_TARGET_NOT_HALTED
;
920 LOG_ERROR("Hardware doesn't support page-level unprotect. "
921 "Try the 'recover' command.");
922 return ERROR_COMMAND_SYNTAX_ERROR
;
925 if (stellaris
->did1
== 0)
926 return ERROR_FLASH_BANK_NOT_PROBED
;
928 if (stellaris
->target_class
== 0x03 &&
929 !((stellaris
->did0
>> 8) & 0xFF) &&
930 !((stellaris
->did0
) & 0xFF)) {
931 LOG_ERROR("DustDevil A0 parts can't be unprotected, see errata; refusing to proceed");
932 return ERROR_FLASH_OPERATION_FAILED
;
935 if (!bits_per_page
&& (first
% 2 || !(last
% 2))) {
936 LOG_ERROR("Can't protect unaligned pages");
937 return ERROR_FLASH_SECTOR_INVALID
;
940 /* Refresh flash controller timing */
941 stellaris_read_clock_info(bank
);
942 stellaris_set_flash_timing(bank
);
944 /* Clear and disable flash programming interrupts */
945 target_write_u32(target
, FLASH_CIM
, 0);
946 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
948 uint32_t flash_sizek
= stellaris
->pagesize
/ 1024 *
949 stellaris
->num_pages
;
952 if (stellaris
->target_class
>= 0x0a || flash_sizek
> 64)
953 fmppe_addr
= SCB_BASE
| FMPPE0
;
955 fmppe_addr
= SCB_BASE
| FMPPE
;
958 unsigned int lockbitnum
, lockbitcnt
= flash_sizek
/ 2;
959 /* Every lock bit always corresponds to a 2k region */
960 for (lockbitnum
= 0; lockbitnum
< lockbitcnt
; lockbitnum
+= 32) {
963 target_read_u32(target
, fmppe_addr
, &fmppe
);
964 for (unsigned int i
= 0;
965 i
< 32 && lockbitnum
+ i
< lockbitcnt
;
967 if (page
>= first
&& page
<= last
)
971 if (!((i
+ 1) % bits_per_page
))
973 } else { /* 1024k pages, every lockbit covers 2 pages */
977 target_write_u32(target
, fmppe_addr
, fmppe
);
980 target_write_u32(target
, FLASH_FMA
, 1 + lockbitnum
/ 16);
981 /* Write commit command */
982 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_COMT
);
984 /* Wait until commit complete */
986 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
987 } while (flash_fmc
& FMC_COMT
);
989 /* Check access violations */
990 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
991 if (flash_cris
& (AMASK
)) {
992 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32
"", flash_cris
);
993 target_write_u32(target
, FLASH_CRIS
, 0);
994 return ERROR_FLASH_OPERATION_FAILED
;
1003 /* see contib/loaders/flash/stellaris.s for src */
1005 static const uint8_t stellaris_write_code
[] = {
1007 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */
1008 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */
1010 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
1011 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
1012 0x17, 0xD0, /* beq exit */
1013 0x47, 0x68, /* ldr r7, [r0, #4] */
1014 0x47, 0x45, /* cmp r7, r8 */
1015 0xF7, 0xD0, /* beq wait_fifo */
1017 0x22, 0x60, /* str r2, [r4, #0] */
1018 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */
1019 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */
1020 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */
1021 0xA5, 0x60, /* str r5, [r4, #8] */
1023 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */
1024 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */
1025 0xFA, 0xD1, /* bne busy */
1026 0x8F, 0x42, /* cmp r7, r1 */
1027 0x28, 0xBF, /* it cs */
1028 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
1029 0x47, 0x60, /* str r7, [r0, #4] */
1030 0x01, 0x3B, /* subs r3, r3, #1 */
1031 0x03, 0xB1, /* cbz r3, exit */
1032 0xE2, 0xE7, /* b wait_fifo */
1034 0x00, 0xBE, /* bkpt #0 */
1036 /* pFLASH_CTRL_BASE: */
1037 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
1038 /* FLASHWRITECMD: */
1039 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
1041 static int stellaris_write_block(struct flash_bank
*bank
,
1042 const uint8_t *buffer
, uint32_t offset
, uint32_t wcount
)
1044 struct target
*target
= bank
->target
;
1045 uint32_t buffer_size
= 16384;
1046 struct working_area
*source
;
1047 struct working_area
*write_algorithm
;
1048 uint32_t address
= bank
->base
+ offset
;
1049 struct reg_param reg_params
[4];
1050 struct armv7m_algorithm armv7m_info
;
1051 int retval
= ERROR_OK
;
1053 /* power of two, and multiple of word size */
1054 static const unsigned buf_min
= 128;
1056 /* for small buffers it's faster not to download an algorithm */
1057 if (wcount
* 4 < buf_min
)
1058 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1060 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" wcount=%08" PRIx32
"",
1061 bank
, buffer
, offset
, wcount
);
1063 /* flash write code */
1064 if (target_alloc_working_area(target
, sizeof(stellaris_write_code
),
1065 &write_algorithm
) != ERROR_OK
) {
1066 LOG_DEBUG("no working area for block memory writes");
1067 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1070 /* plus a buffer big enough for this data */
1071 if (wcount
* 4 < buffer_size
)
1072 buffer_size
= wcount
* 4;
1075 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
1077 if (buffer_size
<= buf_min
) {
1078 target_free_working_area(target
, write_algorithm
);
1079 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1081 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1082 target_name(target
), (unsigned) buffer_size
);
1085 target_write_buffer(target
, write_algorithm
->address
,
1086 sizeof(stellaris_write_code
),
1087 stellaris_write_code
);
1089 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
1090 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
1092 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1093 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1094 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
1095 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
1097 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
1098 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
1099 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
1100 buf_set_u32(reg_params
[3].value
, 0, 32, wcount
);
1102 retval
= target_run_flash_async_algorithm(target
, buffer
, wcount
, 4,
1105 source
->address
, source
->size
,
1106 write_algorithm
->address
, 0,
1109 if (retval
== ERROR_FLASH_OPERATION_FAILED
)
1110 LOG_ERROR("error %d executing stellaris flash write algorithm", retval
);
1112 target_free_working_area(target
, write_algorithm
);
1113 target_free_working_area(target
, source
);
1115 destroy_reg_param(®_params
[0]);
1116 destroy_reg_param(®_params
[1]);
1117 destroy_reg_param(®_params
[2]);
1118 destroy_reg_param(®_params
[3]);
1123 static int stellaris_write(struct flash_bank
*bank
, const uint8_t *buffer
,
1124 uint32_t offset
, uint32_t count
)
1126 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1127 struct target
*target
= bank
->target
;
1128 uint32_t address
= offset
;
1129 uint32_t flash_cris
, flash_fmc
;
1130 uint32_t words_remaining
= (count
/ 4);
1131 uint32_t bytes_remaining
= (count
& 0x00000003);
1132 uint32_t bytes_written
= 0;
1135 if (bank
->target
->state
!= TARGET_HALTED
) {
1136 LOG_ERROR("Target not halted");
1137 return ERROR_TARGET_NOT_HALTED
;
1140 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32
" count=%08" PRIx32
"",
1141 bank
, buffer
, offset
, count
);
1143 if (stellaris_info
->did1
== 0)
1144 return ERROR_FLASH_BANK_NOT_PROBED
;
1147 LOG_WARNING("offset size must be word aligned");
1148 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1151 if (offset
+ count
> bank
->size
)
1152 return ERROR_FLASH_DST_OUT_OF_BANK
;
1154 /* Refresh flash controller timing */
1155 stellaris_read_clock_info(bank
);
1156 stellaris_set_flash_timing(bank
);
1158 /* Clear and disable flash programming interrupts */
1159 target_write_u32(target
, FLASH_CIM
, 0);
1160 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1162 /* REVISIT this clobbers state set by any halted firmware ...
1163 * it might want to process those IRQs.
1166 /* multiple words to be programmed? */
1167 if (words_remaining
> 0) {
1168 /* try using a block write */
1169 retval
= stellaris_write_block(bank
, buffer
, offset
,
1171 if (retval
!= ERROR_OK
) {
1172 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
1173 LOG_DEBUG("writing flash word-at-a-time");
1174 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
1175 /* if an error occured, we examine the reason, and quit */
1176 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1178 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32
"", flash_cris
);
1179 return ERROR_FLASH_OPERATION_FAILED
;
1182 buffer
+= words_remaining
* 4;
1183 address
+= words_remaining
* 4;
1184 words_remaining
= 0;
1188 while (words_remaining
> 0) {
1189 if (!(address
& 0xff))
1190 LOG_DEBUG("0x%" PRIx32
"", address
);
1192 /* Program one word */
1193 target_write_u32(target
, FLASH_FMA
, address
);
1194 target_write_buffer(target
, FLASH_FMD
, 4, buffer
);
1195 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1196 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1197 /* Wait until write complete */
1199 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1200 } while (flash_fmc
& FMC_WRITE
);
1207 if (bytes_remaining
) {
1208 uint8_t last_word
[4] = {0xff, 0xff, 0xff, 0xff};
1210 /* copy the last remaining bytes into the write buffer */
1211 memcpy(last_word
, buffer
+bytes_written
, bytes_remaining
);
1213 if (!(address
& 0xff))
1214 LOG_DEBUG("0x%" PRIx32
"", address
);
1216 /* Program one word */
1217 target_write_u32(target
, FLASH_FMA
, address
);
1218 target_write_buffer(target
, FLASH_FMD
, 4, last_word
);
1219 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_WRITE
);
1220 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1221 /* Wait until write complete */
1223 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1224 } while (flash_fmc
& FMC_WRITE
);
1227 /* Check access violations */
1228 target_read_u32(target
, FLASH_CRIS
, &flash_cris
);
1229 if (flash_cris
& (AMASK
)) {
1230 LOG_DEBUG("flash_cris 0x%" PRIx32
"", flash_cris
);
1231 return ERROR_FLASH_OPERATION_FAILED
;
1236 static int stellaris_probe(struct flash_bank
*bank
)
1238 struct stellaris_flash_bank
*stellaris_info
= bank
->driver_priv
;
1241 /* If this is a stellaris chip, it has flash; probe() is just
1242 * to figure out how much is present. Only do it once.
1244 if (stellaris_info
->did1
!= 0)
1247 /* stellaris_read_part_info() already handled error checking and
1248 * reporting. Note that it doesn't write, so we don't care about
1249 * whether the target is halted or not.
1251 retval
= stellaris_read_part_info(bank
);
1252 if (retval
!= ERROR_OK
)
1255 if (bank
->sectors
) {
1256 free(bank
->sectors
);
1257 bank
->sectors
= NULL
;
1260 /* provide this for the benefit of the NOR flash framework */
1261 bank
->size
= stellaris_info
->num_pages
* stellaris_info
->pagesize
;
1262 bank
->num_sectors
= stellaris_info
->num_pages
;
1263 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
1264 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
1265 bank
->sectors
[i
].offset
= i
* stellaris_info
->pagesize
;
1266 bank
->sectors
[i
].size
= stellaris_info
->pagesize
;
1267 bank
->sectors
[i
].is_erased
= -1;
1268 bank
->sectors
[i
].is_protected
= -1;
1274 static int stellaris_mass_erase(struct flash_bank
*bank
)
1276 struct target
*target
= NULL
;
1277 struct stellaris_flash_bank
*stellaris_info
= NULL
;
1280 stellaris_info
= bank
->driver_priv
;
1281 target
= bank
->target
;
1283 if (target
->state
!= TARGET_HALTED
) {
1284 LOG_ERROR("Target not halted");
1285 return ERROR_TARGET_NOT_HALTED
;
1288 if (stellaris_info
->did1
== 0)
1289 return ERROR_FLASH_BANK_NOT_PROBED
;
1291 /* Refresh flash controller timing */
1292 stellaris_read_clock_info(bank
);
1293 stellaris_set_flash_timing(bank
);
1295 /* Clear and disable flash programming interrupts */
1296 target_write_u32(target
, FLASH_CIM
, 0);
1297 target_write_u32(target
, FLASH_MISC
, PMISC
| AMISC
);
1299 /* REVISIT this clobbers state set by any halted firmware ...
1300 * it might want to process those IRQs.
1303 target_write_u32(target
, FLASH_FMA
, 0);
1304 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1305 /* Wait until erase complete */
1307 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1308 } while (flash_fmc
& FMC_MERASE
);
1310 /* if device has > 128k, then second erase cycle is needed
1311 * this is only valid for older devices, but will not hurt */
1312 if (stellaris_info
->num_pages
* stellaris_info
->pagesize
> 0x20000) {
1313 target_write_u32(target
, FLASH_FMA
, 0x20000);
1314 target_write_u32(target
, FLASH_FMC
, FMC_WRKEY
| FMC_MERASE
);
1315 /* Wait until erase complete */
1317 target_read_u32(target
, FLASH_FMC
, &flash_fmc
);
1318 } while (flash_fmc
& FMC_MERASE
);
1324 COMMAND_HANDLER(stellaris_handle_mass_erase_command
)
1329 return ERROR_COMMAND_SYNTAX_ERROR
;
1331 struct flash_bank
*bank
;
1332 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1333 if (ERROR_OK
!= retval
)
1336 if (stellaris_mass_erase(bank
) == ERROR_OK
) {
1337 /* set all sectors as erased */
1338 for (i
= 0; i
< bank
->num_sectors
; i
++)
1339 bank
->sectors
[i
].is_erased
= 1;
1341 command_print(CMD_CTX
, "stellaris mass erase complete");
1343 command_print(CMD_CTX
, "stellaris mass erase failed");
1349 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1350 * This performs a mass erase and then restores all nonvolatile registers
1351 * (including USER_* registers and flash lock bits) to their defaults.
1352 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1354 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1355 * can affect this operation if flash protection has been enabled.
1357 COMMAND_HANDLER(stellaris_handle_recover_command
)
1359 struct flash_bank
*bank
;
1363 return ERROR_COMMAND_SYNTAX_ERROR
;
1365 bank
= get_flash_bank_by_num_noprobe(0);
1369 /* REVISIT ... it may be worth sanity checking that the AP is
1370 * inactive before we start. ARM documents that switching a DP's
1371 * mode while it's active can cause fault modes that need a power
1375 Jim_Eval_Named(CMD_CTX
->interp
, "catch { hla_command \"debug unlock\" }", 0, 0);
1376 if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX
->interp
), NULL
), "0")) {
1382 if (!(jtag_get_reset_config() & RESET_HAS_SRST
)) {
1383 LOG_ERROR("Can't recover Stellaris flash without SRST");
1386 adapter_assert_reset();
1388 for (int i
= 0; i
< 5; i
++) {
1389 retval
= dap_to_swd(bank
->target
);
1390 if (retval
!= ERROR_OK
)
1393 retval
= dap_to_jtag(bank
->target
);
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 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
,
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)