eCos flash driver.
[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 "replacements.h"
25
26
27 #include "flash.h"
28
29 #include "target.h"
30
31 #include "flash.h"
32 #include "target.h"
33 #include "log.h"
34 #include "binarybuffer.h"
35 #include "../target/embeddedice.h"
36 #include "types.h"
37
38
39
40 int ecosflash_register_commands(struct command_context_s *cmd_ctx);
41 int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
42 int ecosflash_erase(struct flash_bank_s *bank, int first, int last);
43 int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last);
44 int ecosflash_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
45 int ecosflash_probe(struct flash_bank_s *bank);
46 int ecosflash_erase_check(struct flash_bank_s *bank);
47 int ecosflash_protect_check(struct flash_bank_s *bank);
48 int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size);
49
50 u32 ecosflash_get_flash_status(flash_bank_t *bank);
51 void ecosflash_set_flash_mode(flash_bank_t *bank,int mode);
52 u32 ecosflash_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout);
53 int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
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 = ecosflash_erase_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 #define FLASH_ERR_OK 0x00 // No error - operation complete
82 #define FLASH_ERR_INVALID 0x01 // Invalid FLASH address
83 #define FLASH_ERR_ERASE 0x02 // Error trying to erase
84 #define FLASH_ERR_LOCK 0x03 // Error trying to lock/unlock
85 #define FLASH_ERR_PROGRAM 0x04 // Error trying to program
86 #define FLASH_ERR_PROTOCOL 0x05 // Generic error
87 #define FLASH_ERR_PROTECT 0x06 // Device/region is write-protected
88 #define FLASH_ERR_NOT_INIT 0x07 // FLASH info not yet initialized
89 #define FLASH_ERR_HWR 0x08 // Hardware (configuration?) problem
90 #define FLASH_ERR_ERASE_SUSPEND 0x09 // Device is in erase suspend mode
91 #define FLASH_ERR_PROGRAM_SUSPEND 0x0a // Device is in in program suspend mode
92 #define FLASH_ERR_DRV_VERIFY 0x0b // Driver failed to verify data
93 #define FLASH_ERR_DRV_TIMEOUT 0x0c // Driver timed out waiting for device
94 #define FLASH_ERR_DRV_WRONG_PART 0x0d // Driver does not support device
95 #define FLASH_ERR_LOW_VOLTAGE 0x0e // Not enough juice to complete job
96
97
98 char *
99 flash_errmsg(int err)
100 {
101 switch (err) {
102 case FLASH_ERR_OK:
103 return "No error - operation complete";
104 case FLASH_ERR_ERASE_SUSPEND:
105 return "Device is in erase suspend state";
106 case FLASH_ERR_PROGRAM_SUSPEND:
107 return "Device is in program suspend state";
108 case FLASH_ERR_INVALID:
109 return "Invalid FLASH address";
110 case FLASH_ERR_ERASE:
111 return "Error trying to erase";
112 case FLASH_ERR_LOCK:
113 return "Error trying to lock/unlock";
114 case FLASH_ERR_PROGRAM:
115 return "Error trying to program";
116 case FLASH_ERR_PROTOCOL:
117 return "Generic error";
118 case FLASH_ERR_PROTECT:
119 return "Device/region is write-protected";
120 case FLASH_ERR_NOT_INIT:
121 return "FLASH sub-system not initialized";
122 case FLASH_ERR_DRV_VERIFY:
123 return "Data verify failed after operation";
124 case FLASH_ERR_DRV_TIMEOUT:
125 return "Driver timed out waiting for device";
126 case FLASH_ERR_DRV_WRONG_PART:
127 return "Driver does not support device";
128 case FLASH_ERR_LOW_VOLTAGE:
129 return "Device reports low voltage";
130 default:
131 return "Unknown error";
132 }
133 }
134
135
136 /* flash bank ecosflash <base> <size> <chip_width> <bus_width> <target#> <driverPath>
137 */
138 int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
139 {
140 ecosflash_flash_bank_t *info;
141
142 if (argc < 7)
143 {
144 WARNING("incomplete flash_bank ecosflash configuration");
145 return ERROR_FLASH_BANK_INVALID;
146 }
147
148 info = malloc(sizeof(ecosflash_flash_bank_t));
149 if(info == NULL)
150 {
151 ERROR("no memory for flash bank info");
152 exit(-1);
153 }
154 bank->driver_priv = info;
155 info->driverPath=strdup(args[6]);
156
157 // eCos flash sector sizes are not exposed to OpenOCD, use 0x10000 as
158 // a way to improve impeadance matach between OpenOCD and eCos flash
159 // driver
160 int i = 0;
161 u32 offset = 0;
162 bank->num_sectors=bank->size/sectorSize;
163 bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
164 for (i = 0; i < bank->num_sectors; i++)
165 {
166 bank->sectors[i].offset = offset;
167 bank->sectors[i].size = sectorSize;
168 offset += bank->sectors[i].size;
169 bank->sectors[i].is_erased = -1;
170 bank->sectors[i].is_protected = 0;
171 }
172
173 info->target = get_target_by_num(strtoul(args[5], NULL, 0));
174 if (info->target == NULL)
175 {
176 ERROR("no target '%i' configured", (int)strtoul(args[5], NULL, 0));
177 exit(-1);
178 }
179 return ERROR_OK;
180 }
181
182
183 int loadDriver(ecosflash_flash_bank_t *info)
184 {
185 u32 buf_cnt;
186 u32 image_size;
187 image_t image;
188
189 image.base_address_set = 0;
190 image.start_address_set = 0;
191 target_t *target=info->target;
192
193 if (image_open(&image, info->driverPath, NULL) != ERROR_OK)
194 {
195 ERROR("load_image error: %s", image.error_str);
196 return ERROR_FLASH_BANK_INVALID;
197 }
198
199 info->start_address=image.start_address;
200
201 image_size = 0x0;
202 int i;
203 for (i = 0; i < image.num_sections; i++)
204 {
205 void *buffer = malloc(image.sections[i].size);
206 int retval;
207 if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
208 {
209 ERROR("image_read_section failed with error code: %i", retval);
210 free(buffer);
211 image_close(&image);
212 return ERROR_FLASH_BANK_INVALID;
213 }
214 target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
215 image_size += buf_cnt;
216 DEBUG("%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);
217
218 free(buffer);
219 }
220
221 image_close(&image);
222
223 return ERROR_OK;
224 }
225
226
227 static int const OFFSET_ERASE=0x0;
228 static int const OFFSET_ERASE_SIZE=0x8;
229 static int const OFFSET_FLASH=0xc;
230 static int const OFFSET_FLASH_SIZE=0x8;
231 static int const OFFSET_GET_WORKAREA=0x18;
232 static int const OFFSET_GET_WORKAREA_SIZE=0x4;
233
234
235 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 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 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 ERROR("Flash erase failed with %d (%s)\n", flashErr, flash_errmsg(flashErr));
301 return ERROR_JTAG_DEVICE_ERROR;
302 }
303
304 return ERROR_OK;
305 }
306
307 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 int 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, ((char *)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 ERROR("Flash prog failed with %d (%s)\n", flashErr, flash_errmsg(flashErr));
360 return ERROR_JTAG_DEVICE_ERROR;
361 }
362 }
363 return ERROR_OK;
364 }
365
366
367 int ecosflash_probe(struct flash_bank_s *bank)
368 {
369 return ERROR_OK;
370 }
371
372
373 int ecosflash_register_commands(struct command_context_s *cmd_ctx)
374 {
375 register_command(cmd_ctx, NULL, "ecosflash", NULL, COMMAND_ANY, NULL);
376
377 return ERROR_OK;
378 }
379
380 /*
381 static void command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf)
382 {
383 ecosflash_flash_bank_t *info = bank->driver_priv;
384 int i;
385
386 if (info->target->endianness == TARGET_LITTLE_ENDIAN)
387 {
388 for (i = bank->bus_width; i > 0; i--)
389 {
390 *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
391 }
392 }
393 else
394 {
395 for (i = 1; i <= bank->bus_width; i++)
396 {
397 *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
398 }
399 }
400 }
401 */
402
403 u32 ecosflash_address(struct flash_bank_s *bank, u32 address)
404 {
405 u32 retval = 0;
406 switch(bank->bus_width)
407 {
408 case 4:
409 retval = address & 0xfffffffc;
410 case 2:
411 retval = address & 0xfffffffe;
412 case 1:
413 retval = address;
414 }
415
416 return retval + bank->base;
417 }
418
419
420 int ecosflash_erase(struct flash_bank_s *bank, int first, int last)
421 {
422 struct flash_bank_s *c=bank;
423 ecosflash_flash_bank_t *info = bank->driver_priv;
424 return eCosBoard_erase(info, c->base+first*sectorSize, sectorSize*(last-first+1));
425 }
426
427 int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last)
428 {
429 return ERROR_OK;
430 }
431
432
433 int ecosflash_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
434 {
435 ecosflash_flash_bank_t *info = bank->driver_priv;
436 struct flash_bank_s *c=bank;
437 return eCosBoard_flash(info, buffer, c->base+offset, count);
438 }
439
440
441 int ecosflash_erase_check(struct flash_bank_s *bank)
442 {
443 return ERROR_OK;
444 }
445
446 int ecosflash_protect_check(struct flash_bank_s *bank)
447 {
448 return ERROR_OK;
449 }
450
451 int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size)
452 {
453 ecosflash_flash_bank_t *info = bank->driver_priv;
454 snprintf(buf, buf_size, "eCos flash driver: %s", info->driverPath);
455 return ERROR_OK;
456 }
457
458
459 u32 ecosflash_get_flash_status(flash_bank_t *bank)
460 {
461 return ERROR_OK;
462 }
463
464 void ecosflash_set_flash_mode(flash_bank_t *bank,int mode)
465 {
466
467 }
468
469 u32 ecosflash_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout)
470 {
471 return ERROR_OK;
472 }
473
474 int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
475 {
476 return ERROR_OK;
477 }
478
479
480
481

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)