diff --git a/src/Makefile b/src/Makefile index 47baab4a..8147fd3c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -61,6 +61,9 @@ export OBJS := \ \ ../src/tasks/task_list.o \ \ +../src/tasks/adcs/adcs_main.o \ +../src/tasks/adcs/adcs_task.o \ + \ ../src/tasks/photodiode/photodiode_main.o \ ../src/tasks/photodiode/photodiode_task.o \ ../src/tasks/photodiode/photodiode_driver.o \ @@ -84,6 +87,7 @@ export EXTRA_VPATH := \ ../../src/tasks/display/image_buffers \ ../../src/tasks/task_manager \ ../../src/tasks/command_dispatcher \ +../../src/tasks/adcs \ ../../src/tasks/magnetometer \ ../../src/tasks/shell \ ../../src/tasks/photodiode \ diff --git a/src/tasks/adcs/adcs_main.c b/src/tasks/adcs/adcs_main.c new file mode 100644 index 00000000..27dbbd16 --- /dev/null +++ b/src/tasks/adcs/adcs_main.c @@ -0,0 +1,52 @@ +/** + * adcs_main.c + * + * Main loop of the satellite's ADCS (Attitude Determination and Control System) RTOS task + * + * Created: Nov 23, 2025 + * Authors: Yi Lyo + **/ + +#include "adcs_task.h" + +// ADCS Task memory structures +adcs_task_memory_t adcs_mem; + +/** + * \fn main_adcs + * + * \param pvParameters a void pointer to the parameters required by the + * ADCS task; not currently set by config + * + * \warning should never return + */ +void main_adcs(void *pvParameters) { + info("adcs: Task Started!\n"); + + // Obtain a pointer to the current task within the global task list + pvdx_task_t *const current_task = get_current_task(); + // Cache the watchdog checkin command to avoid creating it every iteration + command_t cmd_checkin = get_watchdog_checkin_command(current_task); + // Calculate the maximum time the command dispatcher should block (and thus be unable to check in with the watchdog) + const TickType_t queue_block_time_ticks = get_command_queue_block_time_ticks(current_task); + // Variable to hold commands popped off the queue + command_t cmd; + + while (true) { + debug_impl("\n---------- ADCS Task Loop ----------\n"); + + // Execute all commands contained in the queue + if (xQueueReceive(p_adcs_task->command_queue, &cmd, queue_block_time_ticks) == pdPASS) { + do { + debug("adcs: Command popped off queue. Target: %s, Operation: %d\n", cmd.target->name, cmd.operation); + exec_command_adcs(&cmd); + } while (xQueueReceive(p_adcs_task->command_queue, &cmd, 0) == pdPASS); + } + debug("adcs: No more commands queued.\n"); + + if (should_checkin(current_task)) { + enqueue_command(&cmd_checkin); + debug("adcs: Enqueued watchdog checkin command\n"); + } + } +} diff --git a/src/tasks/adcs/adcs_task.c b/src/tasks/adcs/adcs_task.c new file mode 100644 index 00000000..392e26cf --- /dev/null +++ b/src/tasks/adcs/adcs_task.c @@ -0,0 +1,60 @@ +/** + * adcs_task.c + * + * RTOS task for Attitude Determination and Control System (ADCS) + * + * Created: Nov 23, 2025 + * Authors: Yi Lyo + */ + +#include "adcs_task.h" + +extern adcs_task_memory_t adcs_mem; + +/* ---------- DISPATCHABLE FUNCTIONS (sent as commands through the command dispatcher task) ---------- */ + +// TODO: Add ADCS-specific dispatchable functions here + +/* ---------- NON-DISPATCHABLE FUNCTIONS (do not go through the command dispatcher) ---------- */ + +/** + * \fn exec_command_adcs + * + * \brief Executes a command received by the ADCS task + * + * \param p_cmd Pointer to the received command + */ +void exec_command_adcs(command_t *const p_cmd) { + if (p_cmd->target != p_adcs_task) { + fatal("adcs: command target is not ADCS! target: %s operation: %d\n", p_cmd->target->name, p_cmd->operation); + } + + switch (p_cmd->operation) { + // TODO: Add ADCS-specific operations here + default: + fatal("adcs: Invalid operation! target: %s operation: %d\n", p_cmd->target->name, p_cmd->operation); + break; + } +} + +/** + * \fn init_adcs + * + * \brief Initializes the ADCS task, including hardware setup and command queue creation + * + * \return Handle to the ADCS task's command queue + */ +QueueHandle_t init_adcs(void) { + // TODO: Add hardware initialization here + // fatal_on_error(init_adcs_hardware(), "adcs: Hardware initialization failed!"); + + // Initialize the ADCS command queue + QueueHandle_t adcs_command_queue_handle = + xQueueCreateStatic(COMMAND_QUEUE_MAX_COMMANDS, COMMAND_QUEUE_ITEM_SIZE, adcs_mem.adcs_command_queue_buffer, + &adcs_mem.adcs_task_queue); + if (adcs_command_queue_handle == NULL) { + fatal("Failed to create ADCS queue!\n"); + } + + return adcs_command_queue_handle; +} diff --git a/src/tasks/adcs/adcs_task.h b/src/tasks/adcs/adcs_task.h new file mode 100644 index 00000000..aced5438 --- /dev/null +++ b/src/tasks/adcs/adcs_task.h @@ -0,0 +1,33 @@ +#ifndef ADCS_TASK_H +#define ADCS_TASK_H + +#include +#include +#include "globals.h" +#include "logging.h" +#include "rtos_start.h" +#include "stdbool.h" +#include "string.h" +#include "watchdog_task.h" + +// FreeRTOS Task structs +// Memory for the ADCS task +#define ADCS_TASK_STACK_SIZE 1024 // Size of the stack in words (multiply by 4 to get bytes) + +// Placed in a struct to ensure that the TCB is placed higher than the stack in memory +// ^ This ensures that stack overflows do not corrupt the TCB (since the stack grows downwards) +typedef struct { + StackType_t overflow_buffer[TASK_STACK_OVERFLOW_PADDING]; + StackType_t adcs_task_stack[ADCS_TASK_STACK_SIZE]; + uint8_t adcs_command_queue_buffer[COMMAND_QUEUE_MAX_COMMANDS * COMMAND_QUEUE_ITEM_SIZE]; + StaticQueue_t adcs_task_queue; + StaticTask_t adcs_task_tcb; +} adcs_task_memory_t; + +extern adcs_task_memory_t adcs_mem; + +QueueHandle_t init_adcs(void); +void exec_command_adcs(command_t *const p_cmd); +void main_adcs(void *pvParameters); + +#endif // ADCS_TASK_H diff --git a/src/tasks/task_list.c b/src/tasks/task_list.c index 998625d9..d0ea20e6 100644 --- a/src/tasks/task_list.c +++ b/src/tasks/task_list.c @@ -65,6 +65,24 @@ pvdx_task_t task_manager_task = { .task_type = OS }; +pvdx_task_t adcs_task = { + .name = "ADCS", + .enabled = false, + .handle = NULL, + .command_queue = NULL, + .init = init_adcs, + .function = main_adcs, + .stack_size = ADCS_TASK_STACK_SIZE, + .stack_buffer = adcs_mem.adcs_task_stack, + .pvParameters = NULL, + .priority = 2, + .task_tcb = &adcs_mem.adcs_task_tcb, + .watchdog_timeout_ms = 10000, + .last_checkin_time_ticks = 0xDEADBEEF, + .has_registered = false, + .task_type = ACTUATOR +}; + pvdx_task_t magnetometer_task = { .name = "Magnetometer", .enabled = false, @@ -159,6 +177,7 @@ pvdx_task_t heartbeat_task = { pvdx_task_t *const p_watchdog_task = &watchdog_task; pvdx_task_t *const p_command_dispatcher_task = &command_dispatcher_task; pvdx_task_t *const p_task_manager_task = &task_manager_task; +pvdx_task_t *const p_adcs_task = &adcs_task; pvdx_task_t *const p_magnetometer_task = &magnetometer_task; pvdx_task_t *const p_photodiode_task = &photodiode_task; pvdx_task_t *const p_shell_task = &shell_task; @@ -176,6 +195,7 @@ pvdx_task_t *task_list[] = { p_watchdog_task, p_command_dispatcher_task, p_task_manager_task, + p_adcs_task, p_magnetometer_task, p_photodiode_task, p_shell_task, diff --git a/src/tasks/task_list.h b/src/tasks/task_list.h index 3d17c470..e49c5684 100644 --- a/src/tasks/task_list.h +++ b/src/tasks/task_list.h @@ -2,6 +2,7 @@ #define TASK_LIST_H // Includes +#include "adcs_task.h" #include "command_dispatcher_task.h" #include "display_task.h" #include "globals.h" @@ -16,6 +17,7 @@ extern pvdx_task_t *const p_watchdog_task; extern pvdx_task_t *const p_command_dispatcher_task; extern pvdx_task_t *const p_task_manager_task; +extern pvdx_task_t *const p_adcs_task; extern pvdx_task_t *const p_magnetometer_task; extern pvdx_task_t *const p_photodiode_task; extern pvdx_task_t *const p_shell_task;