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

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)