optimize: replace while loop by memcpy
[openocd.git] / src / flash / nor / stellaris.c
1 /***************************************************************************
2 * Copyright (C) 2006 by Magnus Lundin *
3 * lundin@mlu.mine.nu *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
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. *
12 * *
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. *
17 * *
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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23
24 /***************************************************************************
25 * STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more.
26 ***************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "imp.h"
32 #include <target/algorithm.h>
33 #include <target/armv7m.h>
34
35
36 #define DID0_VER(did0) ((did0 >> 28)&0x07)
37
38 /* STELLARIS control registers */
39 #define SCB_BASE 0x400FE000
40 #define DID0 0x000
41 #define DID1 0x004
42 #define DC0 0x008
43 #define DC1 0x010
44 #define DC2 0x014
45 #define DC3 0x018
46 #define DC4 0x01C
47
48 #define RIS 0x050
49 #define RCC 0x060
50 #define PLLCFG 0x064
51 #define RCC2 0x070
52 #define NVMSTAT 0x1a0
53
54 /* "legacy" flash memory protection registers (64KB max) */
55 #define FMPRE 0x130
56 #define FMPPE 0x134
57
58 /* new flash memory protection registers (for more than 64KB) */
59 #define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */
60 #define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */
61
62 #define USECRL 0x140
63
64 #define FLASH_CONTROL_BASE 0x400FD000
65 #define FLASH_FMA (FLASH_CONTROL_BASE | 0x000)
66 #define FLASH_FMD (FLASH_CONTROL_BASE | 0x004)
67 #define FLASH_FMC (FLASH_CONTROL_BASE | 0x008)
68 #define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C)
69 #define FLASH_CIM (FLASH_CONTROL_BASE | 0x010)
70 #define FLASH_MISC (FLASH_CONTROL_BASE | 0x014)
71
72 #define AMISC 1
73 #define PMISC 2
74
75 #define AMASK 1
76 #define PMASK 2
77
78 /* Flash Controller Command bits */
79 #define FMC_WRKEY (0xA442 << 16)
80 #define FMC_COMT (1 << 3)
81 #define FMC_MERASE (1 << 2)
82 #define FMC_ERASE (1 << 1)
83 #define FMC_WRITE (1 << 0)
84
85 /* STELLARIS constants */
86
87 /* values to write in FMA to commit write-"once" values */
88 #define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */
89 #define FLASH_FMA_PPE(x) (2 * (x) + 1) /* for FMPPPEx */
90
91
92 static void stellaris_read_clock_info(struct flash_bank *bank);
93 static int stellaris_mass_erase(struct flash_bank *bank);
94
95 struct stellaris_flash_bank
96 {
97 /* chip id register */
98 uint32_t did0;
99 uint32_t did1;
100 uint32_t dc0;
101 uint32_t dc1;
102
103 const char * target_name;
104
105 uint32_t sramsiz;
106 uint32_t flshsz;
107 /* flash geometry */
108 uint32_t num_pages;
109 uint32_t pagesize;
110 uint32_t pages_in_lockregion;
111
112 /* nv memory bits */
113 uint16_t num_lockbits;
114
115 /* main clock status */
116 uint32_t rcc;
117 uint32_t rcc2;
118 uint8_t mck_valid;
119 uint8_t xtal_mask;
120 uint32_t iosc_freq;
121 uint32_t mck_freq;
122 const char *iosc_desc;
123 const char *mck_desc;
124 };
125
126 // Autogenerated by contrib/gen-stellaris-part-header.pl
127 // From Stellaris Firmware Development Package revision 8049
128 static struct {
129 uint8_t class;
130 uint8_t partno;
131 const char *partname;
132 } StellarisParts[] = {
133 {0x00, 0x01, "LM3S101"},
134 {0x00, 0x02, "LM3S102"},
135 {0x01, 0xBF, "LM3S1110"},
136 {0x01, 0xC3, "LM3S1133"},
137 {0x01, 0xC5, "LM3S1138"},
138 {0x01, 0xC1, "LM3S1150"},
139 {0x01, 0xC4, "LM3S1162"},
140 {0x01, 0xC2, "LM3S1165"},
141 {0x01, 0xEC, "LM3S1166"},
142 {0x01, 0xC6, "LM3S1332"},
143 {0x01, 0xBC, "LM3S1435"},
144 {0x01, 0xBA, "LM3S1439"},
145 {0x01, 0xBB, "LM3S1512"},
146 {0x01, 0xC7, "LM3S1538"},
147 {0x01, 0xDB, "LM3S1601"},
148 {0x03, 0x06, "LM3S1607"},
149 {0x01, 0xDA, "LM3S1608"},
150 {0x01, 0xC0, "LM3S1620"},
151 {0x04, 0xCD, "LM3S1621"},
152 {0x03, 0x03, "LM3S1625"},
153 {0x03, 0x04, "LM3S1626"},
154 {0x03, 0x05, "LM3S1627"},
155 {0x01, 0xB3, "LM3S1635"},
156 {0x01, 0xEB, "LM3S1636"},
157 {0x01, 0xBD, "LM3S1637"},
158 {0x04, 0xB1, "LM3S1651"},
159 {0x01, 0xB9, "LM3S1751"},
160 {0x03, 0x10, "LM3S1776"},
161 {0x04, 0x16, "LM3S1811"},
162 {0x04, 0x3D, "LM3S1816"},
163 {0x01, 0xB4, "LM3S1850"},
164 {0x01, 0xDD, "LM3S1911"},
165 {0x01, 0xDC, "LM3S1918"},
166 {0x01, 0xB7, "LM3S1937"},
167 {0x01, 0xBE, "LM3S1958"},
168 {0x01, 0xB5, "LM3S1960"},
169 {0x01, 0xB8, "LM3S1968"},
170 {0x01, 0xEA, "LM3S1969"},
171 {0x04, 0xCE, "LM3S1B21"},
172 {0x06, 0xCA, "LM3S1C21"},
173 {0x06, 0xCB, "LM3S1C26"},
174 {0x06, 0x98, "LM3S1C58"},
175 {0x06, 0xB0, "LM3S1D21"},
176 {0x06, 0xCC, "LM3S1D26"},
177 {0x06, 0x1D, "LM3S1F11"},
178 {0x06, 0x1B, "LM3S1F16"},
179 {0x06, 0xAF, "LM3S1G21"},
180 {0x06, 0x95, "LM3S1G58"},
181 {0x06, 0x1E, "LM3S1H11"},
182 {0x06, 0x1C, "LM3S1H16"},
183 {0x04, 0x0F, "LM3S1J11"},
184 {0x04, 0x3C, "LM3S1J16"},
185 {0x04, 0x0E, "LM3S1N11"},
186 {0x04, 0x3B, "LM3S1N16"},
187 {0x04, 0xB2, "LM3S1P51"},
188 {0x04, 0x9E, "LM3S1R21"},
189 {0x04, 0xC9, "LM3S1R26"},
190 {0x04, 0x30, "LM3S1W16"},
191 {0x04, 0x2F, "LM3S1Z16"},
192 {0x01, 0xD4, "LM3S2016"},
193 {0x01, 0x51, "LM3S2110"},
194 {0x01, 0x84, "LM3S2139"},
195 {0x03, 0x39, "LM3S2276"},
196 {0x01, 0xA2, "LM3S2410"},
197 {0x01, 0x59, "LM3S2412"},
198 {0x01, 0x56, "LM3S2432"},
199 {0x01, 0x5A, "LM3S2533"},
200 {0x01, 0xE1, "LM3S2601"},
201 {0x01, 0xE0, "LM3S2608"},
202 {0x03, 0x33, "LM3S2616"},
203 {0x01, 0x57, "LM3S2620"},
204 {0x01, 0x85, "LM3S2637"},
205 {0x01, 0x53, "LM3S2651"},
206 {0x03, 0x80, "LM3S2671"},
207 {0x03, 0x50, "LM3S2678"},
208 {0x01, 0xA4, "LM3S2730"},
209 {0x01, 0x52, "LM3S2739"},
210 {0x03, 0x3A, "LM3S2776"},
211 {0x04, 0x6D, "LM3S2793"},
212 {0x01, 0xE3, "LM3S2911"},
213 {0x01, 0xE2, "LM3S2918"},
214 {0x01, 0xED, "LM3S2919"},
215 {0x01, 0x54, "LM3S2939"},
216 {0x01, 0x8F, "LM3S2948"},
217 {0x01, 0x58, "LM3S2950"},
218 {0x01, 0x55, "LM3S2965"},
219 {0x04, 0x6C, "LM3S2B93"},
220 {0x06, 0x94, "LM3S2D93"},
221 {0x06, 0x93, "LM3S2U93"},
222 {0x00, 0x19, "LM3S300"},
223 {0x00, 0x11, "LM3S301"},
224 {0x00, 0x1A, "LM3S308"},
225 {0x00, 0x12, "LM3S310"},
226 {0x00, 0x13, "LM3S315"},
227 {0x00, 0x14, "LM3S316"},
228 {0x00, 0x17, "LM3S317"},
229 {0x00, 0x15, "LM3S328"},
230 {0x03, 0x08, "LM3S3634"},
231 {0x03, 0x43, "LM3S3651"},
232 {0x04, 0xC8, "LM3S3654"},
233 {0x03, 0x44, "LM3S3739"},
234 {0x03, 0x49, "LM3S3748"},
235 {0x03, 0x45, "LM3S3749"},
236 {0x04, 0x42, "LM3S3826"},
237 {0x04, 0x41, "LM3S3J26"},
238 {0x04, 0x40, "LM3S3N26"},
239 {0x04, 0x3F, "LM3S3W26"},
240 {0x04, 0x3E, "LM3S3Z26"},
241 {0x03, 0x81, "LM3S5632"},
242 {0x04, 0x0C, "LM3S5651"},
243 {0x03, 0x8A, "LM3S5652"},
244 {0x04, 0x4D, "LM3S5656"},
245 {0x03, 0x91, "LM3S5662"},
246 {0x03, 0x96, "LM3S5732"},
247 {0x03, 0x97, "LM3S5737"},
248 {0x03, 0xA0, "LM3S5739"},
249 {0x03, 0x99, "LM3S5747"},
250 {0x03, 0xA7, "LM3S5749"},
251 {0x03, 0x9A, "LM3S5752"},
252 {0x03, 0x9C, "LM3S5762"},
253 {0x04, 0x69, "LM3S5791"},
254 {0x04, 0x0B, "LM3S5951"},
255 {0x04, 0x4E, "LM3S5956"},
256 {0x04, 0x68, "LM3S5B91"},
257 {0x06, 0x2E, "LM3S5C31"},
258 {0x06, 0x2C, "LM3S5C36"},
259 {0x06, 0x5E, "LM3S5C51"},
260 {0x06, 0x5B, "LM3S5C56"},
261 {0x06, 0x5F, "LM3S5D51"},
262 {0x06, 0x5C, "LM3S5D56"},
263 {0x06, 0x87, "LM3S5D91"},
264 {0x06, 0x2D, "LM3S5G31"},
265 {0x06, 0x1F, "LM3S5G36"},
266 {0x06, 0x5D, "LM3S5G51"},
267 {0x06, 0x4F, "LM3S5G56"},
268 {0x04, 0x09, "LM3S5K31"},
269 {0x04, 0x4A, "LM3S5K36"},
270 {0x04, 0x0A, "LM3S5P31"},
271 {0x04, 0x48, "LM3S5P36"},
272 {0x04, 0xB6, "LM3S5P3B"},
273 {0x04, 0x0D, "LM3S5P51"},
274 {0x04, 0x4C, "LM3S5P56"},
275 {0x04, 0x07, "LM3S5R31"},
276 {0x04, 0x4B, "LM3S5R36"},
277 {0x04, 0x47, "LM3S5T36"},
278 {0x06, 0x7F, "LM3S5U91"},
279 {0x04, 0x46, "LM3S5Y36"},
280 {0x00, 0x2A, "LM3S600"},
281 {0x00, 0x21, "LM3S601"},
282 {0x00, 0x2B, "LM3S608"},
283 {0x00, 0x22, "LM3S610"},
284 {0x01, 0xA1, "LM3S6100"},
285 {0x00, 0x23, "LM3S611"},
286 {0x01, 0x74, "LM3S6110"},
287 {0x00, 0x24, "LM3S612"},
288 {0x00, 0x25, "LM3S613"},
289 {0x00, 0x26, "LM3S615"},
290 {0x00, 0x28, "LM3S617"},
291 {0x00, 0x29, "LM3S618"},
292 {0x00, 0x27, "LM3S628"},
293 {0x01, 0xA5, "LM3S6420"},
294 {0x01, 0x82, "LM3S6422"},
295 {0x01, 0x75, "LM3S6432"},
296 {0x01, 0x76, "LM3S6537"},
297 {0x01, 0x71, "LM3S6610"},
298 {0x01, 0xE7, "LM3S6611"},
299 {0x01, 0xE6, "LM3S6618"},
300 {0x01, 0x83, "LM3S6633"},
301 {0x01, 0x8B, "LM3S6637"},
302 {0x01, 0xA3, "LM3S6730"},
303 {0x01, 0x77, "LM3S6753"},
304 {0x01, 0xD1, "LM3S6816"},
305 {0x01, 0xE9, "LM3S6911"},
306 {0x01, 0xD3, "LM3S6916"},
307 {0x01, 0xE8, "LM3S6918"},
308 {0x01, 0x89, "LM3S6938"},
309 {0x01, 0x72, "LM3S6950"},
310 {0x01, 0x78, "LM3S6952"},
311 {0x01, 0x73, "LM3S6965"},
312 {0x06, 0xAA, "LM3S6C11"},
313 {0x06, 0xAC, "LM3S6C65"},
314 {0x06, 0x9F, "LM3S6G11"},
315 {0x06, 0xAB, "LM3S6G65"},
316 {0x00, 0x38, "LM3S800"},
317 {0x00, 0x31, "LM3S801"},
318 {0x00, 0x39, "LM3S808"},
319 {0x00, 0x32, "LM3S811"},
320 {0x00, 0x33, "LM3S812"},
321 {0x00, 0x34, "LM3S815"},
322 {0x00, 0x36, "LM3S817"},
323 {0x00, 0x37, "LM3S818"},
324 {0x00, 0x35, "LM3S828"},
325 {0x01, 0x64, "LM3S8530"},
326 {0x01, 0x8E, "LM3S8538"},
327 {0x01, 0x61, "LM3S8630"},
328 {0x01, 0x63, "LM3S8730"},
329 {0x01, 0x8D, "LM3S8733"},
330 {0x01, 0x86, "LM3S8738"},
331 {0x01, 0x65, "LM3S8930"},
332 {0x01, 0x8C, "LM3S8933"},
333 {0x01, 0x88, "LM3S8938"},
334 {0x01, 0xA6, "LM3S8962"},
335 {0x01, 0x62, "LM3S8970"},
336 {0x01, 0xD7, "LM3S8971"},
337 {0x06, 0xAE, "LM3S8C62"},
338 {0x06, 0xAD, "LM3S8G62"},
339 {0x04, 0xCF, "LM3S9781"},
340 {0x04, 0x67, "LM3S9790"},
341 {0x04, 0x6B, "LM3S9792"},
342 {0x04, 0x2D, "LM3S9971"},
343 {0x04, 0x20, "LM3S9997"},
344 {0x04, 0xD0, "LM3S9B81"},
345 {0x04, 0x66, "LM3S9B90"},
346 {0x04, 0x6A, "LM3S9B92"},
347 {0x04, 0x6E, "LM3S9B95"},
348 {0x04, 0x6F, "LM3S9B96"},
349 {0x04, 0x1D, "LM3S9BN2"},
350 {0x04, 0x1E, "LM3S9BN5"},
351 {0x04, 0x1F, "LM3S9BN6"},
352 {0x06, 0x70, "LM3S9C97"},
353 {0x06, 0x7A, "LM3S9CN5"},
354 {0x06, 0xA9, "LM3S9D81"},
355 {0x06, 0x7E, "LM3S9D90"},
356 {0x06, 0x92, "LM3S9D92"},
357 {0x06, 0xC8, "LM3S9D95"},
358 {0x06, 0x9D, "LM3S9D96"},
359 {0x06, 0x7B, "LM3S9DN5"},
360 {0x06, 0x7C, "LM3S9DN6"},
361 {0x06, 0x60, "LM3S9G97"},
362 {0x06, 0x79, "LM3S9GN5"},
363 {0x04, 0x1B, "LM3S9L71"},
364 {0x04, 0x18, "LM3S9L97"},
365 {0x06, 0xA8, "LM3S9U81"},
366 {0x06, 0x7D, "LM3S9U90"},
367 {0x06, 0x90, "LM3S9U92"},
368 {0x06, 0xB7, "LM3S9U95"},
369 {0x06, 0x9B, "LM3S9U96"},
370 {0x05, 0x18, "LM4F110B2QR"},
371 {0x05, 0x19, "LM4F110C4QR"},
372 {0x05, 0x10, "LM4F110E5QR"},
373 {0x05, 0x11, "LM4F110H5QR"},
374 {0x05, 0x22, "LM4F111B2QR"},
375 {0x05, 0x23, "LM4F111C4QR"},
376 {0x05, 0x20, "LM4F111E5QR"},
377 {0x05, 0x21, "LM4F111H5QR"},
378 {0x05, 0x36, "LM4F112C4QC"},
379 {0x05, 0x30, "LM4F112E5QC"},
380 {0x05, 0x31, "LM4F112H5QC"},
381 {0x05, 0x35, "LM4F112H5QD"},
382 {0x05, 0x01, "LM4F120B2QR"},
383 {0x05, 0x02, "LM4F120C4QR"},
384 {0x05, 0x03, "LM4F120E5QR"},
385 {0x05, 0x04, "LM4F120H5QR"},
386 {0x05, 0x08, "LM4F121B2QR"},
387 {0x05, 0x09, "LM4F121C4QR"},
388 {0x05, 0x0A, "LM4F121E5QR"},
389 {0x05, 0x0B, "LM4F121H5QR"},
390 {0x05, 0xD0, "LM4F122C4QC"},
391 {0x05, 0xD1, "LM4F122E5QC"},
392 {0x05, 0xD2, "LM4F122H5QC"},
393 {0x05, 0xD6, "LM4F122H5QD"},
394 {0x05, 0x48, "LM4F130C4QR"},
395 {0x05, 0x40, "LM4F130E5QR"},
396 {0x05, 0x41, "LM4F130H5QR"},
397 {0x05, 0x52, "LM4F131C4QR"},
398 {0x05, 0x50, "LM4F131E5QR"},
399 {0x05, 0x51, "LM4F131H5QR"},
400 {0x05, 0x66, "LM4F132C4QC"},
401 {0x05, 0x60, "LM4F132E5QC"},
402 {0x05, 0x61, "LM4F132H5QC"},
403 {0x05, 0x65, "LM4F132H5QD"},
404 {0x05, 0xA0, "LM4F230E5QR"},
405 {0x05, 0xA1, "LM4F230H5QR"},
406 {0x05, 0xB0, "LM4F231E5QR"},
407 {0x05, 0xB1, "LM4F231H5QR"},
408 {0x05, 0xC0, "LM4F232E5QC"},
409 {0x05, 0xE3, "LM4F232H5BB"},
410 {0x05, 0xC1, "LM4F232H5QC"},
411 {0x05, 0xC5, "LM4F232H5QD"},
412 {0x05, 0xE5, "LM4FS1AH5BB"},
413 {0x05, 0xE4, "LM4FS99H5BB"},
414 {0x05, 0xE0, "LM4FSXAH5BB"},
415 {0xFF, 0x00, "Unknown Part"}
416 };
417
418 static char * StellarisClassname[7] =
419 {
420 "Sandstorm",
421 "Fury",
422 "Unknown",
423 "DustDevil",
424 "Tempest",
425 "Blizzard",
426 "Firestorm"
427 };
428
429 /***************************************************************************
430 * openocd command interface *
431 ***************************************************************************/
432
433 /* flash_bank stellaris <base> <size> 0 0 <target#>
434 */
435 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command)
436 {
437 struct stellaris_flash_bank *stellaris_info;
438
439 if (CMD_ARGC < 6)
440 {
441 return ERROR_COMMAND_SYNTAX_ERROR;
442 }
443
444 stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
445 bank->base = 0x0;
446 bank->driver_priv = stellaris_info;
447
448 stellaris_info->target_name = "Unknown target";
449
450 /* part wasn't probed for info yet */
451 stellaris_info->did1 = 0;
452
453 /* TODO Specify the main crystal speed in kHz using an optional
454 * argument; ditto, the speed of an external oscillator used
455 * instead of a crystal. Avoid programming flash using IOSC.
456 */
457 return ERROR_OK;
458 }
459
460 static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size)
461 {
462 int printed, device_class;
463 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
464
465 if (stellaris_info->did1 == 0)
466 return ERROR_FLASH_BANK_NOT_PROBED;
467
468 /* Read main and master clock freqency register */
469 stellaris_read_clock_info(bank);
470
471 if (DID0_VER(stellaris_info->did0) > 0)
472 {
473 device_class = (stellaris_info->did0 >> 16) & 0xFF;
474 }
475 else
476 {
477 device_class = 0;
478 }
479 printed = snprintf(buf,
480 buf_size,
481 "\nTI/LMI Stellaris information: Chip is "
482 "class %i (%s) %s rev %c%i\n",
483 device_class,
484 StellarisClassname[device_class],
485 stellaris_info->target_name,
486 (int)('A' + ((stellaris_info->did0 >> 8) & 0xFF)),
487 (int)((stellaris_info->did0) & 0xFF));
488 buf += printed;
489 buf_size -= printed;
490
491 printed = snprintf(buf,
492 buf_size,
493 "did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32
494 ", eproc: %s, ramsize: %ik, flashsize: %ik\n",
495 stellaris_info->did1,
496 stellaris_info->did1,
497 "ARMv7M",
498 (int)((1 + ((stellaris_info->dc0 >> 16) & 0xFFFF))/4),
499 (int)((1 + (stellaris_info->dc0 & 0xFFFF))*2));
500 buf += printed;
501 buf_size -= printed;
502
503 printed = snprintf(buf,
504 buf_size,
505 "master clock: %ikHz%s, "
506 "rcc is 0x%" PRIx32 ", rcc2 is 0x%" PRIx32 "\n",
507 (int)(stellaris_info->mck_freq / 1000),
508 stellaris_info->mck_desc,
509 stellaris_info->rcc,
510 stellaris_info->rcc2);
511 buf += printed;
512 buf_size -= printed;
513
514 if (stellaris_info->num_lockbits > 0)
515 {
516 snprintf(buf,
517 buf_size,
518 "pagesize: %" PRIi32 ", pages: %d, "
519 "lockbits: %i, pages per lockbit: %i\n",
520 stellaris_info->pagesize,
521 (unsigned) stellaris_info->num_pages,
522 stellaris_info->num_lockbits,
523 (unsigned) stellaris_info->pages_in_lockregion);
524 }
525 return ERROR_OK;
526 }
527
528 /***************************************************************************
529 * chip identification and status *
530 ***************************************************************************/
531
532 /* Set the flash timimg register to match current clocking */
533 static void stellaris_set_flash_timing(struct flash_bank *bank)
534 {
535 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
536 struct target *target = bank->target;
537 uint32_t usecrl = (stellaris_info->mck_freq/1000000ul-1);
538
539 LOG_DEBUG("usecrl = %i",(int)(usecrl));
540 target_write_u32(target, SCB_BASE | USECRL, usecrl);
541 }
542
543 static const unsigned rcc_xtal[32] = {
544 [0x00] = 1000000, /* no pll */
545 [0x01] = 1843200, /* no pll */
546 [0x02] = 2000000, /* no pll */
547 [0x03] = 2457600, /* no pll */
548
549 [0x04] = 3579545,
550 [0x05] = 3686400,
551 [0x06] = 4000000, /* usb */
552 [0x07] = 4096000,
553
554 [0x08] = 4915200,
555 [0x09] = 5000000, /* usb */
556 [0x0a] = 5120000,
557 [0x0b] = 6000000, /* (reset) usb */
558
559 [0x0c] = 6144000,
560 [0x0d] = 7372800,
561 [0x0e] = 8000000, /* usb */
562 [0x0f] = 8192000,
563
564 /* parts before DustDevil use just 4 bits for xtal spec */
565
566 [0x10] = 10000000, /* usb */
567 [0x11] = 12000000, /* usb */
568 [0x12] = 12288000,
569 [0x13] = 13560000,
570
571 [0x14] = 14318180,
572 [0x15] = 16000000, /* usb */
573 [0x16] = 16384000,
574 };
575
576 /** Read clock configuration and set stellaris_info->usec_clocks. */
577 static void stellaris_read_clock_info(struct flash_bank *bank)
578 {
579 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
580 struct target *target = bank->target;
581 uint32_t rcc, rcc2, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
582 unsigned xtal;
583 unsigned long mainfreq;
584
585 target_read_u32(target, SCB_BASE | RCC, &rcc);
586 LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc);
587
588 target_read_u32(target, SCB_BASE | RCC2, &rcc2);
589 LOG_DEBUG("Stellaris RCC2 %" PRIx32 "", rcc);
590
591 target_read_u32(target, SCB_BASE | PLLCFG, &pllcfg);
592 LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg);
593
594 stellaris_info->rcc = rcc;
595 stellaris_info->rcc = rcc2;
596
597 sysdiv = (rcc >> 23) & 0xF;
598 usesysdiv = (rcc >> 22) & 0x1;
599 bypass = (rcc >> 11) & 0x1;
600 oscsrc = (rcc >> 4) & 0x3;
601 xtal = (rcc >> 6) & stellaris_info->xtal_mask;
602
603 /* NOTE: post-Sandstorm parts have RCC2 which may override
604 * parts of RCC ... with more sysdiv options, option for
605 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
606 * as zero, so the "use RCC2" flag is always clear.
607 */
608 if (rcc2 & (1 << 31)) {
609 sysdiv = (rcc2 >> 23) & 0x3F;
610 bypass = (rcc2 >> 11) & 0x1;
611 oscsrc = (rcc2 >> 4) & 0x7;
612
613 /* FIXME Tempest parts have an additional lsb for
614 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
615 */
616 }
617
618 stellaris_info->mck_desc = "";
619
620 switch (oscsrc)
621 {
622 case 0: /* MOSC */
623 mainfreq = rcc_xtal[xtal];
624 break;
625 case 1: /* IOSC */
626 mainfreq = stellaris_info->iosc_freq;
627 stellaris_info->mck_desc = stellaris_info->iosc_desc;
628 break;
629 case 2: /* IOSC/4 */
630 mainfreq = stellaris_info->iosc_freq / 4;
631 stellaris_info->mck_desc = stellaris_info->iosc_desc;
632 break;
633 case 3: /* lowspeed */
634 /* Sandstorm doesn't have this 30K +/- 30% osc */
635 mainfreq = 30000;
636 stellaris_info->mck_desc = " (±30%)";
637 break;
638 case 8: /* hibernation osc */
639 /* not all parts support hibernation */
640 mainfreq = 32768;
641 break;
642
643 default: /* NOTREACHED */
644 mainfreq = 0;
645 break;
646 }
647
648 /* PLL is used if it's not bypassed; its output is 200 MHz
649 * even when it runs at 400 MHz (adds divide-by-two stage).
650 */
651 if (!bypass)
652 mainfreq = 200000000;
653
654 if (usesysdiv)
655 stellaris_info->mck_freq = mainfreq/(1 + sysdiv);
656 else
657 stellaris_info->mck_freq = mainfreq;
658 }
659
660 /* Read device id register, main clock frequency register and fill in driver info structure */
661 static int stellaris_read_part_info(struct flash_bank *bank)
662 {
663 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
664 struct target *target = bank->target;
665 uint32_t did0, did1, ver, fam;
666 int i;
667
668 /* Read and parse chip identification register */
669 target_read_u32(target, SCB_BASE | DID0, &did0);
670 target_read_u32(target, SCB_BASE | DID1, &did1);
671 target_read_u32(target, SCB_BASE | DC0, &stellaris_info->dc0);
672 target_read_u32(target, SCB_BASE | DC1, &stellaris_info->dc1);
673 LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32 "",
674 did0, did1, stellaris_info->dc0, stellaris_info->dc1);
675
676 ver = did0 >> 28;
677 if ((ver != 0) && (ver != 1))
678 {
679 LOG_WARNING("Unknown did0 version, cannot identify target");
680 return ERROR_FLASH_OPERATION_FAILED;
681 }
682
683 if (did1 == 0)
684 {
685 LOG_WARNING("Cannot identify target as a Stellaris");
686 return ERROR_FLASH_OPERATION_FAILED;
687 }
688
689 ver = did1 >> 28;
690 fam = (did1 >> 24) & 0xF;
691 if (((ver != 0) && (ver != 1)) || (fam != 0))
692 {
693 LOG_WARNING("Unknown did1 version/family.");
694 return ERROR_FLASH_OPERATION_FAILED;
695 }
696
697 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
698 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
699 * even give _both_ numbers! We'll use current numbers; IOSC is
700 * always approximate.
701 *
702 * For Tempest: IOSC is calibrated, 16 MHz
703 */
704 stellaris_info->iosc_freq = 12000000;
705 stellaris_info->iosc_desc = " (±30%)";
706 stellaris_info->xtal_mask = 0x0f;
707
708 switch ((did0 >> 28) & 0x7) {
709 case 0: /* Sandstorm */
710 /*
711 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
712 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
713 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
714 */
715 if (((did0 >> 8) & 0xff) < 2) {
716 stellaris_info->iosc_freq = 15000000;
717 stellaris_info->iosc_desc = " (±50%)";
718 }
719 break;
720 case 1:
721 switch ((did0 >> 16) & 0xff) {
722 case 1: /* Fury */
723 break;
724 case 4: /* Tempest */
725 stellaris_info->iosc_freq = 16000000; /* +/- 1% */
726 stellaris_info->iosc_desc = " (±1%)";
727 /* FALL THROUGH */
728 case 3: /* DustDevil */
729 stellaris_info->xtal_mask = 0x1f;
730 break;
731 default:
732 LOG_WARNING("Unknown did0 class");
733 }
734 break;
735 default:
736 LOG_WARNING("Unknown did0 version");
737 break;
738 }
739
740 for (i = 0; StellarisParts[i].partno; i++)
741 {
742 if ((StellarisParts[i].partno == ((did1 >> 16) & 0xFF)) &&
743 (StellarisParts[i].class == ((did0 >> 16) & 0xFF)))
744 break;
745 }
746
747 stellaris_info->target_name = StellarisParts[i].partname;
748
749 stellaris_info->did0 = did0;
750 stellaris_info->did1 = did1;
751
752 stellaris_info->num_lockbits = 1 + (stellaris_info->dc0 & 0xFFFF);
753 stellaris_info->num_pages = 2 *(1 + (stellaris_info->dc0 & 0xFFFF));
754 stellaris_info->pagesize = 1024;
755 stellaris_info->pages_in_lockregion = 2;
756
757 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
758 * That exposes a 32-word Flash Write Buffer ... enabling
759 * writes of more than one word at a time.
760 */
761
762 return ERROR_OK;
763 }
764
765 /***************************************************************************
766 * flash operations *
767 ***************************************************************************/
768
769 static int stellaris_protect_check(struct flash_bank *bank)
770 {
771 struct stellaris_flash_bank *stellaris = bank->driver_priv;
772 int status = ERROR_OK;
773 unsigned i;
774 unsigned page;
775
776 if (stellaris->did1 == 0)
777 return ERROR_FLASH_BANK_NOT_PROBED;
778
779 for (i = 0; i < (unsigned) bank->num_sectors; i++)
780 bank->sectors[i].is_protected = -1;
781
782 /* Read each Flash Memory Protection Program Enable (FMPPE) register
783 * to report any pages that we can't write. Ignore the Read Enable
784 * register (FMPRE).
785 */
786 for (i = 0, page = 0;
787 i < DIV_ROUND_UP(stellaris->num_lockbits, 32u);
788 i++) {
789 uint32_t lockbits;
790
791 status = target_read_u32(bank->target,
792 SCB_BASE + (i ? (FMPPE0 + 4 * i) : FMPPE),
793 &lockbits);
794 LOG_DEBUG("FMPPE%d = %#8.8x (status %d)", i,
795 (unsigned) lockbits, status);
796 if (status != ERROR_OK)
797 goto done;
798
799 for (unsigned j = 0; j < 32; j++) {
800 unsigned k;
801
802 for (k = 0; k < stellaris->pages_in_lockregion; k++) {
803 if (page >= (unsigned) bank->num_sectors)
804 goto done;
805 bank->sectors[page++].is_protected =
806 !(lockbits & (1 << j));
807 }
808 }
809 }
810
811 done:
812 return status;
813 }
814
815 static int stellaris_erase(struct flash_bank *bank, int first, int last)
816 {
817 int banknr;
818 uint32_t flash_fmc, flash_cris;
819 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
820 struct target *target = bank->target;
821
822 if (bank->target->state != TARGET_HALTED)
823 {
824 LOG_ERROR("Target not halted");
825 return ERROR_TARGET_NOT_HALTED;
826 }
827
828 if (stellaris_info->did1 == 0)
829 return ERROR_FLASH_BANK_NOT_PROBED;
830
831 if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
832 {
833 return ERROR_FLASH_SECTOR_INVALID;
834 }
835
836 if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
837 {
838 return stellaris_mass_erase(bank);
839 }
840
841 /* Refresh flash controller timing */
842 stellaris_read_clock_info(bank);
843 stellaris_set_flash_timing(bank);
844
845 /* Clear and disable flash programming interrupts */
846 target_write_u32(target, FLASH_CIM, 0);
847 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
848
849 /* REVISIT this clobbers state set by any halted firmware ...
850 * it might want to process those IRQs.
851 */
852
853 for (banknr = first; banknr <= last; banknr++)
854 {
855 /* Address is first word in page */
856 target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
857 /* Write erase command */
858 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
859 /* Wait until erase complete */
860 do
861 {
862 target_read_u32(target, FLASH_FMC, &flash_fmc);
863 }
864 while (flash_fmc & FMC_ERASE);
865
866 /* Check acess violations */
867 target_read_u32(target, FLASH_CRIS, &flash_cris);
868 if (flash_cris & (AMASK))
869 {
870 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", banknr, flash_cris);
871 target_write_u32(target, FLASH_CRIS, 0);
872 return ERROR_FLASH_OPERATION_FAILED;
873 }
874
875 bank->sectors[banknr].is_erased = 1;
876 }
877
878 return ERROR_OK;
879 }
880
881 static int stellaris_protect(struct flash_bank *bank, int set, int first, int last)
882 {
883 uint32_t fmppe, flash_fmc, flash_cris;
884 int lockregion;
885
886 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
887 struct target *target = bank->target;
888
889 if (bank->target->state != TARGET_HALTED)
890 {
891 LOG_ERROR("Target not halted");
892 return ERROR_TARGET_NOT_HALTED;
893 }
894
895 if (!set)
896 {
897 LOG_ERROR("Hardware doesn't support page-level unprotect. "
898 "Try the 'recover' command.");
899 return ERROR_COMMAND_SYNTAX_ERROR;
900 }
901
902 if (stellaris_info->did1 == 0)
903 return ERROR_FLASH_BANK_NOT_PROBED;
904
905 /* lockregions are 2 pages ... must protect [even..odd] */
906 if ((first < 0) || (first & 1)
907 || (last < first) || !(last & 1)
908 || (last >= 2 * stellaris_info->num_lockbits))
909 {
910 LOG_ERROR("Can't protect unaligned or out-of-range pages.");
911 return ERROR_FLASH_SECTOR_INVALID;
912 }
913
914 /* Refresh flash controller timing */
915 stellaris_read_clock_info(bank);
916 stellaris_set_flash_timing(bank);
917
918 /* convert from pages to lockregions */
919 first /= 2;
920 last /= 2;
921
922 /* FIXME this assumes single FMPPE, for a max of 64K of flash!!
923 * Current parts can be much bigger.
924 */
925 if (last >= 32) {
926 LOG_ERROR("No support yet for protection > 64K");
927 return ERROR_FLASH_OPERATION_FAILED;
928 }
929
930 target_read_u32(target, SCB_BASE | FMPPE, &fmppe);
931
932 for (lockregion = first; lockregion <= last; lockregion++)
933 fmppe &= ~(1 << lockregion);
934
935 /* Clear and disable flash programming interrupts */
936 target_write_u32(target, FLASH_CIM, 0);
937 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
938
939 /* REVISIT this clobbers state set by any halted firmware ...
940 * it might want to process those IRQs.
941 */
942
943 LOG_DEBUG("fmppe 0x%" PRIx32 "",fmppe);
944 target_write_u32(target, SCB_BASE | FMPPE, fmppe);
945
946 /* Commit FMPPE */
947 target_write_u32(target, FLASH_FMA, 1);
948
949 /* Write commit command */
950 /* REVISIT safety check, since this cannot be undone
951 * except by the "Recover a locked device" procedure.
952 * REVISIT DustDevil-A0 parts have an erratum making FMPPE commits
953 * inadvisable ... it makes future mass erase operations fail.
954 */
955 LOG_WARNING("Flash protection cannot be removed once committed, commit is NOT executed !");
956 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
957
958 /* Wait until erase complete */
959 do
960 {
961 target_read_u32(target, FLASH_FMC, &flash_fmc);
962 }
963 while (flash_fmc & FMC_COMT);
964
965 /* Check acess violations */
966 target_read_u32(target, FLASH_CRIS, &flash_cris);
967 if (flash_cris & (AMASK))
968 {
969 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
970 target_write_u32(target, FLASH_CRIS, 0);
971 return ERROR_FLASH_OPERATION_FAILED;
972 }
973
974 return ERROR_OK;
975 }
976
977 /* see contib/loaders/flash/stellaris.s for src */
978
979 static const uint8_t stellaris_write_code[] =
980 {
981 /*
982 Call with :
983 r0 = buffer address
984 r1 = destination address
985 r2 = bytecount (in) - endaddr (work)
986
987 Used registers:
988 r3 = pFLASH_CTRL_BASE
989 r4 = FLASHWRITECMD
990 r5 = #1
991 r6 = bytes written
992 r7 = temp reg
993 */
994 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
995 0x08,0x4C, /* ldr r4,FLASHWRITECMD */
996 0x01,0x25, /* movs r5, 1 */
997 0x00,0x26, /* movs r6, #0 */
998 /* mainloop: */
999 0x19,0x60, /* str r1, [r3, #0] */
1000 0x87,0x59, /* ldr r7, [r0, r6] */
1001 0x5F,0x60, /* str r7, [r3, #4] */
1002 0x9C,0x60, /* str r4, [r3, #8] */
1003 /* waitloop: */
1004 0x9F,0x68, /* ldr r7, [r3, #8] */
1005 0x2F,0x42, /* tst r7, r5 */
1006 0xFC,0xD1, /* bne waitloop */
1007 0x04,0x31, /* adds r1, r1, #4 */
1008 0x04,0x36, /* adds r6, r6, #4 */
1009 0x96,0x42, /* cmp r6, r2 */
1010 0xF4,0xD1, /* bne mainloop */
1011 0x00,0xBE, /* bkpt #0 */
1012 /* pFLASH_CTRL_BASE: */
1013 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
1014 /* FLASHWRITECMD: */
1015 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
1016 };
1017
1018 static int stellaris_write_block(struct flash_bank *bank,
1019 uint8_t *buffer, uint32_t offset, uint32_t wcount)
1020 {
1021 struct target *target = bank->target;
1022 uint32_t buffer_size = 16384;
1023 struct working_area *source;
1024 struct working_area *write_algorithm;
1025 uint32_t address = bank->base + offset;
1026 struct reg_param reg_params[3];
1027 struct armv7m_algorithm armv7m_info;
1028 int retval = ERROR_OK;
1029
1030 /* power of two, and multiple of word size */
1031 static const unsigned buf_min = 128;
1032
1033 /* for small buffers it's faster not to download an algorithm */
1034 if (wcount * 4 < buf_min)
1035 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1036
1037 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
1038 bank, buffer, offset, wcount);
1039
1040 /* flash write code */
1041 if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
1042 {
1043 LOG_DEBUG("no working area for block memory writes");
1044 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1045 };
1046
1047 /* plus a buffer big enough for this data */
1048 if (wcount * 4 < buffer_size)
1049 buffer_size = wcount * 4;
1050
1051 /* memory buffer */
1052 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
1053 {
1054 buffer_size /= 2;
1055 if (buffer_size <= buf_min)
1056 {
1057 target_free_working_area(target, write_algorithm);
1058 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1059 }
1060 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1061 target_name(target), (unsigned) buffer_size);
1062 };
1063
1064 retval = target_write_buffer(target, write_algorithm->address,
1065 sizeof(stellaris_write_code),
1066 (uint8_t *) stellaris_write_code);
1067
1068 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
1069 armv7m_info.core_mode = ARMV7M_MODE_ANY;
1070
1071 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
1072 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
1073 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
1074
1075 while (wcount > 0)
1076 {
1077 uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
1078
1079 target_write_buffer(target, source->address, thisrun_count * 4, buffer);
1080
1081 buf_set_u32(reg_params[0].value, 0, 32, source->address);
1082 buf_set_u32(reg_params[1].value, 0, 32, address);
1083 buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
1084 LOG_DEBUG("Algorithm flash write %u words to 0x%" PRIx32
1085 ", %u remaining",
1086 (unsigned) thisrun_count, address,
1087 (unsigned) (wcount - thisrun_count));
1088 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
1089 write_algorithm->address,
1090 0,
1091 10000, &armv7m_info);
1092 if (retval != ERROR_OK)
1093 {
1094 LOG_ERROR("error %d executing stellaris "
1095 "flash write algorithm",
1096 retval);
1097 retval = ERROR_FLASH_OPERATION_FAILED;
1098 break;
1099 }
1100
1101 buffer += thisrun_count * 4;
1102 address += thisrun_count * 4;
1103 wcount -= thisrun_count;
1104 }
1105
1106 /* REVISIT we could speed up writing multi-section images by
1107 * not freeing the initialized write_algorithm this way.
1108 */
1109
1110 target_free_working_area(target, write_algorithm);
1111 target_free_working_area(target, source);
1112
1113 destroy_reg_param(&reg_params[0]);
1114 destroy_reg_param(&reg_params[1]);
1115 destroy_reg_param(&reg_params[2]);
1116
1117 return retval;
1118 }
1119
1120 static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
1121 {
1122 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1123 struct target *target = bank->target;
1124 uint32_t address = offset;
1125 uint32_t flash_cris, flash_fmc;
1126 uint32_t words_remaining = (count / 4);
1127 uint32_t bytes_remaining = (count & 0x00000003);
1128 uint32_t bytes_written = 0;
1129 int retval;
1130
1131 if (bank->target->state != TARGET_HALTED)
1132 {
1133 LOG_ERROR("Target not halted");
1134 return ERROR_TARGET_NOT_HALTED;
1135 }
1136
1137 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
1138 bank, buffer, offset, count);
1139
1140 if (stellaris_info->did1 == 0)
1141 return ERROR_FLASH_BANK_NOT_PROBED;
1142
1143 if (offset & 0x3)
1144 {
1145 LOG_WARNING("offset size must be word aligned");
1146 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1147 }
1148
1149 if (offset + count > bank->size)
1150 return ERROR_FLASH_DST_OUT_OF_BANK;
1151
1152 /* Refresh flash controller timing */
1153 stellaris_read_clock_info(bank);
1154 stellaris_set_flash_timing(bank);
1155
1156 /* Clear and disable flash programming interrupts */
1157 target_write_u32(target, FLASH_CIM, 0);
1158 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1159
1160 /* REVISIT this clobbers state set by any halted firmware ...
1161 * it might want to process those IRQs.
1162 */
1163
1164 /* multiple words to be programmed? */
1165 if (words_remaining > 0)
1166 {
1167 /* try using a block write */
1168 retval = stellaris_write_block(bank, buffer, offset,
1169 words_remaining);
1170 if (retval != ERROR_OK)
1171 {
1172 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
1173 {
1174 LOG_DEBUG("writing flash word-at-a-time");
1175 }
1176 else if (retval == ERROR_FLASH_OPERATION_FAILED)
1177 {
1178 /* if an error occured, we examine the reason, and quit */
1179 target_read_u32(target, FLASH_CRIS, &flash_cris);
1180
1181 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
1182 return ERROR_FLASH_OPERATION_FAILED;
1183 }
1184 }
1185 else
1186 {
1187 buffer += words_remaining * 4;
1188 address += words_remaining * 4;
1189 words_remaining = 0;
1190 }
1191 }
1192
1193 while (words_remaining > 0)
1194 {
1195 if (!(address & 0xff))
1196 LOG_DEBUG("0x%" PRIx32 "", address);
1197
1198 /* Program one word */
1199 target_write_u32(target, FLASH_FMA, address);
1200 target_write_buffer(target, FLASH_FMD, 4, buffer);
1201 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1202 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1203 /* Wait until write complete */
1204 do
1205 {
1206 target_read_u32(target, FLASH_FMC, &flash_fmc);
1207 } while (flash_fmc & FMC_WRITE);
1208
1209 buffer += 4;
1210 address += 4;
1211 words_remaining--;
1212 }
1213
1214 if (bytes_remaining)
1215 {
1216 uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
1217
1218 /* copy the last remaining bytes into the write buffer */
1219 memcpy(last_word, buffer+bytes_written, bytes_remaining);
1220
1221 if (!(address & 0xff))
1222 LOG_DEBUG("0x%" PRIx32 "", address);
1223
1224 /* Program one word */
1225 target_write_u32(target, FLASH_FMA, address);
1226 target_write_buffer(target, FLASH_FMD, 4, last_word);
1227 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1228 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1229 /* Wait until write complete */
1230 do
1231 {
1232 target_read_u32(target, FLASH_FMC, &flash_fmc);
1233 } while (flash_fmc & FMC_WRITE);
1234 }
1235
1236 /* Check access violations */
1237 target_read_u32(target, FLASH_CRIS, &flash_cris);
1238 if (flash_cris & (AMASK))
1239 {
1240 LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
1241 return ERROR_FLASH_OPERATION_FAILED;
1242 }
1243 return ERROR_OK;
1244 }
1245
1246 static int stellaris_probe(struct flash_bank *bank)
1247 {
1248 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1249 int retval;
1250
1251 /* If this is a stellaris chip, it has flash; probe() is just
1252 * to figure out how much is present. Only do it once.
1253 */
1254 if (stellaris_info->did1 != 0)
1255 return ERROR_OK;
1256
1257 /* stellaris_read_part_info() already handled error checking and
1258 * reporting. Note that it doesn't write, so we don't care about
1259 * whether the target is halted or not.
1260 */
1261 retval = stellaris_read_part_info(bank);
1262 if (retval != ERROR_OK)
1263 return retval;
1264
1265 if (bank->sectors)
1266 {
1267 free(bank->sectors);
1268 bank->sectors = NULL;
1269 }
1270
1271 /* provide this for the benefit of the NOR flash framework */
1272 bank->size = 1024 * stellaris_info->num_pages;
1273 bank->num_sectors = stellaris_info->num_pages;
1274 bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
1275 for (int i = 0; i < bank->num_sectors; i++)
1276 {
1277 bank->sectors[i].offset = i * stellaris_info->pagesize;
1278 bank->sectors[i].size = stellaris_info->pagesize;
1279 bank->sectors[i].is_erased = -1;
1280 bank->sectors[i].is_protected = -1;
1281 }
1282
1283 return retval;
1284 }
1285
1286 static int stellaris_mass_erase(struct flash_bank *bank)
1287 {
1288 struct target *target = NULL;
1289 struct stellaris_flash_bank *stellaris_info = NULL;
1290 uint32_t flash_fmc;
1291
1292 stellaris_info = bank->driver_priv;
1293 target = bank->target;
1294
1295 if (target->state != TARGET_HALTED)
1296 {
1297 LOG_ERROR("Target not halted");
1298 return ERROR_TARGET_NOT_HALTED;
1299 }
1300
1301 if (stellaris_info->did1 == 0)
1302 return ERROR_FLASH_BANK_NOT_PROBED;
1303
1304 /* Refresh flash controller timing */
1305 stellaris_read_clock_info(bank);
1306 stellaris_set_flash_timing(bank);
1307
1308 /* Clear and disable flash programming interrupts */
1309 target_write_u32(target, FLASH_CIM, 0);
1310 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1311
1312 /* REVISIT this clobbers state set by any halted firmware ...
1313 * it might want to process those IRQs.
1314 */
1315
1316 target_write_u32(target, FLASH_FMA, 0);
1317 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1318 /* Wait until erase complete */
1319 do
1320 {
1321 target_read_u32(target, FLASH_FMC, &flash_fmc);
1322 }
1323 while (flash_fmc & FMC_MERASE);
1324
1325 /* if device has > 128k, then second erase cycle is needed
1326 * this is only valid for older devices, but will not hurt */
1327 if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
1328 {
1329 target_write_u32(target, FLASH_FMA, 0x20000);
1330 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1331 /* Wait until erase complete */
1332 do
1333 {
1334 target_read_u32(target, FLASH_FMC, &flash_fmc);
1335 }
1336 while (flash_fmc & FMC_MERASE);
1337 }
1338
1339 return ERROR_OK;
1340 }
1341
1342 COMMAND_HANDLER(stellaris_handle_mass_erase_command)
1343 {
1344 int i;
1345
1346 if (CMD_ARGC < 1)
1347 {
1348 return ERROR_COMMAND_SYNTAX_ERROR;
1349 }
1350
1351 struct flash_bank *bank;
1352 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1353 if (ERROR_OK != retval)
1354 return retval;
1355
1356 if (stellaris_mass_erase(bank) == ERROR_OK)
1357 {
1358 /* set all sectors as erased */
1359 for (i = 0; i < bank->num_sectors; i++)
1360 {
1361 bank->sectors[i].is_erased = 1;
1362 }
1363
1364 command_print(CMD_CTX, "stellaris mass erase complete");
1365 }
1366 else
1367 {
1368 command_print(CMD_CTX, "stellaris mass erase failed");
1369 }
1370
1371 return ERROR_OK;
1372 }
1373
1374 /**
1375 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1376 * This performs a mass erase and then restores all nonvolatile registers
1377 * (including USER_* registers and flash lock bits) to their defaults.
1378 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1379 *
1380 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1381 * can affect this operation if flash protection has been enabled.
1382 */
1383 COMMAND_HANDLER(stellaris_handle_recover_command)
1384 {
1385 struct flash_bank *bank;
1386 int retval;
1387
1388 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1389 if (retval != ERROR_OK)
1390 return retval;
1391
1392 /* REVISIT ... it may be worth sanity checking that the AP is
1393 * inactive before we start. ARM documents that switching a DP's
1394 * mode while it's active can cause fault modes that need a power
1395 * cycle to recover.
1396 */
1397
1398 /* assert SRST */
1399 if (!(jtag_get_reset_config() & RESET_HAS_SRST)) {
1400 LOG_ERROR("Can't recover Stellaris flash without SRST");
1401 return ERROR_FAIL;
1402 }
1403 jtag_add_reset(0, 1);
1404
1405 for (int i = 0; i < 5; i++) {
1406 retval = dap_to_swd(bank->target);
1407 if (retval != ERROR_OK)
1408 goto done;
1409
1410 retval = dap_to_jtag(bank->target);
1411 if (retval != ERROR_OK)
1412 goto done;
1413 }
1414
1415 /* de-assert SRST */
1416 jtag_add_reset(0, 0);
1417 retval = jtag_execute_queue();
1418
1419 /* wait 400+ msec ... OK, "1+ second" is simpler */
1420 usleep(1000);
1421
1422 /* USER INTERVENTION required for the power cycle
1423 * Restarting OpenOCD is likely needed because of mode switching.
1424 */
1425 LOG_INFO("USER ACTION: "
1426 "power cycle Stellaris chip, then restart OpenOCD.");
1427
1428 done:
1429 return retval;
1430 }
1431
1432 static const struct command_registration stellaris_exec_command_handlers[] = {
1433 {
1434 .name = "mass_erase",
1435 .usage = "<bank>",
1436 .handler = stellaris_handle_mass_erase_command,
1437 .mode = COMMAND_EXEC,
1438 .help = "erase entire device",
1439 },
1440 {
1441 .name = "recover",
1442 .handler = stellaris_handle_recover_command,
1443 .mode = COMMAND_EXEC,
1444 .usage = "bank_id",
1445 .help = "recover (and erase) locked device",
1446 },
1447 COMMAND_REGISTRATION_DONE
1448 };
1449 static const struct command_registration stellaris_command_handlers[] = {
1450 {
1451 .name = "stellaris",
1452 .mode = COMMAND_EXEC,
1453 .help = "Stellaris flash command group",
1454 .chain = stellaris_exec_command_handlers,
1455 },
1456 COMMAND_REGISTRATION_DONE
1457 };
1458
1459 struct flash_driver stellaris_flash = {
1460 .name = "stellaris",
1461 .commands = stellaris_command_handlers,
1462 .flash_bank_command = stellaris_flash_bank_command,
1463 .erase = stellaris_erase,
1464 .protect = stellaris_protect,
1465 .write = stellaris_write,
1466 .read = default_flash_read,
1467 .probe = stellaris_probe,
1468 .auto_probe = stellaris_probe,
1469 .erase_check = default_flash_mem_blank_check,
1470 .protect_check = stellaris_protect_check,
1471 .info = get_stellaris_info,
1472 };

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)