Skip to content

Commit 0a084c2

Browse files
borneoatarek-bochkati
authored andcommitted
target: cortex-m: defer cache identification on Cortex-M7 under reset
On Cortex-M7 only, several registers in System Control Space (SCS) are not accessible when the CPU is under reset, generating a bus error. This cause OpenOCD to fail examining the CPU when the board reset button is pressed or when the flag 'connect_assert_srst' is used on 'reset_config' command. Introduce a deferred identification of the cache and run it during polling and at target halted (just in case of polling disabled). Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-by: Ahmed HAOUES <ahmed.haoues@st.com>
1 parent 71a5893 commit 0a084c2

3 files changed

Lines changed: 73 additions & 7 deletions

File tree

src/target/armv7m_cache.c

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static struct armv7m_cache_size decode_ccsidr(uint32_t ccsidr)
6868
return size;
6969
}
7070

71-
int armv7m_identify_cache(struct target *target)
71+
static int armv7m_identify_cache_internal(struct target *target)
7272
{
7373
struct armv7m_common *armv7m = target_to_armv7m(target);
7474
struct armv7m_cache_common *cache = &armv7m->armv7m_cache;
@@ -189,6 +189,54 @@ int armv7m_identify_cache(struct target *target)
189189
return ERROR_OK;
190190
}
191191

192+
/*
193+
* On Cortex-M7 only, when the CPU is kept in reset, several registers of the
194+
* System Control Space (SCS) are not accessible and return bus error.
195+
* The list of accessible registers is:
196+
* - 0xE000ED00
197+
* - 0xE000ED30
198+
* - 0xE000EDF0 ... 0xE000EEFC
199+
* - 0xE000EF40 ... 0xE000EF48
200+
* - 0xE000EFD0 ... 0xE000EFFC
201+
* This makes impossible detecting the cache during the reset.
202+
* Use a deferred mechanism to detect the cache during polling or when the
203+
* Cortex-M7 halts.
204+
*/
205+
int armv7m_identify_cache(struct target *target)
206+
{
207+
struct cortex_m_common *cortex_m = target_to_cm(target);
208+
struct armv7m_common *armv7m = target_to_armv7m(target);
209+
struct armv7m_cache_common *cache = &armv7m->armv7m_cache;
210+
211+
if (cache->info_valid)
212+
return ERROR_OK;
213+
214+
if (cortex_m->core_info->impl_part == CORTEX_M7_PARTNO
215+
&& cortex_m->dcb_dhcsr & S_RESET_ST) {
216+
cache->defer_identification = true;
217+
return ERROR_OK;
218+
}
219+
220+
return armv7m_identify_cache_internal(target);
221+
}
222+
223+
int armv7m_deferred_identify_cache(struct target *target)
224+
{
225+
struct armv7m_common *armv7m = target_to_armv7m(target);
226+
struct armv7m_cache_common *cache = &armv7m->armv7m_cache;
227+
228+
if (cache->info_valid || !cache->defer_identification)
229+
return ERROR_OK;
230+
231+
int retval = armv7m_identify_cache_internal(target);
232+
if (retval != ERROR_OK)
233+
return retval;
234+
235+
cache->defer_identification = false;
236+
237+
return ERROR_OK;
238+
}
239+
192240
extern struct command_context *global_cmd_ctx;
193241

194242
static int armv7m_cache_helper(struct target *target, const char *helper,
@@ -334,6 +382,11 @@ int armv7m_handle_cache_info_command(struct command_invocation *cmd,
334382
return ERROR_FAIL;
335383
}
336384

385+
if (cache->defer_identification) {
386+
command_print(cmd, "Cache not detected yet");
387+
return ERROR_OK;
388+
}
389+
337390
if (!cache->info_valid) {
338391
command_print(cmd, "No cache detected");
339392
return ERROR_OK;

src/target/armv7m_cache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct armv7m_arch_cache {
3838
// common cache information
3939
struct armv7m_cache_common {
4040
bool info_valid;
41+
bool defer_identification;
4142
unsigned int loc; // level of coherency
4243
uint32_t d_min_line_len; // minimum d-cache line_len
4344
uint32_t i_min_line_len; // minimum i-cache line_len
@@ -47,6 +48,7 @@ struct armv7m_cache_common {
4748
};
4849

4950
int armv7m_identify_cache(struct target *target);
51+
int armv7m_deferred_identify_cache(struct target *target);
5052
int armv7m_d_cache_flush(struct target *target, uint32_t address,
5153
unsigned int length);
5254
int armv7m_i_cache_inval(struct target *target, uint32_t address,

src/target/cortex_m.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,9 @@ static int cortex_m_debug_entry(struct target *target)
832832
}
833833

834834
// read caches state
835+
retval = armv7m_deferred_identify_cache(target);
836+
if (retval != ERROR_OK)
837+
return retval;
835838
uint32_t ccr = 0;
836839
if (armv7m->armv7m_cache.info_valid) {
837840
retval = mem_ap_read_u32(armv7m->debug_ap, CCR, &ccr);
@@ -951,6 +954,10 @@ static int cortex_m_poll_one(struct target *target)
951954
LOG_TARGET_INFO(target, "external reset detected");
952955
}
953956
return ERROR_OK;
957+
} else {
958+
retval = armv7m_deferred_identify_cache(target);
959+
if (retval != ERROR_OK)
960+
return retval;
954961
}
955962

956963
if (target->state == TARGET_RESET) {
@@ -2698,6 +2705,16 @@ int cortex_m_examine(struct target *target)
26982705
if (retval != ERROR_OK)
26992706
return retval;
27002707

2708+
/*
2709+
* Use a safe value of sticky S_RESET_ST for cache detection, before
2710+
* clearing it below.
2711+
*/
2712+
retval = armv7m_identify_cache(target);
2713+
if (retval != ERROR_OK) {
2714+
LOG_ERROR("Cannot detect cache");
2715+
return retval;
2716+
}
2717+
27012718
/* Don't cumulate sticky S_RESET_ST at the very first read of DHCSR
27022719
* as S_RESET_ST may indicate a reset that happened long time ago
27032720
* (most probably the power-on reset before OpenOCD was started).
@@ -2767,12 +2784,6 @@ int cortex_m_examine(struct target *target)
27672784
LOG_TARGET_INFO(target, "target has %d breakpoints, %d watchpoints",
27682785
cortex_m->fp_num_code,
27692786
cortex_m->dwt_num_comp);
2770-
2771-
retval = armv7m_identify_cache(target);
2772-
if (retval != ERROR_OK) {
2773-
LOG_ERROR("Cannot detect cache");
2774-
return retval;
2775-
}
27762787
}
27772788

27782789
return ERROR_OK;

0 commit comments

Comments
 (0)