Skip to content

Commit b27911b

Browse files
committed
Get MRI working on Cortex-M7 over Serial1
This commit includes a few changes that I needed to make to the MRI library in this repository to get it working on the Cortex-M7 over Serial1. * Pass in an empty string to __mriInit() from setup() instead of NULL. * I modified armv7-m_asm.S to expose mriFaultHandler as a global symbol named __mriFaultHandler so that HardFault_IRQn, MemoryManagement_IRQn, BusFault_IRQn, and UsageFault_IRQn could be dynamically set appropriately when initializing the MRI library. mbed-os has its own handlers defined in the FLASH based interrupt vector that stop us from placing the MRI ones there. * I modified Platform_CommHasReceiveData() to clear the overrun flag that can sometimes be set if MRI is doing something else when GDB first sends a command. Once the flag gets set, no more data will be received until software clears it. It should be ok to ignore overrun as it will just result in a packet checksum error to which MRI will issue a NAK. * I commented out my code in MRI which uses the MPU to disable caching. Disabling caching on a Cortex-M7 caused the core to see stale data when the newer data was still sitting in the cache. It turns out that this disabling of the cache isn't needed on the M7 core anyway as the DSB/ISB instructions work as expected with respect to write buffering. On Cortex-M3/M4 cores I used the MPU to disable caching so that bus faults for writes to bad addresses would be synchronous so that they could be properly caught and reported back to GDB when the GDB user attempted to write to an invalid piece of memory. DSB/ISB seemed to be ignored on Cortex-M3. * Cortex-M7 microcontrollers use the newer version 2 of the Flash Patch and Breakpoint unit to allow for setting hardware breakpoints. When the hardware breakpoint setting code in MRI was originally written, only version 1 existed so it contained no code to properly handle this newer version. Setting the breakpoint address as in version 1 on version 2 hardware will not set the breakpoint properly. This commit includes code that can detect this new FPB version and set the breakpoint address appropriately. * I also fixed a bug in set/getMPURegionAddress() where I was shifting the base address left by 5 bits when I should have just been masking off the lower 5 bits. Since I only used this function to set a base address of 0 from MRI, I never noticed that it was wrong before. I just happened to notice it during a code review comparing code in debug_cm3.h to the latest version of the ARMv7-M Architecture Reference Manual.
1 parent f1cd896 commit b27911b

File tree

5 files changed

+149
-143
lines changed

5 files changed

+149
-143
lines changed

libraries/MRI/examples/MRI/MRI.ino

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
void setup() {
99
Serial1.begin(115200); /* Initialize Serial1 via mbed ... should actually be done within MRI library to have the configuration we need */
10-
__mriInit(0);
10+
__mriInit("");
1111
}
1212

