Skip to content

Commit

Permalink
Enabled hooks, defined task switch hook (#324)
Browse files Browse the repository at this point in the history
* Enabled hooks, defined task switch hook

* Added basic test

* Now keeps track of last 8 tasks, ignores tick task

* Added comments, ignore OS-spawned tasks

* Made task trace length configurable
  • Loading branch information
Cam0Cow authored Jul 7, 2023
1 parent 765571b commit 69bb125
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 0 deletions.
22 changes: 22 additions & 0 deletions Apps/Inc/Tasks.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ extern OS_Q CANBus_MsgQ;
*/
extern OS_SEM FaultState_Sem4;

/**
* @brief Initialize the task switch hook
* Registers the hook with the RTOS
*/
void TaskSwHook_Init(void);


/**
* Global Variables
Expand Down Expand Up @@ -152,6 +158,22 @@ typedef enum{
FAULT_BPS = 0x20, // for if BPS trips
} fault_bitmap_t;

/**
* Task trace
*
* Stores the last TASK_TRACE_LENGTH tasks that were run
* The most recent task is at tasks[index], the one before at tasks[index-1],
* wrapping back around at the beginnning
*
*/
#define TASK_TRACE_LENGTH 8
typedef struct {
OS_TCB *tasks[TASK_TRACE_LENGTH];
uint32_t index;
} task_trace_t;

extern task_trace_t PrevTasks;

/**
* Error variables
*/
Expand Down
30 changes: 30 additions & 0 deletions Apps/Src/Tasks.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ OS_TCB Telemetry_TCB;
OS_TCB DebugDump_TCB;
OS_TCB CommandLine_TCB;

task_trace_t PrevTasks;

/**
* Stacks
*/
Expand Down Expand Up @@ -58,4 +60,32 @@ void _assertOSError(uint16_t OS_err_loc, OS_ERR err)
OSSemPost(&FaultState_Sem4, OS_OPT_POST_1, &err);
EnterFaultState();
}
}

/**
* @brief Hook that's called every context switch
*
* This function will append the task being switched out to the task trace if and only if:
* 1. It's not a task created automatically by the RTOS
* 2. It's not the previously recorded task (a long running task interrupted by the
* tick task will only show up once)
* This function will overwrite tasks that have been in the trace for a while, keeping only
* the 8 most recent tasks
*/
void App_OS_TaskSwHook(void) {
OS_TCB *cur = OSTCBCurPtr;
uint32_t idx = PrevTasks.index;
if (cur == &OSTickTaskTCB) return; // Ignore the tick task
if (cur == &OSIdleTaskTCB) return; // Ignore the idle task
if (cur == &OSTmrTaskTCB ) return; // Ignore the timer task
if (cur == &OSStatTaskTCB) return; // Ignore the stat task
if (cur == PrevTasks.tasks[idx]) return; // Don't record the same task again
if (++idx == TASK_TRACE_LENGTH) idx = 0;
PrevTasks.tasks[idx] = cur;
PrevTasks.index = idx;
}

void TaskSwHook_Init(void) {
PrevTasks.index = TASK_TRACE_LENGTH - 1; // List starts out empty
OS_AppTaskSwHookPtr = App_OS_TaskSwHook;
}
1 change: 1 addition & 0 deletions Apps/Src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ int main(void) {

OS_ERR err;
OSInit(&err);
TaskSwHook_Init();
OSSemCreate(&FaultState_Sem4, "Fault State Semaphore", 0, &err);

assertOSError(OS_MAIN_LOC, err);
Expand Down
93 changes: 93 additions & 0 deletions Tests/Test_TaskSwHook.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include "Tasks.h"
#include "os.h"
#include "bsp.h"

static char *getTCBName(OS_TCB *tcb) {
return tcb ? tcb->NamePtr : "No Task";
}

void dumpTrace(void) {
int idx = PrevTasks.index;
printf("Task trace: [");
for (int i=0; i<8; i++) {
if (!PrevTasks.tasks[idx]) break;
printf("%s, ", getTCBName(PrevTasks.tasks[idx]));
idx = (idx + TASK_TRACE_LENGTH - 1) % TASK_TRACE_LENGTH; // decrement idx, wrapping around at 0
}
printf("]\n\r");
}

#define expect(str) printf("Previous expected: %s, previous actual: %s\n\r", (str), getTCBName(PrevTasks.tasks[PrevTasks.index]))

static OS_TCB Task1TCB, Task2TCB;
static CPU_STK Task1Stk[DEFAULT_STACK_SIZE], Task2Stk[DEFAULT_STACK_SIZE];

void Task1(void *p_arg) {
(void) p_arg;
OS_ERR err;

CPU_Init();
OS_CPU_SysTickInit(SystemCoreClock / (CPU_INT32U)OSCfg_TickRate_Hz);
BSP_UART_Init(UART_2);

expect("No Task");
dumpTrace();
OSTimeDlyHMSM(0, 0, 0, 500, OS_OPT_TIME_HMSM_STRICT, &err);
expect("Task 2");
dumpTrace();
OSTimeDlyHMSM(0, 0, 1, 0, OS_OPT_TIME_HMSM_STRICT, &err);
expect("Task 2");
dumpTrace();
while (1);

}

void Task2(void *p_arg) {
(void) p_arg;
OS_ERR err;

expect("Task 1");
dumpTrace();
OSTimeDlyHMSM(0, 0, 0, 600, OS_OPT_TIME_HMSM_STRICT, &err);
expect("Task 1");
dumpTrace();
while (1);
}

int main(void) {
OS_ERR err;
OSInit(&err);
TaskSwHook_Init();

OSTaskCreate(
(OS_TCB *)&Task1TCB,
(CPU_CHAR *)"Task 1",
(OS_TASK_PTR)Task1,
(void *)NULL,
(OS_PRIO)5,
(CPU_STK *)Task1Stk,
(CPU_STK_SIZE)DEFAULT_STACK_SIZE / 10,
(CPU_STK_SIZE)DEFAULT_STACK_SIZE,
(OS_MSG_QTY)0,
(OS_TICK)NULL,
(void *)NULL,
(OS_OPT)(OS_OPT_TASK_STK_CLR),
(OS_ERR *)&err);

OSTaskCreate(
(OS_TCB *)&Task2TCB,
(CPU_CHAR *)"Task 2",
(OS_TASK_PTR)Task2,
(void *)NULL,
(OS_PRIO)6,
(CPU_STK *)Task2Stk,
(CPU_STK_SIZE)DEFAULT_STACK_SIZE / 10,
(CPU_STK_SIZE)DEFAULT_STACK_SIZE,
(OS_MSG_QTY)0,
(OS_TICK)NULL,
(void *)NULL,
(OS_OPT)(OS_OPT_TASK_STK_CLR),
(OS_ERR *)&err);

OSStart(&err);
}

0 comments on commit 69bb125

Please sign in to comment.