Skip to content

Commit 6d5ec5a

Browse files
adamgreenfacchinm
authored andcommitted
Refactor single step code
Changes include: * Now only uses the assembly language stubs for SVCall, PendSV, and SysTick when single stepping. When not single stepping, the original RTX versions of these handlers are restored so that there is no stub overhead. * The code now records the original addresses of the RTX handlers before switching them to the debug stubs so that: * They can be restored when no longer single stepping as mentioned above. * Reduce code duplication by having a unique stub for each of SVCall, PendSV, and SysTick that just loads the original address into R0 and then transfers control to mriRTXHandlerStub() which does the work of pending a DebugMon interrupt to fire later and set the single stepping bit in the DEMCR based on the current thread. Once DebugMon has been pended, it will branch to the original handler pointed to by R0.
1 parent 9b42cf6 commit 6d5ec5a

File tree

2 files changed

+62
-44
lines changed

2 files changed

+62
-44
lines changed

libraries/ThreadMRI/src/ThreadMRI.cpp

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,15 @@ static volatile uint32_t g_enableDWTandFPB;
9595
// Accessed by this module and the assembly language handlers in ThreadMRI_asm.S.
9696
volatile osThreadId_t mriThreadSingleStepThreadId;
9797

98+
// Addresses of the original RTX handlers for SVCall, SysTick, and PendSV when hooks to them have been inserted for
99+
// enabling single step.
100+
volatile uint32_t mriThreadOrigSVCall;
101+
volatile uint32_t mriThreadOrigSysTick;
102+
volatile uint32_t mriThreadOrigPendSV;
103+
98104
// UNDONE: For debugging. If different than g_haltedThreadId then the mriMain() thread was signalled when the previous
99105
// instance was still running.
100-
static volatile osThreadId_t g_debugThreadId;
106+
static volatile osThreadId_t g_debugThreadId;
101107

102108

103109

@@ -116,12 +122,13 @@ static __NO_RETURN void mriMain(void *pv);
116122
static void suspendAllApplicationThreads();
117123
static void resumeApplicationThreads();
118124
static void readThreadContext(osThreadId_t thread);
125+
static void switchRtxHandlersToDebugStubsForSingleStepping();
126+
static void restoreRtxHandlers();
119127
static bool hasEncounteredDebugEvent();
120128
static void recordAndClearFaultStatusBits();
121129
static void wakeMriMainToDebugCurrentThread();
122130
static void stopSingleStepping();
123131
static void switchFaultHandlersToDebugger();
124-
static void switchRtxHandlersToDebugStubs();
125132

126133

127134

@@ -171,13 +178,17 @@ static __NO_RETURN void mriMain(void *pv)
171178
ASSERT ( g_haltedThreadId != 0 );
172179
suspendAllApplicationThreads();
173180
readThreadContext(g_haltedThreadId);
181+
if (Platform_IsSingleStepping()) {
182+
restoreRtxHandlers();
183+
}
174184

175185
osThreadSetPriority(osThreadGetId(), osPriorityNormal);
176186
mriDebugException();
177187
osThreadSetPriority(osThreadGetId(), osPriorityRealtime7);
178188

179189
if (Platform_IsSingleStepping()) {
180190
mriThreadSingleStepThreadId = g_haltedThreadId;
191+
switchRtxHandlersToDebugStubsForSingleStepping();
181192
osThreadResume(mriThreadSingleStepThreadId);
182193
} else {
183194
resumeApplicationThreads();
@@ -262,6 +273,24 @@ static void readThreadContext(osThreadId_t thread)
262273
}
263274
}
264275

276+
static void switchRtxHandlersToDebugStubsForSingleStepping()
277+
{
278+
mriThreadOrigSVCall = NVIC_GetVector(SVCall_IRQn);
279+
mriThreadOrigPendSV = NVIC_GetVector(PendSV_IRQn);
280+
mriThreadOrigSysTick = NVIC_GetVector(SysTick_IRQn);
281+
NVIC_SetVector(SVCall_IRQn, (uint32_t)mriSVCHandlerStub);
282+
NVIC_SetVector(PendSV_IRQn, (uint32_t)mriPendSVHandlerStub);
283+
NVIC_SetVector(SysTick_IRQn, (uint32_t)mriSysTickHandlerStub);
284+
}
285+
286+
static void restoreRtxHandlers()
287+
{
288+
NVIC_SetVector(SVCall_IRQn, mriThreadOrigSVCall);
289+
NVIC_SetVector(PendSV_IRQn, mriThreadOrigPendSV);
290+
NVIC_SetVector(SysTick_IRQn, mriThreadOrigSysTick);
291+
}
292+
293+
265294

266295

267296
// ---------------------------------------------------------------------------------------------------------------------
@@ -278,7 +307,6 @@ void Platform_Init(Token* pParameterTokens)
278307
g_enableDWTandFPB = 0;
279308
mriThreadSingleStepThreadId = NULL;
280309
switchFaultHandlersToDebugger();
281-
switchRtxHandlersToDebugStubs();
282310
}
283311

