fe18451c92710280f0bff4e27728eed4eb4821cb
[openocd.git] / src / flash / nor / kinetis.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Mathias Kuester *
3 * kesmtp@freenet.de *
4 * *
5 * Copyright (C) 2011 sleep(5) ltd *
6 * tomas@sleepfive.com *
7 * *
8 * Copyright (C) 2012 by Christopher D. Kilgour *
9 * techie at whiterocker.com *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "imp.h"
32 #include "helper/binarybuffer.h"
33
34 /*
35 * Implementation Notes
36 *
37 * The persistent memories in the Kinetis chip families K10 through
38 * K70 are all manipulated with the Flash Memory Module. Some
39 * variants call this module the FTFE, others call it the FTFL. To
40 * indicate that both are considered here, we use FTFX.
41 *
42 * Within the module, according to the chip variant, the persistent
43 * memory is divided into what Freescale terms Program Flash, FlexNVM,
44 * and FlexRAM. All chip variants have Program Flash. Some chip
45 * variants also have FlexNVM and FlexRAM, which always appear
46 * together.
47 *
48 * A given Kinetis chip may have 2 or 4 blocks of flash. Here we map
49 * each block to a separate bank. Each block size varies by chip and
50 * may be determined by the read-only SIM_FCFG1 register. The sector
51 * size within each bank/block varies by the chip granularity as
52 * described below.
53 *
54 * Kinetis offers four different of flash granularities applicable
55 * across the chip families. The granularity is apparently reflected
56 * by at least the reference manual suffix. For example, for chip
57 * MK60FN1M0VLQ12, reference manual K60P144M150SF3RM ends in "SF3RM",
58 * where the "3" indicates there are four flash blocks with 4kiB
59 * sectors. All possible granularities are indicated below.
60 *
61 * The first half of the flash (1 or 2 blocks, depending on the
62 * granularity) is always Program Flash and always starts at address
63 * 0x00000000. The "PFLSH" flag, bit 23 of the read-only SIM_FCFG2
64 * register, determines whether the second half of the flash is also
65 * Program Flash or FlexNVM+FlexRAM. When PFLSH is set, the second
66 * half of flash is Program Flash and is contiguous in the memory map
67 * from the first half. When PFLSH is clear, the second half of flash
68 * is FlexNVM and always starts at address 0x10000000. FlexRAM, which
69 * is also present when PFLSH is clear, always starts at address
70 * 0x14000000.
71 *
72 * The Flash Memory Module provides a register set where flash
73 * commands are loaded to perform flash operations like erase and
74 * program. Different commands are available depending on whether
75 * Program Flash or FlexNVM/FlexRAM is being manipulated. Although
76 * the commands used are quite consistent between flash blocks, the
77 * parameters they accept differ according to the flash granularity.
78 * Some Kinetis chips have different granularity between Program Flash
79 * and FlexNVM/FlexRAM, so flash command arguments may differ between
80 * blocks in the same chip.
81 *
82 * Although not documented as such by Freescale, it appears that bits
83 * 8:7 of the read-only SIM_SDID register reflect the granularity
84 * settings 0..3, so sector sizes and block counts are applicable
85 * according to the following table.
86 */
87 const struct {
88 unsigned pflash_sector_size_bytes;
89 unsigned nvm_sector_size_bytes;
90 unsigned num_blocks;
91 } kinetis_flash_params[4] = {
92 { 1<<10, 1<<10, 2 },
93 { 2<<10, 1<<10, 2 },
94 { 2<<10, 2<<10, 2 },
95 { 4<<10, 4<<10, 4 }
96 };
97
98 /* Addressess */
99 #define FLEXRAM 0x14000000
100 #define FTFx_FSTAT 0x40020000
101 #define FTFx_FCNFG 0x40020001
102 #define FTFx_FCCOB3 0x40020004
103 #define FTFx_FPROT3 0x40020010
104 #define SIM_SDID 0x40048024
105 #define SIM_FCFG1 0x4004804c
106 #define SIM_FCFG2 0x40048050
107
108 /* Commands */
109 #define FTFx_CMD_BLOCKSTAT 0x00
110 #define FTFx_CMD_SECTSTAT 0x01
111 #define FTFx_CMD_LWORDPROG 0x06
112 #define FTFx_CMD_SECTERASE 0x09
113 #define FTFx_CMD_SECTWRITE 0x0b
114 #define FTFx_CMD_SETFLEXRAM 0x81
115
116 struct kinetis_flash_bank {
117 unsigned granularity;
118 unsigned bank_ordinal;
119 uint32_t sector_size;
120 uint32_t protection_size;
121
122 uint32_t sim_sdid;
123 uint32_t sim_fcfg1;
124 uint32_t sim_fcfg2;
125
126 enum {
127 FC_AUTO = 0,
128 FC_PFLASH,
129 FC_FLEX_NVM,
130 FC_FLEX_RAM,
131 } flash_class;
132 };
133
134 FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)
135 {
136 struct kinetis_flash_bank *bank_info;
137
138 if (CMD_ARGC < 6)
139 return ERROR_COMMAND_SYNTAX_ERROR;
140
141 LOG_INFO("add flash_bank kinetis %s", bank->name);
142
143 bank_info = malloc(sizeof(struct kinetis_flash_bank));
144
145 memset(bank_info, 0, sizeof(struct kinetis_flash_bank));
146
147 bank->driver_priv = bank_info;
148
149 return ERROR_OK;
150 }
151
152 static int kinetis_protect(struct flash_bank *bank, int set, int first,
153 int last)
154 {
155 LOG_WARNING("kinetis_protect not supported yet");
156 /* FIXME: TODO */
157
158 if (bank->target->state != TARGET_HALTED) {
159 LOG_ERROR("Target not halted");
160 return ERROR_TARGET_NOT_HALTED;
161 }
162
163 return ERROR_FLASH_BANK_INVALID;
164 }
165
166 static int kinetis_protect_check(struct flash_bank *bank)
167 {
168 struct kinetis_flash_bank *kinfo = bank->driver_priv;
169
170 if (bank->target->state != TARGET_HALTED) {
171 LOG_ERROR("Target not halted");
172 return ERROR_TARGET_NOT_HALTED;
173 }
174
175 if (kinfo->flash_class == FC_PFLASH) {
176 int result;
177 uint8_t buffer[4];
178 uint32_t fprot, psec;
179 int i, b;
180
181 /* read protection register */
182 result = target_read_memory(bank->target, FTFx_FPROT3, 1, 4, buffer);
183
184 if (result != ERROR_OK)
185 return result;
186
187 fprot = target_buffer_get_u32(bank->target, buffer);
188
189 /*
190 * Every bit protects 1/32 of the full flash (not necessarily
191 * just this bank), but we enforce the bank ordinals for
192 * PFlash to start at zero.
193 */
194 b = kinfo->bank_ordinal * (bank->size / kinfo->protection_size);
195 for (psec = 0, i = 0; i < bank->num_sectors; i++) {
196 if ((fprot >> b) & 1)
197 bank->sectors[i].is_protected = 0;
198 else
199 bank->sectors[i].is_protected = 1;
200
201 psec += bank->sectors[i].size;
202
203 if (psec >= kinfo->protection_size) {
204 psec = 0;
205 b++;
206 }
207 }
208 } else {
209 LOG_ERROR("Protection checks for FlexNVM not yet supported");
210 return ERROR_FLASH_BANK_INVALID;
211 }
212
213 return ERROR_OK;
214 }
215
216 static int kinetis_ftfx_command(struct flash_bank *bank, uint8_t fcmd, uint32_t faddr,
217 uint8_t fccob4, uint8_t fccob5, uint8_t fccob6, uint8_t fccob7,
218 uint8_t fccob8, uint8_t fccob9, uint8_t fccoba, uint8_t fccobb,
219 uint8_t *ftfx_fstat)
220 {
221 uint8_t command[12] = {faddr & 0xff, (faddr >> 8) & 0xff, (faddr >> 16) & 0xff, fcmd,
222 fccob7, fccob6, fccob5, fccob4,
223 fccobb, fccoba, fccob9, fccob8};
224 int result, i;
225 uint8_t buffer;
226
227 /* wait for done */
228 for (i = 0; i < 50; i++) {
229 result =
230 target_read_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer);
231
232 if (result != ERROR_OK)
233 return result;
234
235 if (buffer & 0x80)
236 break;
237
238 buffer = 0x00;
239 }
240
241 if (buffer != 0x80) {
242 /* reset error flags */
243 buffer = 0x30;
244 result =
245 target_write_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer);
246 if (result != ERROR_OK)
247 return result;
248 }
249
250 result = target_write_memory(bank->target, FTFx_FCCOB3, 4, 3, command);
251
252 if (result != ERROR_OK)
253 return result;
254
255 /* start command */
256 buffer = 0x80;
257 result = target_write_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer);
258 if (result != ERROR_OK)
259 return result;
260
261 /* wait for done */
262 for (i = 0; i < 50; i++) {
263 result =
264 target_read_memory(bank->target, FTFx_FSTAT, 1, 1, ftfx_fstat);
265
266 if (result != ERROR_OK)
267 return result;
268
269 if (*ftfx_fstat & 0x80)
270 break;
271 }
272
273 if ((*ftfx_fstat & 0xf0) != 0x80) {
274 LOG_ERROR
275 ("ftfx command failed FSTAT: %02X FCCOB: %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X",
276 *ftfx_fstat, command[3], command[2], command[1], command[0],
277 command[7], command[6], command[5], command[4],
278 command[11], command[10], command[9], command[8]);
279 return ERROR_FLASH_OPERATION_FAILED;
280 }
281
282 return ERROR_OK;
283 }
284
285 static int kinetis_erase(struct flash_bank *bank, int first, int last)
286 {
287 int result, i;
288
289 if (bank->target->state != TARGET_HALTED) {
290 LOG_ERROR("Target not halted");
291 return ERROR_TARGET_NOT_HALTED;
292 }
293
294 if ((first > bank->num_sectors) || (last > bank->num_sectors))
295 return ERROR_FLASH_OPERATION_FAILED;
296
297 /*
298 * FIXME: TODO: use the 'Erase Flash Block' command if the
299 * requested erase is PFlash or NVM and encompasses the entire
300 * block. Should be quicker.
301 */
302 for (i = first; i <= last; i++) {
303 uint8_t ftfx_fstat;
304 /* set command and sector address */
305 result = kinetis_ftfx_command(bank, FTFx_CMD_SECTERASE, bank->base + bank->sectors[i].offset,
306 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat);
307
308 if (result != ERROR_OK) {
309 LOG_WARNING("erase sector %d failed", i);
310 return ERROR_FLASH_OPERATION_FAILED;
311 }
312
313 bank->sectors[i].is_erased = 1;
314 }
315
316 if (first == 0) {
317 LOG_WARNING
318 ("flash configuration field erased, please reset the device");
319 }
320
321 return ERROR_OK;
322 }
323
324 static int kinetis_write(struct flash_bank *bank, uint8_t *buffer,
325 uint32_t offset, uint32_t count)
326 {
327 unsigned int i, result, fallback = 0;
328 uint8_t buf[8];
329 uint32_t wc;
330 struct kinetis_flash_bank *kinfo = bank->driver_priv;
331
332 if (bank->target->state != TARGET_HALTED) {
333 LOG_ERROR("Target not halted");
334 return ERROR_TARGET_NOT_HALTED;
335 }
336
337 if (kinfo->flash_class == FC_FLEX_NVM) {
338 uint8_t ftfx_fstat;
339
340 LOG_DEBUG("flash write into FlexNVM @%08X", offset);
341
342 /* make flex ram available */
343 result = kinetis_ftfx_command(bank, FTFx_CMD_SETFLEXRAM, 0x00ff0000, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat);
344
345 if (result != ERROR_OK)
346 return ERROR_FLASH_OPERATION_FAILED;
347
348 /* check if ram ready */
349 result = target_read_memory(bank->target, FTFx_FCNFG, 1, 1, buf);
350
351 if (result != ERROR_OK)
352 return result;
353
354 if (!(buf[0] & (1 << 1))) {
355 /* fallback to longword write */
356 fallback = 1;
357
358 LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)",
359 buf[0]);
360 }
361 } else {
362 LOG_DEBUG("flash write into PFLASH @08%X", offset);
363 }
364
365
366 /* program section command */
367 if (fallback == 0) {
368 /*
369 * Kinetis uses different terms for the granularity of
370 * sector writes, e.g. "phrase" or "128 bits". We use
371 * the generic term "chunk". The largest possible
372 * Kinetis "chunk" is 16 bytes (128 bits).
373 */
374 unsigned prog_section_chunk_bytes = kinfo->sector_size >> 8;
375 /* assume the NVM sector size is half the FlexRAM size */
376 unsigned prog_size_bytes = MIN(kinfo->sector_size,
377 kinetis_flash_params[kinfo->granularity].nvm_sector_size_bytes);
378 for (i = 0; i < count; i += prog_size_bytes) {
379 uint8_t residual_buffer[16];
380 uint8_t ftfx_fstat;
381 uint32_t section_count = prog_size_bytes / prog_section_chunk_bytes;
382 uint32_t residual_wc = 0;
383
384 /*
385 * Assume the word count covers an entire
386 * sector.
387 */
388 wc = prog_size_bytes / 4;
389
390 /*
391 * If bytes to be programmed are less than the
392 * full sector, then determine the number of
393 * full-words to program, and put together the
394 * residual buffer so that a full "section"
395 * may always be programmed.
396 */
397 if ((count - i) < prog_size_bytes) {
398 /* number of bytes to program beyond full section */
399 unsigned residual_bc = (count-i) % prog_section_chunk_bytes;
400
401 /* number of complete words to copy directly from buffer */
402 wc = (count - i) / 4;
403
404 /* number of total sections to write, including residual */
405 section_count = DIV_ROUND_UP((count-i), prog_section_chunk_bytes);
406
407 /* any residual bytes delivers a whole residual section */
408 residual_wc = (residual_bc ? prog_section_chunk_bytes : 0)/4;
409
410 /* clear residual buffer then populate residual bytes */
411 (void) memset(residual_buffer, 0xff, prog_section_chunk_bytes);
412 (void) memcpy(residual_buffer, &buffer[i+4*wc], residual_bc);
413 }
414
415 LOG_DEBUG("write section @ %08X with length %d bytes",
416 offset + i, wc*4);
417
418 /* write data to flexram as whole-words */
419 result = target_write_memory(bank->target, FLEXRAM, 4, wc,
420 buffer + i);
421
422 if (result != ERROR_OK) {
423 LOG_ERROR("target_write_memory failed");
424 return result;
425 }
426
427 /* write the residual words to the flexram */
428 if (residual_wc) {
429 result = target_write_memory(bank->target,
430 FLEXRAM+4*wc,
431 4, residual_wc,
432 residual_buffer);
433
434 if (result != ERROR_OK) {
435 LOG_ERROR("target_write_memory failed");
436 return result;
437 }
438 }
439
440 /* execute section-write command */
441 result = kinetis_ftfx_command(bank, FTFx_CMD_SECTWRITE, bank->base + offset + i,
442 section_count>>8, section_count, 0, 0,
443 0, 0, 0, 0, &ftfx_fstat);
444
445 if (result != ERROR_OK)
446 return ERROR_FLASH_OPERATION_FAILED;
447 }
448 }
449 /* program longword command, not supported in "SF3" devices */
450 else if (kinfo->granularity != 3) {
451 for (i = 0; i < count; i += 4) {
452 uint8_t ftfx_fstat;
453
454 LOG_DEBUG("write longword @ %08X", offset + i);
455
456 uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff};
457 memcpy(padding, buffer + i, MIN(4, count-i));
458 result = kinetis_ftfx_command(bank, FTFx_CMD_LWORDPROG, bank->base + offset + i,
459 padding[3], padding[2], padding[1], padding[0],
460 0, 0, 0, 0, &ftfx_fstat);
461
462 if (result != ERROR_OK)
463 return ERROR_FLASH_OPERATION_FAILED;
464 }
465 } else {
466 LOG_ERROR("Flash write strategy not implemented");
467 return ERROR_FLASH_OPERATION_FAILED;
468 }
469
470 return ERROR_OK;
471 }
472
473 static int kinetis_read_part_info(struct flash_bank *bank)
474 {
475 int result, i;
476 uint8_t buf[4];
477 uint32_t offset = 0;
478 uint8_t fcfg1_nvmsize, fcfg1_pfsize, fcfg1_eesize, fcfg2_pflsh;
479 uint32_t nvm_size = 0, pf_size = 0, ee_size = 0;
480 unsigned granularity, num_blocks = 0, num_pflash_blocks = 0, num_nvm_blocks = 0,
481 first_nvm_bank = 0, reassign = 0;
482 struct kinetis_flash_bank *kinfo = bank->driver_priv;
483
484 result = target_read_memory(bank->target, SIM_SDID, 1, 4, buf);
485 if (result != ERROR_OK)
486 return result;
487 kinfo->sim_sdid = target_buffer_get_u32(bank->target, buf);
488 granularity = (kinfo->sim_sdid >> 7) & 0x03;
489
490 result = target_read_memory(bank->target, SIM_FCFG1, 1, 4, buf);
491 if (result != ERROR_OK)
492 return result;
493 kinfo->sim_fcfg1 = target_buffer_get_u32(bank->target, buf);
494
495 result = target_read_memory(bank->target, SIM_FCFG2, 1, 4, buf);
496 if (result != ERROR_OK)
497 return result;
498 kinfo->sim_fcfg2 = target_buffer_get_u32(bank->target, buf);
499 fcfg2_pflsh = (kinfo->sim_fcfg2 >> 23) & 0x01;
500
501 LOG_DEBUG("SDID: %08X FCFG1: %08X FCFG2: %08X", kinfo->sim_sdid,
502 kinfo->sim_fcfg1, kinfo->sim_fcfg2);
503
504 fcfg1_nvmsize = (uint8_t)((kinfo->sim_fcfg1 >> 28) & 0x0f);
505 fcfg1_pfsize = (uint8_t)((kinfo->sim_fcfg1 >> 24) & 0x0f);
506 fcfg1_eesize = (uint8_t)((kinfo->sim_fcfg1 >> 16) & 0x0f);
507
508 /* when the PFLSH bit is set, there is no FlexNVM/FlexRAM */
509 if (!fcfg2_pflsh) {
510 switch (fcfg1_nvmsize) {
511 case 0x03:
512 case 0x07:
513 case 0x09:
514 case 0x0b:
515 nvm_size = 1 << (14 + (fcfg1_nvmsize >> 1));
516 break;
517 case 0x0f:
518 if (granularity == 3)
519 nvm_size = 512<<10;
520 else
521 nvm_size = 256<<10;
522 break;
523 default:
524 nvm_size = 0;
525 break;
526 }
527
528 switch (fcfg1_eesize) {
529 case 0x00:
530 case 0x01:
531 case 0x02:
532 case 0x03:
533 case 0x04:
534 case 0x05:
535 case 0x06:
536 case 0x07:
537 case 0x08:
538 case 0x09:
539 ee_size = (16 << (10 - fcfg1_eesize));
540 break;
541 default:
542 ee_size = 0;
543 break;
544 }
545 }
546
547 switch (fcfg1_pfsize) {
548 case 0x03:
549 case 0x05:
550 case 0x07:
551 case 0x09:
552 case 0x0b:
553 case 0x0d:
554 pf_size = 1 << (14 + (fcfg1_pfsize >> 1));
555 break;
556 case 0x0f:
557 if (granularity == 3)
558 pf_size = 1024<<10;
559 else if (fcfg2_pflsh)
560 pf_size = 512<<10;
561 else
562 pf_size = 256<<10;
563 break;
564 default:
565 pf_size = 0;
566 break;
567 }
568
569 LOG_DEBUG("FlexNVM: %d PFlash: %d FlexRAM: %d PFLSH: %d",
570 nvm_size, pf_size, ee_size, fcfg2_pflsh);
571
572 num_blocks = kinetis_flash_params[granularity].num_blocks;
573 num_pflash_blocks = num_blocks / (2 - fcfg2_pflsh);
574 first_nvm_bank = num_pflash_blocks;
575 num_nvm_blocks = num_blocks - num_pflash_blocks;
576
577 LOG_DEBUG("%d blocks total: %d PFlash, %d FlexNVM",
578 num_blocks, num_pflash_blocks, num_nvm_blocks);
579
580 /*
581 * If the flash class is already assigned, verify the
582 * parameters.
583 */
584 if (kinfo->flash_class != FC_AUTO) {
585 if (kinfo->bank_ordinal != (unsigned) bank->bank_number) {
586 LOG_WARNING("Flash ordinal/bank number mismatch");
587 reassign = 1;
588 } else if (kinfo->granularity != granularity) {
589 LOG_WARNING("Flash granularity mismatch");
590 reassign = 1;
591 } else {
592 switch (kinfo->flash_class) {
593 case FC_PFLASH:
594 if (kinfo->bank_ordinal >= first_nvm_bank) {
595 LOG_WARNING("Class mismatch, bank %d is not PFlash",
596 bank->bank_number);
597 reassign = 1;
598 } else if (bank->size != (pf_size / num_pflash_blocks)) {
599 LOG_WARNING("PFlash size mismatch");
600 reassign = 1;
601 } else if (bank->base !=
602 (0x00000000 + bank->size * kinfo->bank_ordinal)) {
603 LOG_WARNING("PFlash address range mismatch");
604 reassign = 1;
605 } else if (kinfo->sector_size !=
606 kinetis_flash_params[granularity].pflash_sector_size_bytes) {
607 LOG_WARNING("PFlash sector size mismatch");
608 reassign = 1;
609 } else {
610 LOG_DEBUG("PFlash bank %d already configured okay",
611 kinfo->bank_ordinal);
612 }
613 break;
614 case FC_FLEX_NVM:
615 if ((kinfo->bank_ordinal >= num_blocks) ||
616 (kinfo->bank_ordinal < first_nvm_bank)) {
617 LOG_WARNING("Class mismatch, bank %d is not FlexNVM",
618 bank->bank_number);
619 reassign = 1;
620 } else if (bank->size != (nvm_size / num_nvm_blocks)) {
621 LOG_WARNING("FlexNVM size mismatch");
622 reassign = 1;
623 } else if (bank->base !=
624 (0x10000000 + bank->size * kinfo->bank_ordinal)) {
625 LOG_WARNING("FlexNVM address range mismatch");
626 reassign = 1;
627 } else if (kinfo->sector_size !=
628 kinetis_flash_params[granularity].nvm_sector_size_bytes) {
629 LOG_WARNING("FlexNVM sector size mismatch");
630 reassign = 1;
631 } else {
632 LOG_DEBUG("FlexNVM bank %d already configured okay",
633 kinfo->bank_ordinal);
634 }
635 break;
636 case FC_FLEX_RAM:
637 if (kinfo->bank_ordinal != num_blocks) {
638 LOG_WARNING("Class mismatch, bank %d is not FlexRAM",
639 bank->bank_number);
640 reassign = 1;
641 } else if (bank->size != ee_size) {
642 LOG_WARNING("FlexRAM size mismatch");
643 reassign = 1;
644 } else if (bank->base != FLEXRAM) {
645 LOG_WARNING("FlexRAM address mismatch");
646 reassign = 1;
647 } else if (kinfo->sector_size !=
648 kinetis_flash_params[granularity].nvm_sector_size_bytes) {
649 LOG_WARNING("FlexRAM sector size mismatch");
650 reassign = 1;
651 } else {
652 LOG_DEBUG("FlexRAM bank %d already configured okay",
653 kinfo->bank_ordinal);
654 }
655 break;
656
657 default:
658 LOG_WARNING("Unknown or inconsistent flash class");
659 reassign = 1;
660 break;
661 }
662 }
663 } else {
664 LOG_INFO("Probing flash info for bank %d", bank->bank_number);
665 reassign = 1;
666 }
667
668 if (!reassign)
669 return ERROR_OK;
670
671 kinfo->granularity = granularity;
672
673 if ((unsigned)bank->bank_number < num_pflash_blocks) {
674 /* pflash, banks start at address zero */
675 kinfo->flash_class = FC_PFLASH;
676 bank->size = (pf_size / num_pflash_blocks);
677 bank->base = 0x00000000 + bank->size * bank->bank_number;
678 kinfo->sector_size = kinetis_flash_params[granularity].pflash_sector_size_bytes;
679 kinfo->protection_size = pf_size / 32;
680 } else if ((unsigned)bank->bank_number < num_blocks) {
681 /* nvm, banks start at address 0x10000000 */
682 kinfo->flash_class = FC_FLEX_NVM;
683 bank->size = (nvm_size / num_nvm_blocks);
684 bank->base = 0x10000000 + bank->size * (bank->bank_number - first_nvm_bank);
685 kinfo->sector_size = kinetis_flash_params[granularity].nvm_sector_size_bytes;
686 kinfo->protection_size = 0; /* FIXME: TODO: depends on DEPART bits, chip */
687 } else if ((unsigned)bank->bank_number == num_blocks) {
688 LOG_ERROR("FlexRAM support not yet implemented");
689 return ERROR_FLASH_OPER_UNSUPPORTED;
690 } else {
691 LOG_ERROR("Cannot determine parameters for bank %d, only %d banks on device",
692 bank->bank_number, num_blocks);
693 return ERROR_FLASH_BANK_INVALID;
694 }
695
696 if (bank->sectors) {
697 free(bank->sectors);
698 bank->sectors = NULL;
699 }
700
701 bank->num_sectors = bank->size / kinfo->sector_size;
702 assert(bank->num_sectors > 0);
703 bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
704
705 for (i = 0; i < bank->num_sectors; i++) {
706 bank->sectors[i].offset = offset;
707 bank->sectors[i].size = kinfo->sector_size;
708 offset += kinfo->sector_size;
709 bank->sectors[i].is_erased = -1;
710 bank->sectors[i].is_protected = 1;
711 }
712
713 return ERROR_OK;
714 }
715
716 static int kinetis_probe(struct flash_bank *bank)
717 {
718 if (bank->target->state != TARGET_HALTED) {
719 LOG_WARNING("Cannot communicate... target not halted.");
720 return ERROR_TARGET_NOT_HALTED;
721 }
722
723 return kinetis_read_part_info(bank);
724 }
725
726 static int kinetis_auto_probe(struct flash_bank *bank)
727 {
728 struct kinetis_flash_bank *kinfo = bank->driver_priv;
729
730 if (kinfo->sim_sdid)
731 return ERROR_OK;
732
733 return kinetis_probe(bank);
734 }
735
736 static int kinetis_info(struct flash_bank *bank, char *buf, int buf_size)
737 {
738 const char *bank_class_names[] = {
739 "(ANY)", "PFlash", "FlexNVM", "FlexRAM"
740 };
741
742 struct kinetis_flash_bank *kinfo = bank->driver_priv;
743
744 (void) snprintf(buf, buf_size,
745 "%s driver for %s flash bank %s at 0x%8.8" PRIx32 "",
746 bank->driver->name, bank_class_names[kinfo->flash_class],
747 bank->name, bank->base);
748
749 return ERROR_OK;
750 }
751
752 static int kinetis_blank_check(struct flash_bank *bank)
753 {
754 struct kinetis_flash_bank *kinfo = bank->driver_priv;
755
756 if (bank->target->state != TARGET_HALTED) {
757 LOG_ERROR("Target not halted");
758 return ERROR_TARGET_NOT_HALTED;
759 }
760
761 if (kinfo->flash_class == FC_PFLASH) {
762 int result;
763 uint8_t ftfx_fstat;
764
765 /* check if whole bank is blank */
766 result = kinetis_ftfx_command(bank, FTFx_CMD_BLOCKSTAT, bank->base, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat);
767
768 if (result != ERROR_OK)
769 return result;
770
771 if (ftfx_fstat & 0x01) {
772 /* the whole bank is not erased, check sector-by-sector */
773 int i;
774 for (i = 0; i < bank->num_sectors; i++) {
775 /* normal margin */
776 result = kinetis_ftfx_command(bank, FTFx_CMD_SECTSTAT, bank->base + bank->sectors[i].offset,
777 1, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat);
778
779 if (result == ERROR_OK) {
780 bank->sectors[i].is_erased = !(ftfx_fstat & 0x01);
781 } else {
782 LOG_DEBUG("Ignoring errored PFlash sector blank-check");
783 bank->sectors[i].is_erased = -1;
784 }
785 }
786 } else {
787 /* the whole bank is erased, update all sectors */
788 int i;
789 for (i = 0; i < bank->num_sectors; i++)
790 bank->sectors[i].is_erased = 1;
791 }
792 } else {
793 LOG_WARNING("kinetis_blank_check not supported yet for FlexNVM");
794 return ERROR_FLASH_OPERATION_FAILED;
795 }
796
797 return ERROR_OK;
798 }
799
800 static int kinetis_flash_read(struct flash_bank *bank,
801 uint8_t *buffer, uint32_t offset, uint32_t count)
802 {
803 LOG_WARNING("kinetis_flash_read not supported yet");
804
805 if (bank->target->state != TARGET_HALTED) {
806 LOG_ERROR("Target not halted");
807 return ERROR_TARGET_NOT_HALTED;
808 }
809
810 return ERROR_FLASH_OPERATION_FAILED;
811 }
812
813 struct flash_driver kinetis_flash = {
814 .name = "kinetis",
815 .flash_bank_command = kinetis_flash_bank_command,
816 .erase = kinetis_erase,
817 .protect = kinetis_protect,
818 .write = kinetis_write,
819 .read = kinetis_flash_read,
820 .probe = kinetis_probe,
821 .auto_probe = kinetis_auto_probe,
822 .erase_check = kinetis_blank_check,
823 .protect_check = kinetis_protect_check,
824 .info = kinetis_info,
825 };

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)