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

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)