284312
static void switchFaultHandlersToDebugger(void)
@@ -290,13 +318,6 @@ static void switchFaultHandlersToDebugger(void)
290318
NVIC_SetVector(DebugMonitor_IRQn, (uint32_t)mriDebugMonitorHandlerStub);
291319
}
292320

293-
static void switchRtxHandlersToDebugStubs(void)
294-
{
295-
NVIC_SetVector(SVCall_IRQn, (uint32_t)mriSVCHandlerStub);
296-
NVIC_SetVector(PendSV_IRQn, (uint32_t)mriPendSVHandlerStub);
297-
NVIC_SetVector(SysTick_IRQn, (uint32_t)mriSysTickHandlerStub);
298-
}
299-
300321

301322

302323

libraries/ThreadMRI/src/ThreadMRI_asm.S

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,25 @@ mriFaultHandlerStub:
8080
.size mriFaultHandlerStub, .-mriFaultHandlerStub
8181

8282

83+
.global mriRTXHandlerStub
84+
.type mriRTXHandlerStub, function
85+
.thumb_func
86+
/* extern "C" void mriRTXHandlerStub(void (*pOrigHandler)(void));
87+
This stub pends a DebugMon interrupt whenever a RTX interrupt occurs that could perform a context switch so
88+
that it has a chance to enable single stepping if switching to the thread to be single stepped.
89+
*/
90+
mriRTXHandlerStub:
91+
/* Need to queue up a DebugMon interrupt to enable single stepping when switching to thread of interest. */
92+
ldr r1, =DEMCR
93+
ldr r2, [r1]
94+
orr r2, #DEMCR_MON_PEND_BIT
95+
str r2, [r1]
96+
/* Run actual RTX handler. */
97+
1$: mov pc, r0
98+
.pool
99+
.size mriRTXHandlerStub, .-mriRTXHandlerStub
100+
101+
83102
.global mriSVCHandlerStub
84103
.type mriSVCHandlerStub, function
85104
.thumb_func
@@ -88,18 +107,10 @@ mriFaultHandlerStub:
88107
that it has a chance to enable single stepping if switching to the thread to be single stepped.
89108
*/
90109
mriSVCHandlerStub:
91-
/* Need to queue DebugMon on potential context switch when single stepping is enabled. */
92-
ldr r0, =mriThreadSingleStepThreadId
93-
ldr r1, [r0]
94-
cbz r1, 1$
95-
/* Need to queue up a DebugMon interrupt. */
96-
ldr r0, =DEMCR
97-
ldr r1, [r0]
98-
orr r1, #DEMCR_MON_PEND_BIT
99-
str r1, [r0]
100-
/* Run actual handler. */
101-
// UNDONE: Use function pointer instead as it could have been changed dynamically.
102-
1$: b.w SVC_Handler
110+
/* Load address of real RTX handler into r0 & call generic stub to pend DebugMon for single stepping. */
111+
ldr r0, =mriThreadOrigSVCall
112+
ldr r0, [r0]
113+
b mriRTXHandlerStub
103114
.pool
104115
.size mriSVCHandlerStub, .-mriSVCHandlerStub
105116

@@ -112,17 +123,10 @@ mriSVCHandlerStub:
112123
that it has a chance to enable single stepping if switching to the thread to be single stepped.
113124
*/
114125
mriPendSVHandlerStub:
115-
/* Need to queue DebugMon on potential context switch when single stepping is enabled. */
116-
ldr r0, =mriThreadSingleStepThreadId
117-
ldr r1, [r0]
118-
cbz r1, 1$
119-
/* Need to queue up a DebugMon interrupt. */
120-
ldr r0, =DEMCR
121-
ldr r1, [r0]
122-
orr r1, #DEMCR_MON_PEND_BIT
123-
str r1, [r0]
124-
/* Run actual handler. */
125-
1$: b.w PendSV_Handler
126+
/* Load address of real RTX handler into r0 & call generic stub to pend DebugMon for single stepping. */
127+
ldr r0, =mriThreadOrigPendSV
128+
ldr r0, [r0]
129+
b mriRTXHandlerStub
126130
.pool
127131
.size mriPendSVHandlerStub, .-mriPendSVHandlerStub
128132

@@ -135,17 +139,10 @@ mriPendSVHandlerStub:
135139
that it has a chance to enable single stepping if switching to the thread to be single stepped.
136140
*/
137141
mriSysTickHandlerStub:
138-
/* Need to queue DebugMon on potential context switch when single stepping is enabled. */
139-
ldr r0, =mriThreadSingleStepThreadId
140-
ldr r1, [r0]
141-
cbz r1, 1$
142-
/* Need to queue up a DebugMon interrupt. */
143-
ldr r0, =DEMCR
144-
ldr r1, [r0]
145-
orr r1, #DEMCR_MON_PEND_BIT
146-
str r1, [r0]
147-
/* Run actual handler. */
148-
1$: b.w SysTick_Handler
142+
/* Load address of real RTX handler into r0 & call generic stub to pend DebugMon for single stepping. */
143+
ldr r0, =mriThreadOrigSysTick
144+
ldr r0, [r0]
145+
b mriRTXHandlerStub
149146
.pool
150147
.size mriSysTickHandlerStub, .-mriSysTickHandlerStub
151148

0 commit comments

Comments
 (0)