1313
void loop() {

libraries/MRI/src/architectures/armv7-m/armv7-m.c

+1-47
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2017 Adam Green (https://github.com/adamgreen/)
1+
/* Copyright 2020 Adam Green (https://github.com/adamgreen/)
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -619,9 +619,6 @@ static void displayUsageFaultCauseToGdbConsole(void)
619619

620620

621621
static void clearMemoryFaultFlag(void);
622-
static void configureMpuToAccessAllMemoryWithNoCaching(void);
623-
static void saveOriginalMpuConfiguration(void);
624-
static void configureHighestMpuRegionToAccessAllMemoryWithNoCaching(void);
625622
static void cleanupIfSingleStepping(void);
626623
static void restoreBasePriorityIfNeeded(void);
627624
static uint32_t shouldRestoreBasePriority(void);
@@ -634,7 +631,6 @@ void Platform_EnteringDebugger(void)
634631
{
635632
clearMemoryFaultFlag();
636633
__mriCortexMState.originalPC = __mriCortexMState.context.PC;
637-
configureMpuToAccessAllMemoryWithNoCaching();
638634
cleanupIfSingleStepping();
639635
}
640636

@@ -643,36 +639,6 @@ static void clearMemoryFaultFlag(void)
643639
__mriCortexMState.flags &= ~CORTEXM_FLAGS_FAULT_DURING_DEBUG;
644640
}
645641

646-
static void configureMpuToAccessAllMemoryWithNoCaching(void)
647-
{
648-
saveOriginalMpuConfiguration();
649-
disableMPU();
650-
configureHighestMpuRegionToAccessAllMemoryWithNoCaching();
651-
enableMPUWithHardAndNMIFaults();
652-
}
653-
654-
static void saveOriginalMpuConfiguration(void)
655-
{
656-
__mriCortexMState.originalMPUControlValue = getMPUControlValue();
657-
__mriCortexMState.originalMPURegionNumber = getCurrentMPURegionNumber();
658-
prepareToAccessMPURegion(getHighestMPUDataRegionIndex());
659-
__mriCortexMState.originalMPURegionAddress = getMPURegionAddress();
660-
__mriCortexMState.originalMPURegionAttributesAndSize = getMPURegionAttributeAndSize();
661-
}
662-
663-
static void configureHighestMpuRegionToAccessAllMemoryWithNoCaching(void)
664-
{
665-
static const uint32_t regionToStartAtAddress0 = 0U;
666-
static const uint32_t regionReadWrite = 1 << MPU_RASR_AP_SHIFT;
667-
static const uint32_t regionSizeAt4GB = 31 << MPU_RASR_SIZE_SHIFT; /* 4GB = 2^(31+1) */
668-
static const uint32_t regionEnable = MPU_RASR_ENABLE;
669-
static const uint32_t regionSizeAndAttributes = regionReadWrite | regionSizeAt4GB | regionEnable;
670-
671-
prepareToAccessMPURegion(getHighestMPUDataRegionIndex());
672-
setMPURegionAddress(regionToStartAtAddress0);
673-
setMPURegionAttributeAndSize(regionSizeAndAttributes);
674-
}
675-
676642
static void cleanupIfSingleStepping(void)
677643
{
678644
restoreBasePriorityIfNeeded();
@@ -725,25 +691,13 @@ static void clearHardwareBreakpointOnSvcHandler(void)
725691
}
726692

727693

728-
static void restoreMPUConfiguration(void);
729694
static void checkStack(void);
730695
void Platform_LeavingDebugger(void)
731696
{
732-
restoreMPUConfiguration();
733697
checkStack();
734698
clearMonitorPending();
735699
}
736700

737-
static void restoreMPUConfiguration(void)
738-
{
739-
disableMPU();
740-
prepareToAccessMPURegion(getHighestMPUDataRegionIndex());
741-
setMPURegionAddress(__mriCortexMState.originalMPURegionAddress);
742-
setMPURegionAttributeAndSize(__mriCortexMState.originalMPURegionAttributesAndSize);
743-
prepareToAccessMPURegion(__mriCortexMState.originalMPURegionNumber);
744-
setMPUControlValue(__mriCortexMState.originalMPUControlValue);
745-
}
746-
747701
static void checkStack(void)
748702
{
749703
uint32_t* pCurr = (uint32_t*)__mriCortexMState.debuggerStack;

libraries/MRI/src/architectures/armv7-m/armv7-m_asm.S

+21-18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2017 Adam Green (http://mbed.org/users/AdamGreen/)
1+
/* Copyright 2020 Adam Green (https://github.com/adamgreen/)
22

33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -39,14 +39,17 @@
3939
__mriExceptionHandler:
4040
ldr r0, =mriSaveRestoreContext
4141
b mriGetSPAndCallHandler
42-
4342

43+
44+
.global __mriFaultHandler
45+
.type __mriFaultHandler, function
46+
.thumb_func
4447
/* Like MriExceptionHandler above but it also checks and handles stacking/unstacking faults. */
45-
mriFaultHandler:
48+
__mriFaultHandler:
4649
ldr r0, =checkForStackError
4750
b mriGetSPAndCallHandler
48-
49-
51+
52+
5053
/* Determines whether task context was saved in PSP or MSP and places the correct stack pointer address into
5154
the R1 register before calling the caller provided fault handler pointed to by the r0 register.
5255
*/
@@ -61,8 +64,8 @@ mriGetSPAndCallHandler:
6164
str r1, [r2]
6265
/* Call specified handler exception handler routine */
6366
mov pc, r0
64-
65-
67+
68+
6669
.type checkForStackError, function
6770
.thumb_func
6871
/* Handles hard/memory/bus fault exceptions by checking for stacking/unstacking errors before calling the main
@@ -85,7 +88,7 @@ checkForStackError:
8588
/* Handles exception invokations for MRI. Its main job is to store the interrupted task's context, call into
8689
the C based __mriDebugException, and then restore the task's context (which may have been modified by the
8790
debugger.
88-
91+
8992
Layout of the registers which are pushed on the stack automatically by Cortex-M3 curing exception execution:
9093
SP Value in MSP or PSP task was interrupted.
9194
PSR SP - 4
@@ -96,7 +99,7 @@ checkForStackError:
9699
R2 SP - 24
97100
R1 SP - 28
98101
R0 SP - 32 Value in MSP or PSP when handler is started.
99-
102+
100103
Layout of the SContext record used by gdb for 'g' and 'G' commands.
101104
typedef struct
102105
{
@@ -132,7 +135,7 @@ mriSaveRestoreContext:
132135
/* Set the debugger active flag so that subsequent exceptions will be caught. */
133136
orr r2, #CORTEXM_FLAGS_ACTIVE_DEBUG
134137
str r2, [r0]
135-
138+
136139
/* Fill the debugger stack with 0xDEADBEEF. */
137140
movs r0, #CORTEXM_DEBUGGER_STACK_SIZE
138141
ldr r12, =(__mriCortexMState + CORTEXM_STATE_DEBUGGER_STACK_OFFSET + CORTEXM_DEBUGGER_STACK_SIZE_IN_BYTES)
@@ -149,7 +152,7 @@ mriSaveRestoreContext:
149152
str r2, [r0]
150153
ldr r0, =(__mriCortexMState + CORTEXM_STATE_DEBUGGER_STACK_OFFSET + CORTEXM_DEBUGGER_STACK_SIZE_IN_BYTES)
151154
msr msp, r0
152-
155+
153156
/**** Copy R0-R3, R12, LR, PC, and PSR from running task's stack and place in MRI context structure. */
154157
ldr r0, =(__mriCortexMState + CORTEXM_STATE_CONTEXT_OFFSET)
155158
/* Now that R1 contains the SP, we can push away the current LR (and R12 to just keep 8-byte alignment.) */
@@ -223,7 +226,7 @@ mriSaveRestoreContext:
223226
tst r5, #PSR_STACK_ALIGN
224227
it ne
225228
addne r1, r1, #4
226-
/* Jump back past the CONTROL, FAULTMASK, BASEPRI, PRIMASK, PSP, MSP, PSR, PC and LR that were placed in context
229+
/* Jump back past the CONTROL, FAULTMASK, BASEPRI, PRIMASK, PSP, MSP, PSR, PC and LR that were placed in context
227230
to store the potentially updated SP. */
228231
str r1, [r0, #-40]
229232

@@ -309,7 +312,7 @@ mriSaveRestoreContext:
309312
/**** Make sure that any modifications to the instruction stream by data writes are seen. */
310313
dsb
311314
isb
312-
315+
313316
/**** Return to task after clearing fault status bits. */
314317
b mriClearFaultStatusBitsAndReturn
315318

@@ -367,8 +370,8 @@ mriClearFaultStatusBitsAndReturn:
367370
*/
368371
//HardFault_Handler:
369372
// b mriFaultHandler
370-
371-
373+
374+
372375
// .global MemManage_Handler
373376
// .type MemManage_Handler, function
374377
// .thumb_func
@@ -377,7 +380,7 @@ mriClearFaultStatusBitsAndReturn:
377380
*/
378381
//MemManage_Handler:
379382
// b mriFaultHandler
380-
383+
381384

382385
// .global BusFault_Handler
383386
// .type BusFault_Handler, function
@@ -387,7 +390,7 @@ mriClearFaultStatusBitsAndReturn:
387390
*/
388391
//BusFault_Handler:
389392
// b mriFaultHandler
390-
393+
391394

392395
// .global UsageFault_Handler
393396
// .type UsageFault_Handler, function
@@ -397,7 +400,7 @@ mriClearFaultStatusBitsAndReturn:
397400
*/
398401
//UsageFault_Handler:
399402
// b __mriExceptionHandler
400-
403+
401404

402405
.global DebugMon_Handler
403406
.type DebugMon_Handler, function

0 commit comments

Comments
 (0)