X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fkinetis.c;h=86785905211f2522fd703d6462f01d7aefc41487;hb=b1a1a48b30243d3582a8443f4baf3dd500683eda;hp=51e7676fa26e66115db3b4efedf817a01752666b;hpb=1c41362aeaca98e6a4e25e0f7e9d85c0c3a490aa;p=openocd diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 51e7676f..86785905 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -84,13 +84,9 @@ * 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. */ -const struct { +static const struct { unsigned pflash_sector_size_bytes; unsigned nvm_sector_size_bytes; unsigned num_blocks; @@ -120,6 +116,67 @@ const struct { #define FTFx_CMD_SETFLEXRAM 0x81 #define FTFx_CMD_MASSERASE 0x44 +/* 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; unsigned bank_ordinal; @@ -221,7 +278,7 @@ static const uint8_t kinetis_flash_write_code[] = { }; /* 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; @@ -292,11 +349,6 @@ static int kinetis_write_block(struct flash_bank *bank, uint8_t *buffer, 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; @@ -437,7 +489,7 @@ static int kinetis_ftfx_command(struct flash_bank *bank, uint8_t fcmd, uint32_t 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); @@ -471,15 +523,15 @@ static int kinetis_mass_erase(struct flash_bank *bank) } /* 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 */ @@ -495,7 +547,6 @@ static int kinetis_mass_erase(struct flash_bank *bank) 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"); @@ -505,7 +556,7 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last) 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); /* @@ -535,7 +586,7 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last) 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; @@ -553,12 +604,12 @@ static int kinetis_write(struct flash_bank *bank, uint8_t *buffer, /* 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); + 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 @%08X", offset); + 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); @@ -579,7 +630,7 @@ static int kinetis_write(struct flash_bank *bank, uint8_t *buffer, LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)", buf[0]); } } else { - LOG_DEBUG("flash write into PFLASH @08%X", offset); + LOG_DEBUG("flash write into PFLASH @08%" PRIX32, offset); } @@ -632,8 +683,8 @@ static int kinetis_write(struct flash_bank *bank, uint8_t *buffer, (void) memcpy(residual_buffer, &buffer[i+4*wc], residual_bc); } - LOG_DEBUG("write section @ %08X with length %d bytes", - offset + i, wc*4); + LOG_DEBUG("write section @ %08" PRIX32 " with length %" PRIu32 " bytes", + offset + i, (uint32_t)wc*4); /* write data to flexram as whole-words */ result = target_write_memory(bank->target, FLEXRAM, 4, wc, @@ -678,9 +729,9 @@ static int kinetis_write(struct flash_bank *bank, uint8_t *buffer, "for padding buffer"); return ERROR_FAIL; } - LOG_INFO("odd number of bytes to write (%d), extending to %d " + 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); } @@ -698,7 +749,7 @@ static int kinetis_write(struct flash_bank *bank, uint8_t *buffer, for (i = 0; i < count; i += 4) { uint8_t ftfx_fstat; - LOG_DEBUG("write longword @ %08X", offset + i); + LOG_DEBUG("write longword @ %08" PRIX32, (uint32_t)(offset + i)); uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff}; memcpy(padding, buffer + i, MIN(4, count-i)); @@ -735,14 +786,62 @@ static int kinetis_read_part_info(struct flash_bank *bank) 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 - 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) @@ -753,7 +852,7 @@ static int kinetis_read_part_info(struct flash_bank *bank) return result; fcfg2_pflsh = (kinfo->sim_fcfg2 >> 23) & 0x01; - LOG_DEBUG("SDID: 0x%08X FCFG1: 0x%08X FCFG2: 0x%08X", kinfo->sim_sdid, + LOG_DEBUG("SDID: 0x%08" PRIX32 " FCFG1: 0x%08" PRIX32 " FCFG2: 0x%08" PRIX32, kinfo->sim_sdid, kinfo->sim_fcfg1, kinfo->sim_fcfg2); fcfg1_nvmsize = (uint8_t)((kinfo->sim_fcfg1 >> 28) & 0x0f); @@ -821,7 +920,7 @@ static int kinetis_read_part_info(struct flash_bank *bank) break; } - LOG_DEBUG("FlexNVM: %d PFlash: %d FlexRAM: %d PFLSH: %d", + LOG_DEBUG("FlexNVM: %" PRIu32 " PFlash: %" PRIu32 " FlexRAM: %" PRIu32 " PFLSH: %d", nvm_size, pf_size, ee_size, fcfg2_pflsh); if (kinfo->klxx) num_blocks = 1; @@ -1051,26 +1150,13 @@ static int kinetis_blank_check(struct flash_bank *bank) return ERROR_OK; } -static int kinetis_flash_read(struct flash_bank *bank, - uint8_t *buffer, uint32_t offset, uint32_t count) -{ - LOG_WARNING("kinetis_flash_read not supported yet"); - - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - return ERROR_FLASH_OPERATION_FAILED; -} - struct flash_driver kinetis_flash = { .name = "kinetis", .flash_bank_command = kinetis_flash_bank_command, .erase = kinetis_erase, .protect = kinetis_protect, .write = kinetis_write, - .read = kinetis_flash_read, + .read = default_flash_read, .probe = kinetis_probe, .auto_probe = kinetis_auto_probe, .erase_check = kinetis_blank_check,