extern struct target_type or1k_target;
extern struct target_type quark_x10xx_target;
extern struct target_type quark_d20xx_target;
+extern struct target_type stm8_target;
static struct target_type *target_types[] = {
&arm7tdmi_target,
&or1k_target,
&quark_x10xx_target,
&quark_d20xx_target,
+ &stm8_target,
#if BUILD_TARGET64
&aarch64_target,
#endif
{ .value = TARGET_EVENT_RESET_ASSERT_POST, .name = "reset-assert-post" },
{ .value = TARGET_EVENT_RESET_DEASSERT_PRE, .name = "reset-deassert-pre" },
{ .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" },
- { .value = TARGET_EVENT_RESET_HALT_PRE, .name = "reset-halt-pre" },
- { .value = TARGET_EVENT_RESET_HALT_POST, .name = "reset-halt-post" },
- { .value = TARGET_EVENT_RESET_WAIT_PRE, .name = "reset-wait-pre" },
- { .value = TARGET_EVENT_RESET_WAIT_POST, .name = "reset-wait-post" },
{ .value = TARGET_EVENT_RESET_INIT, .name = "reset-init" },
{ .value = TARGET_EVENT_RESET_END, .name = "reset-end" },
}
/**
- * Downloads a target-specific native code algorithm to the target,
- * executes and leaves it running.
+ * Executes a target-specific native code algorithm and leaves it running.
*
* @param target used to run the algorithm
* @param arch_info target-specific description of the algorithm.
}
/**
- * Executes a target-specific native code algorithm in the target.
- * It differs from target_run_algorithm in that the algorithm is asynchronous.
- * Because of this it requires an compliant algorithm:
- * see contrib/loaders/flash/stm32f1x.S for example.
+ * Streams data to a circular buffer on target intended for consumption by code
+ * running asynchronously on target.
+ *
+ * This is intended for applications where target-specific native code runs
+ * on the target, receives data from the circular buffer, does something with
+ * it (most likely writing it to a flash memory), and advances the circular
+ * buffer pointer.
+ *
+ * This assumes that the helper algorithm has already been loaded to the target,
+ * but has not been started yet. Given memory and register parameters are passed
+ * to the algorithm.
+ *
+ * The buffer is defined by (buffer_start, buffer_size) arguments and has the
+ * following format:
+ *
+ * [buffer_start + 0, buffer_start + 4):
+ * Write Pointer address (aka head). Written and updated by this
+ * routine when new data is written to the circular buffer.
+ * [buffer_start + 4, buffer_start + 8):
+ * Read Pointer address (aka tail). Updated by code running on the
+ * target after it consumes data.
+ * [buffer_start + 8, buffer_start + buffer_size):
+ * Circular buffer contents.
+ *
+ * See contrib/loaders/flash/stm32f1x.S for an example.
*
* @param target used to run the algorithm
+ * @param buffer address on the host where data to be sent is located
+ * @param count number of blocks to send
+ * @param block_size size in bytes of each block
+ * @param num_mem_params count of memory-based params to pass to algorithm
+ * @param mem_params memory-based params to pass to algorithm
+ * @param num_reg_params count of register-based params to pass to algorithm
+ * @param reg_params memory-based params to pass to algorithm
+ * @param buffer_start address on the target of the circular buffer structure
+ * @param buffer_size size of the circular buffer structure
+ * @param entry_point address on the target to execute to start the algorithm
+ * @param exit_point address at which to set a breakpoint to catch the
+ * end of the algorithm; can be 0 if target triggers a breakpoint itself
*/
int target_run_flash_async_algorithm(struct target *target,
int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
{
struct target_timer_callback **callbacks_p = &target_timer_callbacks;
- struct timeval now;
if (callback == NULL)
return ERROR_COMMAND_SYNTAX_ERROR;
(*callbacks_p)->time_ms = time_ms;
(*callbacks_p)->removed = false;
- gettimeofday(&now, NULL);
- (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
- time_ms -= (time_ms % 1000);
- (*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000);
- if ((*callbacks_p)->when.tv_usec > 1000000) {
- (*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000;
- (*callbacks_p)->when.tv_sec += 1;
- }
+ gettimeofday(&(*callbacks_p)->when, NULL);
+ timeval_add_time(&(*callbacks_p)->when, 0, time_ms * 1000);
(*callbacks_p)->priv = priv;
(*callbacks_p)->next = NULL;
static int target_timer_callback_periodic_restart(
struct target_timer_callback *cb, struct timeval *now)
{
- int time_ms = cb->time_ms;
- cb->when.tv_usec = now->tv_usec + (time_ms % 1000) * 1000;
- time_ms -= (time_ms % 1000);
- cb->when.tv_sec = now->tv_sec + time_ms / 1000;
- if (cb->when.tv_usec > 1000000) {
- cb->when.tv_usec = cb->when.tv_usec - 1000000;
- cb->when.tv_sec += 1;
- }
+ cb->when = *now;
+ timeval_add_time(&cb->when, 0, cb->time_ms * 1000L);
return ERROR_OK;
}
bool call_it = (*callback)->callback &&
((!checktime && (*callback)->periodic) ||
- now.tv_sec > (*callback)->when.tv_sec ||
- (now.tv_sec == (*callback)->when.tv_sec &&
- now.tv_usec >= (*callback)->when.tv_usec));
+ timeval_compare(&now, &(*callback)->when) >= 0);
if (call_it)
target_call_timer_callback(*callback, &now);
break;
gettimeofday(&now, NULL);
- if ((sample_count >= max_num_samples) ||
- ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) {
+ if ((sample_count >= max_num_samples) || timeval_compare(&now, &timeout) >= 0) {
LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count);
break;
}
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count);
uint8_t *buffer = calloc(count, size);
+ if (buffer == NULL) {
+ LOG_ERROR("Failed to allocate md read buffer");
+ return ERROR_FAIL;
+ }
struct target *target = get_current_target(CMD_CTX);
int retval = fn(target, address, size, count, buffer);
/* Dump a gmon.out histogram file. */
static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename, bool with_range,
- uint32_t start_address, uint32_t end_address, struct target *target)
+ uint32_t start_address, uint32_t end_address, struct target *target, uint32_t duration_ms)
{
uint32_t i;
FILE *f = fopen(filename, "w");
writeLong(f, min, target); /* low_pc */
writeLong(f, max, target); /* high_pc */
writeLong(f, numBuckets, target); /* # of buckets */
- writeLong(f, 100, target); /* KLUDGE! We lie, ca. 100Hz best case. */
+ float sample_rate = sampleNum / (duration_ms / 1000.0);
+ writeLong(f, sample_rate, target);
writeString(f, "seconds");
for (i = 0; i < (15-strlen("seconds")); i++)
writeData(f, &zero, 1);
return ERROR_FAIL;
}
+ uint64_t timestart_ms = timeval_ms();
/**
* Some cores let us sample the PC without the
* annoying halt/resume step; for example, ARMv7 PCSR.
free(samples);
return retval;
}
+ uint32_t duration_ms = timeval_ms() - timestart_ms;
assert(num_of_samples <= MAX_PROFILE_SAMPLE_NUM);
}
write_gmon(samples, num_of_samples, CMD_ARGV[1],
- with_range, start_address, end_address, target);
+ with_range, start_address, end_address, target, duration_ms);
command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]);
free(samples);