4127cf5304d41faa33790383b54c4e3b417a2817
[openocd.git] / src / flash / ecos.c
1 /***************************************************************************
2 * Copyright (C) 2008 Øyvind Harboe *
3 * oyvind.harboe@zylin.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <string.h>
25
26 #include "replacements.h"
27
28
29 #include "flash.h"
30
31 #include "target.h"
32
33 #include "flash.h"
34 #include "target.h"
35 #include "log.h"
36 #include "binarybuffer.h"
37 #include "../target/embeddedice.h"
38 #include "types.h"
39
40
41
42 int ecosflash_register_commands(struct command_context_s *cmd_ctx);
43 int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
44 int ecosflash_erase(struct flash_bank_s *bank, int first, int last);
45 int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last);
46 int ecosflash_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
47 int ecosflash_probe(struct flash_bank_s *bank);
48 int ecosflash_erase_check(struct flash_bank_s *bank);
49 int ecosflash_protect_check(struct flash_bank_s *bank);
50 int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size);
51
52 u32 ecosflash_get_flash_status(flash_bank_t *bank);
53 void ecosflash_set_flash_mode(flash_bank_t *bank,int mode);
54 u32 ecosflash_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout);
55 int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
56
57 flash_driver_t ecosflash_flash =
58 {
59 .name = "ecosflash",
60 .register_commands = ecosflash_register_commands,
61 .flash_bank_command = ecosflash_flash_bank_command,
62 .erase = ecosflash_erase,
63 .protect = ecosflash_protect,
64 .write = ecosflash_write,
65 .probe = ecosflash_probe,
66 .auto_probe = ecosflash_probe,
67 .erase_check = ecosflash_erase_check,
68 .protect_check = ecosflash_protect_check,
69 .info = ecosflash_info
70 };
71
72 typedef struct ecosflash_flash_bank_s
73 {
74 struct target_s *target;
75 working_area_t *write_algorithm;
76 working_area_t *erase_check_algorithm;
77 char *driverPath;
78 u32 start_address;
79 } ecosflash_flash_bank_t;
80
81 static const int sectorSize=0x10000;
82
83 char *
84 flash_errmsg(int err);
85
86 #ifndef __ECOS
87 #define FLASH_ERR_OK 0x00 /* No error - operation complete */
88 #define FLASH_ERR_INVALID 0x01 /* Invalid FLASH address */
89 #define FLASH_ERR_ERASE 0x02 /* Error trying to erase */
90 #define FLASH_ERR_LOCK 0x03 /* Error trying to lock/unlock */
91 #define FLASH_ERR_PROGRAM 0x04 /* Error trying to program */
92 #define FLASH_ERR_PROTOCOL 0x05 /* Generic error */
93 #define FLASH_ERR_PROTECT 0x06 /* Device/region is write-protected */
94 #define FLASH_ERR_NOT_INIT 0x07 /* FLASH info not yet initialized */
95 #define FLASH_ERR_HWR 0x08 /* Hardware (configuration?) problem */
96 #define FLASH_ERR_ERASE_SUSPEND 0x09 /* Device is in erase suspend mode */
97 #define FLASH_ERR_PROGRAM_SUSPEND 0x0a /* Device is in in program suspend mode */
98 #define FLASH_ERR_DRV_VERIFY 0x0b /* Driver failed to verify data */
99 #define FLASH_ERR_DRV_TIMEOUT 0x0c /* Driver timed out waiting for device */
100 #define FLASH_ERR_DRV_WRONG_PART 0x0d /* Driver does not support device */
101 #define FLASH_ERR_LOW_VOLTAGE 0x0e /* Not enough juice to complete job */
102
103
104 char *
105 flash_errmsg(int err)
106 {
107 switch (err) {
108 case FLASH_ERR_OK:
109 return "No error - operation complete";
110 case FLASH_ERR_ERASE_SUSPEND:
111 return "Device is in erase suspend state";
112 case FLASH_ERR_PROGRAM_SUSPEND:
113 return "Device is in program suspend state";
114 case FLASH_ERR_INVALID:
115 return "Invalid FLASH address";
116 case FLASH_ERR_ERASE:
117 return "Error trying to erase";
118 case FLASH_ERR_LOCK:
119 return "Error trying to lock/unlock";
120 case FLASH_ERR_PROGRAM:
121 return "Error trying to program";
122 case FLASH_ERR_PROTOCOL:
123 return "Generic error";
124 case FLASH_ERR_PROTECT:
125 return "Device/region is write-protected";
126 case FLASH_ERR_NOT_INIT:
127 return "FLASH sub-system not initialized";
128 case FLASH_ERR_DRV_VERIFY:
129 return "Data verify failed after operation";
130 case FLASH_ERR_DRV_TIMEOUT:
131 return "Driver timed out waiting for device";
132 case FLASH_ERR_DRV_WRONG_PART:
133 return "Driver does not support device";
134 case FLASH_ERR_LOW_VOLTAGE:
135 return "Device reports low voltage";
136 default:
137 return "Unknown error";
138 }
139 }
140 #endif
141
142 /* flash bank ecosflash <base> <size> <chip_width> <bus_width> <target#> <driverPath>
143 */
144 int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
145 {
146 ecosflash_flash_bank_t *info;
147
148 if (argc < 7)
149 {
150 WARNING("incomplete flash_bank ecosflash configuration");
151 return ERROR_FLASH_BANK_INVALID;
152 }
153
154 info = malloc(sizeof(ecosflash_flash_bank_t));
155 if(info == NULL)
156 {
157 ERROR("no memory for flash bank info");
158 exit(-1);
159 }
160 bank->driver_priv = info;
161 info->driverPath=strdup(args[6]);
162
163 /* eCos flash sector sizes are not exposed to OpenOCD, use 0x10000 as
164 * a way to improve impeadance matach between OpenOCD and eCos flash
165 * driver.
166 */
167 int i = 0;
168 u32 offset = 0;
169 bank->num_sectors=bank->size/sectorSize;
170 bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
171 for (i = 0; i < bank->num_sectors; i++)
172 {
173 bank->sectors[i].offset = offset;
174 bank->sectors[i].size = sectorSize;
175 offset += bank->sectors[i].size;
176 bank->sectors[i].is_erased = -1;
177 bank->sectors[i].is_protected = 0;
178 }
179
180 info->target = get_target_by_num(strtoul(args[5], NULL, 0));
181 if (info->target == NULL)
182 {
183 ERROR("no target '%i' configured", (int)strtoul(args[5], NULL, 0));
184 exit(-1);
185 }
186 return ERROR_OK;
187 }
188
189
190 int loadDriver(ecosflash_flash_bank_t *info)
191 {
192 u32 buf_cnt;
193 u32 image_size;
194 image_t image;
195
196 image.base_address_set = 0;
197 image.start_address_set = 0;
198 target_t *target=info->target;
199
200 if (image_open(&image, info->driverPath, NULL) != ERROR_OK)
201 {
202 return ERROR_FLASH_BANK_INVALID;
203 }
204
205 info->start_address=image.start_address;
206
207 image_size = 0x0;
208 int i;
209 for (i = 0; i < image.num_sections; i++)
210 {
211 void *buffer = malloc(image.sections[i].size);
212 int retval;
213 if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
214 {
215 ERROR("image_read_section failed with error code: %i", retval);
216 free(buffer);
217 image_close(&image);
218 return ERROR_FLASH_BANK_INVALID;
219 }
220 target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
221 image_size += buf_cnt;
222 DEBUG("%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);
223
224 free(buffer);
225 }
226
227 image_close(&image);
228
229 return ERROR_OK;
230 }
231
232
233 static int const OFFSET_ERASE=0x0;
234 static int const OFFSET_ERASE_SIZE=0x8;
235 static int const OFFSET_FLASH=0xc;
236 static int const OFFSET_FLASH_SIZE=0x8;
237 static int const OFFSET_GET_WORKAREA=0x18;
238 static int const OFFSET_GET_WORKAREA_SIZE=0x4;
239
240
241 int runCode(ecosflash_flash_bank_t *info,
242 u32 codeStart, u32 codeStop, u32 r0, u32 r1, u32 r2,
243 u32 *result,
244 /* timeout in ms */
245 int timeout)
246 {
247 target_t *target=info->target;
248
249 reg_param_t reg_params[3];
250 armv4_5_algorithm_t armv4_5_info;
251 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
252 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
253 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
254
255 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
256 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
257 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
258
259 buf_set_u32(reg_params[0].value, 0, 32, r0);
260 buf_set_u32(reg_params[1].value, 0, 32, r1);
261 buf_set_u32(reg_params[2].value, 0, 32, r2);
262
263 int retval;
264 if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params,
265 codeStart,
266 codeStop, timeout,
267 &armv4_5_info)) != ERROR_OK)
268 {
269 ERROR("error executing eCos flash algorithm");
270 return retval;
271 }
272
273 *result=buf_get_u32(reg_params[0].value, 0, 32);
274
275 destroy_reg_param(&reg_params[0]);
276 destroy_reg_param(&reg_params[1]);
277 destroy_reg_param(&reg_params[2]);
278
279 return ERROR_OK;
280 }
281
282 int eCosBoard_erase(ecosflash_flash_bank_t *info, u32 address, u32 len)
283 {
284 int retval;
285 int timeout = (len / 20480 + 1) * 1000; /*asume 20 KB/s*/
286
287 retval=loadDriver(info);
288 if (retval!=ERROR_OK)
289 return retval;
290
291 u32 flashErr;
292 retval=runCode(info,
293 info->start_address+OFFSET_ERASE,
294 info->start_address+OFFSET_ERASE+OFFSET_ERASE_SIZE,
295 address,
296 len,
297 0,
298 &flashErr,
299 timeout
300 );
301 if (retval!=ERROR_OK)
302 return retval;
303
304 if (flashErr != 0x0)
305 {
306 ERROR("Flash erase failed with %d (%s)\n", flashErr, flash_errmsg(flashErr));
307 return ERROR_JTAG_DEVICE_ERROR;
308 }
309
310 return ERROR_OK;
311 }
312
313 int eCosBoard_flash(ecosflash_flash_bank_t *info, void *data, u32 address, u32 len)
314 {
315 target_t *target=info->target;
316 const int chunk=8192;
317 int retval=ERROR_OK;
318 int timeout = (chunk / 20480 + 1) * 1000; /*asume 20 KB/s + 1 second*/
319
320 retval=loadDriver(info);
321 if (retval!=ERROR_OK)
322 return retval;
323
324 u32 buffer;
325 retval=runCode(info,
326 info->start_address+OFFSET_GET_WORKAREA,
327 info->start_address+OFFSET_GET_WORKAREA+OFFSET_GET_WORKAREA_SIZE,
328 0,
329 0,
330 0,
331 &buffer,
332 1000);
333 if (retval!=ERROR_OK)
334 return retval;
335
336
337 int i;
338 for (i=0; i<len; i+=chunk)
339 {
340 int t=len-i;
341 if (t>chunk)
342 {
343 t=chunk;
344 }
345
346 int retval;
347 retval=target_write_buffer(target, buffer, t, ((u8 *)data)+i);
348 if (retval != ERROR_OK)
349 return retval;
350
351 u32 flashErr;
352 retval=runCode(info,
353 info->start_address+OFFSET_FLASH,
354 info->start_address+OFFSET_FLASH+OFFSET_FLASH_SIZE,
355 buffer,
356 address+i,
357 t,
358 &flashErr,
359 timeout);
360 if (retval != ERROR_OK)
361 return retval;
362
363 if (flashErr != 0x0)
364 {
365 ERROR("Flash prog failed with %d (%s)\n", flashErr, flash_errmsg(flashErr));
366 return ERROR_JTAG_DEVICE_ERROR;
367 }
368 }
369 return ERROR_OK;
370 }
371
372
373 int ecosflash_probe(struct flash_bank_s *bank)
374 {
375 return ERROR_OK;
376 }
377
378
379 int ecosflash_register_commands(struct command_context_s *cmd_ctx)
380 {
381 register_command(cmd_ctx, NULL, "ecosflash", NULL, COMMAND_ANY, NULL);
382
383 return ERROR_OK;
384 }
385
386 /*
387 static void command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf)
388 {
389 ecosflash_flash_bank_t *info = bank->driver_priv;
390 int i;
391
392 if (info->target->endianness == TARGET_LITTLE_ENDIAN)
393 {
394 for (i = bank->bus_width; i > 0; i--)
395 {
396 *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
397 }
398 }
399 else
400 {
401 for (i = 1; i <= bank->bus_width; i++)
402 {
403 *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
404 }
405 }
406 }
407 */
408
409 u32 ecosflash_address(struct flash_bank_s *bank, u32 address)
410 {
411 u32 retval = 0;
412 switch(bank->bus_width)
413 {
414 case 4:
415 retval = address & 0xfffffffc;
416 case 2:
417 retval = address & 0xfffffffe;
418 case 1:
419 retval = address;
420 }
421
422 return retval + bank->base;
423 }
424
425
426 int ecosflash_erase(struct flash_bank_s *bank, int first, int last)
427 {
428 struct flash_bank_s *c=bank;
429 ecosflash_flash_bank_t *info = bank->driver_priv;
430 return eCosBoard_erase(info, c->base+first*sectorSize, sectorSize*(last-first+1));
431 }
432
433 int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last)
434 {
435 return ERROR_OK;
436 }
437
438
439 int ecosflash_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
440 {
441 ecosflash_flash_bank_t *info = bank->driver_priv;
442 struct flash_bank_s *c=bank;
443 return eCosBoard_flash(info, buffer, c->base+offset, count);
444 }
445
446
447 int ecosflash_erase_check(struct flash_bank_s *bank)
448 {
449 return ERROR_OK;
450 }
451
452 int ecosflash_protect_check(struct flash_bank_s *bank)
453 {
454 return ERROR_OK;
455 }
456
457 int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size)
458 {
459 ecosflash_flash_bank_t *info = bank->driver_priv;
460 snprintf(buf, buf_size, "eCos flash driver: %s", info->driverPath);
461 return ERROR_OK;
462 }
463
464
465 u32 ecosflash_get_flash_status(flash_bank_t *bank)
466 {
467 return ERROR_OK;
468 }
469
470 void ecosflash_set_flash_mode(flash_bank_t *bank,int mode)
471 {
472
473 }
474
475 u32 ecosflash_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout)
476 {
477 return ERROR_OK;
478 }
479
480 int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
481 {
482 return ERROR_OK;
483 }
484
485
486
487

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)