X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fstellaris.c;h=8d35f9b10f1d158f07725ffefa9cff145bf185fa;hb=fb4239866c6a9aa429b58be7488a93ec1245597b;hp=34649fcaba4f7c385382f3c75a3e90113dbca78f;hpb=1cd7b3b49b33860a5652b9dd2829e9ed71ac6289;p=openocd.git diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index 34649fcaba..8d35f9b10f 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -553,6 +553,11 @@ static int stellaris_read_part_info(struct flash_bank *bank) stellaris_info->pagesize = 1024; stellaris_info->pages_in_lockregion = 2; + /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too. + * That exposes a 32-word Flash Write Buffer ... enabling + * writes of more than one word at a time. + */ + return ERROR_OK; } @@ -640,6 +645,10 @@ static int stellaris_erase(struct flash_bank *bank, int first, int last) target_write_u32(target, FLASH_CIM, 0); target_write_u32(target, FLASH_MISC, PMISC | AMISC); + /* REVISIT this clobbers state set by any halted firmware ... + * it might want to process those IRQs. + */ + for (banknr = first; banknr <= last; banknr++) { /* Address is first word in page */ @@ -726,6 +735,10 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la target_write_u32(target, FLASH_CIM, 0); target_write_u32(target, FLASH_MISC, PMISC | AMISC); + /* REVISIT this clobbers state set by any halted firmware ... + * it might want to process those IRQs. + */ + LOG_DEBUG("fmppe 0x%" PRIx32 "",fmppe); target_write_u32(target, SCB_BASE | FMPPE, fmppe); @@ -735,6 +748,8 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la /* Write commit command */ /* REVISIT safety check, since this cannot be undone * except by the "Recover a locked device" procedure. + * REVISIT DustDevil-A0 parts have an erratum making FMPPE commits + * inadvisable ... it makes future mass erase operations fail. */ LOG_WARNING("Flash protection cannot be removed once commited, commit is NOT executed !"); /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */ @@ -810,37 +825,44 @@ static int stellaris_write_block(struct flash_bank *bank, struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; + /* power of two, and multiple of word size */ + static const unsigned buf_min = 128; + + /* for small buffers it's faster not to download an algorithm */ + if (wcount * 4 < buf_min) + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "", bank, buffer, offset, wcount); /* flash write code */ if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK) { - LOG_WARNING("no working area available, can't do block memory writes"); + LOG_DEBUG("no working area for block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; }; - target_write_buffer(target, write_algorithm->address, - sizeof(stellaris_write_code), - (uint8_t *) stellaris_write_code); + /* plus a buffer big enough for this data */ + if (wcount * 4 < buffer_size) + buffer_size = wcount * 4; /* memory buffer */ while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) { - LOG_DEBUG("called target_alloc_working_area(target=%p buffer_size=%08" PRIx32 " source=%p)", - target, buffer_size, source); buffer_size /= 2; - if (buffer_size <= 256) + if (buffer_size <= buf_min) { - /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */ - if (write_algorithm) - target_free_working_area(target, write_algorithm); - - LOG_WARNING("no large enough working area available, can't do block memory writes"); + target_free_working_area(target, write_algorithm); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } + LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)", + target_name(target), (unsigned) buffer_size); }; + retval = target_write_buffer(target, write_algorithm->address, + sizeof(stellaris_write_code), + (uint8_t *) stellaris_write_code); + armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARMV7M_MODE_ANY; @@ -857,11 +879,20 @@ static int stellaris_write_block(struct flash_bank *bank, buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, address); buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count); - LOG_INFO("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, (wcount - thisrun_count)); - LOG_DEBUG("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, (wcount - thisrun_count)); - if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params, write_algorithm->address, write_algorithm->address + sizeof(stellaris_write_code)-10, 10000, &armv7m_info)) != ERROR_OK) + LOG_DEBUG("Algorithm flash write %u words to 0x%" PRIx32 + ", %u remaining", + (unsigned) thisrun_count, address, + (unsigned) (wcount - thisrun_count)); + retval = target_run_algorithm(target, 0, NULL, 3, reg_params, + write_algorithm->address, + write_algorithm->address + + sizeof(stellaris_write_code) - 10, + 10000, &armv7m_info); + if (retval != ERROR_OK) { - LOG_ERROR("error executing stellaris flash write algorithm"); + LOG_ERROR("error %d executing stellaris " + "flash write algorithm", + retval); retval = ERROR_FLASH_OPERATION_FAILED; break; } @@ -871,6 +902,10 @@ static int stellaris_write_block(struct flash_bank *bank, wcount -= thisrun_count; } + /* REVISIT we could speed up writing multi-section images by + * not freeing the initialized write_algorithm this way. + */ + target_free_working_area(target, write_algorithm); target_free_working_area(target, source); @@ -921,17 +956,21 @@ static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t of target_write_u32(target, FLASH_CIM, 0); target_write_u32(target, FLASH_MISC, PMISC | AMISC); + /* REVISIT this clobbers state set by any halted firmware ... + * it might want to process those IRQs. + */ + /* multiple words to be programmed? */ if (words_remaining > 0) { /* try using a block write */ - if ((retval = stellaris_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) + retval = stellaris_write_block(bank, buffer, offset, + words_remaining); + if (retval != ERROR_OK) { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { - /* if block write failed (no sufficient working area), - * we use normal (slow) single dword accesses */ - LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); + LOG_DEBUG("writing flash word-at-a-time"); } else if (retval == ERROR_FLASH_OPERATION_FAILED) { @@ -1068,6 +1107,10 @@ static int stellaris_mass_erase(struct flash_bank *bank) target_write_u32(target, FLASH_CIM, 0); target_write_u32(target, FLASH_MISC, PMISC | AMISC); + /* REVISIT this clobbers state set by any halted firmware ... + * it might want to process those IRQs. + */ + target_write_u32(target, FLASH_FMA, 0); target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); /* Wait until erase complete */ @@ -1139,7 +1182,7 @@ static const struct command_registration stellaris_exec_command_handlers[] = { static const struct command_registration stellaris_command_handlers[] = { { .name = "stellaris", - .mode = COMMAND_ANY, + .mode = COMMAND_EXEC, .help = "Stellaris flash command group", .chain = stellaris_exec_command_handlers, },