Try to right-size the SRAM buffers, by not:
- using them for very small writes
- giving up when a large buffer isn't available
- allocating buffers much larger than their data
Also don't:
- bother loading the code unless we can allocate the buffer too
- be so verbose with messaging (including, too-high severity)
The minimum buffer size is something of a guess. It's eight
times smaller than before, almost the same size as the code
being downloaded. It probably deserves some tuning.
Also, note an erratum affecting flash protection on some chips.
---
src/flash/nor/stellaris.c | 66 ++++++++++++++++++++++++++++++--------------
1 file changed, 46 insertions(+), 20 deletions(-)
--- a/src/flash/nor/stellaris.c
+++ b/src/flash/nor/stellaris.c
@@ -748,6 +748,9 @@ static int stellaris_protect(struct flas
/* Write commit command */
/* REVISIT safety check, since this cannot be undone
* except by the "Recover a locked device" procedure.
+ * REVISIT some chips (e.g. '3748-A0, DustDevil) have an erratum
+ * making FMPPE writes 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); */
@@ -823,37 +826,49 @@ static int stellaris_write_block(struct
struct armv7m_algorithm armv7m_info;
int retval = ERROR_OK;
+ /* power of two, and multiple of word size */
+ static const unsigned buf_min = 32;
+
+ /* for small buffers it's faster not to download an algorithm */
+ if (wcount < 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 available, can't do 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 < buffer_size) {
+ buffer_size = wcount;
+ buffer_size += buf_min - 1;
+ buffer_size &= ~(buf_min - 1);
+ }
/* 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);
+ target_free_working_area(target, write_algorithm);
- LOG_WARNING("no large enough working area available,
can't do block memory writes");
+ LOG_DEBUG("no buffer; can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
+ LOG_DEBUG("retry target_alloc_working_area(%s, size=%d)",
+ 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;
@@ -870,11 +885,18 @@ static int stellaris_write_block(struct
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 %" 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_ERROR("error executing stellaris flash write
algorithm");
+ LOG_ERROR("error %d executing stellaris "
+ "flash write algorithm",
+ retval);
retval = ERROR_FLASH_OPERATION_FAILED;
break;
}
@@ -884,6 +906,10 @@ static int stellaris_write_block(struct
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);
@@ -941,14 +967,14 @@ static int stellaris_write(struct flash_
/* 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)
+ /* try using block writes */
+ 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_INFO("writing flash word-at-a-time");
}
else if (retval == ERROR_FLASH_OPERATION_FAILED)
{
_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development