Kinetis: fix preparation of FlexRAM before flash programming
[openocd.git] / src / flash / nor / kinetis.c
index 484bc479375e884af0ef14fe74adef3e71c4d194..a1625ffee64bef805d74904a4eeca452f0f5e6ed 100644 (file)
@@ -34,6 +34,7 @@
 #include "jtag/interface.h"
 #include "imp.h"
 #include <helper/binarybuffer.h>
+#include <target/target_type.h>
 #include <target/algorithm.h>
 #include <target/armv7m.h>
 #include <target/cortex_m.h>
@@ -82,6 +83,7 @@
 #define FTFx_FCNFG     0x40020001
 #define FTFx_FCCOB3    0x40020004
 #define FTFx_FPROT3    0x40020010
+#define FTFx_FDPROT    0x40020017
 #define SIM_SDID       0x40048024
 #define SIM_SOPT1      0x40047000
 #define SIM_FCFG1      0x4004804c
 #define KINETIS_SDID_FAMILYID_K7X   0x70000000
 
 struct kinetis_flash_bank {
-       unsigned bank_ordinal;
+       bool probed;
        uint32_t sector_size;
        uint32_t max_flash_prog_size;
        uint32_t protection_size;
+       uint32_t prog_base;             /* base address for FTFx operations */
+                                       /* same as bank->base for pflash, differs for FlexNVM */
+       uint32_t protection_block;      /* number of first protection block in this bank */
 
        uint32_t sim_sdid;
        uint32_t sim_fcfg1;
@@ -244,7 +249,7 @@ static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint3
        int retval;
        LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value);
 
-       retval = dap_queue_ap_write(dap, reg, value);
+       retval = dap_queue_ap_write(dap_ap(dap, 1), reg, value);
        if (retval != ERROR_OK) {
                LOG_DEBUG("MDM: failed to queue a write request");
                return retval;
@@ -263,7 +268,8 @@ static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint3
 static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result)
 {
        int retval;
-       retval = dap_queue_ap_read(dap, reg, result);
+
+       retval = dap_queue_ap_read(dap_ap(dap, 1), reg, result);
        if (retval != ERROR_OK) {
                LOG_DEBUG("MDM: failed to queue a read request");
                return retval;
@@ -315,7 +321,6 @@ COMMAND_HANDLER(kinetis_mdm_mass_erase)
        }
 
        int retval;
-       const uint8_t original_ap = dap->ap_current;
 
        /*
         * ... Power on the processor, or if power has already been
@@ -332,8 +337,6 @@ COMMAND_HANDLER(kinetis_mdm_mass_erase)
                LOG_WARNING("Attempting mass erase without hardware reset. This is not reliable; "
                            "it's recommended you connect SRST and use ``reset_config srst_only''.");
 
-       dap_ap_select(dap, 1);
-
        retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, MEM_CTRL_SYS_RES_REQ);
        if (retval != ERROR_OK)
                return retval;
@@ -383,10 +386,13 @@ COMMAND_HANDLER(kinetis_mdm_mass_erase)
        if (retval != ERROR_OK)
                return retval;
 
-       if (jtag_get_reset_config() & RESET_HAS_SRST)
-               adapter_deassert_reset();
+       if (jtag_get_reset_config() & RESET_HAS_SRST) {
+               /* halt MCU otherwise it loops in hard fault - WDOG reset cycle */
+               target->reset_halt = true;
+               target->type->assert_reset(target);
+               target->type->deassert_reset(target);
+       }
 
-       dap_ap_select(dap, original_ap);
        return ERROR_OK;
 }
 
@@ -414,10 +420,6 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
 
        uint32_t val;
        int retval;
