Skip to content

Commit 72cc7d4

Browse files
committed
Add mriIdle() thread
When the debug monitor is active, this thread will take the place of RTX's idle thread which will be suspended like other application threads. The mriIdle thread will be suspended again before the application's threads are resumed so it is only used in place of RTX's idle thread when halted in GDB. This change was made so that RTX's idle thread can be treated like any other application thread which means that GDB is allowed to break into it if nothing else is running. Without this change, it wouldn't make sense to break into the code when nothing was actively running and the idle thread was active since it was a thread that ThreadDebug wasn't allowed to suspend.
1 parent 3551e7b commit 72cc7d4

File tree

1 file changed

+47
-32
lines changed

1 file changed

+47
-32
lines changed

libraries/ThreadDebug/src/ThreadDebug.cpp

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ extern "C"
3939
// ---------------------------------------------------------------------------------------------------------------------
4040
// Configuration Parameters
4141
// ---------------------------------------------------------------------------------------------------------------------
42-
// The size of the mriThread() stack in uint64_t objects.
42+
// The size of the mriMain() stack in uint64_t objects.
4343
#define MRI_THREAD_STACK_SIZE 128
44-
// The maximum number of active threads that can be handled by the debugger.
45-
#define MAXIMUM_ACTIVE_THREADS 64
44+
// The size of the mriIdle() stack in uint64_t objects.
45+
#define IDLE_THREAD_STACK_SIZE 40
4646

