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