Skip to content

Commit 90d0686

Browse files
adamgreenfacchinm
authored andcommitted
Support CTRL+C halting of running threads
Hook the USART ISR and pend a DebugMon interrupt if GDB sends data while the debuggee is running, typically this will be a CTRL+C but stopping for any command is a good thing. Now uses the CORTEXM_FLAGS_CTRL_C flag to determine if SIGINT should be returned from Platform_DetermineCauseOfException() as the cause of a debug halt. Previously it was hardcoded to use the exception numbers of the LPC176x UART handlers.
1 parent 6421d41 commit 90d0686

File tree

3 files changed

+64
-9
lines changed

3 files changed

+64
-9
lines changed

libraries/ThreadMRI/src/ThreadMRI.cpp

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ extern "C"
3232
// UNDONE: Switch back to the USB/CDC based serial port.
3333
#undef Serial
3434
#define Serial Serial1
35+
#define MRI_SERIAL_IRQ USART1_IRQn
3536

3637

3738
// Configuration Parameters
@@ -111,6 +112,8 @@ volatile uint32_t mriThreadOrigHardFault;
111112
volatile uint32_t mriThreadOrigMemManagement;
112113
volatile uint32_t mriThreadOrigBusFault;
113114
volatile uint32_t mriThreadOrigUsageFault;
115+
// Address of the original Serial peripheral ISR to be hooked.
116+
void (*g_origSerialISR)(void);
114117

115118
// UNDONE: For debugging. If different than g_haltedThreadId then the mriMain() thread was signalled when the previous
116119
// instance was still running.
@@ -142,23 +145,27 @@ static void setDebugActiveFlag();
142145
static void clearDebugActiveFlag();
143146
static bool isThreadMode(uint32_t excReturn);
144147
static bool hasEncounteredDebugEvent();
148+
static bool hasControlCBeenDetected();
145149
static void recordAndClearFaultStatusBits();
146150
static void wakeMriMainToDebugCurrentThread();
147151
static void stopSingleStepping();
148152
static void recordAndSwitchFaultHandlersToDebugger();
153+
static void hookSerialISR();
149154
static bool isDebugThreadActive();
150155
static void setFaultDetectedFlag();
151156
static bool isImpreciseBusFault();
152157
static void advancePCToNextInstruction(uint32_t excReturn, uint32_t psp, uint32_t msp);
153158
static uint32_t* threadSP(uint32_t excReturn, uint32_t psp, uint32_t msp);
154159
static bool isInstruction32Bit(uint16_t firstWordOfInstruction);
160+
static void serialISRHook();
161+
static bool isDebuggerActive();
162+
static void setControlCFlag();
155163

156164

157165

158166

159167
ThreadMRI::ThreadMRI()
160168
{
161-
mriInit("");
162169
}
163170

164171

@@ -169,6 +176,9 @@ bool ThreadMRI::begin()
169176
return false;
170177
}
171178

179+
// UNDONE: Move into constructor.
180+
mriInit("");
181+
172182
static uint64_t stack[MRI_THREAD_STACK_SIZE];
173183
static osRtxThread_t threadTcb;
174184
static const osThreadAttr_t threadAttr =
@@ -341,6 +351,7 @@ void Platform_Init(Token* pParameterTokens)
341351
g_enableDWTandFPB = 0;
342352
mriThreadSingleStepThreadId = NULL;
343353
recordAndSwitchFaultHandlersToDebugger();
354+
hookSerialISR();
344355
}
345356

346357
static void recordAndSwitchFaultHandlersToDebugger()
@@ -357,6 +368,12 @@ static void recordAndSwitchFaultHandlersToDebugger()
357368
NVIC_SetVector(DebugMonitor_IRQn, (uint32_t)mriDebugMonitorHandlerStub);
358369
}
359370

371+
static void hookSerialISR()
372+
{
373+
g_origSerialISR = (void(*)(void))NVIC_GetVector(MRI_SERIAL_IRQ);
374+
NVIC_SetVector(MRI_SERIAL_IRQ, (uint32_t)serialISRHook);
375+
}
376+
360377

361378

362379

@@ -457,7 +474,7 @@ extern "C" void mriDebugMonitorHandler(uint32_t excReturn)
457474
// DebugMon is running at such low priority that we should be getting ready to return to thread mode.
458475
}
459476