47-
// Threads with these names will not be suspended when a debug event is occurred.
47+
// Threads with these names will not be suspended when a debug event has occurred.
4848
// Typically these will be threads used by the communication stack to communicate with GDB or other important system
4949
// threads.
5050
static const char* g_threadNamesToIgnore[] = {
@@ -119,15 +119,15 @@ static uint32_t g_threadCount;
119119
static uint32_t g_threadIndex;
120120
// Buffer to be used for storing extra thread info.
121121
static char g_threadExtraInfo[64];
122-
// The ID of the rtx_idle thread to be skipped when providing list of threads to GDB.
123-
static osThreadId_t g_idleThread;
124122

125123
// This flag is set to a non-zero value if the DebugMon handler is to re-enable DWT watchpoints and FPB breakpoints
126124
// after being disabled by the HardFault handler when a debug event is encounted in handler mode.
127125
static volatile uint32_t g_enableDWTandFPB;
128126

129127
// The ID of the mriMain() thread.
130128
volatile osThreadId_t mriThreadId;
129+
// The ID of the mriIdle() thread.
130+
static osThreadId_t g_mriIdleThreadId;
131131

132132
// If non-NULL, this is the thread that we want to single step.
133133
// If NULL, single stepping is not enabled.
@@ -183,6 +183,7 @@ extern "C" void mriPendSVHandlerStub(void);
183183
extern "C" void mriSysTickHandlerStub(void);
184184

185185
// Forward Function Declarations
186+
static __NO_RETURN void mriIdle(void *pv);
186187
static __NO_RETURN void mriMain(void *pv);
187188
static void suspendAllApplicationThreads();
188189
static bool isThreadToIgnore(osThreadId_t thread);
@@ -199,7 +200,6 @@ static void wakeMriMainToDebugCurrentThread();
199200
static void stopSingleStepping();
200201
static void recordAndSwitchFaultHandlersToDebugger();
201202
static void skipNullThreadIds();
202-
static bool isNullOrIdleThread(osThreadId_t threadId);
203203
static const char* getThreadStateName(uint8_t threadState);
204204
static bool isDebugThreadActive();
205205
static void setFaultDetectedFlag();
@@ -234,27 +234,53 @@ ThreadDebug::ThreadDebug(DebugCommInterface* pCommInterface, bool breakInSetup,
234234
// Initialize the MRI core.
235235
mriInit("");
236236

237+
// Start the debugger's idle thread and suspend it for now.
238+
static uint64_t idleStack[IDLE_THREAD_STACK_SIZE];
239+
static osRtxThread_t idleThreadTcb;
240+
static const osThreadAttr_t idleThreadAttr =
241+
{
242+
.name = "mriIdle",
243+
.attr_bits = osThreadDetached,
244+
.cb_mem = &idleThreadTcb,
245+
.cb_size = sizeof(idleThreadTcb),
246+
.stack_mem = idleStack,
247+
.stack_size = sizeof(idleStack),
248+
.priority = (osPriority_t)(osPriorityIdle + 1)
249+
};
250+
g_mriIdleThreadId = osThreadNew(mriIdle, NULL, &idleThreadAttr);
251+
if (g_mriIdleThreadId == NULL) {
252+
return;
253+
}
254+
osThreadSuspend(g_mriIdleThreadId);
255+
237256
// Start the debugger thread.
238-
static uint64_t stack[MRI_THREAD_STACK_SIZE];
239-
static osRtxThread_t threadTcb;
240-
static const osThreadAttr_t threadAttr =
257+
static uint64_t mainStack[MRI_THREAD_STACK_SIZE];
258+
static osRtxThread_t mainThreadTcb;
259+
static const osThreadAttr_t mainThreadAttr =
241260
{
242261
.name = "mriMain",
243262
.attr_bits = osThreadDetached,
244-
.cb_mem = &threadTcb,
245-
.cb_size = sizeof(threadTcb),
246-
.stack_mem = stack,
247-
.stack_size = sizeof(stack),
263+
.cb_mem = &mainThreadTcb,
264+
.cb_size = sizeof(mainThreadTcb),
265+
.stack_mem = mainStack,
266+
.stack_size = sizeof(mainStack),
248267
.priority = osPriorityNormal
249268
};
250-
mriThreadId = osThreadNew(mriMain, NULL, &threadAttr);
269+
mriThreadId = osThreadNew(mriMain, NULL, &mainThreadAttr);
251270
if (mriThreadId == NULL) {
252271
return;
253272
}
254273

255274
callAttachFromSetup();
256275
}
257276

277+
static __NO_RETURN void mriIdle(void *pv)
278+
{
279+
while (true) {
280+
// Infinite loop at low priority if nothing else to do while debugging.
281+
}
282+
}
283+
258284
static __NO_RETURN void mriMain(void *pv)
259285
{
260286
// Run the code which suspends, resumes, etc the other threads at highest priority so that it doesn't context
@@ -271,9 +297,11 @@ static __NO_RETURN void mriMain(void *pv)
271297
restoreRtxHandlers();
272298
}
273299

300+
osThreadResume(g_mriIdleThreadId);
274301
osThreadSetPriority(osThreadGetId(), osPriorityNormal);
275302
mriDebugException(&mriCortexMState.context);
276303
osThreadSetPriority(osThreadGetId(), osPriorityISR);
304+
osThreadSuspend(g_mriIdleThreadId);
277305

278306
if (Platform_IsSingleStepping()) {
279307
mriThreadSingleStepThreadId = g_haltedThreadId;
@@ -287,20 +315,12 @@ static __NO_RETURN void mriMain(void *pv)
287315
static void suspendAllApplicationThreads()
288316
{
289317
// Suspend application threads by setting their priorities to the lowest setting, osPriorityIdle.
290-
// Bump rtx_idle thread up one priority level so that it will run instead of the 'suspended' application threads if
291-
// the debug related threads go idle.
292-
g_idleThread = 0;
293318
g_threadCount = osThreadGetCount();
294319
ASSERT ( g_threadCount <= g_maxThreadCount );
295320
osThreadEnumerate(g_pSuspendedThreads, g_maxThreadCount);
296321
for (uint32_t i = 0 ; i < g_threadCount ; i++) {
297322
osThreadId_t thread = g_pSuspendedThreads[i];
298323
osPriority_t newPriority = osPriorityIdle;
299-
const char* pThreadName = osThreadGetName(thread);
300-
if (strcmp(pThreadName, "rtx_idle") == 0) {
301-
newPriority = (osPriority_t)(osPriorityIdle + 1);
302-
g_idleThread = thread;
303-
}
304324

305325
if (isThreadToIgnore(thread)) {
306326
g_pSuspendedThreads[i] = 0;
@@ -315,8 +335,8 @@ static void suspendAllApplicationThreads()
315335

316336
static bool isThreadToIgnore(osThreadId_t thread)
317337
{
318-
if (thread == mriThreadId) {
319-
// Don't want to suspend the debugger thread itself.
338+
if (thread == mriThreadId || thread == g_mriIdleThreadId) {
339+
// Don't want to suspend the debugger threads themselves.
320340
return true;
321341
}
322342

@@ -589,15 +609,10 @@ uint32_t Platform_RtosGetNextThreadId(void)
589609

590610
static void skipNullThreadIds()
591611
{
592-
while (g_threadIndex < g_threadCount && isNullOrIdleThread(g_pSuspendedThreads[g_threadIndex]))
612+
while (g_threadIndex < g_threadCount && g_pSuspendedThreads[g_threadIndex] == 0)
593613
g_threadIndex++;
594614
}
595615

596-
static bool isNullOrIdleThread(osThreadId_t threadId)
597-
{
598-
return threadId == 0 || threadId == g_idleThread;
599-
}
600-
601616
const char* Platform_RtosGetExtraThreadInfo(uint32_t threadId)
602617
{
603618
const char* pThreadName = osThreadGetName((osThreadId)threadId);
@@ -823,7 +838,7 @@ static void clearFaultStatusBits()
823838

824839
static void serialISRHook()
825840
{
826-
if (!isDebuggerActive() && g_pComm->readable()) {
841+
if (!isDebuggerActive() && !isThreadToIgnore(osThreadGetId()) && g_pComm->readable()) {
827842
// Pend a halt into the debug monitor now that there is data from GDB ready to be read by it.
828843
setControlCFlag();
829844
setMonitorPending();

0 commit comments

Comments
 (0)