- prepare OpenOCD for branching, created ./trunk/
[openocd.git] / src / flash / str7x.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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
21 #include "str7x.h"
22 #include "flash.h"
23 #include "target.h"
24 #include "log.h"
25 #include "armv4_5.h"
26 #include "algorithm.h"
27 #include "binarybuffer.h"
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32
33 str7x_mem_layout_t mem_layout[] = {
34 {0x00000000, 0x02000, 0x01},
35 {0x00002000, 0x02000, 0x01},
36 {0x00004000, 0x02000, 0x01},
37 {0x00006000, 0x02000, 0x01},
38 {0x00008000, 0x08000, 0x01},
39 {0x00010000, 0x10000, 0x01},
40 {0x00020000, 0x10000, 0x01},
41 {0x00030000, 0x10000, 0x01},
42 {0x000C0000, 0x02000, 0x10},
43 {0x000C2000, 0x02000, 0x10},
44 {0,0},
45 };
46
47 int str7x_register_commands(struct command_context_s *cmd_ctx);
48 int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
49 int str7x_erase(struct flash_bank_s *bank, int first, int last);
50 int str7x_protect(struct flash_bank_s *bank, int set, int first, int last);
51 int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
52 int str7x_probe(struct flash_bank_s *bank);
53 int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
54 int str7x_protect_check(struct flash_bank_s *bank);
55 int str7x_erase_check(struct flash_bank_s *bank);
56 int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size);
57
58 flash_driver_t str7x_flash =
59 {
60 .name = "str7x",
61 .register_commands = str7x_register_commands,
62 .flash_bank_command = str7x_flash_bank_command,
63 .erase = str7x_erase,
64 .protect = str7x_protect,
65 .write = str7x_write,
66 .probe = str7x_probe,
67 .erase_check = str7x_erase_check,
68 .protect_check = str7x_protect_check,
69 .info = str7x_info
70 };
71
72 int str7x_register_commands(struct command_context_s *cmd_ctx)
73 {
74
75 return ERROR_OK;
76 }
77
78 int str7x_get_flash_adr(struct flash_bank_s *bank, u32 reg)
79 {
80 str7x_flash_bank_t *str7x_info = bank->driver_priv;
81 return (str7x_info->flash_base|reg);
82 }
83
84 int str7x_build_block_list(struct flash_bank_s *bank)
85 {
86 str7x_flash_bank_t *str7x_info = bank->driver_priv;
87
88 int i;
89 int num_sectors;
90
91 switch (bank->size)
92 {
93 case 16 * 1024:
94 num_sectors = 2;
95 break;
96 case 64 * 1024:
97 num_sectors = 5;
98 break;
99 case 128 * 1024:
100 num_sectors = 6;
101 break;
102 case 256 * 1024:
103 num_sectors = 8;
104 break;
105 default:
106 ERROR("BUG: unknown bank->size encountered");
107 exit(-1);
108 }
109
110 if( str7x_info->bank1 == 1 )
111 {
112 num_sectors += 2;
113 }
114
115 bank->num_sectors = num_sectors;
116 bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
117
118 for (i = 0; i < num_sectors; i++)
119 {
120 bank->sectors[i].offset = mem_layout[i].sector_start;
121 bank->sectors[i].size = mem_layout[i].sector_size;
122 bank->sectors[i].is_erased = -1;
123 bank->sectors[i].is_protected = 1;
124 }
125
126 return ERROR_OK;
127 }
128
129 /* flash bank str7x <base> <size> 0 0 <str71_variant> <target#>
130 */
131 int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
132 {
133 str7x_flash_bank_t *str7x_info;
134
135 if (argc < 7)
136 {
137 WARNING("incomplete flash_bank str7x configuration");
138 return ERROR_FLASH_BANK_INVALID;
139 }
140
141 str7x_info = malloc(sizeof(str7x_flash_bank_t));
142 bank->driver_priv = str7x_info;
143
144 if (strcmp(args[5], "STR71x") == 0)
145 {
146 str7x_info->bank1 = 1;
147 str7x_info->flash_base = 0x40000000;
148 }
149 else if (strcmp(args[5], "STR73x") == 0)
150 {
151 str7x_info->bank1 = 0;
152 str7x_info->flash_base = 0x80000000;
153 }
154 else
155 {
156 ERROR("unknown STR7x variant");
157 free(str7x_info);
158 return ERROR_FLASH_BANK_INVALID;
159 }
160
161 str7x_info->target = get_target_by_num(strtoul(args[6], NULL, 0));
162 if (!str7x_info->target)
163 {
164 ERROR("no target '%i' configured", args[6]);
165 exit(-1);
166 }
167
168 str7x_build_block_list(bank);
169
170 return ERROR_OK;
171 }
172
173 u32 str7x_status(struct flash_bank_s *bank)
174 {
175 str7x_flash_bank_t *str7x_info = bank->driver_priv;
176 target_t *target = str7x_info->target;
177 u32 retval;
178
179 target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&retval);
180
181 return retval;
182 }
183
184 u32 str7x_result(struct flash_bank_s *bank)
185 {
186 str7x_flash_bank_t *str7x_info = bank->driver_priv;
187 target_t *target = str7x_info->target;
188 u32 retval;
189
190 target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_ER), 4, 1, (u8*)&retval);
191
192 return retval;
193 }
194
195 int str7x_blank_check(struct flash_bank_s *bank, int first, int last)
196 {
197 str7x_flash_bank_t *str7x_info = bank->driver_priv;
198 target_t *target = str7x_info->target;
199 u8 *buffer;
200 int i;
201 int nBytes;
202
203 if ((first < 0) || (last > bank->num_sectors))
204 return ERROR_FLASH_SECTOR_INVALID;
205
206 if (str7x_info->target->state != TARGET_HALTED)
207 {
208 return ERROR_TARGET_NOT_HALTED;
209 }
210
211 buffer = malloc(256);
212
213 for (i = first; i <= last; i++)
214 {
215 bank->sectors[i].is_erased = 1;
216
217 target->type->read_memory(target, bank->base + bank->sectors[i].offset, 4, 256/4, buffer);
218
219 for (nBytes = 0; nBytes < 256; nBytes++)
220 {
221 if (buffer[nBytes] != 0xFF)
222 {
223 bank->sectors[i].is_erased = 0;
224 break;
225 }
226 }
227 }
228
229 free(buffer);
230
231 return ERROR_OK;
232 }
233
234 int str7x_protect_check(struct flash_bank_s *bank)
235 {
236 str7x_flash_bank_t *str7x_info = bank->driver_priv;
237 target_t *target = str7x_info->target;
238
239 int i;
240 int retval;
241
242 if (str7x_info->target->state != TARGET_HALTED)
243 {
244 return ERROR_TARGET_NOT_HALTED;
245 }
246
247 target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), 4, 1, (u8*)&retval);
248
249 for (i = 0; i < bank->num_sectors; i++)
250 {
251 if (retval & (mem_layout[i].reg_offset << i))
252 bank->sectors[i].is_protected = 0;
253 else
254 bank->sectors[i].is_protected = 1;
255 }
256
257 return ERROR_OK;
258 }
259
260 int str7x_erase(struct flash_bank_s *bank, int first, int last)
261 {
262 str7x_flash_bank_t *str7x_info = bank->driver_priv;
263 target_t *target = str7x_info->target;
264
265 int i;
266 u32 cmd;
267 u32 retval;
268 u32 erase_blocks;
269
270 if (str7x_info->target->state != TARGET_HALTED)
271 {
272 return ERROR_TARGET_NOT_HALTED;
273 }
274
275 erase_blocks = 0;
276
277 for (i = first; i <= last; i++)
278 erase_blocks |= (mem_layout[i].reg_offset << i);
279
280 cmd = FLASH_SER;
281 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
282
283 cmd = erase_blocks;
284 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR1), 4, 1, (u8*)&cmd);
285
286 cmd = FLASH_SER|FLASH_WMS;
287 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
288
289 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
290 usleep(1000);
291 }
292
293 retval = str7x_result(bank);
294
295 if (retval & FLASH_ERER)
296 return ERROR_FLASH_SECTOR_NOT_ERASED;
297 else if (retval & FLASH_WPF)
298 return ERROR_FLASH_OPERATION_FAILED;
299
300 for (i = first; i <= last; i++)
301 bank->sectors[i].is_erased = 1;
302
303 return ERROR_OK;
304 }
305
306 int str7x_protect(struct flash_bank_s *bank, int set, int first, int last)
307 {
308 str7x_flash_bank_t *str7x_info = bank->driver_priv;
309 target_t *target = str7x_info->target;
310 int i;
311 u32 cmd;
312 u32 retval;
313 u32 protect_blocks;
314
315 if (str7x_info->target->state != TARGET_HALTED)
316 {
317 return ERROR_TARGET_NOT_HALTED;
318 }
319
320 protect_blocks = 0xFFFFFFFF;
321
322 if( set )
323 {
324 for (i = first; i <= last; i++)
325 protect_blocks &= ~(mem_layout[i].reg_offset << i);
326 }
327
328 cmd = FLASH_SPR;
329 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
330
331 cmd = str7x_get_flash_adr(bank, FLASH_NVWPAR);
332 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
333
334 cmd = protect_blocks;
335 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
336
337 cmd = FLASH_SPR|FLASH_WMS;
338 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
339
340 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
341 usleep(1000);
342 }
343
344 retval = str7x_result(bank);
345
346 if (retval & FLASH_ERER)
347 return ERROR_FLASH_SECTOR_NOT_ERASED;
348 else if (retval & FLASH_WPF)
349 return ERROR_FLASH_OPERATION_FAILED;
350
351 return ERROR_OK;
352 }
353
354 int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
355 {
356 str7x_flash_bank_t *str7x_info = bank->driver_priv;
357 target_t *target = str7x_info->target;
358 u32 dwords_remaining = (count / 8);
359 u32 bytes_remaining = (count & 0x00000007);
360 u32 address = bank->base + offset;
361 u32 *wordbuffer = (u32*)buffer;
362 u32 bytes_written = 0;
363 u32 cmd;
364 u32 retval;
365
366 if (str7x_info->target->state != TARGET_HALTED)
367 {
368 return ERROR_TARGET_NOT_HALTED;
369 }
370
371 if (offset + count > bank->size)
372 return ERROR_FLASH_DST_OUT_OF_BANK;
373
374 while (dwords_remaining > 0)
375 {
376 // command
377 cmd = FLASH_DWPG;
378 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
379
380 // address
381 cmd = address;
382 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
383
384 // data byte 1
385 cmd = wordbuffer[bytes_written/4];
386 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
387 bytes_written += 4;
388
389 // data byte 2
390 cmd = wordbuffer[bytes_written/4];
391 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, (u8*)&cmd);
392 bytes_written += 4;
393
394 /* start programming cycle */
395 cmd = FLASH_DWPG|FLASH_WMS;
396 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
397
398 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
399 usleep(1000);
400 }
401
402 retval = str7x_result(bank);
403
404 if (retval & FLASH_PGER)
405 return ERROR_FLASH_OPERATION_FAILED;
406 else if (retval & FLASH_WPF)
407 return ERROR_FLASH_OPERATION_FAILED;
408
409 dwords_remaining--;
410 address += 8;
411 }
412
413 while( bytes_remaining > 0 )
414 {
415 // command
416 cmd = FLASH_WPG;
417 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
418
419 // address
420 cmd = address;
421 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
422
423 // data byte
424 cmd = buffer[bytes_written];
425 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
426
427 /* start programming cycle */
428 cmd = FLASH_WPG|FLASH_WMS;
429 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
430
431 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
432 usleep(1000);
433 }
434
435 retval = str7x_result(bank);
436
437 if (retval & FLASH_PGER)
438 return ERROR_FLASH_OPERATION_FAILED;
439 else if (retval & FLASH_WPF)
440 return ERROR_FLASH_OPERATION_FAILED;
441
442 address++;
443 bytes_remaining--;
444 bytes_written++;
445 }
446
447 return ERROR_OK;
448 }
449
450 int str7x_probe(struct flash_bank_s *bank)
451 {
452 return ERROR_OK;
453 }
454
455 int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
456 {
457 return ERROR_OK;
458 }
459
460 int str7x_erase_check(struct flash_bank_s *bank)
461 {
462 return str7x_blank_check(bank, 0, bank->num_sectors - 1);
463 }
464
465 int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size)
466 {
467 snprintf(buf, buf_size, "str7x flash driver info" );
468 return ERROR_OK;
469 }

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)