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

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)