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

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)