-       const uint8_t origninal_ap = dap->ap_current;
-
-       dap_ap_select(dap, 1);
-
 
        /*
         * ... The MDM-AP ID register can be read to verify that the
@@ -464,6 +466,29 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
                goto fail;
        }
 
+       if ((val & (MDM_STAT_SYSSEC | MDM_STAT_CORE_HALTED)) == MDM_STAT_SYSSEC) {
+               LOG_WARNING("MDM: Secured MCU state detected however it may be a false alarm");
+               LOG_WARNING("MDM: Halting target to detect secured state reliably");
+
+               retval = target_halt(target);
+               if (retval == ERROR_OK)
+                       retval = target_wait_state(target, TARGET_HALTED, 100);
+
+               if (retval != ERROR_OK) {
+                       LOG_WARNING("MDM: Target not halted, trying reset halt");
+                       target->reset_halt = true;
+                       target->type->assert_reset(target);
+                       target->type->deassert_reset(target);
+               }
+
+               /* re-read status */
+               retval = kinetis_mdm_read_register(dap, MDM_REG_STAT, &val);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("MDM: failed to read MDM_REG_STAT");
+                       goto fail;
+               }
+       }
+
        if (val & MDM_STAT_SYSSEC) {
                jtag_poll_set_enabled(false);
 
@@ -481,8 +506,6 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
                jtag_poll_set_enabled(true);
        }
 
-       dap_ap_select(dap, origninal_ap);
-
        return ERROR_OK;
 
 fail:
@@ -684,7 +707,8 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer,
        uint32_t buffer_size = 2048;            /* Default minimum value */
        struct working_area *write_algorithm;
        struct working_area *source;
-       uint32_t address = bank->base + offset;
+       struct kinetis_flash_bank *kinfo = bank->driver_priv;
+       uint32_t address = kinfo->prog_base + offset;
        struct reg_param reg_params[3];
        struct armv7m_algorithm armv7m_info;
        int retval = ERROR_OK;
