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

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)