X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=6d3a99decd8adc9031124c8506a9411601ad7e86;hb=78807eb6ec79b4ea2a6a1fa4aa074d6ccd56b4b0;hp=c71c536030f867ea980835e4abeeabebbb0316b6;hpb=63a23e6fc862b94f00e0833ab474bd02901a019f;p=openocd.git diff --git a/src/target/target.c b/src/target/target.c index c71c536030..6d3a99decd 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -822,6 +822,7 @@ int target_run_flash_async_algorithm(struct target *target, uint32_t entry_point, uint32_t exit_point, void *arch_info) { int retval; + int timeout = 0; /* Set up working area. First word is write pointer, second word is read pointer, * rest is fifo data area. */ @@ -893,9 +894,19 @@ int target_run_flash_async_algorithm(struct target *target, * less than buffer size / flash speed. This is very unlikely to * run when using high latency connections such as USB. */ alive_sleep(10); + + /* to stop an infinite loop on some targets check and increment a timeout + * this issue was observed on a stellaris using the new ICDI interface */ + if (timeout++ >= 500) { + LOG_ERROR("timeout waiting for algorithm, a target reset is recommended"); + return ERROR_FLASH_OPERATION_FAILED; + } continue; } + /* reset our timeout */ + timeout = 0; + /* Limit to the amount of data we actually want to write */ if (thisrun_bytes > count * block_size) thisrun_bytes = count * block_size; @@ -1405,6 +1416,7 @@ static void target_split_working_area(struct working_area *area, uint32_t size) new_wa->size = area->size - size; new_wa->address = area->address + size; new_wa->backup = NULL; + new_wa->user = NULL; new_wa->free = true; area->next = new_wa; @@ -1493,6 +1505,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w new_wa->size = target->working_area_size & ~3UL; /* 4-byte align */ new_wa->address = target->working_area; new_wa->backup = NULL; + new_wa->user = NULL; new_wa->free = true; } @@ -1536,6 +1549,9 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w c->free = false; *area = c; + /* user pointer */ + c->user = area; + print_wa_layout(target); return ERROR_OK; @@ -1586,6 +1602,13 @@ static int target_free_working_area_restore(struct target *target, struct workin LOG_DEBUG("freed %"PRIu32" bytes of working area at address 0x%08"PRIx32, area->size, area->address); + /* mark user pointer invalid */ + /* TODO: Is this really safe? It points to some previous caller's memory. + * How could we know that the area pointer is still in that place and not + * some other vital data? What's the purpose of this, anyway? */ + *area->user = NULL; + area->user = NULL; + target_merge_working_areas(target); print_wa_layout(target); @@ -1613,6 +1636,8 @@ static void target_free_all_working_areas_restore(struct target *target, int res if (restore) target_restore_working_area(target, c); c->free = true; + *c->user = NULL; /* Same as above */ + c->user = NULL; } c = c->next; }