@@ -795,6 +819,9 @@ static int kinetis_protect(struct flash_bank *bank, int set, int first, int last
 static int kinetis_protect_check(struct flash_bank *bank)
 {
        struct kinetis_flash_bank *kinfo = bank->driver_priv;
+       int result;
+       int i, b;
+       uint32_t fprot, psec;
 
        if (bank->target->state != TARGET_HALTED) {
                LOG_ERROR("Target not halted");
@@ -802,10 +829,7 @@ static int kinetis_protect_check(struct flash_bank *bank)
        }
 
        if (kinfo->flash_class == FC_PFLASH) {
-               int result;
                uint8_t buffer[4];
-               uint32_t fprot, psec;
-               int i, b;
 
                /* read protection register */
                result = target_read_memory(bank->target, FTFx_FPROT3, 1, 4, buffer);
@@ -814,35 +838,43 @@ static int kinetis_protect_check(struct flash_bank *bank)
                        return result;
 
                fprot = target_buffer_get_u32(bank->target, buffer);
+               /* Every bit protects 1/32 of the full flash (not necessarily just this bank) */
 
-               /*
-                * Every bit protects 1/32 of the full flash (not necessarily
-                * just this bank), but we enforce the bank ordinals for
-                * PFlash to start at zero.
-                */
-               b = kinfo->bank_ordinal * (bank->size / kinfo->protection_size);
-               for (psec = 0, i = 0; i < bank->num_sectors; i++) {
-                       if ((fprot >> b) & 1)
-                               bank->sectors[i].is_protected = 0;
-                       else
-                               bank->sectors[i].is_protected = 1;
+       } else if (kinfo->flash_class == FC_FLEX_NVM) {
+               uint8_t fdprot;
+
+               /* read protection register */
+               result = target_read_memory(bank->target, FTFx_FDPROT, 1, 1, &fdprot);
 
-                       psec += bank->sectors[i].size;
+               if (result != ERROR_OK)
+                       return result;
+
+               fprot = fdprot;
 
-                       if (psec >= kinfo->protection_size) {
-                               psec = 0;
-                               b++;
-                       }
-               }
        } else {
-               LOG_ERROR("Protection checks for FlexNVM not yet supported");
+               LOG_ERROR("Protection checks for FlexRAM not supported");
                return ERROR_FLASH_BANK_INVALID;
        }
 
+       b = kinfo->protection_block;
+       for (psec = 0, i = 0; i < bank->num_sectors; i++) {
+               if ((fprot >> b) & 1)
+                       bank->sectors[i].is_protected = 0;
+               else
+                       bank->sectors[i].is_protected = 1;
+
+               psec += bank->sectors[i].size;
+
+               if (psec >= kinfo->protection_size) {
+                       psec = 0;
+                       b++;
+               }
+       }
+
        return ERROR_OK;
 }
 
-static int kinetis_ftfx_command(struct flash_bank *bank, uint8_t fcmd, uint32_t faddr,
+static int kinetis_ftfx_command(struct target *target, uint8_t fcmd, uint32_t faddr,
                                uint8_t fccob4, uint8_t fccob5, uint8_t fccob6, uint8_t fccob7,
                                uint8_t fccob8, uint8_t fccob9, uint8_t fccoba, uint8_t fccobb,
                                uint8_t *ftfx_fstat)
@@ -856,7 +888,7 @@ static int kinetis_ftfx_command(struct flash_bank *bank, uint8_t fcmd, uint32_t
        /* wait for done */
        for (i = 0; i < 50; i++) {
                result =
-                       target_read_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer);
+                       target_read_memory(target, FTFx_FSTAT, 1, 1, &buffer);
 
                if (result != ERROR_OK)
                        return result;
@@ -871,26 +903,26 @@ static int kinetis_ftfx_command(struct flash_bank *bank, uint8_t fcmd, uint32_t
                /* reset error flags */
                buffer = 0x30;
                result =
-                       target_write_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer);
+                       target_write_memory(target, FTFx_FSTAT, 1, 1, &buffer);
                if (result != ERROR_OK)
                        return result;
        }
 
-       result = target_write_memory(bank->target, FTFx_FCCOB3, 4, 3, command);
+       result = target_write_memory(target, FTFx_FCCOB3, 4, 3, command);
 
        if (result != ERROR_OK)
                return result;
 
        /* start command */
        buffer = 0x80;
-       result = target_write_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer);
+       result = target_write_memory(target, FTFx_FSTAT, 1, 1, &buffer);
        if (result != ERROR_OK)
                return result;
 
        /* wait for done */
        for (i = 0; i < 240; i++) { /* Need longtime for "Mass Erase" Command Nemui Changed */
                result =
-                       target_read_memory(bank->target, FTFx_FSTAT, 1, 1, ftfx_fstat);
+                       target_read_memory(target, FTFx_FSTAT, 1, 1, ftfx_fstat);
 
                if (result != ERROR_OK)
                        return result;
@@ -911,31 +943,11 @@ static int kinetis_ftfx_command(struct flash_bank *bank, uint8_t fcmd, uint32_t
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(kinetis_securing_test)
-{
-       int result;
-       uint8_t ftfx_fstat;
-       struct target *target = get_current_target(CMD_CTX);
-       struct flash_bank *bank = NULL;
-
-       result = get_flash_bank_by_addr(target, 0x00000000, true, &bank);
-       if (result != ERROR_OK)
-               return result;
-
-       assert(bank != NULL);
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
-       return kinetis_ftfx_command(bank, FTFx_CMD_SECTERASE, bank->base + 0x00000400,
-                                     0, 0, 0, 0,  0, 0, 0, 0,  &ftfx_fstat);
-}
 
 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");
@@ -953,7 +965,7 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last)
        for (i = first; i <= last; i++) {
                uint8_t ftfx_fstat;
                /* set command and sector address */
-               result = kinetis_ftfx_command(bank, FTFx_CMD_SECTERASE, bank->base + bank->sectors[i].offset,
+               result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTERASE, kinfo->prog_base + bank->sectors[i].offset,
                                0, 0, 0, 0,  0, 0, 0, 0,  &ftfx_fstat);
 
                if (result != ERROR_OK) {
@@ -972,11 +984,41 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last)
        return ERROR_OK;
 }
 
+static int kinetis_make_ram_ready(struct target *target)
+{
+       int result;
+       uint8_t ftfx_fstat;
+       uint8_t ftfx_fcnfg;
+
+       /* check if ram ready */
+       result = target_read_memory(target, FTFx_FCNFG, 1, 1, &ftfx_fcnfg);
+       if (result != ERROR_OK)
+               return result;
+
+       if (ftfx_fcnfg & (1 << 1))
+               return ERROR_OK;        /* ram ready */
+
+       /* make flex ram available */
+       result = kinetis_ftfx_command(target, FTFx_CMD_SETFLEXRAM, 0x00ff0000,
+                                0, 0, 0, 0,  0, 0, 0, 0,  &ftfx_fstat);
+       if (result != ERROR_OK)
+               return ERROR_FLASH_OPERATION_FAILED;
+
+       /* check again */
+       result = target_read_memory(target, FTFx_FCNFG, 1, 1, &ftfx_fcnfg);
+       if (result != ERROR_OK)
+               return result;
+
+       if (ftfx_fcnfg & (1 << 1))
+               return ERROR_OK;        /* ram ready */
+
+       return ERROR_FLASH_OPERATION_FAILED;
+}
+
 static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
                         uint32_t offset, uint32_t count)
 {
        unsigned int i, result, fallback = 0;
-       uint8_t buf[8];
        uint32_t wc;
        struct kinetis_flash_bank *kinfo = bank->driver_priv;
        uint8_t *new_buffer = NULL;
@@ -990,35 +1032,16 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
                /* fallback to longword write */
                fallback = 1;
                LOG_WARNING("This device supports Program Longword execution only.");
-               LOG_DEBUG("flash write into PFLASH @08%" PRIX32, offset);
-
-       } else if (kinfo->flash_class == FC_FLEX_NVM) {
-               uint8_t ftfx_fstat;
-
-               LOG_DEBUG("flash write into FlexNVM @%08" PRIX32, offset);
-
-               /* make flex ram available */
-               result = kinetis_ftfx_command(bank, FTFx_CMD_SETFLEXRAM, 0x00ff0000, 0, 0, 0, 0,  0, 0, 0, 0,  &ftfx_fstat);
-
-               if (result != ERROR_OK)
-                       return ERROR_FLASH_OPERATION_FAILED;
-
-               /* check if ram ready */
-               result = target_read_memory(bank->target, FTFx_FCNFG, 1, 1, buf);
-
-               if (result != ERROR_OK)
-                       return result;
-
-               if (!(buf[0] & (1 << 1))) {
-                       /* fallback to longword write */
+       } else {
+               result = kinetis_make_ram_ready(bank->target);
+               if (result != ERROR_OK) {
                        fallback = 1;
-
-                       LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)", buf[0]);
+                       LOG_WARNING("FlexRAM not ready, fallback to slow longword write.");
                }
-       } else {
-               LOG_DEBUG("flash write into PFLASH @08%" PRIX32, offset);
        }
 
+       LOG_DEBUG("flash write @08%" PRIX32, offset);
+
 
        /* program section command */
        if (fallback == 0) {
@@ -1054,7 +1077,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
                                unsigned residual_bc = (count-i) % prog_section_chunk_bytes;
 
                                /* number of complete words to copy directly from buffer */
-                               wc = (count - i) / 4;
+                               wc = (count - i - residual_bc) / 4;
 
                                /* number of total sections to write, including residual */
                                section_count = DIV_ROUND_UP((count-i), prog_section_chunk_bytes);
@@ -1093,7 +1116,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
                        }
 
                        /* execute section-write command */
-                       result = kinetis_ftfx_command(bank, FTFx_CMD_SECTWRITE, bank->base + offset + i,
+                       result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTWRITE, kinfo->prog_base + offset + i,
                                        section_count>>8, section_count, 0, 0,
                                        0, 0, 0, 0,  &ftfx_fstat);
 
@@ -1139,7 +1162,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
                                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,
+                               result = kinetis_ftfx_command(bank->target, FTFx_CMD_LWORDPROG, kinfo->prog_base + offset + i,
                                                padding[3], padding[2], padding[1], padding[0],
                                                0, 0, 0, 0,  &ftfx_fstat);
 
@@ -1159,13 +1182,16 @@ static int kinetis_read_part_info(struct flash_bank *bank)
 {
        int result, i;
        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;
+       uint8_t fcfg1_nvmsize, fcfg1_pfsize, fcfg1_eesize, fcfg1_depart;
+       uint8_t fcfg2_pflsh;
+       uint32_t nvm_size = 0, pf_size = 0, df_size = 0, ee_size = 0;
        unsigned num_blocks = 0, num_pflash_blocks = 0, num_nvm_blocks = 0, first_nvm_bank = 0,
-                       reassign = 0, pflash_sector_size_bytes = 0, nvm_sector_size_bytes = 0;
+                       pflash_sector_size_bytes = 0, nvm_sector_size_bytes = 0;
        struct target *target = bank->target;
        struct kinetis_flash_bank *kinfo = bank->driver_priv;
 
+       kinfo->probed = false;
+
        result = target_read_u32(target, SIM_SDID, &kinfo->sim_sdid);
        if (result != ERROR_OK)
                return result;
@@ -1339,7 +1365,6 @@ static int kinetis_read_part_info(struct flash_bank *bank)
        result = target_read_u32(target, SIM_FCFG2, &kinfo->sim_fcfg2);
        if (result != ERROR_OK)
                return result;
-       fcfg2_pflsh = (kinfo->sim_fcfg2 >> 23) & 0x01;
 
        LOG_DEBUG("SDID: 0x%08" PRIX32 " FCFG1: 0x%08" PRIX32 " FCFG2: 0x%08" PRIX32, kinfo->sim_sdid,
                        kinfo->sim_fcfg1, kinfo->sim_fcfg2);
@@ -1347,11 +1372,15 @@ static int kinetis_read_part_info(struct flash_bank *bank)
        fcfg1_nvmsize = (uint8_t)((kinfo->sim_fcfg1 >> 28) & 0x0f);
        fcfg1_pfsize = (uint8_t)((kinfo->sim_fcfg1 >> 24) & 0x0f);
        fcfg1_eesize = (uint8_t)((kinfo->sim_fcfg1 >> 16) & 0x0f);
+       fcfg1_depart = (uint8_t)((kinfo->sim_fcfg1 >> 8) & 0x0f);
+
+       fcfg2_pflsh = (uint8_t)((kinfo->sim_fcfg2 >> 23) & 0x01);
 
        /* when the PFLSH bit is set, there is no FlexNVM/FlexRAM */
        if (!fcfg2_pflsh) {
                switch (fcfg1_nvmsize) {
                case 0x03:
+               case 0x05:
                case 0x07:
                case 0x09:
                case 0x0b:
@@ -1386,6 +1415,30 @@ static int kinetis_read_part_info(struct flash_bank *bank)
                        ee_size = 0;
                        break;
                }
+
+               switch (fcfg1_depart) {
+               case 0x01:
+               case 0x02:
+               case 0x03:
+               case 0x04:
+               case 0x05:
+               case 0x06:
+                       df_size = nvm_size - (4096 << fcfg1_depart);
+                       break;
+               case 0x08:
+                       df_size = 0;
+                       break;
+               case 0x09:
+               case 0x0a:
+               case 0x0b:
+               case 0x0c:
+               case 0x0d:
+                       df_size = 4096 << (fcfg1_depart & 0x7);
+                       break;
+               default:
+                       df_size = nvm_size;
+                       break;
+               }
        }
 
        switch (fcfg1_pfsize) {
@@ -1420,101 +1473,52 @@ static int kinetis_read_part_info(struct flash_bank *bank)
        LOG_DEBUG("%d blocks total: %d PFlash, %d FlexNVM",
                        num_blocks, num_pflash_blocks, num_nvm_blocks);
 
-       /*
-        * If the flash class is already assigned, verify the
-        * parameters.
-        */
-       if (kinfo->flash_class != FC_AUTO) {
-               if (kinfo->bank_ordinal != (unsigned) bank->bank_number) {
-                       LOG_WARNING("Flash ordinal/bank number mismatch");
-                       reassign = 1;
-               } else {
-                       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);
-                                       reassign = 1;
-                               } else if (bank->size != (pf_size / num_pflash_blocks)) {
-                                       LOG_WARNING("PFlash size mismatch");
-                                       reassign = 1;
-                               } else if (bank->base !=
-                                        (0x00000000 + bank->size * kinfo->bank_ordinal)) {
-                                       LOG_WARNING("PFlash address range mismatch");
-                                       reassign = 1;
-                               } else if (kinfo->sector_size != pflash_sector_size_bytes) {
-                                       LOG_WARNING("PFlash sector size mismatch");
-                                       reassign = 1;
-                               } else {
-                                       LOG_DEBUG("PFlash bank %d already configured okay",
-                                                 kinfo->bank_ordinal);
-                               }
-                               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);
-                                       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)) {
-                                       LOG_WARNING("FlexNVM address range mismatch");
-                                       reassign = 1;
-                               } else if (kinfo->sector_size != nvm_sector_size_bytes) {
-                                       LOG_WARNING("FlexNVM sector size mismatch");
-                                       reassign = 1;
-                               } else {
-                                       LOG_DEBUG("FlexNVM bank %d already configured okay",
-                                                 kinfo->bank_ordinal);
-                               }
-                               break;
-                       case FC_FLEX_RAM:
-                               if (kinfo->bank_ordinal != num_blocks) {
-                                       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");
-                                       reassign = 1;
-                               } else if (bank->base != FLEXRAM) {
-                                       LOG_WARNING("FlexRAM address mismatch");
-                                       reassign = 1;
-                               } else if (kinfo->sector_size != nvm_sector_size_bytes) {
-                                       LOG_WARNING("FlexRAM sector size mismatch");
-                                       reassign = 1;
-                               } else {
-                                       LOG_DEBUG("FlexRAM bank %d already configured okay", kinfo->bank_ordinal);
-                               }
-                               break;
-
-                       default:
-                               LOG_WARNING("Unknown or inconsistent flash class");
-                               reassign = 1;
-                               break;
-                       }
-               }
-       } else {
-               LOG_INFO("Probing flash info for bank %d", bank->bank_number);
-               reassign = 1;
-       }
-
-       if (!reassign)
-               return ERROR_OK;
+       LOG_INFO("Probing flash info for bank %d", bank->bank_number);
 
        if ((unsigned)bank->bank_number < num_pflash_blocks) {
                /* pflash, banks start at address zero */
                kinfo->flash_class = FC_PFLASH;
                bank->size = (pf_size / num_pflash_blocks);
                bank->base = 0x00000000 + bank->size * bank->bank_number;
+               kinfo->prog_base = bank->base;
                kinfo->sector_size = pflash_sector_size_bytes;
                kinfo->protection_size = pf_size / 32;
+               kinfo->protection_block = (32 / num_pflash_blocks) * bank->bank_number;
+
        } else if ((unsigned)bank->bank_number < num_blocks) {
                /* nvm, banks start at address 0x10000000 */
+               unsigned nvm_ord = bank->bank_number - first_nvm_bank;
+               uint32_t limit;
+
                kinfo->flash_class = FC_FLEX_NVM;
                bank->size = (nvm_size / num_nvm_blocks);
-               bank->base = 0x10000000 + bank->size * (bank->bank_number - first_nvm_bank);
+               bank->base = 0x10000000 + bank->size * nvm_ord;
+               kinfo->prog_base = 0x00800000 + bank->size * nvm_ord;
                kinfo->sector_size = nvm_sector_size_bytes;
-               kinfo->protection_size = 0; /* FIXME: TODO: depends on DEPART bits, chip */
+               if (df_size == 0) {
+                       kinfo->protection_size = 0;
+               } else {
+                       for (i = df_size; ~i & 1; i >>= 1)
+                               ;
+                       if (i == 1)
+                               kinfo->protection_size = df_size / 8;   /* data flash size = 2^^n */
+                       else
+                               kinfo->protection_size = nvm_size / 8;  /* TODO: verify on SF1, not documented in RM */
+               }
+               kinfo->protection_block = (8 / num_nvm_blocks) * nvm_ord;
+
+               /* EEPROM backup part of FlexNVM is not accessible, use df_size as a limit */
+               if (df_size > bank->size * nvm_ord)
+                       limit = df_size - bank->size * nvm_ord;
+               else
+                       limit = 0;
+
+               if (bank->size > limit) {
+                       bank->size = limit;
+                       LOG_DEBUG("FlexNVM bank %d limited to 0x%08" PRIx32 " due to active EEPROM backup",
+                               bank->bank_number, limit);
+               }
+
        } else if ((unsigned)bank->bank_number == num_blocks) {
                LOG_ERROR("FlexRAM support not yet implemented");
                return ERROR_FLASH_OPER_UNSUPPORTED;
@@ -1541,17 +1545,22 @@ static int kinetis_read_part_info(struct flash_bank *bank)
        }
 
        bank->num_sectors = bank->size / kinfo->sector_size;
