/** * @file task.c * @brief Task management implementation */ #include "kernel.h" #include "task.h" #include "scheduler.h" #include "isr.h" /* Task List Head */ static TaskHandle_t task_list_head = NULL; static TaskHandle_t task_list_tail = NULL; static uint32_t next_task_id = 0; static TaskHandle_t current_task = NULL; /* Stack Overflow Pattern */ #define STACK_FILL_PATTERN 0xA5A5A5A5 #define STACK_CHECK_PATTERN 0xDEADBEEF /* Initialize Task Management */ void task_init(void) { task_list_head = NULL; task_list_tail = NULL; next_task_id = 1; current_task = NULL; } /* Create Task */ TaskHandle_t task_create(const TaskConfig_t* config) { if (config == NULL || config->function == NULL) { return NULL; } if (config->priority >= MAX_PRIORITY_LEVELS) { return NULL; } /* Allocate task control block */ TaskHandle_t task = (TaskHandle_t)malloc(sizeof(struct TaskControlBlock)); if (task == NULL) { return NULL; } /* Initialize task control block */ memset(task, 0, sizeof(struct TaskControlBlock)); /* Set task name */ if (config->name != NULL) { strncpy(task->name, config->name, MAX_TASK_NAME_LENGTH - 1); } else { snprintf(task->name, MAX_TASK_NAME_LENGTH, "task_%u", next_task_id); } /* Initialize task fields */ task->task_id = next_task_id++; task->function = config->function; task->parameters = config->parameters; task->priority = config->priority; task->state = TASK_SUSPENDED; task->period_ticks = config->period_ticks; task->last_wake_time = 0; /* Allocate stack */ task->stack_size = config->stack_size; task->stack_base = (uint32_t*)malloc(task->stack_size); if (task->stack_base == NULL) { free(task); return NULL; } /* Initialize stack with pattern for overflow detection */ memset(task->stack_base, STACK_FILL_PATTERN, task->stack_size); /* Set initial stack pointer (grows downward on ARM) */ task->stack_pointer = task->stack_base + (task->stack_size / sizeof(uint32_t)) - 16; /* Initialize task context for first run */ task->context[0] = (uint32_t)task->function; /* PC */ task->context[1] = 0x01000000; /* xPSR */ task->context[2] = (uint32_t)task->parameters; /* R0 */ task->context[3] = 0; /* R1 */ task->context[4] = 0; /* R2 */ task->context[5] = 0; /* R3 */ task->context[6] = 0; /* R12 */ task->context[7] = 0; /* LR */ task->context[8] = (uint32_t)task->stack_pointer; /* PSP */ /* Add to task list */ critical_section_enter(); if (task_list_head == NULL) { task_list_head = task; task_list_tail = task; } else { task_list_tail->next = task; task->prev = task_list_tail; task_list_tail = task; } /* Make task ready */ task->state = TASK_READY; scheduler_add_task(task); critical_section_exit(); return task; } /* Delete Task */ KernelStatus_t task_delete(TaskHandle_t task) { if (task == NULL || task == current_task) { return KERNEL_INVALID_PARAMETER; } critical_section_enter(); /* Remove from scheduler */ scheduler_remove_task(task); /* Remove from task list */ if (task->prev != NULL) { task->prev->next = task->next; } else { task_list_head = task->next; } if (task->next != NULL) { task->next->prev = task->prev; } else { task_list_tail = task->prev; } /* Free stack and task control block */ free(task->stack_base); free(task); critical_section_exit(); return KERNEL_OK; } /* Suspend Task */ KernelStatus_t task_suspend(TaskHandle_t task) { if (task == NULL) { return KERNEL_INVALID_PARAMETER; } critical_section_enter(); if (task->state != TASK_SUSPENDED) { task->state = TASK_SUSPENDED; scheduler_update_task_state(task, TASK_SUSPENDED); } critical_section_exit(); if (task == current_task) { scheduler_yield(); } return KERNEL_OK; } /* Resume Task */ KernelStatus_t task_resume(TaskHandle_t task) { if (task == NULL) { return KERNEL_INVALID_PARAMETER; } critical_section_enter(); if (task->state == TASK_SUSPENDED) { task->state = TASK_READY; scheduler_update_task_state(task, TASK_READY); } critical_section_exit(); return KERNEL_OK; } /* Set Task Priority */ KernelStatus_t task_set_priority(TaskHandle_t task, TaskPriority_t new_priority) { if (task == NULL || new_priority >= MAX_PRIORITY_LEVELS) { return KERNEL_INVALID_PARAMETER; } critical_section_enter(); task->priority = new_priority; critical_section_exit(); /* Reschedule if needed */ scheduler_yield(); return KERNEL_OK; } /* Get Task Priority */ TaskPriority_t task_get_priority(TaskHandle_t task) { if (task == NULL) { return MAX_PRIORITY_LEVELS; } return task->priority; } /* Get Task State */ TaskState_t task_get_state(TaskHandle_t task) { if (task == NULL) { return TASK_TERMINATED; } return task->state; } /* Get Task Statistics */ KernelStatus_t task_get_statistics(TaskHandle_t task, TaskStatistics_t* stats) { if (task == NULL || stats == NULL) { return KERNEL_INVALID_PARAMETER; } critical_section_enter(); memcpy(stats, &task->statistics, sizeof(TaskStatistics_t)); /* Update stack high water mark */ task_check_stack_overflow(); stats->stack_high_water_mark = task->stack_high_water_mark; critical_section_exit(); return KERNEL_OK; } /* Switch Context to Next Task */ void task_switch_context(TaskHandle_t next_task) { if (next_task == NULL || next_task == current_task) { return; } TaskHandle_t previous_task = current_task; current_task = next_task; /* Update task states */ if (previous_task != NULL && previous_task->state == TASK_RUNNING) { previous_task->state = TASK_READY; } next_task->state = TASK_RUNNING; /* Perform architecture-specific context switch */ // This is implemented in port_asm.s port_context_switch(&previous_task->context, &next_task->context); } /* Get Idle Task */ TaskHandle_t task_get_idle_task(void) { /* Return the idle task (stored in kernel state) */ extern TaskHandle_t kernel_get_idle_task(void); return kernel_get_idle_task(); } /* Update Task Statistics */ void task_update_statistics(void) { if (current_task == NULL) { return; } TickType_t current_time = kernel_get_tick_count(); current_task->statistics.execution_count++; current_task->statistics.last_execution_time = current_time; /* Check for deadline miss */ if (current_task->deadline_ticks > 0 && current_time > current_task->deadline_ticks) { current_task->statistics.deadline_misses++; } } /* Check Stack Overflow */ void task_check_stack_overflow(void) { if (current_task == NULL || current_task->stack_base == NULL) { return; } /* Check stack guard pattern */ uint32_t* stack_bottom = current_task->stack_base; uint32_t guard_size = 16; /* Number of guard words */ for (uint32_t i = 0; i < guard_size; i++) { if (stack_bottom[i] != STACK_FILL_PATTERN) { /* Stack overflow detected! */ fault_handler_stack_overflow(current_task); break; } } /* Calculate stack usage */ uint32_t* stack_ptr = current_task->stack_base; uint32_t* stack_top = current_task->stack_base + (current_task->stack_size / sizeof(uint32_t)); uint32_t used_words = 0; while (stack_ptr < stack_top && *stack_ptr != STACK_FILL_PATTERN) { used_words++; stack_ptr++; } current_task->stack_high_water_mark = used_words * sizeof(uint32_t); } /* Check if Task is Ready */ bool task_is_ready(TaskHandle_t task) { return (task != NULL && task->state == TASK_READY); }