460-
if (!hasEncounteredDebugEvent()) {
477+
if (!hasEncounteredDebugEvent() && !hasControlCBeenDetected()) {
461478
if (g_enableDWTandFPB) {
462479
enableDWTandITM();
463480
enableFPB();
@@ -528,6 +545,11 @@ static bool hasEncounteredDebugEvent()
528545

529546
}
530547

548+
static bool hasControlCBeenDetected()
549+
{
550+
return mriCortexMState.flags & CORTEXM_FLAGS_CTRL_C;
551+
}
552+
531553
static void recordAndClearFaultStatusBits()
532554
{
533555
mriCortexMState.exceptionNumber = getCurrentlyExecutingExceptionNumber();
@@ -595,7 +617,6 @@ static uint32_t* threadSP(uint32_t excReturn, uint32_t psp, uint32_t msp)
595617
return (uint32_t*)sp;
596618
}
597619

598-
599620
static bool isInstruction32Bit(uint16_t firstWordOfInstruction)
600621
{
601622
uint16_t maskedOffUpper5BitsOfWord = firstWordOfInstruction & 0xF800;
@@ -606,3 +627,24 @@ static bool isInstruction32Bit(uint16_t firstWordOfInstruction)
606627
maskedOffUpper5BitsOfWord == 0xF000 ||
607628
maskedOffUpper5BitsOfWord == 0xF800);
608629
}
630+
631+
632+
static void serialISRHook()
633+
{
634+
g_origSerialISR();
635+
if (!isDebuggerActive() && Serial.available() > 0) {
636+
// Pend a halt into the debug monitor now that there is data from GDB ready to be read by it.
637+
setControlCFlag();
638+
setMonitorPending();
639+
}
640+
}
641+
642+
static bool isDebuggerActive()
643+
{
644+
return mriCortexMState.flags & CORTEXM_FLAGS_ACTIVE_DEBUG;
645+
}
646+
647+
static void setControlCFlag()
648+
{
649+
mriCortexMState.flags |= CORTEXM_FLAGS_CTRL_C;
650+
}

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -380,11 +380,17 @@ uint32_t Platform_GetPacketBufferSize(void)
380380
}
381381

382382

383+
static uint32_t hasControlCBeenDetected();
383384
static uint8_t determineCauseOfDebugEvent(void);
384385
uint8_t Platform_DetermineCauseOfException(void)
385386
{
386387
uint32_t exceptionNumber = mriCortexMState.exceptionNumber;
387388

389+
if (hasControlCBeenDetected())
390+
{
391+
return SIGINT;
392+
}
393+
388394
switch(exceptionNumber)
389395
{
390396
case 2:
@@ -405,18 +411,17 @@ uint8_t Platform_DetermineCauseOfException(void)
405411
case 12:
406412
/* Debug Monitor */
407413
return determineCauseOfDebugEvent();
408-
case 21:
409-
case 22:
410-
case 23:
411-
case 24:
412-
/* UART* */
413-
return SIGINT;
414414
default:
415415
/* NOTE: Catch all signal will be SIGSTOP. */
416416
return SIGSTOP;
417417
}
418418
}
419419

420+
static uint32_t hasControlCBeenDetected()
421+
{
422+
return mriCortexMState.flags & CORTEXM_FLAGS_CTRL_C;
423+
}
424+
420425
static uint8_t determineCauseOfDebugEvent(void)
421426
{
422427
static struct
@@ -704,9 +709,11 @@ static void clearHardwareBreakpointOnSvcHandler(void)
704709

705710

706711
static void checkStack(void);
712+
static void clearControlCFlag(void);
707713
void Platform_LeavingDebugger(void)
708714
{
709715
checkStack();
716+
clearControlCFlag();
710717
clearMonitorPending();
711718
}
712719

@@ -724,6 +731,11 @@ static void checkStack(void)
724731
mriCortexMState.maxStackUsed = spaceUsed;
725732
}
726733

734+
static void clearControlCFlag(void)
735+
{
736+
mriCortexMState.flags &= ~CORTEXM_FLAGS_CTRL_C;
737+
}
738+
727739

728740
uint32_t Platform_GetProgramCounter(void)
729741
{

libraries/ThreadMRI/src/architectures/armv7-m/armv7-m.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#define CORTEXM_FLAGS_SINGLE_STEPPING (1 << 2)
2525
#define CORTEXM_FLAGS_RESTORE_BASEPRI (1 << 3)
2626
#define CORTEXM_FLAGS_SVC_STEP (1 << 4)
27+
#define CORTEXM_FLAGS_CTRL_C (1 << 5)
2728

2829
/* Constants related to special memory area used by the debugger for its stack so that it doesn't interfere with
2930
the task's stack contents. */

0 commit comments

Comments
 (0)