d2638c152dd9e5672314d7c7c24e8cf7d65b0f3e
[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 } stellaris_parts[] = {
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 stellaris_classname[] = {
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 stellaris_classname[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; stellaris_parts[i].partno; i++) {
747 if ((stellaris_parts[i].partno == ((did1 >> 16) & 0xFF)) &&
748 (stellaris_parts[i].class == stellaris_info->target_class))
749 break;
750 }
751
752 stellaris_info->target_name = stellaris_parts[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
891 return ERROR_OK;
892 }
893
894 static int stellaris_protect(struct flash_bank *bank, int set,
895 unsigned int first, unsigned int last)
896 {
897 struct stellaris_flash_bank *stellaris = bank->driver_priv;
898 struct target *target = bank->target;
899 uint32_t flash_fmc, flash_cris;
900 unsigned int bits_per_page = stellaris->pagesize / 2048;
901
902 if (target->state != TARGET_HALTED) {
903 LOG_ERROR("Target not halted");
904 return ERROR_TARGET_NOT_HALTED;
905 }
906
907 if (!set) {
908 LOG_ERROR("Hardware doesn't support page-level unprotect. "
909 "Try the 'recover' command.");
910 return ERROR_COMMAND_SYNTAX_ERROR;
911 }
912
913 if (stellaris->did1 == 0)
914 return ERROR_FLASH_BANK_NOT_PROBED;
915
916 if (stellaris->target_class == 0x03 &&
917 !((stellaris->did0 >> 8) & 0xFF) &&
918 !((stellaris->did0) & 0xFF)) {
919 LOG_ERROR("DustDevil A0 parts can't be unprotected, see errata; refusing to proceed");
920 return ERROR_FLASH_OPERATION_FAILED;
921 }
922
923 if (!bits_per_page && (first % 2 || !(last % 2))) {
924 LOG_ERROR("Can't protect unaligned pages");
925 return ERROR_FLASH_SECTOR_INVALID;
926 }
927
928 /* Refresh flash controller timing */
929 stellaris_read_clock_info(bank);
930 stellaris_set_flash_timing(bank);
931
932 /* Clear and disable flash programming interrupts */
933 target_write_u32(target, FLASH_CIM, 0);
934 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
935
936 uint32_t flash_sizek = stellaris->pagesize / 1024 *
937 stellaris->num_pages;
938 uint32_t fmppe_addr;
939
940 if (stellaris->target_class >= 0x0a || flash_sizek > 64)
941 fmppe_addr = SCB_BASE | FMPPE0;
942 else
943 fmppe_addr = SCB_BASE | FMPPE;
944
945 unsigned int page = 0;
946 unsigned int lockbitnum, lockbitcnt = flash_sizek / 2;
947 /* Every lock bit always corresponds to a 2k region */
948 for (lockbitnum = 0; lockbitnum < lockbitcnt; lockbitnum += 32) {
949 uint32_t fmppe;
950
951 target_read_u32(target, fmppe_addr, &fmppe);
952 for (unsigned int i = 0;
953 i < 32 && lockbitnum + i < lockbitcnt;
954 i++) {
955 if (page >= first && page <= last)
956 fmppe &= ~(1 << i);
957
958 if (bits_per_page) {
959 if (!((i + 1) % bits_per_page))
960 page++;
961 } else { /* 1024k pages, every lockbit covers 2 pages */
962 page += 2;
963 }
964 }
965 target_write_u32(target, fmppe_addr, fmppe);
966
967 /* Commit FMPPE* */
968 target_write_u32(target, FLASH_FMA, 1 + lockbitnum / 16);
969 /* Write commit command */
970 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT);
971
972 /* Wait until commit complete */
973 do {
974 target_read_u32(target, FLASH_FMC, &flash_fmc);
975 } while (flash_fmc & FMC_COMT);
976
977 /* Check access violations */
978 target_read_u32(target, FLASH_CRIS, &flash_cris);
979 if (flash_cris & (AMASK)) {
980 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
981 target_write_u32(target, FLASH_CRIS, 0);
982 return ERROR_FLASH_OPERATION_FAILED;
983 }
984
985 fmppe_addr += 4;
986 }
987
988 return ERROR_OK;
989 }
990
991 /* see contrib/loaders/flash/stellaris.s for src */
992
993 static const uint8_t stellaris_write_code[] = {
994 /* write: */
995 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */
996 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */
997 /* wait_fifo: */
998 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
999 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
1000 0x17, 0xD0, /* beq exit */
1001 0x47, 0x68, /* ldr r7, [r0, #4] */
1002 0x47, 0x45, /* cmp r7, r8 */
1003 0xF7, 0xD0, /* beq wait_fifo */
1004 /* mainloop: */
1005 0x22, 0x60, /* str r2, [r4, #0] */
1006 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */
1007 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */
1008 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */
1009 0xA5, 0x60, /* str r5, [r4, #8] */
1010 /* busy: */
1011 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */
1012 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */
1013 0xFA, 0xD1, /* bne busy */
1014 0x8F, 0x42, /* cmp r7, r1 */
1015 0x28, 0xBF, /* it cs */
1016 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
1017 0x47, 0x60, /* str r7, [r0, #4] */
1018 0x01, 0x3B, /* subs r3, r3, #1 */
1019 0x03, 0xB1, /* cbz r3, exit */
1020 0xE2, 0xE7, /* b wait_fifo */
1021 /* exit: */
1022 0x00, 0xBE, /* bkpt #0 */
1023
1024 /* pFLASH_CTRL_BASE: */
1025 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
1026 /* FLASHWRITECMD: */
1027 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
1028 };
1029 static int stellaris_write_block(struct flash_bank *bank,
1030 const uint8_t *buffer, uint32_t offset, uint32_t wcount)
1031 {
1032 struct target *target = bank->target;
1033 uint32_t buffer_size = 16384;
1034 struct working_area *source;
1035 struct working_area *write_algorithm;
1036 uint32_t address = bank->base + offset;
1037 struct reg_param reg_params[4];
1038 struct armv7m_algorithm armv7m_info;
1039 int retval = ERROR_OK;
1040
1041 /* power of two, and multiple of word size */
1042 static const unsigned buf_min = 128;
1043
1044 /* for small buffers it's faster not to download an algorithm */
1045 if (wcount * 4 < buf_min)
1046 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1047
1048 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
1049 bank, buffer, offset, wcount);
1050
1051 /* flash write code */
1052 if (target_alloc_working_area(target, sizeof(stellaris_write_code),
1053 &write_algorithm) != ERROR_OK) {
1054 LOG_DEBUG("no working area for block memory writes");
1055 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1056 }
1057
1058 /* plus a buffer big enough for this data */
1059 if (wcount * 4 < buffer_size)
1060 buffer_size = wcount * 4;
1061
1062 /* memory buffer */
1063 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
1064 buffer_size /= 2;
1065 if (buffer_size <= buf_min) {
1066 target_free_working_area(target, write_algorithm);
1067 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1068 }
1069 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1070 target_name(target), (unsigned) buffer_size);
1071 }
1072
1073 target_write_buffer(target, write_algorithm->address,
1074 sizeof(stellaris_write_code),
1075 stellaris_write_code);
1076
1077 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
1078 armv7m_info.core_mode = ARM_MODE_THREAD;
1079
1080 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
1081 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
1082 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
1083 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
1084
1085 buf_set_u32(reg_params[0].value, 0, 32, source->address);
1086 buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
1087 buf_set_u32(reg_params[2].value, 0, 32, address);
1088 buf_set_u32(reg_params[3].value, 0, 32, wcount);
1089
1090 retval = target_run_flash_async_algorithm(target, buffer, wcount, 4,
1091 0, NULL,
1092 4, reg_params,
1093 source->address, source->size,
1094 write_algorithm->address, 0,
1095 &armv7m_info);
1096
1097 if (retval == ERROR_FLASH_OPERATION_FAILED)
1098 LOG_ERROR("error %d executing stellaris flash write algorithm", retval);
1099
1100 target_free_working_area(target, write_algorithm);
1101 target_free_working_area(target, source);
1102
1103 destroy_reg_param(&reg_params[0]);
1104 destroy_reg_param(&reg_params[1]);
1105 destroy_reg_param(&reg_params[2]);
1106 destroy_reg_param(&reg_params[3]);
1107
1108 return retval;
1109 }
1110
1111 static int stellaris_write(struct flash_bank *bank, const uint8_t *buffer,
1112 uint32_t offset, uint32_t count)
1113 {
1114 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1115 struct target *target = bank->target;
1116 uint32_t address = offset;
1117 uint32_t flash_cris, flash_fmc;
1118 uint32_t words_remaining = (count / 4);
1119 uint32_t bytes_remaining = (count & 0x00000003);
1120 uint32_t bytes_written = 0;
1121 int retval;
1122
1123 if (bank->target->state != TARGET_HALTED) {
1124 LOG_ERROR("Target not halted");
1125 return ERROR_TARGET_NOT_HALTED;
1126 }
1127
1128 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
1129 bank, buffer, offset, count);
1130
1131 if (stellaris_info->did1 == 0)
1132 return ERROR_FLASH_BANK_NOT_PROBED;
1133
1134 if (offset & 0x3) {
1135 LOG_WARNING("offset size must be word aligned");
1136 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1137 }
1138
1139 if (offset + count > bank->size)
1140 return ERROR_FLASH_DST_OUT_OF_BANK;
1141
1142 /* Refresh flash controller timing */
1143 stellaris_read_clock_info(bank);
1144 stellaris_set_flash_timing(bank);
1145
1146 /* Clear and disable flash programming interrupts */
1147 target_write_u32(target, FLASH_CIM, 0);
1148 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1149
1150 /* REVISIT this clobbers state set by any halted firmware ...
1151 * it might want to process those IRQs.
1152 */
1153
1154 /* multiple words to be programmed? */
1155 if (words_remaining > 0) {
1156 /* try using a block write */
1157 retval = stellaris_write_block(bank, buffer, offset,
1158 words_remaining);
1159 if (retval != ERROR_OK) {
1160 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
1161 LOG_DEBUG("writing flash word-at-a-time");
1162 } else if (retval == ERROR_FLASH_OPERATION_FAILED) {
1163 /* if an error occurred, we examine the reason, and quit */
1164 target_read_u32(target, FLASH_CRIS, &flash_cris);
1165
1166 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
1167 return ERROR_FLASH_OPERATION_FAILED;
1168 }
1169 } else {
1170 buffer += words_remaining * 4;
1171 address += words_remaining * 4;
1172 words_remaining = 0;
1173 }
1174 }
1175
1176 while (words_remaining > 0) {
1177 if (!(address & 0xff))
1178 LOG_DEBUG("0x%" PRIx32 "", address);
1179
1180 /* Program one word */
1181 target_write_u32(target, FLASH_FMA, address);
1182 target_write_buffer(target, FLASH_FMD, 4, buffer);
1183 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1184 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1185 /* Wait until write complete */
1186 do {
1187 target_read_u32(target, FLASH_FMC, &flash_fmc);
1188 } while (flash_fmc & FMC_WRITE);
1189
1190 buffer += 4;
1191 address += 4;
1192 words_remaining--;
1193 }
1194
1195 if (bytes_remaining) {
1196 uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
1197
1198 /* copy the last remaining bytes into the write buffer */
1199 memcpy(last_word, buffer+bytes_written, bytes_remaining);
1200
1201 if (!(address & 0xff))
1202 LOG_DEBUG("0x%" PRIx32 "", address);
1203
1204 /* Program one word */
1205 target_write_u32(target, FLASH_FMA, address);
1206 target_write_buffer(target, FLASH_FMD, 4, last_word);
1207 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1208 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1209 /* Wait until write complete */
1210 do {
1211 target_read_u32(target, FLASH_FMC, &flash_fmc);
1212 } while (flash_fmc & FMC_WRITE);
1213 }
1214
1215 /* Check access violations */
1216 target_read_u32(target, FLASH_CRIS, &flash_cris);
1217 if (flash_cris & (AMASK)) {
1218 LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
1219 return ERROR_FLASH_OPERATION_FAILED;
1220 }
1221 return ERROR_OK;
1222 }
1223
1224 static int stellaris_probe(struct flash_bank *bank)
1225 {
1226 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1227 int retval;
1228
1229 /* If this is a stellaris chip, it has flash; probe() is just
1230 * to figure out how much is present. Only do it once.
1231 */
1232 if (stellaris_info->did1 != 0)
1233 return ERROR_OK;
1234
1235 /* stellaris_read_part_info() already handled error checking and
1236 * reporting. Note that it doesn't write, so we don't care about
1237 * whether the target is halted or not.
1238 */
1239 retval = stellaris_read_part_info(bank);
1240 if (retval != ERROR_OK)
1241 return retval;
1242
1243 free(bank->sectors);
1244
1245 /* provide this for the benefit of the NOR flash framework */
1246 bank->size = stellaris_info->num_pages * stellaris_info->pagesize;
1247 bank->num_sectors = stellaris_info->num_pages;
1248 bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
1249 for (unsigned int i = 0; i < bank->num_sectors; i++) {
1250 bank->sectors[i].offset = i * stellaris_info->pagesize;
1251 bank->sectors[i].size = stellaris_info->pagesize;
1252 bank->sectors[i].is_erased = -1;
1253 bank->sectors[i].is_protected = -1;
1254 }
1255
1256 return retval;
1257 }
1258
1259 static int stellaris_mass_erase(struct flash_bank *bank)
1260 {
1261 struct target *target = NULL;
1262 struct stellaris_flash_bank *stellaris_info = NULL;
1263 uint32_t flash_fmc;
1264
1265 stellaris_info = bank->driver_priv;
1266 target = bank->target;
1267
1268 if (target->state != TARGET_HALTED) {
1269 LOG_ERROR("Target not halted");
1270 return ERROR_TARGET_NOT_HALTED;
1271 }
1272
1273 if (stellaris_info->did1 == 0)
1274 return ERROR_FLASH_BANK_NOT_PROBED;
1275
1276 /* Refresh flash controller timing */
1277 stellaris_read_clock_info(bank);
1278 stellaris_set_flash_timing(bank);
1279
1280 /* Clear and disable flash programming interrupts */
1281 target_write_u32(target, FLASH_CIM, 0);
1282 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1283
1284 /* REVISIT this clobbers state set by any halted firmware ...
1285 * it might want to process those IRQs.
1286 */
1287
1288 target_write_u32(target, FLASH_FMA, 0);
1289 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1290 /* Wait until erase complete */
1291 do {
1292 target_read_u32(target, FLASH_FMC, &flash_fmc);
1293 } while (flash_fmc & FMC_MERASE);
1294
1295 /* if device has > 128k, then second erase cycle is needed
1296 * this is only valid for older devices, but will not hurt */
1297 if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) {
1298 target_write_u32(target, FLASH_FMA, 0x20000);
1299 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1300 /* Wait until erase complete */
1301 do {
1302 target_read_u32(target, FLASH_FMC, &flash_fmc);
1303 } while (flash_fmc & FMC_MERASE);
1304 }
1305
1306 return ERROR_OK;
1307 }
1308
1309 COMMAND_HANDLER(stellaris_handle_mass_erase_command)
1310 {
1311 if (CMD_ARGC < 1)
1312 return ERROR_COMMAND_SYNTAX_ERROR;
1313
1314 struct flash_bank *bank;
1315 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1316 if (retval != ERROR_OK)
1317 return retval;
1318
1319 if (stellaris_mass_erase(bank) == ERROR_OK)
1320 command_print(CMD, "stellaris mass erase complete");
1321 else
1322 command_print(CMD, "stellaris mass erase failed");
1323
1324 return ERROR_OK;
1325 }
1326
1327 /**
1328 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1329 * This performs a mass erase and then restores all nonvolatile registers
1330 * (including USER_* registers and flash lock bits) to their defaults.
1331 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1332 *
1333 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1334 * can affect this operation if flash protection has been enabled.
1335 */
1336 COMMAND_HANDLER(stellaris_handle_recover_command)
1337 {
1338 struct flash_bank *bank;
1339 struct arm *arm;
1340 int retval;
1341
1342 if (CMD_ARGC != 0)
1343 return ERROR_COMMAND_SYNTAX_ERROR;
1344
1345 bank = get_flash_bank_by_num_noprobe(0);
1346 if (!bank)
1347 return ERROR_FAIL;
1348
1349 /* REVISIT ... it may be worth sanity checking that the AP is
1350 * inactive before we start. ARM documents that switching a DP's
1351 * mode while it's active can cause fault modes that need a power
1352 * cycle to recover.
1353 */
1354
1355 Jim_Eval_Named(CMD_CTX->interp, "catch { hla_command \"debug unlock\" }", 0, 0);
1356 if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL), "0")) {
1357 retval = ERROR_OK;
1358 goto user_action;
1359 }
1360
1361 /* assert SRST */
1362 if (!(jtag_get_reset_config() & RESET_HAS_SRST)) {
1363 LOG_ERROR("Can't recover Stellaris flash without SRST");
1364 return ERROR_FAIL;
1365 }
1366 adapter_assert_reset();
1367
1368 arm = target_to_arm(bank->target);
1369 for (int i = 0; i < 5; i++) {
1370 retval = dap_to_swd(arm->dap);
1371 if (retval != ERROR_OK)
1372 goto done;
1373
1374 retval = dap_to_jtag(arm->dap);
1375 if (retval != ERROR_OK)
1376 goto done;
1377 }
1378
1379 /* de-assert SRST */
1380 adapter_deassert_reset();
1381 retval = jtag_execute_queue();
1382
1383 /* wait 400+ msec ... OK, "1+ second" is simpler */
1384 usleep(1000);
1385
1386 user_action:
1387 /* USER INTERVENTION required for the power cycle
1388 * Restarting OpenOCD is likely needed because of mode switching.
1389 */
1390 LOG_INFO("USER ACTION: "
1391 "power cycle Stellaris chip, then restart OpenOCD.");
1392
1393 done:
1394 return retval;
1395 }
1396
1397 static const struct command_registration stellaris_exec_command_handlers[] = {
1398 {
1399 .name = "mass_erase",
1400 .usage = "<bank>",
1401 .handler = stellaris_handle_mass_erase_command,
1402 .mode = COMMAND_EXEC,
1403 .help = "erase entire device",
1404 },
1405 {
1406 .name = "recover",
1407 .handler = stellaris_handle_recover_command,
1408 .mode = COMMAND_EXEC,
1409 .usage = "",
1410 .help = "recover (and erase) locked device",
1411 },
1412 COMMAND_REGISTRATION_DONE
1413 };
1414 static const struct command_registration stellaris_command_handlers[] = {
1415 {
1416 .name = "stellaris",
1417 .mode = COMMAND_EXEC,
1418 .help = "Stellaris flash command group",
1419 .usage = "",
1420 .chain = stellaris_exec_command_handlers,
1421 },
1422 COMMAND_REGISTRATION_DONE
1423 };
1424
1425 const struct flash_driver stellaris_flash = {
1426 .name = "stellaris",
1427 .commands = stellaris_command_handlers,
1428 .flash_bank_command = stellaris_flash_bank_command,
1429 .erase = stellaris_erase,
1430 .protect = stellaris_protect,
1431 .write = stellaris_write,
1432 .read = default_flash_read,
1433 .probe = stellaris_probe,
1434 .auto_probe = stellaris_probe,
1435 .erase_check = default_flash_blank_check,
1436 .protect_check = stellaris_protect_check,
1437 .info = get_stellaris_info,
1438 .free_driver_priv = default_flash_free_driver_priv,
1439 };

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)