This is an automated email from Gerrit. Tomas Vanek ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/2987
-- gerrit commit 3e849c8af56c9d956bec952409836055df95f280 Author: Tomas Vanek <[email protected]> Date: Tue Sep 29 17:48:17 2015 +0200 kinetis: FlexNVM handling FlexNVM (data flash) is memory mapped at 0x10000000. Driver used to send the same address to FTFx controller for erase/write ops. This was wrong as FTFx accepts only low 24 bits of address. To fix addressing for flash controller kinfo->prog_base was introduced. Added FlexNVM protection check, blank check and data flash size calculation. Change-Id: Ia60b938266963e5d056701278cdf7bf2f62a429a Signed-off-by: Tomas Vanek <[email protected]> diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index ba3f5ea..4b88edd 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -82,6 +82,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 @@ -190,6 +191,9 @@ struct kinetis_flash_bank { 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; @@ -579,7 +583,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; @@ -690,6 +695,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"); @@ -697,10 +705,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); @@ -709,31 +714,39 @@ 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; - psec += bank->sectors[i].size; + /* read protection register */ + result = target_read_memory(bank->target, FTFx_FDPROT, 1, 1, &fdprot); + + 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; } @@ -831,6 +844,7 @@ COMMAND_HANDLER(kinetis_securing_test) 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"); @@ -848,7 +862,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, FTFx_CMD_SECTERASE, kinfo->prog_base + bank->sectors[i].offset, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); if (result != ERROR_OK) { @@ -988,7 +1002,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, FTFx_CMD_SECTWRITE, kinfo->prog_base + offset + i, section_count>>8, section_count, 0, 0, 0, 0, 0, 0, &ftfx_fstat); @@ -1032,7 +1046,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, FTFx_CMD_LWORDPROG, kinfo->prog_base + offset + i, padding[3], padding[2], padding[1], padding[0], 0, 0, 0, 0, &ftfx_fstat); @@ -1052,8 +1066,9 @@ 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; struct target *target = bank->target; @@ -1232,7 +1247,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); @@ -1240,11 +1254,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: @@ -1279,6 +1297,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) { @@ -1399,15 +1441,32 @@ static int kinetis_read_part_info(struct flash_bank *bank) 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 */ kinfo->flash_class = FC_FLEX_NVM; bank->size = (nvm_size / num_nvm_blocks); bank->base = 0x10000000 + bank->size * (bank->bank_number - first_nvm_bank); + kinfo->prog_base = 0x00800000 + bank->size * (bank->bank_number - first_nvm_bank); 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 if (nvm_sector_size_bytes < 4096) + kinfo->protection_size = 8 << 10; + else + kinfo->protection_size = 32 << 10; + } + kinfo->protection_block = (8 / num_nvm_blocks) * (bank->bank_number - first_nvm_bank); + } else if ((unsigned)bank->bank_number == num_blocks) { LOG_ERROR("FlexRAM support not yet implemented"); return ERROR_FLASH_OPER_UNSUPPORTED; @@ -1493,12 +1552,12 @@ 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; 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); + result = kinetis_ftfx_command(bank, FTFx_CMD_BLOCKSTAT, kinfo->prog_base, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); if (result != ERROR_OK) return result; @@ -1508,7 +1567,7 @@ static int kinetis_blank_check(struct flash_bank *bank) 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, FTFx_CMD_SECTSTAT, kinfo->prog_base + bank->sectors[i].offset, 1, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); if (result == ERROR_OK) { @@ -1525,7 +1584,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; } -- ------------------------------------------------------------------------------ _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