-       assert(bank->num_sectors > 0);
-       bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
-
-       for (i = 0; i < bank->num_sectors; i++) {
-               bank->sectors[i].offset = offset;
-               bank->sectors[i].size = kinfo->sector_size;
-               offset += kinfo->sector_size;
-               bank->sectors[i].is_erased = -1;
-               bank->sectors[i].is_protected = 1;
+
+       if (bank->num_sectors > 0) {
+               /* FlexNVM bank can be used for EEPROM backup therefore zero sized */
+               bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
+
+               for (i = 0; i < bank->num_sectors; i++) {
+                       bank->sectors[i].offset = offset;
+                       bank->sectors[i].size = kinfo->sector_size;
+                       offset += kinfo->sector_size;
+                       bank->sectors[i].is_erased = -1;
+                       bank->sectors[i].is_protected = 1;
+               }
        }
 
+       kinfo->probed = true;
+
        return ERROR_OK;
 }
 
@@ -1569,7 +1578,7 @@ static int kinetis_auto_probe(struct flash_bank *bank)
 {
        struct kinetis_flash_bank *kinfo = bank->driver_priv;
 
-       if (kinfo->sim_sdid)
+       if (kinfo && kinfo->probed)
                return ERROR_OK;
 
        return kinetis_probe(bank);
@@ -1600,22 +1609,34 @@ static int kinetis_blank_check(struct flash_bank *bank)
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       if (kinfo->flash_class == FC_PFLASH) {
+       if (kinfo->flash_class == FC_PFLASH || kinfo->flash_class == FC_FLEX_NVM) {
                int result;
+               bool block_dirty = false;
                uint8_t ftfx_fstat;
 
-               /* check if whole bank is blank */
-               result = kinetis_ftfx_command(bank, FTFx_CMD_BLOCKSTAT, bank->base, 0, 0, 0, 0,  0, 0, 0, 0, &ftfx_fstat);
+               if (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;
+               }
 
-               if (result != ERROR_OK)
-                       return result;
+               if (!block_dirty) {
+                       /* 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 (ftfx_fstat & 0x01) {
+                       if (result != ERROR_OK || (ftfx_fstat & 0x01))
+                               block_dirty = true;
+               }
+
+               if (block_dirty) {
                        /* the whole bank is not erased, check sector-by-sector */
                        int i;
                        for (i = 0; i < bank->num_sectors; i++) {
                                /* normal margin */
-                               result = kinetis_ftfx_command(bank, FTFx_CMD_SECTSTAT, bank->base + bank->sectors[i].offset,
+                               result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTSTAT,
+                                               kinfo->prog_base + bank->sectors[i].offset,
                                                1, 0, 0, 0,  0, 0, 0, 0, &ftfx_fstat);
 
                                if (result == ERROR_OK) {
@@ -1632,7 +1653,7 @@ static int kinetis_blank_check(struct flash_bank *bank)
                                bank->sectors[i].is_erased = 1;
                }
        } else {
-               LOG_WARNING("kinetis_blank_check not supported yet for FlexNVM");
+               LOG_WARNING("kinetis_blank_check not supported yet for FlexRAM");
                return ERROR_FLASH_OPERATION_FAILED;
        }
 
@@ -1654,13 +1675,6 @@ static const struct command_registration kinetis_securtiy_command_handlers[] = {
                .usage = "",
                .handler = kinetis_mdm_mass_erase,
        },
-       {
-               .name = "test_securing",
-               .mode = COMMAND_EXEC,
-               .help = "",
-               .usage = "",
-               .handler = kinetis_securing_test,
-       },
        COMMAND_REGISTRATION_DONE
 };
 
@@ -1686,7 +1700,7 @@ static const struct command_registration kinetis_command_handler[] = {
        {
                .name = "kinetis",
                .mode = COMMAND_ANY,
-               .help = "kinetis NAND flash controller commands",
+               .help = "kinetis flash controller commands",
                .usage = "",
                .chain = kinetis_exec_command_handlers,
        },

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)