Update: Dec 19, 2025
Author: Mann Patel
Note: Documentation reflects the Osiris Payload
The Osiris Payload System is an embedded flight computer designed for rocket payloads. It runs on an STM32H7 microcontroller using FreeRTOS and manages sensor data collection, state transitions, and hardware control throughout a rocket's flight.
The system follows a task-based architecture using FreeRTOS, where different subsystems run as independent tasks that communicate via command queues. A state machine manages the flight phases and controls hardware accordingly.
Sensors are named after Nintendo characters (God knows why?) :(
The system uses multiple FreeRTOS tasks that run concurrently:
| Task | Priority | Purpose |
|---|---|---|
| FlightTask | 2 | Main flight logic and state machine coordination |
| IMUTask | 2 | Reads IMU (Inertial Measurement Unit) data |
| BaroTask | 2 | Reads barometer/pressure sensor data |
| DebugTask | 2 | Handles debug output via UART |
| CubeTask | 2 | Framework task (Cube++ RTOS wrapper) |
The flight computer transitions through 5 states during operation:
PRELAUNCH -> LAUNCH -> DROGUE -> MAIN -> POSTLAUNCH
Each state controls different hardware peripherals and responds to different commands.
The system controls various hardware via GPIO pins:
Tasks communicate using a Command object with:
typedef struct BarometerData {
float marioPressure; // LPS22HH U3
float marioTemperature;
float luigiPressure; // LPS22HH U4
float luigiTemperature;
uint32_t bowserPressure; // MS5611
uint32_t bowserTemperature;
} BarometerData;
typedef struct IMUData {
float xAccel;
float yAccel;
float zAccel;
} IMUData;
IMU_REQUEST_LIN_ACC: Request linear accelerationIMU_REQUEST_ANG_ACC: Request angular accelerationIMUData to FlightTaskBARO_REQUEST_NEW_SAMPLE: Read all sensorsBARO_REQUEST_DEBUG: Print sensor valuesBARO_REQUEST_FLASH_LOG: Log data to flash memoryBarometerData to FlightTaskDriver::uart6)From any state, you can return to PRELAUNCH using:
OSC_ANY_TO_PRELAUNCH
Driver::uart6)The system boots through main_system.cpp:
void run_main() {
// 1. Initialize all tasks
CubeTask::Inst().InitTask();
DebugTask::Inst().InitTask();
FlightTask::Inst().InitTask();
IMUTask::Inst().InitTask();
BaroTask::Inst().InitTask();
// 2. Print boot info
SOAR_PRINT("\n-- SOAR SYSTEM --\n");
// 3. Test sensors (example)
Command testIMU(REQUEST_COMMAND, IMU_REQUEST_LIN_ACC);
IMUTask::Inst().GetEventQueue()->Send(testIMU);
// 4. Start FreeRTOS scheduler
osKernelStart();
}
Task priorities and stack sizes are defined in SystemDefines.hpp:
// All tasks currently have priority 2
constexpr uint8_t FLIGHT_TASK_RTOS_PRIORITY = 2;
constexpr uint8_t IMU_TASK_RTOS_PRIORITY = 2;
constexpr uint8_t BARO_TASK_RTOS_PRIORITY = 2;
// Stack sizes (in words)
constexpr uint16_t FLIGHT_TASK_STACK_DEPTH_WORDS = 512;
constexpr uint16_t IMU_TASK_STACK_DEPTH_WORDS = 512;
constexpr uint16_t BARO_TASK_STACK_DEPTH_WORDS = 512;
// Create a command to request linear acceleration
Command cmd(REQUEST_COMMAND, IMU_REQUEST_LIN_ACC);
// Send to IMU task
IMUTask::Inst().GetEventQueue()->Send(cmd);
// IMUTask will respond by sending IMUData to FlightTask
// Open solenoid valve 1
Command cmd(CONTROL_ACTION, OSC_OPEN_SOL1);
FlightTask::Inst().GetEventQueue()->Send(cmd);
// Close solenoid valve 1
Command cmd2(CONTROL_ACTION, OSC_CLOSE_SOL1);
FlightTask::Inst().GetEventQueue()->Send(cmd2);
// Request new barometer sample
Command cmd(REQUEST_COMMAND, BARO_REQUEST_NEW_SAMPLE);
BaroTask::Inst().GetEventQueue()->Send(cmd);
// Request debug output of barometer values
Command cmd2(REQUEST_COMMAND, BARO_REQUEST_DEBUG);
BaroTask::Inst().GetEventQueue()->Send(cmd2);
Each task uses Task::Inst() to access a single instance:
FlightTask::Inst().GetEventQueue()->Send(command);
All inter-task communication uses Command objects with specific command types
Flight logic organized into distinct states with entry/exit handlers
GPIO operations wrapped in namespace functions:
GPIO::LED_GREEN::On();
GPIO::SOL1::Off();