From 7422dc33472cd2db9fb7dfca365b834b8864e81c Mon Sep 17 00:00:00 2001 From: Nathan Date: Thu, 13 Aug 2026 20:38:15 -0400 Subject: [PATCH 1/2] cpp --- .gitignore | 3 ++- CMakeLists.txt | 6 +++++- Core/Inc/device-init.h | 21 +++++++++++++++++++++ Core/Src/device-init.cpp | 20 ++++++++++++++++++++ Core/Src/main.c | 4 ++++ 5 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 Core/Inc/device-init.h create mode 100644 Core/Src/device-init.cpp diff --git a/.gitignore b/.gitignore index 3f3b177..27f4697 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ build/ +.vscode .settings -.cproject .project .launch +.cproject .cache \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c6e9023..f067d59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,9 @@ set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS ON) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) # Define the build type if(NOT CMAKE_BUILD_TYPE) @@ -29,7 +32,7 @@ project(${CMAKE_PROJECT_NAME}) message("Build type: " ${CMAKE_BUILD_TYPE}) # Enable CMake support for ASM and C languages -enable_language(C ASM) +enable_language(C CXX ASM) # Create an executable object type add_executable(${CMAKE_PROJECT_NAME}) @@ -46,6 +49,7 @@ target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE # Add sources to executable target_sources(${CMAKE_PROJECT_NAME} PRIVATE # Add user sources here + ./Core/Src/device-init.cpp ) # Add include paths diff --git a/Core/Inc/device-init.h b/Core/Inc/device-init.h new file mode 100644 index 0000000..6c4a141 --- /dev/null +++ b/Core/Inc/device-init.h @@ -0,0 +1,21 @@ +/** + * + */ + +#ifndef DEVICE_INIT_H_ +#define DEVICE_INIT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief device init + */ +void device_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Core/Src/device-init.cpp b/Core/Src/device-init.cpp new file mode 100644 index 0000000..a69c3e0 --- /dev/null +++ b/Core/Src/device-init.cpp @@ -0,0 +1,20 @@ +/** + * + */ + +#include "device-init.h" +#include "main.h" + +class TEST_CLASS +{ +public: + TEST_CLASS() = default; + +private: + bool var; +}; + +void device_init(void) +{ + TEST_CLASS thing; +} diff --git a/Core/Src/main.c b/Core/Src/main.c index 1fabd3f..b2b1b9a 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -28,6 +28,7 @@ #include "bmi088.h" #include "bmp581.h" #include "gd5f1gq5xe.h" +#include "device-init.h" #include "semphr.h" #include "usb_device.h" @@ -276,6 +277,9 @@ int main(void) uint32_t boot_count = flash_boot_count(&flash, false); uint32_t file_size = flash_open(&flash, &packet_file, "packets"); } + + device_init(); + /* USER CODE END 2 */ /* Init scheduler */ From 60fd5471b66e11f035a6d164e4e088266a5a71cc Mon Sep 17 00:00:00 2001 From: wispl Date: Sun, 16 Aug 2026 17:50:37 -0400 Subject: [PATCH 2/2] feat: use cpp Note that this requires the cpp branch of CommonDrivers to be merged --- CMakeLists.txt | 1 + Core/Inc/device-init.h | 5 +- Core/Src/device-init.cpp | 192 +++++++++++++++++++++++++++++++++++--- Core/Src/main.c | 195 ++------------------------------------- Drivers/CommonDrivers | 2 +- 5 files changed, 193 insertions(+), 202 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f067d59..5be603c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE # Add project symbols (macros) target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE # Add user defined symbols + USE_CDC_DEBUG ) # Remove wrong libob.a library dependency when using cpp files diff --git a/Core/Inc/device-init.h b/Core/Inc/device-init.h index 6c4a141..c26bfc4 100644 --- a/Core/Inc/device-init.h +++ b/Core/Inc/device-init.h @@ -9,10 +9,13 @@ extern "C" { #endif +#include "hal.h" + /** * @brief device init */ -void device_init(void); +void device_init(SPI_HandleTypeDef *hspi1, SPI_HandleTypeDef *hspi2, SPI_HandleTypeDef *hspi3, CRC_HandleTypeDef *hcrc); +void device_disable_flash(); #ifdef __cplusplus } diff --git a/Core/Src/device-init.cpp b/Core/Src/device-init.cpp index a69c3e0..e3a1a9a 100644 --- a/Core/Src/device-init.cpp +++ b/Core/Src/device-init.cpp @@ -1,20 +1,188 @@ -/** - * - */ - #include "device-init.h" + #include "main.h" +#include "FreeRTOS.h" +#include "semphr.h" -class TEST_CLASS -{ -public: - TEST_CLASS() = default; +#include "log.h" + +#include "sensor.h" +#include "spi.h" +#include "bmi088.h" +#include "bmp581.h" +#include "gd5f1gq5xe.h" +#include "stm32f411xe.h" +#include "stm32f4xx_hal_crc.h" + +#include +#include + +namespace { + inline uint32_t checksum(CRC_HandleTypeDef &hcrc, const uint8_t *data, size_t length) { + return HAL_CRC_Calculate(&hcrc, (uint32_t *)data, length); + } +} +enum Sensors { BMP581, BMI088, NUM_SENSORS }; +class TEST_CLASS { private: - bool var; + CRC_HandleTypeDef &hcrc; + + // Peripherals + Common::SPI accel; + Common::SPI gyro; + Common::SPI bmp; + Common::SPI flash; + + // Sensors and Flash + Common::GD5F1GQ5XE flash_dev; + Common::BMP581 bmp581_dev; + Common::BMI088 bmi088_dev; + std::array sensors; + + // Runtime State + SemaphoreHandle_t packet_mutex = xSemaphoreCreateMutex(); + Common::Packet packet = Common::Packet(); + volatile bool save_to_flash = false; + lfs_file_t packet_file; + + int32_t fs_size = 0; + uint32_t boot_count = 0; + uint32_t file_size = 0; + + // Task attributes + TaskHandle_t sensor_task_handle = NULL; + TaskHandle_t flash_task_handle = NULL; + // Tasks + static void sensor_task(void *argument) { + auto *self = static_cast(argument); + self->sensor_loop(); + } + + static void flash_task(void *argument) { + auto *self = static_cast(argument); + self->flash_loop(); + } +public: + TEST_CLASS(SPI_HandleTypeDef &hspi1, SPI_HandleTypeDef &hspi2, SPI_HandleTypeDef &hspi3, CRC_HandleTypeDef &hcrc) + : hcrc(hcrc), + accel(&hspi1, IMU2_ACC_CS_GPIO_Port, IMU2_ACC_CS_Pin), + gyro(&hspi1, IMU2_GYRO_CS_GPIO_Port, IMU2_GYRO_CS_Pin), + bmp(&hspi2, BAR1_CS_GPIO_Port, BAR1_CS_Pin), + flash(&hspi3, FLASH_CS_GPIO_Port, FLASH_CS_Pin), + + flash_dev(flash), + bmp581_dev(bmp), + bmi088_dev(accel, gyro), + sensors{&bmp581_dev, &bmi088_dev} + { + // Initialize sensors + for (auto& sensor : sensors) { + bool ready = 0; + for (int c = 0; c < 10; ++c) { + ready = sensor->init(); + if (ready) break; + Delay(20000); + } + if (!ready) sensor = nullptr; + } + + // Initialize flash + for (int c = 0; c < 3; ++c) { + if (flash_dev.init()) { + fs_size = flash_dev.mount(); + if (fs_size >= 0) { + save_to_flash = true; + boot_count = flash_dev.bootcount(false); + file_size = flash_dev.open(&packet_file, "packets"); + } + break; + } + Delay(5000); + } + Common::LOG("Flash: %u (size), %u (boot), %u (packet_size)\r\n", fs_size, boot_count, file_size); + } + + void sensor_loop() { + // Simple counter for task notification + uint32_t counter = 0; + // Run this task 200 times per second + TickType_t last_wake_up = xTaskGetTickCount(); + int hertz = 200; + + for (;;) { + if (xSemaphoreTake(packet_mutex, portMAX_DELAY) == pdTRUE) { + // Read from all sensors + for (auto *sensor : sensors) + if (sensor != nullptr) sensor->read(packet); + + // This is originally for camera, but we will use it for flash for now + packet.status = (flash_task_handle != NULL); + // TODO: change this to microseconds at a later time + packet.time_us = xTaskGetTickCount() * portTICK_PERIOD_MS; + packet.checksum = checksum(hcrc, (const uint8_t *) &packet + sizeof(short), + sizeof(packet) - 6); + HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); + xSemaphoreGive(packet_mutex); + + // Tell flash to save data every other packet + if ((++counter) >= 2 && flash_task_handle != nullptr) { + counter = 0; + if (save_to_flash) xTaskNotifyGive(flash_task_handle); + } + } + // Go to sleep little task... + vTaskDelayUntil(&last_wake_up, configTICK_RATE_HZ / hertz); + } + } + + void flash_loop() { + auto copy = Common::Packet(); + for (;;) { + // Wait until notified + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + // Someone notified us to stop task collection, shut the poor flash down :( + if (!save_to_flash) { + flash_dev.close(&packet_file); + flash_dev.unmount(); + vTaskDelete(NULL); + return; + } + // Make a local copy, so we don't block + if (xSemaphoreTake(packet_mutex, portMAX_DELAY) == pdTRUE) { + copy = packet; + xSemaphoreGive(packet_mutex); + } + + // Save to flash + flash_dev.append(&packet_file, (uint8_t*) ©, sizeof(copy)); + } + } + + void disable_flash() { + if (save_to_flash) { + save_to_flash = false; + vTaskNotifyGiveFromISR(flash_task_handle, NULL); + } + } + + void start_tasks() { + // Idle task has priority of 0 + xTaskCreate(flash_task, "flash task", 512, this, 1, &flash_task_handle); + xTaskCreate(sensor_task, "sensor task", 256, this, 2, &sensor_task_handle); + } }; -void device_init(void) -{ - TEST_CLASS thing; +// TODO: need to discuss how to better do this +static TEST_CLASS* device_ptr = nullptr; +extern "C" { + void device_init(SPI_HandleTypeDef *hspi1, SPI_HandleTypeDef *hspi2, SPI_HandleTypeDef *hspi3, CRC_HandleTypeDef *hcrc) { + static TEST_CLASS device = TEST_CLASS(*hspi1, *hspi2, *hspi3, *hcrc); + device_ptr = &device; + device.start_tasks(); + } + + void device_disable_flash() { + if (device_ptr != nullptr) device_ptr->disable_flash(); + } } diff --git a/Core/Src/main.c b/Core/Src/main.c index b2b1b9a..fb25cbd 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -23,14 +23,10 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ -#include "sensor.h" -#include "flash.h" -#include "bmi088.h" -#include "bmp581.h" -#include "gd5f1gq5xe.h" +/* const int __attribute__((used)) uxTopUsedPriority = configMAX_PRIORITIES - 1; */ #include "device-init.h" +const volatile UBaseType_t uxTopUsedPriority = 15; -#include "semphr.h" #include "usb_device.h" #include "usbd_cdc_if.h" /* USER CODE END Includes */ @@ -63,74 +59,12 @@ TIM_HandleTypeDef htim5; osThreadId_t defaultTaskHandle; const osThreadAttr_t defaultTask_attributes = { .name = "defaultTask", - .stack_size = 128 * 4, + .stack_size = 1024 * 4, .priority = (osPriority_t) osPriorityNormal, }; /* USER CODE BEGIN PV */ /// For openocd, it is an official workaround for the following /// Error: FreeRTOS: uxTopUsedPriority is not defined, consult the OpenOCD manual for a work-around -const int __attribute__((used)) uxTopUsedPriority = configMAX_PRIORITIES - 1; - -/// Sensors -struct bmi088_ctx bmi088 = { - .accel_spi = { - .pin = IMU2_ACC_CS_Pin, - .port = IMU2_ACC_CS_GPIO_Port, - .handle = &hspi1, - }, - .gyro_spi = { - .pin = IMU2_GYRO_CS_Pin, - .port = IMU2_GYRO_CS_GPIO_Port, - .handle = &hspi1, - }, -}; -struct bmp581_ctx bmp581 = { - .handle = { - .protocol = SPI, - .def = { - .spi = { - .pin = BAR1_CS_Pin, - .port = BAR1_CS_GPIO_Port, - .handle = &hspi2, - } - } - } -}; -enum sensors { - BMP581, - BMI088, - NUMBER_SENSORS -}; -struct sensor sensors[NUMBER_SENSORS]; -bool sensors_res[NUMBER_SENSORS]; - -/// Flash -bool save_to_flash = true; -struct flash flash = {0}; -struct handle_spi flash_spi = { - .pin = FLASH_CS_Pin, - .port = FLASH_CS_GPIO_Port, - .handle = &hspi3, -}; - -/// Global Variables -SemaphoreHandle_t packet_mutex = NULL; -lfs_file_t packet_file; -struct packet packet = {0}; - -/// Task handles -osThreadId_t sensor_task_handle = NULL; -const osThreadAttr_t sensor_task_attributes = { - .name = "sensor task", - .stack_size = 128 * 8, - .priority = (osPriority_t) osPriorityHigh, -}; -osThreadId_t flash_task_handle = NULL; -const osThreadAttr_t flash_task_attributes = { - .name = "flash task", - .stack_size = 128 * 8, - .priority = (osPriority_t) osPriorityAboveNormal, -}; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ @@ -145,68 +79,6 @@ static void MX_TIM5_Init(void); void StartDefaultTask(void *argument); /* USER CODE BEGIN PFP */ -static inline uint32_t checksum(const uint8_t *data, size_t length) -{ - return HAL_CRC_Calculate(&hcrc, (uint32_t *)data, length); -} - -static void SensorTask(void *argument) -{ - // Simple counter for task notification - uint32_t counter = 0; - // Run this task 200 times per second - TickType_t last_wake_up = xTaskGetTickCount(); - int hertz = 200; - - for (;;) { - if (xSemaphoreTake(packet_mutex, portMAX_DELAY) == pdTRUE) { - // Read from all sensors - for (int i = 0; i < NUMBER_SENSORS; ++i) { - if (sensors_res[i]) { - sensors[i].read(sensors[i].ctx, &packet); - } - } - - // This is originally for camera, but we will use it for flash for now - packet.status = (flash_task_handle != NULL); - // TODO: change this to microseconds at a later time - packet.time_us = xTaskGetTickCount() * portTICK_PERIOD_MS; - packet.checksum = checksum((const uint8_t *) &packet + sizeof(short), - sizeof(packet) - 6); - HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); - xSemaphoreGive(packet_mutex); - - // Tell flash to save data every other packet - if ((++counter) >= 2 && flash_task_handle != NULL) { - counter = 0; - xTaskNotifyGive(flash_task_handle); - } - } - // Go to sleep little task... - vTaskDelayUntil(&last_wake_up, configTICK_RATE_HZ / hertz); - } -} - -static void FlashTask(void *argument) -{ - struct packet copy = {0}; - - for (;;) { - // Wait until notified - ulTaskNotifyTake(pdTRUE, portMAX_DELAY); - - // Make a local copy, so we don't block - if (xSemaphoreTake(packet_mutex, portMAX_DELAY) == pdTRUE) { - memcpy(©, &packet, sizeof(packet)); - xSemaphoreGive(packet_mutex); - } - - // Save to flash - if (save_to_flash) { - flash_append(&flash, &packet_file, (uint8_t*) ©, sizeof(copy)); - } - } -} /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ @@ -222,7 +94,8 @@ int main(void) { /* USER CODE BEGIN 1 */ - + // Prevents compiler from stripping this out + (void)uxTopUsedPriority; /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ @@ -249,37 +122,6 @@ int main(void) MX_TIM1_Init(); MX_TIM5_Init(); /* USER CODE BEGIN 2 */ - packet.magic = 0xBEEF; - int init_count = 0; - int ready_sensors = 0; - while (init_count < 9 && ready_sensors != NUMBER_SENSORS) { - if (!sensors_res[BMP581]) { - int8_t bmp581_res = bmp581_init(&bmp581, &sensors[BMP581]); - sensors_res[BMP581] = (bmp581_res == BMP5_OK); - if (sensors_res[BMP581]) { - ++ready_sensors; - } - } - if (!sensors_res[BMI088]) { - int8_t bmi088_res = bmi088_init(&bmi088, &sensors[BMI088]); - sensors_res[BMI088] = (bmi088_res == BMI08_OK); - if (sensors_res[BMI088]) { - ++ready_sensors; - } - } - HAL_Delay(20000); - ++init_count; - } - bool flash_enabled = gd5f1gq5xe_init(&flash, &flash_spi); - int32_t fs_size = flash_mount(&flash); - if (fs_size < 0) flash_enabled = false; - if (flash_enabled) { - uint32_t boot_count = flash_boot_count(&flash, false); - uint32_t file_size = flash_open(&flash, &packet_file, "packets"); - } - - device_init(); - /* USER CODE END 2 */ /* Init scheduler */ @@ -287,7 +129,6 @@ int main(void) /* USER CODE BEGIN RTOS_MUTEX */ /* add mutexes, ... */ - packet_mutex = xSemaphoreCreateMutex(); /* USER CODE END RTOS_MUTEX */ /* USER CODE BEGIN RTOS_SEMAPHORES */ @@ -305,13 +146,8 @@ int main(void) /* Create the thread(s) */ /* creation of defaultTask */ defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes); - /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ - sensor_task_handle = osThreadNew(SensorTask, NULL, &sensor_task_attributes); - if (flash_enabled) { - flash_task_handle = osThreadNew(FlashTask, NULL, &flash_task_attributes); - } /* USER CODE END RTOS_THREADS */ /* USER CODE BEGIN RTOS_EVENTS */ @@ -322,22 +158,6 @@ int main(void) osKernelStart(); /* We should never get here as control is now taken by the scheduler */ - - /* Infinite loop */ - /* USER CODE BEGIN WHILE */ - /* while (1) */ - /* { */ - /* USER CODE END WHILE */ - - /* USER CODE BEGIN 3 */ - /* HAL_GPIO_WritePin(GPIOB, PYRO3_Pin, GPIO_PIN_SET); */ - /* } */ - - /* flash_init(&flash, GD5F1GQ5XE); */ - /* flash_mount(&flash, &flash_cfg); */ - /* uint32_t boot_count = flash_boot_count(&flash, false); */ - /* flash_unmount(&flash); */ - /* USER CODE END 3 */ } /** @@ -758,6 +578,7 @@ void StartDefaultTask(void *argument) /* init code for USB_DEVICE */ MX_USB_DEVICE_Init(); /* USER CODE BEGIN 5 */ + device_init(&hspi1, &hspi2, &hspi3, &hcrc); /* Infinite loop */ for(;;) { @@ -786,9 +607,7 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) /* USER CODE BEGIN Callback 1 */ if (htim->Instance == TIM5) { - save_to_flash = false; - flash_close(&flash, &packet_file); - flash_unmount(&flash); + device_disable_flash(); } /* USER CODE END Callback 1 */ } diff --git a/Drivers/CommonDrivers b/Drivers/CommonDrivers index 6426af3..a334c95 160000 --- a/Drivers/CommonDrivers +++ b/Drivers/CommonDrivers @@ -1 +1 @@ -Subproject commit 6426af36cab9ff8dc5888332dd8abb25da051b3b +Subproject commit a334c956057c77d1af110d35b77f3e26c1baca7e