* and FlexNVM/FlexRAM, so flash command arguments may differ between
* blocks in the same chip.
*
- * Although not documented as such by Freescale, it appears that bits
- * 8:7 of the read-only SIM_SDID register reflect the granularity
- * settings 0..3, so sector sizes and block counts are applicable
- * according to the following table.
- * NB. These undocumented bits does not work for all MCUs.
- * A more reliable way is to detect the particular MCU model from the
- * SDID field and pick the correct granularity based on that. See
- * the handling of K21 in kinetis_read_part_info() for an example.
*/
-const struct {
+static const struct {
unsigned pflash_sector_size_bytes;
unsigned nvm_sector_size_bytes;
unsigned num_blocks;
#define FTFx_CMD_SETFLEXRAM 0x81
#define FTFx_CMD_MASSERASE 0x44
-#define KINETIS_SDID_FAMID_MASK 0x00000070
-#define KINETIS_SDID_FAMID_K10 0x00000000
-#define KINETIS_SDID_FAMID_K12 0x00000000
-#define KINETIS_SDID_FAMID_K20 0x00000010
-#define KINETIS_SDID_FAMID_K22 0x00000010
-#define KINETIS_SDID_FAMID_K30 0x00000020
-#define KINETIS_SDID_FAMID_K11 0x00000020
-#define KINETIS_SDID_FAMID_K61 0x00000020
-#define KINETIS_SDID_FAMID_K40 0x00000030
-#define KINETIS_SDID_FAMID_K21 0x00000030
-#define KINETIS_SDID_FAMID_K60 0x00000040
-#define KINETIS_SDID_FAMID_K62 0x00000040
-#define KINETIS_SDID_FAMID_K70 0x00000050
-#define KINETIS_SDID_FAMID_KW24 0x00000060
+/* The Kinetis K series uses the following SDID layout :
+ * Bit 31-16 : 0
+ * Bit 15-12 : REVID
+ * Bit 11-7 : DIEID
+ * Bit 6-4 : FAMID
+ * Bit 3-0 : PINID
+ *
+ * The Kinetis KL series uses the following SDID layout :
+ * Bit 31-28 : FAMID
+ * Bit 27-24 : SUBFAMID
+ * Bit 23-20 : SERIESID
+ * Bit 19-16 : SRAMSIZE
+ * Bit 15-12 : REVID
+ * Bit 6-4 : Reserved (0)
+ * Bit 3-0 : PINID
+ *
+ * SERIESID should be 1 for the KL-series so we assume that if
+ * bits 31-16 are 0 then it's a K-series MCU.
+ */
+
+#define KINETIS_SDID_K_SERIES_MASK 0x0000FFFF
+
+#define KINETIS_SDID_DIEID_MASK 0x00000F80
+#define KINETIS_SDID_DIEID_K_A 0x00000100
+#define KINETIS_SDID_DIEID_K_B 0x00000200
+#define KINETIS_SDID_DIEID_KL 0x00000000
+
+/* We can't rely solely on the FAMID field to determine the MCU
+ * type since some FAMID values identify multiple MCUs with
+ * different flash sector sizes (K20 and K22 for instance).
+ * Therefore we combine it with the DIEID bits which may possibly
+ * break if Freescale bumps the DIEID for a particular MCU. */
+#define KINETIS_K_SDID_TYPE_MASK 0x00000FF0
+#define KINETIS_K_SDID_K10_M50 0x00000000
+#define KINETIS_K_SDID_K10_M72 0x00000080
+#define KINETIS_K_SDID_K10_M100 0x00000100
+#define KINETIS_K_SDID_K10_M120 0x00000180
+#define KINETIS_K_SDID_K11 0x00000220
+#define KINETIS_K_SDID_K12 0x00000200
+#define KINETIS_K_SDID_K20_M50 0x00000010
+#define KINETIS_K_SDID_K20_M72 0x00000090
+#define KINETIS_K_SDID_K20_M100 0x00000110
+#define KINETIS_K_SDID_K20_M120 0x00000190
+#define KINETIS_K_SDID_K21_M50 0x00000230
+#define KINETIS_K_SDID_K21_M120 0x00000330
+#define KINETIS_K_SDID_K22_M50 0x00000210
+#define KINETIS_K_SDID_K22_M120 0x00000310
+#define KINETIS_K_SDID_K30_M72 0x000000A0
+#define KINETIS_K_SDID_K30_M100 0x00000120
+#define KINETIS_K_SDID_K40_M72 0x000000B0
+#define KINETIS_K_SDID_K40_M100 0x00000130
+#define KINETIS_K_SDID_K50_M72 0x000000E0
+#define KINETIS_K_SDID_K51_M72 0x000000F0
+#define KINETIS_K_SDID_K53 0x00000170
+#define KINETIS_K_SDID_K60_M100 0x00000140
+#define KINETIS_K_SDID_K60_M150 0x000001C0
+#define KINETIS_K_SDID_K70_M150 0x000001D0
+
+#define KINETIS_KL_SDID_SERIESID_MASK 0x00F00000
+#define KINETIS_KL_SDID_SERIESID_KL 0x00100000
struct kinetis_flash_bank {
unsigned granularity;
};
/* Program LongWord Block Write */
-static int kinetis_write_block(struct flash_bank *bank, uint8_t *buffer,
+static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t wcount)
{
struct target *target = bank->target;
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;
return result;
/* wait for done */
- for (i = 0; i < 240; i++) { /* Need Entire Erase Nemui Changed */
+ 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);
}
/* check if whole bank is blank */
- LOG_INFO("Kinetis L Series Erase All Blocks");
+ LOG_INFO("Execute 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 */
+ 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat);
+ /* Anyway Result, write FSEC to unsecure forcely */
/* if (result != ERROR_OK)
return result;*/
- /* Write to MCU security status unsecure in Flash security byte(Work around) */
+ /* Write to MCU security status unsecure in Flash security byte(for Kinetis-L need) */
LOG_INFO("Write to MCU security status unsecure Anyway!");
uint8_t padding[4] = {0xFE, 0xFF, 0xFF, 0xFF}; /* Write 0xFFFFFFFE */
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))
+ if ((first == 0) && (last == (bank->num_sectors - 1)))
return kinetis_mass_erase(bank);
/*
return ERROR_OK;
}
-static int kinetis_write(struct flash_bank *bank, uint8_t *buffer,
+static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
unsigned int i, result, fallback = 0;
}
LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32 " "
"and padding with 0xff", old_count, count);
- memset(buffer, 0xff, count);
+ memset(new_buffer, 0xff, count);
buffer = memcpy(new_buffer, buffer, old_count);
}
if (result != ERROR_OK)
return result;
- /* Kinetis L Series SubFamily Check */
kinfo->klxx = 0;
- i = (kinfo->sim_sdid >> 20) & 0x0F;
- if (i == 1) {
+
+ /* K-series MCU? */
+ if ((kinfo->sim_sdid & (~KINETIS_SDID_K_SERIES_MASK)) == 0) {
+ uint32_t mcu_type = kinfo->sim_sdid & KINETIS_K_SDID_TYPE_MASK;
+
+ switch (mcu_type) {
+ case KINETIS_K_SDID_K10_M50:
+ case KINETIS_K_SDID_K20_M50:
+ /* 1kB sectors */
+ granularity = 0;
+ break;
+ case KINETIS_K_SDID_K10_M72:
+ case KINETIS_K_SDID_K20_M72:
+ case KINETIS_K_SDID_K30_M72:
+ case KINETIS_K_SDID_K30_M100:
+ case KINETIS_K_SDID_K40_M72:
+ case KINETIS_K_SDID_K40_M100:
+ case KINETIS_K_SDID_K50_M72:
+ /* 2kB sectors, 1kB FlexNVM sectors */
+ granularity = 1;
+ break;
+ case KINETIS_K_SDID_K10_M100:
+ case KINETIS_K_SDID_K20_M100:
+ case KINETIS_K_SDID_K11:
+ case KINETIS_K_SDID_K12:
+ case KINETIS_K_SDID_K21_M50:
+ case KINETIS_K_SDID_K22_M50:
+ case KINETIS_K_SDID_K51_M72:
+ case KINETIS_K_SDID_K53:
+ case KINETIS_K_SDID_K60_M100:
+ /* 2kB sectors */
+ granularity = 2;
+ break;
+ case KINETIS_K_SDID_K10_M120:
+ case KINETIS_K_SDID_K20_M120:
+ case KINETIS_K_SDID_K21_M120:
+ case KINETIS_K_SDID_K22_M120:
+ case KINETIS_K_SDID_K60_M150:
+ case KINETIS_K_SDID_K70_M150:
+ /* 4kB sectors */
+ granularity = 3;
+ break;
+ default:
+ LOG_ERROR("Unsupported K-family FAMID");
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+ }
+ }
+ /* KL-series? */
+ else if ((kinfo->sim_sdid & KINETIS_KL_SDID_SERIESID_MASK) == KINETIS_KL_SDID_SERIESID_KL) {
kinfo->klxx = 1;
granularity = 0;
- } else if ((kinfo->sim_sdid & KINETIS_SDID_FAMID_MASK)
- == KINETIS_SDID_FAMID_K21) {
- granularity = 2;
- } else
- granularity = (kinfo->sim_sdid >> 7) & 0x03;
+ } else {
+ LOG_ERROR("MCU is unsupported");
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+ }
result = target_read_u32(target, SIM_FCFG1, &kinfo->sim_fcfg1);
if (result != ERROR_OK)