diff --git a/src/server/server.c b/src/server/server.c index 9832762f6..73d8b5b65 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -559,6 +559,7 @@ int server_init(struct command_context *cmd_ctx) int server_quit(void) { remove_services(); + target_quit(); #ifdef _WIN32 WSACleanup(); diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 028bfd808..4dc92c834 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1685,6 +1685,15 @@ static int cortex_m_init_target(struct command_context *cmd_ctx, return ERROR_OK; } +void cortex_m_deinit_target(struct target *target) +{ + struct cortex_m_common *cortex_m = target_to_cm(target); + + free(cortex_m->fp_comparator_list); + cortex_m_dwt_free(target); + free(cortex_m); +} + /* REVISIT cache valid/dirty bits are unmaintained. We could set "valid" * on r/w if the core is not running, and clear on resume or reset ... or * at least, in a post_restore_context() method. @@ -2362,4 +2371,5 @@ struct target_type cortexm_target = { .target_create = cortex_m_target_create, .init_target = cortex_m_init_target, .examine = cortex_m_examine, + .deinit_target = cortex_m_deinit_target, }; diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 8a284bd98..28189e02e 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -210,5 +210,6 @@ int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpo void cortex_m_enable_breakpoints(struct target *target); void cortex_m_enable_watchpoints(struct target *target); void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target); +void cortex_m_deinit_target(struct target *target); #endif /* CORTEX_M_H */ diff --git a/src/target/hla_target.c b/src/target/hla_target.c index f778d23aa..a05a99ff5 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -780,6 +780,7 @@ struct target_type hla_target = { .deprecated_name = "stm32_stlink", .init_target = adapter_init_target, + .deinit_target = cortex_m_deinit_target, .target_create = adapter_target_create, .examine = cortex_m_examine, .commands = adapter_command_handlers, diff --git a/src/target/target.c b/src/target/target.c index b559a5155..5c88384d8 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1800,6 +1800,31 @@ int target_free_working_area(struct target *target, struct working_area *area) return target_free_working_area_restore(target, area, 1); } +void target_quit(void) +{ + struct target_event_callback *pe = target_event_callbacks; + while (pe) { + struct target_event_callback *t = pe->next; + free(pe); + pe = t; + } + target_event_callbacks = NULL; + + struct target_timer_callback *pt = target_timer_callbacks; + while (pt) { + struct target_timer_callback *t = pt->next; + free(pt); + pt = t; + } + target_timer_callbacks = NULL; + + for (struct target *target = all_targets; + target; target = target->next) { + if (target->type->deinit_target) + target->type->deinit_target(target); + } +} + /* free resources and restore memory, if restoring memory fails, * free up resources anyway */ diff --git a/src/target/target.h b/src/target/target.h index f709d6a5a..fbce19f51 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -615,6 +615,11 @@ int target_free_working_area(struct target *target, struct working_area *area); void target_free_all_working_areas(struct target *target); uint32_t target_get_working_area_avail(struct target *target); +/** + * Free all the resources allocated by targets and the target layer + */ +void target_quit(void); + extern struct target *all_targets; uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer); diff --git a/src/target/target_type.h b/src/target/target_type.h index cf3c864c8..234cdfb00 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -225,6 +225,13 @@ struct target_type { * */ int (*init_target)(struct command_context *cmd_ctx, struct target *target); + /** + * Free all the resources allocated by the target. + * + * @param target The target to deinit + */ + void (*deinit_target)(struct target *target); + /* translate from virtual to physical address. Default implementation is successful * no-op(i.e. virtual==physical). */