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

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)