* Copyright (C) 2012 by Christopher D. Kilgour *
* techie at whiterocker.com *
* *
+ * Copyright (C) 2013 Nemui Trinomius *
+ * nemuisan_kawausogasuki@live.jp *
+ * *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
#endif
#include "imp.h"
-#include "helper/binarybuffer.h"
+#include <helper/binarybuffer.h>
+#include <target/algorithm.h>
+#include <target/armv7m.h>
/*
* Implementation Notes
* settings 0..3, so sector sizes and block counts are applicable
* according to the following table.
*/
+
const struct {
unsigned pflash_sector_size_bytes;
unsigned nvm_sector_size_bytes;
#define SIM_FCFG2 0x40048050
/* Commands */
-#define FTFx_CMD_BLOCKSTAT 0x00
-#define FTFx_CMD_SECTSTAT 0x01
-#define FTFx_CMD_LWORDPROG 0x06
-#define FTFx_CMD_SECTERASE 0x09
-#define FTFx_CMD_SECTWRITE 0x0b
+#define FTFx_CMD_BLOCKSTAT 0x00
+#define FTFx_CMD_SECTSTAT 0x01
+#define FTFx_CMD_LWORDPROG 0x06
+#define FTFx_CMD_SECTERASE 0x09
+#define FTFx_CMD_SECTWRITE 0x0b
#define FTFx_CMD_SETFLEXRAM 0x81
+#define FTFx_CMD_MASSERASE 0x44
struct kinetis_flash_bank {
unsigned granularity;
unsigned bank_ordinal;
uint32_t sector_size;
uint32_t protection_size;
+ uint32_t klxx;
uint32_t sim_sdid;
uint32_t sim_fcfg1;
return ERROR_OK;
}
-static int kinetis_protect(struct flash_bank *bank, int set, int first,
- int last)
+/* Kinetis Program-LongWord Microcodes */
+static const uint8_t kinetis_flash_write_code[] = {
+ /* Params:
+ * r0 - workarea buffer
+ * r1 - target address
+ * r2 - wordcount
+ * Clobbered:
+ * r4 - tmp
+ * r5 - tmp
+ * r6 - tmp
+ * r7 - tmp
+ */
+
+ /* .L1: */
+ /* for(register uint32_t i=0;i<wcount;i++){ */
+ 0x04, 0x1C, /* mov r4, r0 */
+ 0x00, 0x23, /* mov r3, #0 */
+ /* .L2: */
+ 0x0E, 0x1A, /* sub r6, r1, r0 */
+ 0xA6, 0x19, /* add r6, r4, r6 */
+ 0x93, 0x42, /* cmp r3, r2 */
+ 0x16, 0xD0, /* beq .L9 */
+ /* .L5: */
+ /* while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){}; */
+ 0x0B, 0x4D, /* ldr r5, .L10 */
+ 0x2F, 0x78, /* ldrb r7, [r5] */
+ 0x7F, 0xB2, /* sxtb r7, r7 */
+ 0x00, 0x2F, /* cmp r7, #0 */
+ 0xFA, 0xDA, /* bge .L5 */
+ /* FTFx_FSTAT = FTFA_FSTAT_ACCERR_MASK|FTFA_FSTAT_FPVIOL_MASK|FTFA_FSTAT_RDCO */
+ 0x70, 0x27, /* mov r7, #112 */
+ 0x2F, 0x70, /* strb r7, [r5] */
+ /* FTFx_FCCOB3 = faddr; */
+ 0x09, 0x4F, /* ldr r7, .L10+4 */
+ 0x3E, 0x60, /* str r6, [r7] */
+ 0x06, 0x27, /* mov r7, #6 */
+ /* FTFx_FCCOB0 = 0x06; */
+ 0x08, 0x4E, /* ldr r6, .L10+8 */
+ 0x37, 0x70, /* strb r7, [r6] */
+ /* FTFx_FCCOB7 = *pLW; */
+ 0x80, 0xCC, /* ldmia r4!, {r7} */
+ 0x08, 0x4E, /* ldr r6, .L10+12 */
+ 0x37, 0x60, /* str r7, [r6] */
+ /* FTFx_FSTAT = FTFA_FSTAT_CCIF_MASK; */
+ 0x80, 0x27, /* mov r7, #128 */
+ 0x2F, 0x70, /* strb r7, [r5] */
+ /* .L4: */
+ /* while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){}; */
+ 0x2E, 0x78, /* ldrb r6, [r5] */
+ 0x77, 0xB2, /* sxtb r7, r6 */
+ 0x00, 0x2F, /* cmp r7, #0 */
+ 0xFB, 0xDA, /* bge .L4 */
+ 0x01, 0x33, /* add r3, r3, #1 */
+ 0xE4, 0xE7, /* b .L2 */
+ /* .L9: */
+ 0x00, 0xBE, /* bkpt #0 */
+ /* .L10: */
+ 0x00, 0x00, 0x02, 0x40, /* .word 1073872896 */
+ 0x04, 0x00, 0x02, 0x40, /* .word 1073872900 */
+ 0x07, 0x00, 0x02, 0x40, /* .word 1073872903 */
+ 0x08, 0x00, 0x02, 0x40, /* .word 1073872904 */
+};
+
+/* Program LongWord Block Write */
+static int kinetis_write_block(struct flash_bank *bank, uint8_t *buffer,
+ uint32_t offset, uint32_t wcount)
+{
+ struct target *target = bank->target;
+ uint32_t buffer_size = 2048; /* Default minimum value */
+ struct working_area *write_algorithm;
+ struct working_area *source;
+ uint32_t address = bank->base + offset;
+ struct reg_param reg_params[3];
+ struct armv7m_algorithm armv7m_info;
+ int retval = ERROR_OK;
+
+ /* Params:
+ * r0 - workarea buffer
+ * r1 - target address
+ * r2 - wordcount
+ * Clobbered:
+ * r4 - tmp
+ * r5 - tmp
+ * r6 - tmp
+ * r7 - tmp
+ */
+
+ /* Increase buffer_size if needed */
+ if (buffer_size < (target->working_area_size/2))
+ buffer_size = (target->working_area_size/2);
+
+ LOG_INFO("Kinetis: FLASH Write ...");
+
+ /* check code alignment */
+ if (offset & 0x1) {
+ LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
+ return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+ }
+
+ /* allocate working area with flash programming code */
+ if (target_alloc_working_area(target, sizeof(kinetis_flash_write_code),
+ &write_algorithm) != ERROR_OK) {
+ LOG_WARNING("no working area available, can't do block memory writes");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+
+ retval = target_write_buffer(target, write_algorithm->address,
+ sizeof(kinetis_flash_write_code), kinetis_flash_write_code);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* memory buffer */
+ while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
+ buffer_size /= 4;
+ if (buffer_size <= 256) {
+ /* free working area, write algorithm already allocated */
+ target_free_working_area(target, write_algorithm);
+
+ LOG_WARNING("No large enough working area available, can't do block memory writes");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ }
+
+ armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+ armv7m_info.core_mode = ARM_MODE_THREAD;
+
+ init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* *pLW (*buffer) */
+ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* faddr */
+ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* number of words to program */
+
+ /* write code buffer and use Flash programming code within kinetis */
+ /* Set breakpoint to 0 with time-out of 1000 ms */
+ while (wcount > 0) {
+ uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
+
+ retval = target_write_buffer(target, write_algorithm->address, 8,
+ kinetis_flash_write_code);
+ if (retval != ERROR_OK)
+ break;
+
+ retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer);
+ if (retval != ERROR_OK)
+ break;
+
+ buf_set_u32(reg_params[0].value, 0, 32, source->address);
+ buf_set_u32(reg_params[1].value, 0, 32, address);
+ buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
+
+ retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
+ write_algorithm->address, 0, 100000, &armv7m_info);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Error executing kinetis Flash programming algorithm");
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
+ }
+
+ buffer += thisrun_count * 4;
+ address += thisrun_count * 4;
+ wcount -= thisrun_count;
+ }
+
+ target_free_working_area(target, source);
+ target_free_working_area(target, write_algorithm);
+
+ destroy_reg_param(®_params[0]);
+ destroy_reg_param(®_params[1]);
+ destroy_reg_param(®_params[2]);
+
+ return retval;
+}
+
+static int kinetis_protect(struct flash_bank *bank, int set, int first, int last)
{
LOG_WARNING("kinetis_protect not supported yet");
/* FIXME: TODO */
uint8_t *ftfx_fstat)
{
uint8_t command[12] = {faddr & 0xff, (faddr >> 8) & 0xff, (faddr >> 16) & 0xff, fcmd,
- fccob7, fccob6, fccob5, fccob4,
- fccobb, fccoba, fccob9, fccob8};
+ fccob7, fccob6, fccob5, fccob4,
+ fccobb, fccoba, fccob9, fccob8};
int result, i;
uint8_t buffer;
return result;
/* wait for done */
- for (i = 0; i < 50; i++) {
+ for (i = 0; i < 240; i++) { /* Need Entire Erase Nemui Changed */
result =
target_read_memory(bank->target, FTFx_FSTAT, 1, 1, ftfx_fstat);
LOG_ERROR
("ftfx command failed FSTAT: %02X FCCOB: %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X",
*ftfx_fstat, command[3], command[2], command[1], command[0],
- command[7], command[6], command[5], command[4],
- command[11], command[10], command[9], command[8]);
+ command[7], command[6], command[5], command[4],
+ command[11], command[10], command[9], command[8]);
return ERROR_FLASH_OPERATION_FAILED;
}
return ERROR_OK;
}
+static int kinetis_mass_erase(struct flash_bank *bank)
+{
+ int result;
+ uint8_t ftfx_fstat;
+
+ if (bank->target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ /* check if whole bank is blank */
+ LOG_INFO("Kinetis L Series Erase All Blocks");
+ /* set command and sector address */
+ result = kinetis_ftfx_command(bank, FTFx_CMD_MASSERASE, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat);
+ /* Anyway Result, write unsecure byte */
+ /* if (result != ERROR_OK)
+ return result;*/
+
+ /* Write to MCU security status unsecure in Flash security byte(Work around) */
+ LOG_INFO("Write to MCU security status unsecure Anyway!");
+ uint8_t padding[4] = {0xFE, 0xFF, 0xFF, 0xFF}; /* Write 0xFFFFFFFE */
+
+ result = kinetis_ftfx_command(bank, FTFx_CMD_LWORDPROG, (bank->base + 0x0000040C),
+ padding[3], padding[2], padding[1], padding[0],
+ 0, 0, 0, 0, &ftfx_fstat);
+ if (result != ERROR_OK)
+ return ERROR_FLASH_OPERATION_FAILED;
+
+ return ERROR_OK;
+}
+
static int kinetis_erase(struct flash_bank *bank, int first, int last)
{
int result, i;
+ struct kinetis_flash_bank *kinfo = bank->driver_priv;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
if ((first > bank->num_sectors) || (last > bank->num_sectors))
return ERROR_FLASH_OPERATION_FAILED;
+ if ((first == 0) && (last == (bank->num_sectors - 1)) && (kinfo->klxx))
+ return kinetis_mass_erase(bank);
+
/*
* FIXME: TODO: use the 'Erase Flash Block' command if the
* requested erase is PFlash or NVM and encompasses the entire
uint8_t ftfx_fstat;
/* set command and sector address */
result = kinetis_ftfx_command(bank, FTFx_CMD_SECTERASE, bank->base + bank->sectors[i].offset,
- 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat);
+ 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat);
if (result != ERROR_OK) {
LOG_WARNING("erase sector %d failed", i);
uint8_t buf[8];
uint32_t wc;
struct kinetis_flash_bank *kinfo = bank->driver_priv;
+ uint8_t *new_buffer = NULL;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
- if (kinfo->flash_class == FC_FLEX_NVM) {
+ if (kinfo->klxx) {
+ /* fallback to longword write */
+ fallback = 1;
+ LOG_WARNING("Kinetis L Series supports Program Longword execution only.");
+ LOG_DEBUG("flash write into PFLASH @08%X", offset);
+
+ } else if (kinfo->flash_class == FC_FLEX_NVM) {
uint8_t ftfx_fstat;
LOG_DEBUG("flash write into FlexNVM @%08X", offset);
/* fallback to longword write */
fallback = 1;
- LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)",
- buf[0]);
+ LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)", buf[0]);
}
} else {
LOG_DEBUG("flash write into PFLASH @08%X", offset);
unsigned prog_section_chunk_bytes = kinfo->sector_size >> 8;
/* assume the NVM sector size is half the FlexRAM size */
unsigned prog_size_bytes = MIN(kinfo->sector_size,
- kinetis_flash_params[kinfo->granularity].nvm_sector_size_bytes);
+ kinetis_flash_params[kinfo->granularity].nvm_sector_size_bytes);
for (i = 0; i < count; i += prog_size_bytes) {
uint8_t residual_buffer[16];
uint8_t ftfx_fstat;
/* write data to flexram as whole-words */
result = target_write_memory(bank->target, FLEXRAM, 4, wc,
- buffer + i);
+ buffer + i);
if (result != ERROR_OK) {
LOG_ERROR("target_write_memory failed");
/* write the residual words to the flexram */
if (residual_wc) {
result = target_write_memory(bank->target,
- FLEXRAM+4*wc,
- 4, residual_wc,
- residual_buffer);
+ FLEXRAM+4*wc,
+ 4, residual_wc,
+ residual_buffer);
if (result != ERROR_OK) {
LOG_ERROR("target_write_memory failed");
/* execute section-write command */
result = kinetis_ftfx_command(bank, FTFx_CMD_SECTWRITE, bank->base + offset + i,
- section_count>>8, section_count, 0, 0,
- 0, 0, 0, 0, &ftfx_fstat);
+ section_count>>8, section_count, 0, 0,
+ 0, 0, 0, 0, &ftfx_fstat);
if (result != ERROR_OK)
return ERROR_FLASH_OPERATION_FAILED;
}
}
/* program longword command, not supported in "SF3" devices */
- else if (kinfo->granularity != 3) {
- for (i = 0; i < count; i += 4) {
- uint8_t ftfx_fstat;
+ else if ((kinfo->granularity != 3) || (kinfo->klxx)) {
+
+ if (count & 0x3) {
+ uint32_t old_count = count;
+ count = (old_count | 3) + 1;
+ new_buffer = malloc(count);
+ if (new_buffer == NULL) {
+ LOG_ERROR("odd number of bytes to write and no memory "
+ "for padding buffer");
+ return ERROR_FAIL;
+ }
+ LOG_INFO("odd number of bytes to write (%d), extending to %d "
+ "and padding with 0xff", old_count, count);
+ memset(buffer, 0xff, count);
+ buffer = memcpy(new_buffer, buffer, old_count);
+ }
- LOG_DEBUG("write longword @ %08X", offset + i);
+ uint32_t words_remaining = count / 4;
- uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff};
- memcpy(padding, buffer + i, MIN(4, count-i));
- result = kinetis_ftfx_command(bank, FTFx_CMD_LWORDPROG, bank->base + offset + i,
- padding[3], padding[2], padding[1], padding[0],
- 0, 0, 0, 0, &ftfx_fstat);
+ /* try using a block write */
+ int retval = kinetis_write_block(bank, buffer, offset, words_remaining);
- if (result != ERROR_OK)
- return ERROR_FLASH_OPERATION_FAILED;
+ if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
+ /* if block write failed (no sufficient working area),
+ * we use normal (slow) single word accesses */
+ LOG_WARNING("couldn't use block writes, falling back to single "
+ "memory accesses");
+
+ for (i = 0; i < count; i += 4) {
+ uint8_t ftfx_fstat;
+
+ LOG_DEBUG("write longword @ %08X", offset + i);
+
+ uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff};
+ memcpy(padding, buffer + i, MIN(4, count-i));
+
+ result = kinetis_ftfx_command(bank, FTFx_CMD_LWORDPROG, bank->base + offset + i,
+ padding[3], padding[2], padding[1], padding[0],
+ 0, 0, 0, 0, &ftfx_fstat);
+
+ if (result != ERROR_OK)
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
}
+
} else {
LOG_ERROR("Flash write strategy not implemented");
return ERROR_FLASH_OPERATION_FAILED;
static int kinetis_read_part_info(struct flash_bank *bank)
{
int result, i;
- uint8_t buf[4];
uint32_t offset = 0;
uint8_t fcfg1_nvmsize, fcfg1_pfsize, fcfg1_eesize, fcfg2_pflsh;
uint32_t nvm_size = 0, pf_size = 0, ee_size = 0;
unsigned granularity, num_blocks = 0, num_pflash_blocks = 0, num_nvm_blocks = 0,
first_nvm_bank = 0, reassign = 0;
+ struct target *target = bank->target;
struct kinetis_flash_bank *kinfo = bank->driver_priv;
- result = target_read_memory(bank->target, SIM_SDID, 1, 4, buf);
+ result = target_read_u32(target, SIM_SDID, &kinfo->sim_sdid);
if (result != ERROR_OK)
return result;
- kinfo->sim_sdid = target_buffer_get_u32(bank->target, buf);
- granularity = (kinfo->sim_sdid >> 7) & 0x03;
- result = target_read_memory(bank->target, SIM_FCFG1, 1, 4, buf);
+ /* Kinetis L Series SubFamily Check */
+ kinfo->klxx = 0;
+ i = (kinfo->sim_sdid >> 20) & 0x0F;
+ if (i == 1) {
+ kinfo->klxx = 1;
+ granularity = 0;
+ } else
+ granularity = (kinfo->sim_sdid >> 7) & 0x03;
+
+ result = target_read_u32(target, SIM_FCFG1, &kinfo->sim_fcfg1);
if (result != ERROR_OK)
return result;
- kinfo->sim_fcfg1 = target_buffer_get_u32(bank->target, buf);
- result = target_read_memory(bank->target, SIM_FCFG2, 1, 4, buf);
+ result = target_read_u32(target, SIM_FCFG2, &kinfo->sim_fcfg2);
if (result != ERROR_OK)
return result;
- kinfo->sim_fcfg2 = target_buffer_get_u32(bank->target, buf);
fcfg2_pflsh = (kinfo->sim_fcfg2 >> 23) & 0x01;
- LOG_DEBUG("SDID: %08X FCFG1: %08X FCFG2: %08X", kinfo->sim_sdid,
- kinfo->sim_fcfg1, kinfo->sim_fcfg2);
+ LOG_DEBUG("SDID: 0x%08X FCFG1: 0x%08X FCFG2: 0x%08X", kinfo->sim_sdid,
+ kinfo->sim_fcfg1, kinfo->sim_fcfg2);
fcfg1_nvmsize = (uint8_t)((kinfo->sim_fcfg1 >> 28) & 0x0f);
fcfg1_pfsize = (uint8_t)((kinfo->sim_fcfg1 >> 24) & 0x0f);
LOG_DEBUG("FlexNVM: %d PFlash: %d FlexRAM: %d PFLSH: %d",
nvm_size, pf_size, ee_size, fcfg2_pflsh);
+ if (kinfo->klxx)
+ num_blocks = 1;
+ else
+ num_blocks = kinetis_flash_params[granularity].num_blocks;
- num_blocks = kinetis_flash_params[granularity].num_blocks;
num_pflash_blocks = num_blocks / (2 - fcfg2_pflsh);
first_nvm_bank = num_pflash_blocks;
num_nvm_blocks = num_blocks - num_pflash_blocks;
LOG_DEBUG("%d blocks total: %d PFlash, %d FlexNVM",
- num_blocks, num_pflash_blocks, num_nvm_blocks);
+ num_blocks, num_pflash_blocks, num_nvm_blocks);
/*
* If the flash class is already assigned, verify the
switch (kinfo->flash_class) {
case FC_PFLASH:
if (kinfo->bank_ordinal >= first_nvm_bank) {
- LOG_WARNING("Class mismatch, bank %d is not PFlash",
- bank->bank_number);
+ LOG_WARNING("Class mismatch, bank %d is not PFlash", bank->bank_number);
reassign = 1;
} else if (bank->size != (pf_size / num_pflash_blocks)) {
LOG_WARNING("PFlash size mismatch");
LOG_WARNING("PFlash address range mismatch");
reassign = 1;
} else if (kinfo->sector_size !=
- kinetis_flash_params[granularity].pflash_sector_size_bytes) {
+ kinetis_flash_params[granularity].pflash_sector_size_bytes) {
LOG_WARNING("PFlash sector size mismatch");
reassign = 1;
} else {
break;
case FC_FLEX_NVM:
if ((kinfo->bank_ordinal >= num_blocks) ||
- (kinfo->bank_ordinal < first_nvm_bank)) {
- LOG_WARNING("Class mismatch, bank %d is not FlexNVM",
- bank->bank_number);
+ (kinfo->bank_ordinal < first_nvm_bank)) {
+ LOG_WARNING("Class mismatch, bank %d is not FlexNVM", bank->bank_number);
reassign = 1;
} else if (bank->size != (nvm_size / num_nvm_blocks)) {
LOG_WARNING("FlexNVM size mismatch");
reassign = 1;
} else if (bank->base !=
- (0x10000000 + bank->size * kinfo->bank_ordinal)) {
+ (0x10000000 + bank->size * kinfo->bank_ordinal)) {
LOG_WARNING("FlexNVM address range mismatch");
reassign = 1;
} else if (kinfo->sector_size !=
- kinetis_flash_params[granularity].nvm_sector_size_bytes) {
+ kinetis_flash_params[granularity].nvm_sector_size_bytes) {
LOG_WARNING("FlexNVM sector size mismatch");
reassign = 1;
} else {
break;
case FC_FLEX_RAM:
if (kinfo->bank_ordinal != num_blocks) {
- LOG_WARNING("Class mismatch, bank %d is not FlexRAM",
- bank->bank_number);
+ LOG_WARNING("Class mismatch, bank %d is not FlexRAM", bank->bank_number);
reassign = 1;
} else if (bank->size != ee_size) {
LOG_WARNING("FlexRAM size mismatch");
LOG_WARNING("FlexRAM sector size mismatch");
reassign = 1;
} else {
- LOG_DEBUG("FlexRAM bank %d already configured okay",
- kinfo->bank_ordinal);
+ LOG_DEBUG("FlexRAM bank %d already configured okay", kinfo->bank_ordinal);
}
break;
return ERROR_FLASH_OPER_UNSUPPORTED;
} else {
LOG_ERROR("Cannot determine parameters for bank %d, only %d banks on device",
- bank->bank_number, num_blocks);
+ bank->bank_number, num_blocks);
return ERROR_FLASH_BANK_INVALID;
}
}
static int kinetis_flash_read(struct flash_bank *bank,
- uint8_t *buffer, uint32_t offset, uint32_t count)
+ uint8_t *buffer, uint32_t offset, uint32_t count)
{
LOG_WARNING("kinetis_flash_read not supported yet");