* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc. *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
{
struct target *target = bank->target;
int retval;
- int timeout = 100;
+ int timeout = 5000;
uint32_t flash_status;
retval = target_read_u32(target, FCIS, &flash_status);
{
struct target *target = bank->target;
int retval;
- int timeout = 100;
+ int timeout = 5000;
uint32_t uflash_status;
retval = target_read_u32(target, UFCIS, &uflash_status);
static int niietcm4_dump_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type)
{
struct target *target = bank->target;
- int i, retval;
+ int i;
+ int retval = ERROR_OK;
uint32_t uflash_cmd;
if (mem_type == INFO_MEM_TYPE)
static int niietcm4_load_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type)
{
struct target *target = bank->target;
- int i, retval;
+ int i;
+ int retval = ERROR_OK;
uint32_t uflash_cmd;
if (mem_type == INFO_MEM_TYPE)
retval = target_read_u32(target, UFMD, &uflash_data);
if (retval != ERROR_OK)
return retval;
- command_print(CMD_CTX, "Read userflash %s region:\n"
- "address = 0x%04x,\n"
- "value = 0x%02x.", CMD_ARGV[0], uflash_addr, uflash_data);
+ command_print(CMD, "Read userflash %s region:\n"
+ "address = 0x%04x,\n"
+ "value = 0x%02x.", CMD_ARGV[0], uflash_addr, uflash_data);
return retval;
}
int page_num = uflash_addr/USERFLASH_PAGE_SIZE;
- command_print(CMD_CTX, "Write userflash %s region:\n"
- "address = 0x%04x,\n"
- "value = 0x%02x.\n"
- "Please wait ... ", CMD_ARGV[0], uflash_addr, uflash_data);
+ command_print(CMD, "Write userflash %s region:\n"
+ "address = 0x%04x,\n"
+ "value = 0x%02x.\n"
+ "Please wait ... ", CMD_ARGV[0], uflash_addr, uflash_data);
/* dump */
uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
niietcm4_dump_uflash_page(bank, uflash_dump, page_num, mem_type);
/* write dump to userflash */
niietcm4_load_uflash_page(bank, uflash_dump, page_num, mem_type);
- command_print(CMD_CTX, "done!");
+ command_print(CMD, "done!");
return retval;
}
retval = niietcm4_uopstatus_check(bank);
if (retval != ERROR_OK)
return retval;
- command_print(CMD_CTX, "Userflash full erase done!");
+ command_print(CMD, "Userflash full erase done!");
return retval;
}
return retval;
}
- command_print(CMD_CTX, "Erase %s userflash pages %d through %d done!", CMD_ARGV[0], first, last);
+ command_print(CMD, "Erase %s userflash pages %d through %d done!", CMD_ARGV[0], first, last);
return retval;
}
return retval;
if (uflash_data & INFOWORD3_LOCK_IFB_UF)
- command_print(CMD_CTX, "All sectors of info userflash are not protected!");
+ command_print(CMD, "All sectors of info userflash are not protected!");
else
- command_print(CMD_CTX, "All sectors of info userflash are protected!");
+ command_print(CMD, "All sectors of info userflash are protected!");
} else {
uflash_addr = UF_LOCK_ADDR;
uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
for (j = 0; j < 8; j++) {
if (uflash_data & 0x1)
- command_print(CMD_CTX, "Userflash sector #%03d: 0x%04x (0x100) is not protected!",
+ command_print(CMD, "Userflash sector #%03d: 0x%04x (0x100) is not protected!",
i*8+j, (i*8+j)*USERFLASH_PAGE_SIZE);
else
- command_print(CMD_CTX, "Userflash sector #%03d: 0x%04x (0x100) is protected!",
+ command_print(CMD, "Userflash sector #%03d: 0x%04x (0x100) is protected!",
i*8+j, (i*8+j)*USERFLASH_PAGE_SIZE);
uflash_data = uflash_data >> 1;
}
int set;
if (strcmp("on", CMD_ARGV[3]) == 0) {
- command_print(CMD_CTX, "Try to enable %s userflash sectors %d through %d protection. Please wait ... ",
+ command_print(CMD, "Try to enable %s userflash sectors %d through %d protection. Please wait ... ",
CMD_ARGV[0], first, last);
set = 1;
} else if (strcmp("off", CMD_ARGV[3]) == 0) {
- command_print(CMD_CTX, "Try to disable %s userflash sectors %d through %d protection. Please wait ... ",
+ command_print(CMD, "Try to disable %s userflash sectors %d through %d protection. Please wait ... ",
CMD_ARGV[0], first, last);
set = 0;
} else
if (retval != ERROR_OK)
return retval;
- command_print(CMD_CTX, "done!");
+ command_print(CMD, "done!");
return retval;
}
int set;
if (strcmp("on", CMD_ARGV[0]) == 0) {
- command_print(CMD_CTX, "Try to enable bootflash info region remap. Please wait ...");
+ command_print(CMD, "Try to enable bootflash info region remap. Please wait ...");
set = 1;
} else if (strcmp("off", CMD_ARGV[0]) == 0) {
- command_print(CMD_CTX, "Try to disable bootflash info region remap. Please wait ...");
+ command_print(CMD, "Try to disable bootflash info region remap. Please wait ...");
set = 0;
} else
return ERROR_COMMAND_SYNTAX_ERROR;
/* write dump to userflash */
niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
- command_print(CMD_CTX, "done!");
+ command_print(CMD, "done!");
return retval;
}
else
return ERROR_COMMAND_SYNTAX_ERROR;
- command_print(CMD_CTX, "Try to configure external memory boot interface:\n"
- "port = %s\n"
- "pin = %s\n"
- "func = %s\n"
- "Please wait ...", CMD_ARGV[0], CMD_ARGV[1], CMD_ARGV[2]);
+ command_print(CMD, "Try to configure external memory boot interface:\n"
+ "port = %s\n"
+ "pin = %s\n"
+ "func = %s\n"
+ "Please wait ...", CMD_ARGV[0], CMD_ARGV[1], CMD_ARGV[2]);
/* dump */
uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
/* write dump to userflash */
niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
- command_print(CMD_CTX, "done!");
+ command_print(CMD, "done!");
return retval;
}
int set;
if (strcmp("on", CMD_ARGV[0]) == 0) {
- command_print(CMD_CTX, "Try to enable boot from external memory. Please wait ...");
+ command_print(CMD, "Try to enable boot from external memory. Please wait ...");
set = 1;
} else if (strcmp("off", CMD_ARGV[0]) == 0) {
- command_print(CMD_CTX, "Try to disable boot from external memory. Please wait ...");
+ command_print(CMD, "Try to disable boot from external memory. Please wait ...");
set = 0;
} else
return ERROR_COMMAND_SYNTAX_ERROR;
/* write dump to userflash */
niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
- command_print(CMD_CTX, "done!");
+ command_print(CMD, "done!");
return retval;
}
return retval;
struct target *target = bank->target;
- command_print(CMD_CTX, "Try to perform service mode erase. Please wait ...");
+ command_print(CMD, "Try to perform service mode erase. Please wait ...");
retval = target_write_u32(target, SERVICE_MODE_ERASE_ADDR, 1);
if (retval != ERROR_OK)
}
busy_sleep(1); /* can use busy sleep for short times. */
}
- command_print(CMD_CTX, "done! All data erased.");
+ command_print(CMD, "done! All data erased.");
return retval;
}
if (retval != ERROR_OK)
return retval;
- command_print(CMD_CTX, "niietcm4 flash driver\n"
+ command_print(CMD, "niietcm4 flash driver\n"
"version: %d.%d\n"
"author: Bogdan Kolbov\n"
"mail: kolbov@niiet.ru",
{
struct niietcm4_flash_bank *niietcm4_info;
- if (CMD_ARGC < 7)
+ if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
niietcm4_info = malloc(sizeof(struct niietcm4_flash_bank));
&write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- };
+ }
retval = target_write_buffer(target, write_algorithm->address,
sizeof(niietcm4_flash_write_code), niietcm4_flash_write_code);
LOG_WARNING("no large enough working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
- };
+ }
init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* write_cmd base (in), status (out) */
init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* count (128bit) */
{
struct target *target = bank->target;
struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
+ uint8_t *new_buffer = NULL;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
- if (offset & 0x3) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
+ if (offset & 0xF) {
+ LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-word alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
+ /* If there's an odd number of words, the data has to be padded. Duplicate
+ * the buffer and use the normal code path with a single block write since
+ * it's probably cheaper than to special case the last odd write using
+ * discrete accesses. */
+
+ int rem = count % 16;
+ if (rem) {
+ new_buffer = malloc(count + 16 - rem);
+ if (new_buffer == NULL) {
+ LOG_ERROR("Odd number of words to write and no memory for padding buffer");
+ return ERROR_FAIL;
+ }
+ LOG_INFO("Odd number of words to write, padding with 0xFFFFFFFF");
+ buffer = memcpy(new_buffer, buffer, count);
+ while (rem < 16) {
+ new_buffer[count++] = 0xff;
+ rem++;
+ }
+ }
+
int retval;
/* try using block write */
flash_addr = offset + i;
retval = target_write_u32(target, FMA, flash_addr);
if (retval != ERROR_OK)
- return retval;
+ goto free_buffer;
- /* if there's an odd number of bytes, the data has to be padded */
- uint8_t padding[16] = { 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff};
- memcpy(padding, buffer + i, MIN(16, count-i));
+ /* Prepare data (4 words) */
+ uint32_t value[4];
+ memcpy(&value, buffer + i*16, 4*sizeof(uint32_t));
/* place in reg 16 bytes of data */
- flash_data = (padding[3]<<24) | (padding[2]<<16) | (padding[1]<<8) | padding[0];
+ flash_data = value[0];
retval = target_write_u32(target, FMD1, flash_data);
if (retval != ERROR_OK)
- return retval;
- flash_data = (padding[7]<<24) | (padding[6]<<16) | (padding[5]<<8) | padding[4];
+ goto free_buffer;
+ flash_data = value[1];
retval = target_write_u32(target, FMD2, flash_data);
if (retval != ERROR_OK)
- return retval;
- flash_data = (padding[11]<<24) | (padding[10]<<16) | (padding[9]<<8) | padding[8];
+ goto free_buffer;
+ flash_data = value[2];
retval = target_write_u32(target, FMD3, flash_data);
if (retval != ERROR_OK)
- return retval;
- flash_data = (padding[15]<<24) | (padding[14]<<16) | (padding[13]<<8) | padding[12];
+ goto free_buffer;
+ flash_data = value[3];
retval = target_write_u32(target, FMD4, flash_data);
if (retval != ERROR_OK)
- return retval;
+ goto free_buffer;
/* write start */
retval = target_write_u32(target, FMC, flash_cmd);
if (retval != ERROR_OK)
- return retval;
+ goto free_buffer;
/* status check */
retval = niietcm4_opstatus_check(bank);
if (retval != ERROR_OK)
- return retval;
+ goto free_buffer;
}
}
+free_buffer:
+ if (new_buffer)
+ free(new_buffer);
+
return retval;
}
char info_bootflash_addr_str[64];
if (niietcm4_info->bflash_info_remap)
- snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str), "0x%08x base adress", bank->base);
+ snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str),
+ TARGET_ADDR_FMT " base adress", bank->base);
else
- snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str), "not maped to global adress space");
+ snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str),
+ "not mapped to global adress space");
snprintf(niietcm4_info->chip_brief,
sizeof(niietcm4_info->chip_brief),
static int get_niietcm4_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
- LOG_INFO("\nNIIET Cortex M4F %s\n%s", niietcm4_info->chip_name, niietcm4_info->chip_brief);
+ LOG_INFO("\nNIIET Cortex-M4F %s\n%s", niietcm4_info->chip_name, niietcm4_info->chip_brief);
snprintf(buf, buf_size, " ");
return ERROR_OK;
}
-struct flash_driver niietcm4_flash = {
+const struct flash_driver niietcm4_flash = {
.name = "niietcm4",
.usage = "flash bank <name> niietcm4 <base> <size> 0 0 <target#>",
.commands = niietcm4_command_handlers,
.erase_check = default_flash_blank_check,
.protect_check = niietcm4_protect_check,
.info = get_niietcm4_info,
+ .free_driver_priv = default_flash_free_driver_priv,
};