X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fkinetis.c;h=08f011df4ce6c89ca279c043234d5c0a1cbad2da;hp=0b738e2db2a1c8ff24aba37f14d59f3e9ae7189f;hb=97d296637e1d08e3198f970ffc2f9f8843d03e49;hpb=5fa3bfa074ccc826c51151ac5c306987c99bf2b2 diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 0b738e2db2..08f011df4c 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -89,6 +89,7 @@ #define FLEXRAM 0x14000000 +#define MSCM_OCMDR0 0x40001400 #define FMC_PFB01CR 0x4001f004 #define FTFx_FSTAT 0x40020000 #define FTFx_FCNFG 0x40020001 @@ -102,6 +103,7 @@ #define WDOG_STCTRH 0x40052000 #define SMC_PMCTRL 0x4007E001 #define SMC_PMSTAT 0x4007E003 +#define MCM_PLACR 0xF000300C /* Values */ #define PM_STAT_RUN 0x01 @@ -186,6 +188,7 @@ #define KINETIS_SDID_SERIESID_MASK 0x00F00000 #define KINETIS_SDID_SERIESID_K 0x00000000 #define KINETIS_SDID_SERIESID_KL 0x00100000 +#define KINETIS_SDID_SERIESID_KE 0x00200000 #define KINETIS_SDID_SERIESID_KW 0x00500000 #define KINETIS_SDID_SERIESID_KV 0x00600000 @@ -197,6 +200,8 @@ #define KINETIS_SDID_SUBFAMID_KX4 0x04000000 #define KINETIS_SDID_SUBFAMID_KX5 0x05000000 #define KINETIS_SDID_SUBFAMID_KX6 0x06000000 +#define KINETIS_SDID_SUBFAMID_KX7 0x07000000 +#define KINETIS_SDID_SUBFAMID_KX8 0x08000000 #define KINETIS_SDID_FAMILYID_MASK 0xF0000000 #define KINETIS_SDID_FAMILYID_K0X 0x00000000 @@ -206,6 +211,13 @@ #define KINETIS_SDID_FAMILYID_K4X 0x40000000 #define KINETIS_SDID_FAMILYID_K6X 0x60000000 #define KINETIS_SDID_FAMILYID_K7X 0x70000000 +#define KINETIS_SDID_FAMILYID_K8X 0x80000000 +#define KINETIS_SDID_FAMILYID_KL8X 0x90000000 + +/* The field originally named DIEID has new name/meaning on KE1x */ +#define KINETIS_SDID_PROJECTID_MASK KINETIS_SDID_DIEID_MASK +#define KINETIS_SDID_PROJECTID_KE1xF 0x00000080 +#define KINETIS_SDID_PROJECTID_KE1xZ 0x00000100 struct kinetis_flash_bank { bool probed; @@ -230,8 +242,11 @@ struct kinetis_flash_bank { enum { FS_PROGRAM_SECTOR = 1, FS_PROGRAM_LONGWORD = 2, - FS_PROGRAM_PHRASE = 4, /* Unsupported */ - FS_INVALIDATE_CACHE = 8, + FS_PROGRAM_PHRASE = 4, /* Unsupported */ + FS_INVALIDATE_CACHE_K = 8, /* using FMC->PFB0CR/PFB01CR */ + FS_INVALIDATE_CACHE_L = 0x10, /* using MCM->PLACR */ + FS_INVALIDATE_CACHE_MSCM = 0x20, + FS_NO_CMD_BLOCKSTAT = 0x40, } flash_support; }; @@ -836,6 +851,12 @@ static int kinetis_ftfx_decode_error(uint8_t fstat) return ERROR_FLASH_OPERATION_FAILED; } +static int kinetis_ftfx_clear_error(struct target *target) +{ + /* reset error flags */ + return target_write_u8(target, FTFx_FSTAT, 0x70); +} + static int kinetis_ftfx_prepare(struct target *target) { @@ -858,72 +879,14 @@ static int kinetis_ftfx_prepare(struct target *target) } if (fstat != 0x80) { /* reset error flags */ - result = target_write_u8(target, FTFx_FSTAT, 0x70); + result = kinetis_ftfx_clear_error(target); } return result; } /* 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;idriver_priv; uint32_t address = kinfo->prog_base + offset; - struct reg_param reg_params[3]; + uint32_t end_address; + struct reg_param reg_params[5]; 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 - */ + int retval; + uint8_t fstat; /* Increase buffer_size if needed */ if (buffer_size < (target->working_area_size/2)) @@ -982,35 +936,39 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer, 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 */ + init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* address */ + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* word count */ + init_reg_param(®_params[2], "r2", 32, PARAM_OUT); + init_reg_param(®_params[3], "r3", 32, PARAM_OUT); + init_reg_param(®_params[4], "r4", 32, PARAM_OUT); - /* 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; + buf_set_u32(reg_params[0].value, 0, 32, address); + buf_set_u32(reg_params[1].value, 0, 32, wcount); + buf_set_u32(reg_params[2].value, 0, 32, source->address); + buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size); + buf_set_u32(reg_params[4].value, 0, 32, FTFx_FSTAT); - retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer); - if (retval != ERROR_OK) - break; + retval = target_run_flash_async_algorithm(target, buffer, wcount, 4, + 0, NULL, + 5, reg_params, + source->address, source->size, + write_algorithm->address, 0, + &armv7m_info); - 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); + if (retval == ERROR_FLASH_OPERATION_FAILED) { + end_address = buf_get_u32(reg_params[0].value, 0, 32); - 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; - } + LOG_ERROR("Error writing flash at %08" PRIx32, end_address); - buffer += thisrun_count * 4; - address += thisrun_count * 4; - wcount -= thisrun_count; - } + retval = target_read_u8(target, FTFx_FSTAT, &fstat); + if (retval == ERROR_OK) { + retval = kinetis_ftfx_decode_error(fstat); + + /* reset error flags */ + target_write_u8(target, FTFx_FSTAT, 0x70); + } + } else if (retval != ERROR_OK) + LOG_ERROR("Error executing kinetis Flash programming algorithm"); target_free_working_area(target, source); target_free_working_area(target, write_algorithm); @@ -1018,6 +976,8 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer, destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); + destroy_reg_param(®_params[3]); + destroy_reg_param(®_params[4]); return retval; } @@ -1239,12 +1199,20 @@ static int kinetis_check_run_mode(struct target *target) static void kinetis_invalidate_flash_cache(struct flash_bank *bank) { struct kinetis_flash_bank *kinfo = bank->driver_priv; - uint8_t pfb01cr_byte2 = 0xf0; - if (!(kinfo->flash_support & FS_INVALIDATE_CACHE)) - return; + if (kinfo->flash_support & FS_INVALIDATE_CACHE_K) + target_write_u8(bank->target, FMC_PFB01CR + 2, 0xf0); + /* Set CINV_WAY bits - request invalidate of all cache ways */ + /* FMC_PFB0CR has same address and CINV_WAY bits as FMC_PFB01CR */ + + else if (kinfo->flash_support & FS_INVALIDATE_CACHE_L) + target_write_u8(bank->target, MCM_PLACR + 1, 0x04); + /* set bit CFCC - Clear Flash Controller Cache */ + + else if (kinfo->flash_support & FS_INVALIDATE_CACHE_MSCM) + target_write_u32(bank->target, MSCM_OCMDR0, 0x30); + /* disable data prefetch and flash speculate */ - target_write_memory(bank->target, FMC_PFB01CR + 2, 1, 1, &pfb01cr_byte2); return; } @@ -1340,7 +1308,7 @@ static int kinetis_make_ram_ready(struct target *target) static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { - int result; + int result = ERROR_OK; struct kinetis_flash_bank *kinfo = bank->driver_priv; uint8_t *buffer_aligned = NULL; /* @@ -1428,7 +1396,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, if (!(kinfo->flash_support & FS_PROGRAM_SECTOR)) { /* fallback to longword write */ fallback = 1; - LOG_WARNING("This device supports Program Longword execution only."); + LOG_INFO("This device supports Program Longword execution only."); } else { result = kinetis_make_ram_ready(bank->target); if (result != ERROR_OK) { @@ -1607,7 +1575,7 @@ static int kinetis_probe(struct flash_bank *bank) pflash_sector_size_bytes = 1<<10; nvm_sector_size_bytes = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K10_M72: case KINETIS_K_SDID_K20_M72: @@ -1620,7 +1588,7 @@ static int kinetis_probe(struct flash_bank *bank) pflash_sector_size_bytes = 2<<10; nvm_sector_size_bytes = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; kinfo->max_flash_prog_size = 1<<10; break; case KINETIS_K_SDID_K10_M100: @@ -1636,7 +1604,7 @@ static int kinetis_probe(struct flash_bank *bank) pflash_sector_size_bytes = 2<<10; nvm_sector_size_bytes = 2<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K21_M120: case KINETIS_K_SDID_K22_M120: @@ -1645,7 +1613,7 @@ static int kinetis_probe(struct flash_bank *bank) kinfo->max_flash_prog_size = 1<<10; nvm_sector_size_bytes = 4<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K10_M120: case KINETIS_K_SDID_K20_M120: @@ -1655,7 +1623,7 @@ static int kinetis_probe(struct flash_bank *bank) pflash_sector_size_bytes = 4<<10; nvm_sector_size_bytes = 4<<10; num_blocks = 4; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; default: LOG_ERROR("Unsupported K-family FAMID"); @@ -1669,7 +1637,7 @@ static int kinetis_probe(struct flash_bank *bank) /* K02FN64, K02FN128: FTFA, 2kB sectors */ pflash_sector_size_bytes = 2<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: { @@ -1684,7 +1652,7 @@ static int kinetis_probe(struct flash_bank *bank) /* MK24FN1M */ pflash_sector_size_bytes = 4<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; kinfo->max_flash_prog_size = 1<<10; break; } @@ -1694,7 +1662,7 @@ static int kinetis_probe(struct flash_bank *bank) /* K22 with new-style SDID - smaller pflash with FTFA, 2kB sectors */ pflash_sector_size_bytes = 2<<10; /* autodetect 1 or 2 blocks */ - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; } LOG_ERROR("Unsupported Kinetis K22 DIEID"); @@ -1705,12 +1673,12 @@ static int kinetis_probe(struct flash_bank *bank) if ((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN256) { /* K24FN256 - smaller pflash with FTFA */ num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; } /* K24FN1M without errata 7534 */ num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; kinfo->max_flash_prog_size = 1<<10; break; @@ -1724,7 +1692,7 @@ static int kinetis_probe(struct flash_bank *bank) nvm_sector_size_bytes = 4<<10; kinfo->max_flash_prog_size = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX6: @@ -1735,8 +1703,26 @@ static int kinetis_probe(struct flash_bank *bank) nvm_sector_size_bytes = 4<<10; kinfo->max_flash_prog_size = 1<<10; num_blocks = 4; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; + + case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX0: + case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX1: + case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX2: + /* K80FN256, K81FN256, K82FN256 */ + pflash_sector_size_bytes = 4<<10; + num_blocks = 1; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K | FS_NO_CMD_BLOCKSTAT; + break; + + case KINETIS_SDID_FAMILYID_KL8X | KINETIS_SDID_SUBFAMID_KX1: + case KINETIS_SDID_FAMILYID_KL8X | KINETIS_SDID_SUBFAMID_KX2: + /* KL81Z128, KL82Z128 */ + pflash_sector_size_bytes = 2<<10; + num_blocks = 1; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L | FS_NO_CMD_BLOCKSTAT; + break; + default: LOG_ERROR("Unsupported Kinetis FAMILYID SUBFAMID"); } @@ -1747,7 +1733,7 @@ static int kinetis_probe(struct flash_bank *bank) pflash_sector_size_bytes = 1<<10; nvm_sector_size_bytes = 1<<10; /* autodetect 1 or 2 blocks */ - kinfo->flash_support = FS_PROGRAM_LONGWORD; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; break; case KINETIS_SDID_SERIESID_KV: @@ -1757,14 +1743,14 @@ static int kinetis_probe(struct flash_bank *bank) /* KV10: FTFA, 1kB sectors */ pflash_sector_size_bytes = 1<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; break; case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX1: /* KV11: FTFA, 2kB sectors */ pflash_sector_size_bytes = 2<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; break; case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX0: @@ -1773,7 +1759,7 @@ static int kinetis_probe(struct flash_bank *bank) /* KV31: FTFA, 2kB sectors, 2 blocks */ pflash_sector_size_bytes = 2<<10; /* autodetect 1 or 2 blocks */ - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX2: @@ -1782,7 +1768,7 @@ static int kinetis_probe(struct flash_bank *bank) /* KV4x: FTFA, 4kB sectors */ pflash_sector_size_bytes = 4<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; default: @@ -1790,6 +1776,36 @@ static int kinetis_probe(struct flash_bank *bank) } break; + case KINETIS_SDID_SERIESID_KE: + /* KE1x-series */ + switch (kinfo->sim_sdid & + (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK | KINETIS_SDID_PROJECTID_MASK)) { + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX4 | KINETIS_SDID_PROJECTID_KE1xZ: + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX5 | KINETIS_SDID_PROJECTID_KE1xZ: + /* KE1xZ: FTFE, 2kB sectors */ + pflash_sector_size_bytes = 2<<10; + nvm_sector_size_bytes = 2<<10; + kinfo->max_flash_prog_size = 1<<9; + num_blocks = 2; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_L; + break; + + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX4 | KINETIS_SDID_PROJECTID_KE1xF: + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX6 | KINETIS_SDID_PROJECTID_KE1xF: + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX8 | KINETIS_SDID_PROJECTID_KE1xF: + /* KE1xF: FTFE, 4kB sectors */ + pflash_sector_size_bytes = 4<<10; + nvm_sector_size_bytes = 2<<10; + kinfo->max_flash_prog_size = 1<<10; + num_blocks = 2; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_MSCM; + break; + + default: + LOG_ERROR("Unsupported KE FAMILYID SUBFAMID"); + } + break; + default: LOG_ERROR("Unsupported K-series"); } @@ -2094,23 +2110,26 @@ static int kinetis_blank_check(struct flash_bank *bank) return result; if (kinfo->flash_class == FC_PFLASH || kinfo->flash_class == FC_FLEX_NVM) { - bool block_dirty = false; + bool block_dirty = true; + bool use_block_cmd = !(kinfo->flash_support & FS_NO_CMD_BLOCKSTAT); uint8_t ftfx_fstat; - if (kinfo->flash_class == FC_FLEX_NVM) { + if (use_block_cmd && kinfo->flash_class == FC_FLEX_NVM) { uint8_t fcfg1_depart = (uint8_t)((kinfo->sim_fcfg1 >> 8) & 0x0f); /* block operation cannot be used on FlexNVM when EEPROM backup partition is set */ if (fcfg1_depart != 0xf && fcfg1_depart != 0) - block_dirty = true; + use_block_cmd = false; } - if (!block_dirty) { + if (use_block_cmd) { /* check if whole bank is blank */ result = kinetis_ftfx_command(bank->target, FTFx_CMD_BLOCKSTAT, kinfo->prog_base, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); - if (result != ERROR_OK || (ftfx_fstat & 0x01)) - block_dirty = true; + if (result != ERROR_OK) + kinetis_ftfx_clear_error(bank->target); + else if ((ftfx_fstat & 0x01) == 0) + block_dirty = false; } if (block_dirty) { @@ -2126,6 +2145,7 @@ static int kinetis_blank_check(struct flash_bank *bank) bank->sectors[i].is_erased = !(ftfx_fstat & 0x01); } else { LOG_DEBUG("Ignoring errored PFlash sector blank-check"); + kinetis_ftfx_clear_error(bank->target); bank->sectors[i].is_erased = -1; } }