retire ERROR_INVALID_ARGUMENTS and replace with ERROR_COMMAND_SYNTAX_ERROR
[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 LOG_WARNING("incomplete flash_bank stellaris configuration");
442 return ERROR_FLASH_BANK_INVALID;
443 }
444
445 stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
446 bank->base = 0x0;
447 bank->driver_priv = stellaris_info;
448
449 stellaris_info->target_name = "Unknown target";
450
451 /* part wasn't probed for info yet */
452 stellaris_info->did1 = 0;
453
454 /* TODO Specify the main crystal speed in kHz using an optional
455 * argument; ditto, the speed of an external oscillator used
456 * instead of a crystal. Avoid programming flash using IOSC.
457 */
458 return ERROR_OK;
459 }
460
461 static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size)
462 {
463 int printed, device_class;
464 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
465
466 if (stellaris_info->did1 == 0)
467 return ERROR_FLASH_BANK_NOT_PROBED;
468
469 /* Read main and master clock freqency register */
470 stellaris_read_clock_info(bank);
471
472 if (DID0_VER(stellaris_info->did0) > 0)
473 {
474 device_class = (stellaris_info->did0 >> 16) & 0xFF;
475 }
476 else
477 {
478 device_class = 0;
479 }
480 printed = snprintf(buf,
481 buf_size,
482 "\nTI/LMI Stellaris information: Chip is "
483 "class %i (%s) %s rev %c%i\n",
484 device_class,
485 StellarisClassname[device_class],
486 stellaris_info->target_name,
487 (int)('A' + ((stellaris_info->did0 >> 8) & 0xFF)),
488 (int)((stellaris_info->did0) & 0xFF));
489 buf += printed;
490 buf_size -= printed;
491
492 printed = snprintf(buf,
493 buf_size,
494 "did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32
495 ", eproc: %s, ramsize: %ik, flashsize: %ik\n",
496 stellaris_info->did1,
497 stellaris_info->did1,
498 "ARMv7M",
499 (int)((1 + ((stellaris_info->dc0 >> 16) & 0xFFFF))/4),
500 (int)((1 + (stellaris_info->dc0 & 0xFFFF))*2));
501 buf += printed;
502 buf_size -= printed;
503
504 printed = snprintf(buf,
505 buf_size,
506 "master clock: %ikHz%s, "
507 "rcc is 0x%" PRIx32 ", rcc2 is 0x%" PRIx32 "\n",
508 (int)(stellaris_info->mck_freq / 1000),
509 stellaris_info->mck_desc,
510 stellaris_info->rcc,
511 stellaris_info->rcc2);
512 buf += printed;
513 buf_size -= printed;
514
515 if (stellaris_info->num_lockbits > 0)
516 {
517 snprintf(buf,
518 buf_size,
519 "pagesize: %" PRIi32 ", pages: %d, "
520 "lockbits: %i, pages per lockbit: %i\n",
521 stellaris_info->pagesize,
522 (unsigned) stellaris_info->num_pages,
523 stellaris_info->num_lockbits,
524 (unsigned) stellaris_info->pages_in_lockregion);
525 }
526 return ERROR_OK;
527 }
528
529 /***************************************************************************
530 * chip identification and status *
531 ***************************************************************************/
532
533 /* Set the flash timimg register to match current clocking */
534 static void stellaris_set_flash_timing(struct flash_bank *bank)
535 {
536 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
537 struct target *target = bank->target;
538 uint32_t usecrl = (stellaris_info->mck_freq/1000000ul-1);
539
540 LOG_DEBUG("usecrl = %i",(int)(usecrl));
541 target_write_u32(target, SCB_BASE | USECRL, usecrl);
542 }
543
544 static const unsigned rcc_xtal[32] = {
545 [0x00] = 1000000, /* no pll */
546 [0x01] = 1843200, /* no pll */
547 [0x02] = 2000000, /* no pll */
548 [0x03] = 2457600, /* no pll */
549
550 [0x04] = 3579545,
551 [0x05] = 3686400,
552 [0x06] = 4000000, /* usb */
553 [0x07] = 4096000,
554
555 [0x08] = 4915200,
556 [0x09] = 5000000, /* usb */
557 [0x0a] = 5120000,
558 [0x0b] = 6000000, /* (reset) usb */
559
560 [0x0c] = 6144000,
561 [0x0d] = 7372800,
562 [0x0e] = 8000000, /* usb */
563 [0x0f] = 8192000,
564
565 /* parts before DustDevil use just 4 bits for xtal spec */
566
567 [0x10] = 10000000, /* usb */
568 [0x11] = 12000000, /* usb */
569 [0x12] = 12288000,
570 [0x13] = 13560000,
571
572 [0x14] = 14318180,
573 [0x15] = 16000000, /* usb */
574 [0x16] = 16384000,
575 };
576
577 /** Read clock configuration and set stellaris_info->usec_clocks. */
578 static void stellaris_read_clock_info(struct flash_bank *bank)
579 {
580 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
581 struct target *target = bank->target;
582 uint32_t rcc, rcc2, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
583 unsigned xtal;
584 unsigned long mainfreq;
585
586 target_read_u32(target, SCB_BASE | RCC, &rcc);
587 LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc);
588
589 target_read_u32(target, SCB_BASE | RCC2, &rcc2);
590 LOG_DEBUG("Stellaris RCC2 %" PRIx32 "", rcc);
591
592 target_read_u32(target, SCB_BASE | PLLCFG, &pllcfg);
593 LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg);
594
595 stellaris_info->rcc = rcc;
596 stellaris_info->rcc = rcc2;
597
598 sysdiv = (rcc >> 23) & 0xF;
599 usesysdiv = (rcc >> 22) & 0x1;
600 bypass = (rcc >> 11) & 0x1;
601 oscsrc = (rcc >> 4) & 0x3;
602 xtal = (rcc >> 6) & stellaris_info->xtal_mask;
603
604 /* NOTE: post-Sandstorm parts have RCC2 which may override
605 * parts of RCC ... with more sysdiv options, option for
606 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
607 * as zero, so the "use RCC2" flag is always clear.
608 */
609 if (rcc2 & (1 << 31)) {
610 sysdiv = (rcc2 >> 23) & 0x3F;
611 bypass = (rcc2 >> 11) & 0x1;
612 oscsrc = (rcc2 >> 4) & 0x7;
613
614 /* FIXME Tempest parts have an additional lsb for
615 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
616 */
617 }
618
619 stellaris_info->mck_desc = "";
620
621 switch (oscsrc)
622 {
623 case 0: /* MOSC */
624 mainfreq = rcc_xtal[xtal];
625 break;
626 case 1: /* IOSC */
627 mainfreq = stellaris_info->iosc_freq;
628 stellaris_info->mck_desc = stellaris_info->iosc_desc;
629 break;
630 case 2: /* IOSC/4 */
631 mainfreq = stellaris_info->iosc_freq / 4;
632 stellaris_info->mck_desc = stellaris_info->iosc_desc;
633 break;
634 case 3: /* lowspeed */
635 /* Sandstorm doesn't have this 30K +/- 30% osc */
636 mainfreq = 30000;
637 stellaris_info->mck_desc = " (±30%)";
638 break;
639 case 8: /* hibernation osc */
640 /* not all parts support hibernation */
641 mainfreq = 32768;
642 break;
643
644 default: /* NOTREACHED */
645 mainfreq = 0;
646 break;
647 }
648
649 /* PLL is used if it's not bypassed; its output is 200 MHz
650 * even when it runs at 400 MHz (adds divide-by-two stage).
651 */
652 if (!bypass)
653 mainfreq = 200000000;
654
655 if (usesysdiv)
656 stellaris_info->mck_freq = mainfreq/(1 + sysdiv);
657 else
658 stellaris_info->mck_freq = mainfreq;
659 }
660
661 /* Read device id register, main clock frequency register and fill in driver info structure */
662 static int stellaris_read_part_info(struct flash_bank *bank)
663 {
664 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
665 struct target *target = bank->target;
666 uint32_t did0, did1, ver, fam;
667 int i;
668
669 /* Read and parse chip identification register */
670 target_read_u32(target, SCB_BASE | DID0, &did0);
671 target_read_u32(target, SCB_BASE | DID1, &did1);
672 target_read_u32(target, SCB_BASE | DC0, &stellaris_info->dc0);
673 target_read_u32(target, SCB_BASE | DC1, &stellaris_info->dc1);
674 LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32 "",
675 did0, did1, stellaris_info->dc0, stellaris_info->dc1);
676
677 ver = did0 >> 28;
678 if ((ver != 0) && (ver != 1))
679 {
680 LOG_WARNING("Unknown did0 version, cannot identify target");
681 return ERROR_FLASH_OPERATION_FAILED;
682 }
683
684 if (did1 == 0)
685 {
686 LOG_WARNING("Cannot identify target as a Stellaris");
687 return ERROR_FLASH_OPERATION_FAILED;
688 }
689
690 ver = did1 >> 28;
691 fam = (did1 >> 24) & 0xF;
692 if (((ver != 0) && (ver != 1)) || (fam != 0))
693 {
694 LOG_WARNING("Unknown did1 version/family.");
695 return ERROR_FLASH_OPERATION_FAILED;
696 }
697
698 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
699 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
700 * even give _both_ numbers! We'll use current numbers; IOSC is
701 * always approximate.
702 *
703 * For Tempest: IOSC is calibrated, 16 MHz
704 */
705 stellaris_info->iosc_freq = 12000000;
706 stellaris_info->iosc_desc = " (±30%)";
707 stellaris_info->xtal_mask = 0x0f;
708
709 switch ((did0 >> 28) & 0x7) {
710 case 0: /* Sandstorm */
711 /*
712 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
713 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
714 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
715 */
716 if (((did0 >> 8) & 0xff) < 2) {
717 stellaris_info->iosc_freq = 15000000;
718 stellaris_info->iosc_desc = " (±50%)";
719 }
720 break;
721 case 1:
722 switch ((did0 >> 16) & 0xff) {
723 case 1: /* Fury */
724 break;
725 case 4: /* Tempest */
726 stellaris_info->iosc_freq = 16000000; /* +/- 1% */
727 stellaris_info->iosc_desc = " (±1%)";
728 /* FALL THROUGH */
729 case 3: /* DustDevil */
730 stellaris_info->xtal_mask = 0x1f;
731 break;
732 default:
733 LOG_WARNING("Unknown did0 class");
734 }
735 break;
736 default:
737 LOG_WARNING("Unknown did0 version");
738 break;
739 }
740
741 for (i = 0; StellarisParts[i].partno; i++)
742 {
743 if ((StellarisParts[i].partno == ((did1 >> 16) & 0xFF)) &&
744 (StellarisParts[i].class == ((did0 >> 16) & 0xFF)))
745 break;
746 }
747
748 stellaris_info->target_name = StellarisParts[i].partname;
749
750 stellaris_info->did0 = did0;
751 stellaris_info->did1 = did1;
752
753 stellaris_info->num_lockbits = 1 + (stellaris_info->dc0 & 0xFFFF);
754 stellaris_info->num_pages = 2 *(1 + (stellaris_info->dc0 & 0xFFFF));
755 stellaris_info->pagesize = 1024;
756 stellaris_info->pages_in_lockregion = 2;
757
758 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
759 * That exposes a 32-word Flash Write Buffer ... enabling
760 * writes of more than one word at a time.
761 */
762
763 return ERROR_OK;
764 }
765
766 /***************************************************************************
767 * flash operations *
768 ***************************************************************************/
769
770 static int stellaris_protect_check(struct flash_bank *bank)
771 {
772 struct stellaris_flash_bank *stellaris = bank->driver_priv;
773 int status = ERROR_OK;
774 unsigned i;
775 unsigned page;
776
777 if (stellaris->did1 == 0)
778 return ERROR_FLASH_BANK_NOT_PROBED;
779
780 for (i = 0; i < (unsigned) bank->num_sectors; i++)
781 bank->sectors[i].is_protected = -1;
782
783 /* Read each Flash Memory Protection Program Enable (FMPPE) register
784 * to report any pages that we can't write. Ignore the Read Enable
785 * register (FMPRE).
786 */
787 for (i = 0, page = 0;
788 i < DIV_ROUND_UP(stellaris->num_lockbits, 32u);
789 i++) {
790 uint32_t lockbits;
791
792 status = target_read_u32(bank->target,
793 SCB_BASE + (i ? (FMPPE0 + 4 * i) : FMPPE),
794 &lockbits);
795 LOG_DEBUG("FMPPE%d = %#8.8x (status %d)", i,
796 (unsigned) lockbits, status);
797 if (status != ERROR_OK)
798 goto done;
799
800 for (unsigned j = 0; j < 32; j++) {
801 unsigned k;
802
803 for (k = 0; k < stellaris->pages_in_lockregion; k++) {
804 if (page >= (unsigned) bank->num_sectors)
805 goto done;
806 bank->sectors[page++].is_protected =
807 !(lockbits & (1 << j));
808 }
809 }
810 }
811
812 done:
813 return status;
814 }
815
816 static int stellaris_erase(struct flash_bank *bank, int first, int last)
817 {
818 int banknr;
819 uint32_t flash_fmc, flash_cris;
820 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
821 struct target *target = bank->target;
822
823 if (bank->target->state != TARGET_HALTED)
824 {
825 LOG_ERROR("Target not halted");
826 return ERROR_TARGET_NOT_HALTED;
827 }
828
829 if (stellaris_info->did1 == 0)
830 return ERROR_FLASH_BANK_NOT_PROBED;
831
832 if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
833 {
834 return ERROR_FLASH_SECTOR_INVALID;
835 }
836
837 if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
838 {
839 return stellaris_mass_erase(bank);
840 }
841
842 /* Refresh flash controller timing */
843 stellaris_read_clock_info(bank);
844 stellaris_set_flash_timing(bank);
845
846 /* Clear and disable flash programming interrupts */
847 target_write_u32(target, FLASH_CIM, 0);
848 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
849
850 /* REVISIT this clobbers state set by any halted firmware ...
851 * it might want to process those IRQs.
852 */
853
854 for (banknr = first; banknr <= last; banknr++)
855 {
856 /* Address is first word in page */
857 target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
858 /* Write erase command */
859 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
860 /* Wait until erase complete */
861 do
862 {
863 target_read_u32(target, FLASH_FMC, &flash_fmc);
864 }
865 while (flash_fmc & FMC_ERASE);
866
867 /* Check acess violations */
868 target_read_u32(target, FLASH_CRIS, &flash_cris);
869 if (flash_cris & (AMASK))
870 {
871 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", banknr, flash_cris);
872 target_write_u32(target, FLASH_CRIS, 0);
873 return ERROR_FLASH_OPERATION_FAILED;
874 }
875
876 bank->sectors[banknr].is_erased = 1;
877 }
878
879 return ERROR_OK;
880 }
881
882 static int stellaris_protect(struct flash_bank *bank, int set, int first, int last)
883 {
884 uint32_t fmppe, flash_fmc, flash_cris;
885 int lockregion;
886
887 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
888 struct target *target = bank->target;
889
890 if (bank->target->state != TARGET_HALTED)
891 {
892 LOG_ERROR("Target not halted");
893 return ERROR_TARGET_NOT_HALTED;
894 }
895
896 if (!set)
897 {
898 LOG_ERROR("Hardware doesn't support page-level unprotect. "
899 "Try the 'recover' command.");
900 return ERROR_COMMAND_SYNTAX_ERROR;
901 }
902
903 if (stellaris_info->did1 == 0)
904 return ERROR_FLASH_BANK_NOT_PROBED;
905
906 /* lockregions are 2 pages ... must protect [even..odd] */
907 if ((first < 0) || (first & 1)
908 || (last < first) || !(last & 1)
909 || (last >= 2 * stellaris_info->num_lockbits))
910 {
911 LOG_ERROR("Can't protect unaligned or out-of-range pages.");
912 return ERROR_FLASH_SECTOR_INVALID;
913 }
914
915 /* Refresh flash controller timing */
916 stellaris_read_clock_info(bank);
917 stellaris_set_flash_timing(bank);
918
919 /* convert from pages to lockregions */
920 first /= 2;
921 last /= 2;
922
923 /* FIXME this assumes single FMPPE, for a max of 64K of flash!!
924 * Current parts can be much bigger.
925 */
926 if (last >= 32) {
927 LOG_ERROR("No support yet for protection > 64K");
928 return ERROR_FLASH_OPERATION_FAILED;
929 }
930
931 target_read_u32(target, SCB_BASE | FMPPE, &fmppe);
932
933 for (lockregion = first; lockregion <= last; lockregion++)
934 fmppe &= ~(1 << lockregion);
935
936 /* Clear and disable flash programming interrupts */
937 target_write_u32(target, FLASH_CIM, 0);
938 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
939
940 /* REVISIT this clobbers state set by any halted firmware ...
941 * it might want to process those IRQs.
942 */
943
944 LOG_DEBUG("fmppe 0x%" PRIx32 "",fmppe);
945 target_write_u32(target, SCB_BASE | FMPPE, fmppe);
946
947 /* Commit FMPPE */
948 target_write_u32(target, FLASH_FMA, 1);
949
950 /* Write commit command */
951 /* REVISIT safety check, since this cannot be undone
952 * except by the "Recover a locked device" procedure.
953 * REVISIT DustDevil-A0 parts have an erratum making FMPPE commits
954 * inadvisable ... it makes future mass erase operations fail.
955 */
956 LOG_WARNING("Flash protection cannot be removed once committed, commit is NOT executed !");
957 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
958
959 /* Wait until erase complete */
960 do
961 {
962 target_read_u32(target, FLASH_FMC, &flash_fmc);
963 }
964 while (flash_fmc & FMC_COMT);
965
966 /* Check acess violations */
967 target_read_u32(target, FLASH_CRIS, &flash_cris);
968 if (flash_cris & (AMASK))
969 {
970 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
971 target_write_u32(target, FLASH_CRIS, 0);
972 return ERROR_FLASH_OPERATION_FAILED;
973 }
974
975 return ERROR_OK;
976 }
977
978 /* see contib/loaders/flash/stellaris.s for src */
979
980 static const uint8_t stellaris_write_code[] =
981 {
982 /*
983 Call with :
984 r0 = buffer address
985 r1 = destination address
986 r2 = bytecount (in) - endaddr (work)
987
988 Used registers:
989 r3 = pFLASH_CTRL_BASE
990 r4 = FLASHWRITECMD
991 r5 = #1
992 r6 = bytes written
993 r7 = temp reg
994 */
995 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
996 0x08,0x4C, /* ldr r4,FLASHWRITECMD */
997 0x01,0x25, /* movs r5, 1 */
998 0x00,0x26, /* movs r6, #0 */
999 /* mainloop: */
1000 0x19,0x60, /* str r1, [r3, #0] */
1001 0x87,0x59, /* ldr r7, [r0, r6] */
1002 0x5F,0x60, /* str r7, [r3, #4] */
1003 0x9C,0x60, /* str r4, [r3, #8] */
1004 /* waitloop: */
1005 0x9F,0x68, /* ldr r7, [r3, #8] */
1006 0x2F,0x42, /* tst r7, r5 */
1007 0xFC,0xD1, /* bne waitloop */
1008 0x04,0x31, /* adds r1, r1, #4 */
1009 0x04,0x36, /* adds r6, r6, #4 */
1010 0x96,0x42, /* cmp r6, r2 */
1011 0xF4,0xD1, /* bne mainloop */
1012 0x00,0xBE, /* bkpt #0 */
1013 /* pFLASH_CTRL_BASE: */
1014 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
1015 /* FLASHWRITECMD: */
1016 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
1017 };
1018
1019 static int stellaris_write_block(struct flash_bank *bank,
1020 uint8_t *buffer, uint32_t offset, uint32_t wcount)
1021 {
1022 struct target *target = bank->target;
1023 uint32_t buffer_size = 16384;
1024 struct working_area *source;
1025 struct working_area *write_algorithm;
1026 uint32_t address = bank->base + offset;
1027 struct reg_param reg_params[3];
1028 struct armv7m_algorithm armv7m_info;
1029 int retval = ERROR_OK;
1030
1031 /* power of two, and multiple of word size */
1032 static const unsigned buf_min = 128;
1033
1034 /* for small buffers it's faster not to download an algorithm */
1035 if (wcount * 4 < buf_min)
1036 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1037
1038 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
1039 bank, buffer, offset, wcount);
1040
1041 /* flash write code */
1042 if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
1043 {
1044 LOG_DEBUG("no working area for block memory writes");
1045 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1046 };
1047
1048 /* plus a buffer big enough for this data */
1049 if (wcount * 4 < buffer_size)
1050 buffer_size = wcount * 4;
1051
1052 /* memory buffer */
1053 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
1054 {
1055 buffer_size /= 2;
1056 if (buffer_size <= buf_min)
1057 {
1058 target_free_working_area(target, write_algorithm);
1059 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1060 }
1061 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1062 target_name(target), (unsigned) buffer_size);
1063 };
1064
1065 retval = target_write_buffer(target, write_algorithm->address,
1066 sizeof(stellaris_write_code),
1067 (uint8_t *) stellaris_write_code);
1068
1069 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
1070 armv7m_info.core_mode = ARMV7M_MODE_ANY;
1071
1072 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
1073 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
1074 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
1075
1076 while (wcount > 0)
1077 {
1078 uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
1079
1080 target_write_buffer(target, source->address, thisrun_count * 4, buffer);
1081
1082 buf_set_u32(reg_params[0].value, 0, 32, source->address);
1083 buf_set_u32(reg_params[1].value, 0, 32, address);
1084 buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
1085 LOG_DEBUG("Algorithm flash write %u words to 0x%" PRIx32
1086 ", %u remaining",
1087 (unsigned) thisrun_count, address,
1088 (unsigned) (wcount - thisrun_count));
1089 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
1090 write_algorithm->address,
1091 0,
1092 10000, &armv7m_info);
1093 if (retval != ERROR_OK)
1094 {
1095 LOG_ERROR("error %d executing stellaris "
1096 "flash write algorithm",
1097 retval);
1098 retval = ERROR_FLASH_OPERATION_FAILED;
1099 break;
1100 }
1101
1102 buffer += thisrun_count * 4;
1103 address += thisrun_count * 4;
1104 wcount -= thisrun_count;
1105 }
1106
1107 /* REVISIT we could speed up writing multi-section images by
1108 * not freeing the initialized write_algorithm this way.
1109 */
1110
1111 target_free_working_area(target, write_algorithm);
1112 target_free_working_area(target, source);
1113
1114 destroy_reg_param(&reg_params[0]);
1115 destroy_reg_param(&reg_params[1]);
1116 destroy_reg_param(&reg_params[2]);
1117
1118 return retval;
1119 }
1120
1121 static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
1122 {
1123 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1124 struct target *target = bank->target;
1125 uint32_t address = offset;
1126 uint32_t flash_cris, flash_fmc;
1127 uint32_t words_remaining = (count / 4);
1128 uint32_t bytes_remaining = (count & 0x00000003);
1129 uint32_t bytes_written = 0;
1130 int retval;
1131
1132 if (bank->target->state != TARGET_HALTED)
1133 {
1134 LOG_ERROR("Target not halted");
1135 return ERROR_TARGET_NOT_HALTED;
1136 }
1137
1138 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
1139 bank, buffer, offset, count);
1140
1141 if (stellaris_info->did1 == 0)
1142 return ERROR_FLASH_BANK_NOT_PROBED;
1143
1144 if (offset & 0x3)
1145 {
1146 LOG_WARNING("offset size must be word aligned");
1147 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1148 }
1149
1150 if (offset + count > bank->size)
1151 return ERROR_FLASH_DST_OUT_OF_BANK;
1152
1153 /* Refresh flash controller timing */
1154 stellaris_read_clock_info(bank);
1155 stellaris_set_flash_timing(bank);
1156
1157 /* Clear and disable flash programming interrupts */
1158 target_write_u32(target, FLASH_CIM, 0);
1159 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1160
1161 /* REVISIT this clobbers state set by any halted firmware ...
1162 * it might want to process those IRQs.
1163 */
1164
1165 /* multiple words to be programmed? */
1166 if (words_remaining > 0)
1167 {
1168 /* try using a block write */
1169 retval = stellaris_write_block(bank, buffer, offset,
1170 words_remaining);
1171 if (retval != ERROR_OK)
1172 {
1173 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
1174 {
1175 LOG_DEBUG("writing flash word-at-a-time");
1176 }
1177 else if (retval == ERROR_FLASH_OPERATION_FAILED)
1178 {
1179 /* if an error occured, we examine the reason, and quit */
1180 target_read_u32(target, FLASH_CRIS, &flash_cris);
1181
1182 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
1183 return ERROR_FLASH_OPERATION_FAILED;
1184 }
1185 }
1186 else
1187 {
1188 buffer += words_remaining * 4;
1189 address += words_remaining * 4;
1190 words_remaining = 0;
1191 }
1192 }
1193
1194 while (words_remaining > 0)
1195 {
1196 if (!(address & 0xff))
1197 LOG_DEBUG("0x%" PRIx32 "", address);
1198
1199 /* Program one word */
1200 target_write_u32(target, FLASH_FMA, address);
1201 target_write_buffer(target, FLASH_FMD, 4, buffer);
1202 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1203 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1204 /* Wait until write complete */
1205 do
1206 {
1207 target_read_u32(target, FLASH_FMC, &flash_fmc);
1208 } while (flash_fmc & FMC_WRITE);
1209
1210 buffer += 4;
1211 address += 4;
1212 words_remaining--;
1213 }
1214
1215 if (bytes_remaining)
1216 {
1217 uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
1218 int i = 0;
1219
1220 while (bytes_remaining > 0)
1221 {
1222 last_word[i++] = *(buffer + bytes_written);
1223 bytes_remaining--;
1224 bytes_written++;
1225 }
1226
1227 if (!(address & 0xff))
1228 LOG_DEBUG("0x%" PRIx32 "", address);
1229
1230 /* Program one word */
1231 target_write_u32(target, FLASH_FMA, address);
1232 target_write_buffer(target, FLASH_FMD, 4, last_word);
1233 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1234 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1235 /* Wait until write complete */
1236 do
1237 {
1238 target_read_u32(target, FLASH_FMC, &flash_fmc);
1239 } while (flash_fmc & FMC_WRITE);
1240 }
1241
1242 /* Check access violations */
1243 target_read_u32(target, FLASH_CRIS, &flash_cris);
1244 if (flash_cris & (AMASK))
1245 {
1246 LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
1247 return ERROR_FLASH_OPERATION_FAILED;
1248 }
1249 return ERROR_OK;
1250 }
1251
1252 static int stellaris_probe(struct flash_bank *bank)
1253 {
1254 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1255 int retval;
1256
1257 /* If this is a stellaris chip, it has flash; probe() is just
1258 * to figure out how much is present. Only do it once.
1259 */
1260 if (stellaris_info->did1 != 0)
1261 return ERROR_OK;
1262
1263 /* stellaris_read_part_info() already handled error checking and
1264 * reporting. Note that it doesn't write, so we don't care about
1265 * whether the target is halted or not.
1266 */
1267 retval = stellaris_read_part_info(bank);
1268 if (retval != ERROR_OK)
1269 return retval;
1270
1271 if (bank->sectors)
1272 {
1273 free(bank->sectors);
1274 bank->sectors = NULL;
1275 }
1276
1277 /* provide this for the benefit of the NOR flash framework */
1278 bank->size = 1024 * stellaris_info->num_pages;
1279 bank->num_sectors = stellaris_info->num_pages;
1280 bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
1281 for (int i = 0; i < bank->num_sectors; i++)
1282 {
1283 bank->sectors[i].offset = i * stellaris_info->pagesize;
1284 bank->sectors[i].size = stellaris_info->pagesize;
1285 bank->sectors[i].is_erased = -1;
1286 bank->sectors[i].is_protected = -1;
1287 }
1288
1289 return retval;
1290 }
1291
1292 static int stellaris_mass_erase(struct flash_bank *bank)
1293 {
1294 struct target *target = NULL;
1295 struct stellaris_flash_bank *stellaris_info = NULL;
1296 uint32_t flash_fmc;
1297
1298 stellaris_info = bank->driver_priv;
1299 target = bank->target;
1300
1301 if (target->state != TARGET_HALTED)
1302 {
1303 LOG_ERROR("Target not halted");
1304 return ERROR_TARGET_NOT_HALTED;
1305 }
1306
1307 if (stellaris_info->did1 == 0)
1308 return ERROR_FLASH_BANK_NOT_PROBED;
1309
1310 /* Refresh flash controller timing */
1311 stellaris_read_clock_info(bank);
1312 stellaris_set_flash_timing(bank);
1313
1314 /* Clear and disable flash programming interrupts */
1315 target_write_u32(target, FLASH_CIM, 0);
1316 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1317
1318 /* REVISIT this clobbers state set by any halted firmware ...
1319 * it might want to process those IRQs.
1320 */
1321
1322 target_write_u32(target, FLASH_FMA, 0);
1323 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1324 /* Wait until erase complete */
1325 do
1326 {
1327 target_read_u32(target, FLASH_FMC, &flash_fmc);
1328 }
1329 while (flash_fmc & FMC_MERASE);
1330
1331 /* if device has > 128k, then second erase cycle is needed
1332 * this is only valid for older devices, but will not hurt */
1333 if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
1334 {
1335 target_write_u32(target, FLASH_FMA, 0x20000);
1336 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1337 /* Wait until erase complete */
1338 do
1339 {
1340 target_read_u32(target, FLASH_FMC, &flash_fmc);
1341 }
1342 while (flash_fmc & FMC_MERASE);
1343 }
1344
1345 return ERROR_OK;
1346 }
1347
1348 COMMAND_HANDLER(stellaris_handle_mass_erase_command)
1349 {
1350 int i;
1351
1352 if (CMD_ARGC < 1)
1353 {
1354 command_print(CMD_CTX, "stellaris mass_erase <bank>");
1355 return ERROR_OK;
1356 }
1357
1358 struct flash_bank *bank;
1359 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1360 if (ERROR_OK != retval)
1361 return retval;
1362
1363 if (stellaris_mass_erase(bank) == ERROR_OK)
1364 {
1365 /* set all sectors as erased */
1366 for (i = 0; i < bank->num_sectors; i++)
1367 {
1368 bank->sectors[i].is_erased = 1;
1369 }
1370
1371 command_print(CMD_CTX, "stellaris mass erase complete");
1372 }
1373 else
1374 {
1375 command_print(CMD_CTX, "stellaris mass erase failed");
1376 }
1377
1378 return ERROR_OK;
1379 }
1380
1381 /**
1382 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1383 * This performs a mass erase and then restores all nonvolatile registers
1384 * (including USER_* registers and flash lock bits) to their defaults.
1385 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1386 *
1387 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1388 * can affect this operation if flash protection has been enabled.
1389 */
1390 COMMAND_HANDLER(stellaris_handle_recover_command)
1391 {
1392 struct flash_bank *bank;
1393 int retval;
1394
1395 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1396 if (retval != ERROR_OK)
1397 return retval;
1398
1399 /* REVISIT ... it may be worth sanity checking that the AP is
1400 * inactive before we start. ARM documents that switching a DP's
1401 * mode while it's active can cause fault modes that need a power
1402 * cycle to recover.
1403 */
1404
1405 /* assert SRST */
1406 if (!(jtag_get_reset_config() & RESET_HAS_SRST)) {
1407 LOG_ERROR("Can't recover Stellaris flash without SRST");
1408 return ERROR_FAIL;
1409 }
1410 jtag_add_reset(0, 1);
1411
1412 for (int i = 0; i < 5; i++) {
1413 retval = dap_to_swd(bank->target);
1414 if (retval != ERROR_OK)
1415 goto done;
1416
1417 retval = dap_to_jtag(bank->target);
1418 if (retval != ERROR_OK)
1419 goto done;
1420 }
1421
1422 /* de-assert SRST */
1423 jtag_add_reset(0, 0);
1424 retval = jtag_execute_queue();
1425
1426 /* wait 400+ msec ... OK, "1+ second" is simpler */
1427 usleep(1000);
1428
1429 /* USER INTERVENTION required for the power cycle
1430 * Restarting OpenOCD is likely needed because of mode switching.
1431 */
1432 LOG_INFO("USER ACTION: "
1433 "power cycle Stellaris chip, then restart OpenOCD.");
1434
1435 done:
1436 return retval;
1437 }
1438
1439 static const struct command_registration stellaris_exec_command_handlers[] = {
1440 {
1441 .name = "mass_erase",
1442 .handler = stellaris_handle_mass_erase_command,
1443 .mode = COMMAND_EXEC,
1444 .usage = "bank_id",
1445 .help = "erase entire device",
1446 },
1447 {
1448 .name = "recover",
1449 .handler = stellaris_handle_recover_command,
1450 .mode = COMMAND_EXEC,
1451 .usage = "bank_id",
1452 .help = "recover (and erase) locked device",
1453 },
1454 COMMAND_REGISTRATION_DONE
1455 };
1456 static const struct command_registration stellaris_command_handlers[] = {
1457 {
1458 .name = "stellaris",
1459 .mode = COMMAND_EXEC,
1460 .help = "Stellaris flash command group",
1461 .chain = stellaris_exec_command_handlers,
1462 },
1463 COMMAND_REGISTRATION_DONE
1464 };
1465
1466 struct flash_driver stellaris_flash = {
1467 .name = "stellaris",
1468 .commands = stellaris_command_handlers,
1469 .flash_bank_command = stellaris_flash_bank_command,
1470 .erase = stellaris_erase,
1471 .protect = stellaris_protect,
1472 .write = stellaris_write,
1473 .read = default_flash_read,
1474 .probe = stellaris_probe,
1475 .auto_probe = stellaris_probe,
1476 .erase_check = default_flash_mem_blank_check,
1477 .protect_check = stellaris_protect_check,
1478 .info = get_stellaris_info,
1479 };

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)