aduc702x_flash_bank_t -> struct aduc702x_flash_bank
[openocd.git] / src / flash / aduc702x.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Kevin McGuire *
3 * Copyright (C) 2008 by Marcel Wijlaars *
4 * Copyright (C) 2009 by Michael Ashton *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20 ***************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "flash.h"
27 #include "armv4_5.h"
28 #include "binarybuffer.h"
29 #include "time_support.h"
30
31
32 static int aduc702x_build_sector_list(struct flash_bank_s *bank);
33 static int aduc702x_check_flash_completion(target_t* target, unsigned int timeout_ms);
34 static int aduc702x_set_write_enable(target_t *target, int enable);
35
36 #define ADUC702x_FLASH 0xfffff800
37 #define ADUC702x_FLASH_FEESTA (0*4)
38 #define ADUC702x_FLASH_FEEMOD (1*4)
39 #define ADUC702x_FLASH_FEECON (2*4)
40 #define ADUC702x_FLASH_FEEDAT (3*4)
41 #define ADUC702x_FLASH_FEEADR (4*4)
42 #define ADUC702x_FLASH_FEESIGN (5*4)
43 #define ADUC702x_FLASH_FEEPRO (6*4)
44 #define ADUC702x_FLASH_FEEHIDE (7*4)
45
46 typedef struct {
47 uint32_t feesta;
48 uint32_t feemod;
49 uint32_t feecon;
50 uint32_t feedat;
51 uint32_t feeadr;
52 uint32_t feesign;
53 uint32_t feepro;
54 uint32_t feehide;
55 } ADUC702x_FLASH_MMIO;
56
57 struct aduc702x_flash_bank {
58 working_area_t *write_algorithm;
59 };
60
61 /* flash bank aduc702x 0 0 0 0 <target#>
62 * The ADC7019-28 devices all have the same flash layout */
63 FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command)
64 {
65 struct aduc702x_flash_bank *nbank;
66
67 nbank = malloc(sizeof(struct aduc702x_flash_bank));
68
69 bank->base = 0x80000;
70 bank->size = 0xF800; // top 4k not accessible
71 bank->driver_priv = nbank;
72
73 aduc702x_build_sector_list(bank);
74
75 return ERROR_OK;
76 }
77
78 static int aduc702x_build_sector_list(struct flash_bank_s *bank)
79 {
80 //aduc7026_flash_bank_t *aduc7026_info = bank->driver_priv;
81
82 int i = 0;
83 uint32_t offset = 0;
84
85 // sector size is 512
86 bank->num_sectors = bank->size / 512;
87 bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
88 for (i = 0; i < bank->num_sectors; ++i)
89 {
90 bank->sectors[i].offset = offset;
91 bank->sectors[i].size = 512;
92 offset += bank->sectors[i].size;
93 bank->sectors[i].is_erased = -1;
94 bank->sectors[i].is_protected = 0;
95 }
96
97 return ERROR_OK;
98 }
99
100 static int aduc702x_protect_check(struct flash_bank_s *bank)
101 {
102 printf("aduc702x_protect_check not implemented yet.\n");
103 return ERROR_OK;
104 }
105
106 static int aduc702x_erase(struct flash_bank_s *bank, int first, int last)
107 {
108 //int res;
109 int x;
110 int count;
111 //uint32_t v;
112 target_t *target = bank->target;
113
114 aduc702x_set_write_enable(target, 1);
115
116 /* mass erase */
117 if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) {
118 LOG_DEBUG("performing mass erase.\n");
119 target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, 0x3cff);
120 target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3);
121 target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06);
122
123 if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK)
124 {
125 LOG_ERROR("mass erase failed\n");
126 aduc702x_set_write_enable(target, 0);
127 return ERROR_FLASH_OPERATION_FAILED;
128 }
129
130 LOG_DEBUG("mass erase successful.\n");
131 return ERROR_OK;
132 } else {
133 unsigned long adr;
134
135 count = last - first + 1;
136 for (x = 0; x < count; ++x)
137 {
138 adr = bank->base + ((first + x) * 512);
139
140 target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr);
141 target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05);
142
143 if (aduc702x_check_flash_completion(target, 50) != ERROR_OK)
144 {
145 LOG_ERROR("failed to erase sector at address 0x%08lX\n", adr);
146 aduc702x_set_write_enable(target, 0);
147 return ERROR_FLASH_SECTOR_NOT_ERASED;
148 }
149
150 LOG_DEBUG("erased sector at address 0x%08lX\n", adr);
151 }
152 }
153
154 aduc702x_set_write_enable(target, 0);
155
156 return ERROR_OK;
157 }
158
159 static int aduc702x_protect(struct flash_bank_s *bank, int set, int first, int last)
160 {
161 printf("aduc702x_protect not implemented yet.\n");
162 return ERROR_FLASH_OPERATION_FAILED;
163 }
164
165 /* If this fn returns ERROR_TARGET_RESOURCE_NOT_AVAILABLE, then the caller can fall
166 * back to another mechanism that does not require onboard RAM
167 *
168 * Caller should not check for other return values specifically
169 */
170 static int aduc702x_write_block(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
171 {
172 struct aduc702x_flash_bank *aduc702x_info = bank->driver_priv;
173 target_t *target = bank->target;
174 uint32_t buffer_size = 7000;
175 working_area_t *source;
176 uint32_t address = bank->base + offset;
177 reg_param_t reg_params[6];
178 armv4_5_algorithm_t armv4_5_info;
179 int retval = ERROR_OK;
180
181 if (((count%2)!=0)||((offset%2)!=0))
182 {
183 LOG_ERROR("write block must be multiple of two bytes in offset & length");
184 return ERROR_FAIL;
185 }
186
187 /* parameters:
188
189 r0 - address of source data (absolute)
190 r1 - number of halfwords to be copied
191 r2 - start address in flash (offset from beginning of flash memory)
192 r3 - exit code
193 r4 - base address of flash controller (0xFFFFF800)
194
195 registers:
196
197 r5 - scratch
198 r6 - set to 2, used to write flash command
199
200 */
201 uint32_t aduc702x_flash_write_code[] = {
202 //<_start>:
203 0xe3a05008, // mov r5, #8 ; 0x8
204 0xe5845004, // str r5, [r4, #4]
205 0xe3a06002, // mov r6, #2 ; 0x2
206 //<next>:
207 0xe1c421b0, // strh r2, [r4, #16]
208 0xe0d050b2, // ldrh r5, [r0], #2
209 0xe1c450bc, // strh r5, [r4, #12]
210 0xe5c46008, // strb r6, [r4, #8]
211 //<wait_complete>:
212 0xe1d430b0, // ldrh r3, [r4]
213 0xe3130004, // tst r3, #4 ; 0x4
214 0x1afffffc, // bne 1001c <wait_complete>
215 0xe2822002, // add r2, r2, #2 ; 0x2
216 0xe2511001, // subs r1, r1, #1 ; 0x1
217 0x0a000001, // beq 1003c <done>
218 0xe3130001, // tst r3, #1 ; 0x1
219 0x1afffff3, // bne 1000c <next>
220 //<done>:
221 0xeafffffe // b 1003c <done>
222 };
223
224 /* flash write code */
225 if (target_alloc_working_area(target, sizeof(aduc702x_flash_write_code),
226 &aduc702x_info->write_algorithm) != ERROR_OK)
227 {
228 LOG_WARNING("no working area available, can't do block memory writes");
229 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
230 };
231
232 retval=target_write_buffer(target, aduc702x_info->write_algorithm->address,
233 sizeof(aduc702x_flash_write_code), (uint8_t*)aduc702x_flash_write_code);
234 if (retval!=ERROR_OK)
235 {
236 return retval;
237 }
238
239 /* memory buffer */
240 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
241 {
242 buffer_size /= 2;
243 if (buffer_size <= 256)
244 {
245 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
246 if (aduc702x_info->write_algorithm)
247 target_free_working_area(target, aduc702x_info->write_algorithm);
248
249 LOG_WARNING("no large enough working area available, can't do block memory writes");
250 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
251 }
252 }
253
254 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
255 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
256 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
257
258 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
259 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
260 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
261 init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
262 init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
263
264 while (count > 0)
265 {
266 uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;
267
268 retval=target_write_buffer(target, source->address, thisrun_count, buffer);
269 if (retval!=ERROR_OK)
270 {
271 break;
272 }
273
274 buf_set_u32(reg_params[0].value, 0, 32, source->address);
275 buf_set_u32(reg_params[1].value, 0, 32, thisrun_count/2);
276 buf_set_u32(reg_params[2].value, 0, 32, address);
277 buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800);
278
279 if ((retval = target_run_algorithm(target, 0, NULL, 5,
280 reg_params, aduc702x_info->write_algorithm->address,
281 aduc702x_info->write_algorithm->address + sizeof(aduc702x_flash_write_code) - 4,
282 10000, &armv4_5_info)) != ERROR_OK)
283 {
284 LOG_ERROR("error executing aduc702x flash write algorithm");
285 break;
286 }
287
288 if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1)
289 {
290 /* FIX!!!! what does this mean??? replace w/sensible error message */
291 LOG_ERROR("aduc702x detected error writing flash");
292 retval = ERROR_FAIL;
293 break;
294 }
295
296 buffer += thisrun_count;
297 address += thisrun_count;
298 count -= thisrun_count;
299 }
300
301 target_free_working_area(target, source);
302 target_free_working_area(target, aduc702x_info->write_algorithm);
303
304 destroy_reg_param(&reg_params[0]);
305 destroy_reg_param(&reg_params[1]);
306 destroy_reg_param(&reg_params[2]);
307 destroy_reg_param(&reg_params[3]);
308 destroy_reg_param(&reg_params[4]);
309
310 return retval;
311 }
312
313 /* All-JTAG, single-access method. Very slow. Used only if there is no
314 * working area available. */
315 static int aduc702x_write_single(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
316 {
317 uint32_t x;
318 uint8_t b;
319 target_t *target = bank->target;
320
321 aduc702x_set_write_enable(target, 1);
322
323 for (x = 0; x < count; x += 2) {
324 // FEEADR = address
325 target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, offset + x);
326
327 // set up data
328 if ((x + 1) == count)
329 {
330 // last byte
331 target_read_u8(target, offset + x + 1, &b);
332 }
333 else
334 b = buffer[x + 1];
335
336 target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, buffer[x] | (b << 8));
337
338 // do single-write command
339 target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x02);
340
341 if (aduc702x_check_flash_completion(target, 1) != ERROR_OK)
342 {
343 LOG_ERROR("single write failed for address 0x%08lX\n", (unsigned long)(offset + x));
344 aduc702x_set_write_enable(target, 0);
345 return ERROR_FLASH_OPERATION_FAILED;
346 }
347
348 }
349 LOG_DEBUG("wrote %d bytes at address 0x%08lX\n", (int)count, (unsigned long)(offset + x));
350
351 aduc702x_set_write_enable(target, 0);
352
353 return ERROR_OK;
354 }
355
356 int aduc702x_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
357 {
358 int retval;
359
360 /* try using a block write */
361 if ((retval = aduc702x_write_block(bank, buffer, offset, count)) != ERROR_OK)
362 {
363 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
364 {
365 /* if block write failed (no sufficient working area),
366 * use normal (slow) JTAG method */
367 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
368
369 if ((retval = aduc702x_write_single(bank, buffer, offset, count)) != ERROR_OK)
370 {
371 LOG_ERROR("slow write failed");
372 return ERROR_FLASH_OPERATION_FAILED;
373 }
374 }
375 }
376
377 return retval;
378 }
379
380 static int aduc702x_probe(struct flash_bank_s *bank)
381 {
382 return ERROR_OK;
383 }
384
385 static int aduc702x_info(struct flash_bank_s *bank, char *buf, int buf_size)
386 {
387 snprintf(buf, buf_size, "aduc702x flash driver info");
388 return ERROR_OK;
389 }
390
391 /* sets FEEMOD bit 3
392 * enable = 1 enables writes & erases, 0 disables them */
393 static int aduc702x_set_write_enable(target_t *target, int enable)
394 {
395 // don't bother to preserve int enable bit here
396 target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0);
397
398 return ERROR_OK;
399 }
400
401 /* wait up to timeout_ms for controller to not be busy,
402 * then check whether the command passed or failed.
403 *
404 * this function sleeps 1ms between checks (after the first one),
405 * so in some cases may slow things down without a usleep after the first read */
406 static int aduc702x_check_flash_completion(target_t* target, unsigned int timeout_ms)
407 {
408 uint8_t v = 4;
409
410 long long endtime = timeval_ms() + timeout_ms;
411 while (1) {
412 target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v);
413 if ((v & 4) == 0) break;
414 alive_sleep(1);
415 if (timeval_ms() >= endtime) break;
416 }
417
418 if (v & 2) return ERROR_FAIL;
419 // if a command is ignored, both the success and fail bits may be 0
420 else if ((v & 3) == 0) return ERROR_FAIL;
421 else return ERROR_OK;
422 }
423
424 struct flash_driver aduc702x_flash = {
425 .name = "aduc702x",
426 .flash_bank_command = &aduc702x_flash_bank_command,
427 .erase = &aduc702x_erase,
428 .protect = &aduc702x_protect,
429 .write = &aduc702x_write,
430 .probe = &aduc702x_probe,
431 .auto_probe = &aduc702x_probe,
432 .erase_check = &default_flash_blank_check,
433 .protect_check = &aduc702x_protect_check,
434 .info = &aduc702x_info
435 };

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)