From 9f458268866e4aa7a00ce75c8a4a44ed4a678ba3 Mon Sep 17 00:00:00 2001 From: Edwin <20777515+Lucien950@users.noreply.github.com> Date: Sat, 18 Jan 2025 23:34:43 -0800 Subject: [PATCH] New Code Style (#1415) ### Changelist ### Testing Done ### Resolved Tickets --- firmware/boot/bootloader.c | 83 ++-- firmware/cmake/bootlib.cmake | 8 +- firmware/cmake/shared.cmake | 11 +- firmware/dev/h7dev/CMakeLists.txt | 6 +- firmware/dev/h7dev/boot/cubemx/Src/main.c | 6 +- firmware/dev/h7dev/src/cubemx/Src/main.c | 66 +-- firmware/quadruna/BMS/CMakeLists.txt | 4 +- firmware/quadruna/BMS/boot/cubemx/Src/main.c | 31 +- firmware/quadruna/BMS/src/app/app_globals.c | 4 +- firmware/quadruna/BMS/src/app/app_globals.h | 14 +- .../BMS/src/app/states/app_allStates.c | 12 +- .../BMS/src/app/states/app_faultState.c | 2 +- .../BMS/src/app/states/app_initState.c | 2 +- .../quadruna/BMS/src/hw/hw_chimeraConfig.c | 37 ++ firmware/quadruna/BMS/src/hw/hw_gpios.c | 28 ++ firmware/quadruna/BMS/src/hw/hw_gpios.h | 28 ++ firmware/quadruna/BMS/src/hw/hw_sds.c | 5 + firmware/quadruna/BMS/src/hw/hw_uarts.c | 4 + firmware/quadruna/BMS/src/hw/hw_uarts.h | 4 + firmware/quadruna/BMS/src/io/io_airs.c | 24 +- firmware/quadruna/BMS/src/io/io_airs.h | 21 - firmware/quadruna/BMS/src/io/io_bmsShdn.c | 12 +- firmware/quadruna/BMS/src/io/io_bmsShdn.h | 15 - firmware/quadruna/BMS/src/io/io_bspdTest.c | 14 +- firmware/quadruna/BMS/src/io/io_bspdTest.h | 16 - .../quadruna/BMS/src/io/io_canQueueConfig.c | 27 ++ firmware/quadruna/BMS/src/io/io_cans.c | 4 + firmware/quadruna/BMS/src/io/io_cans.h | 4 + firmware/quadruna/BMS/src/io/io_faultLatch.c | 24 +- firmware/quadruna/BMS/src/io/io_faultLatch.h | 22 +- firmware/quadruna/BMS/src/io/io_sd.h | 2 +- firmware/quadruna/BMS/src/io/io_thermistors.c | 22 +- firmware/quadruna/BMS/src/io/io_thermistors.h | 24 -- .../quadruna/BMS/src/io/io_tractiveSystem.h | 3 +- firmware/quadruna/BMS/src/jobs.c | 61 +++ firmware/quadruna/BMS/src/jobs.h | 19 + firmware/quadruna/BMS/src/tasks.c | 234 +---------- .../BMS/test/test_bmsBaseStateMachineTest.h | 23 +- firmware/quadruna/CRIT/CMakeLists.txt | 2 +- firmware/quadruna/CRIT/boot/cubemx/Src/main.c | 32 +- firmware/quadruna/CRIT/src/hw/hw_gpios.c | 51 +++ firmware/quadruna/CRIT/src/hw/hw_gpios.h | 51 +++ firmware/quadruna/CRIT/src/io/io_critShdn.c | 4 +- firmware/quadruna/CRIT/src/io/io_critShdn.h | 6 +- firmware/quadruna/CRIT/src/io/io_driveMode.h | 3 +- firmware/quadruna/CRIT/src/tasks.c | 125 ++---- firmware/quadruna/FSM/CMakeLists.txt | 2 +- firmware/quadruna/FSM/boot/cubemx/Src/main.c | 32 +- firmware/quadruna/FSM/src/app/app_brake.c | 1 + firmware/quadruna/FSM/src/hw/hw_gpios.c | 9 + firmware/quadruna/FSM/src/hw/hw_gpios.h | 9 + firmware/quadruna/FSM/src/hw/hw_uarts.c | 4 + firmware/quadruna/FSM/src/hw/hw_uarts.h | 4 + firmware/quadruna/FSM/src/io/io_apps.h | 2 +- firmware/quadruna/FSM/src/io/io_brake.h | 2 +- .../quadruna/FSM/src/io/io_chimeraConfig.c | 26 ++ firmware/quadruna/FSM/src/io/io_fsmShdn.c | 10 +- firmware/quadruna/FSM/src/io/io_fsmShdn.h | 14 - firmware/quadruna/FSM/src/io/io_loadCell.h | 2 +- firmware/quadruna/FSM/src/io/io_steering.h | 2 +- firmware/quadruna/FSM/src/io/io_suspension.h | 2 +- firmware/quadruna/FSM/src/tasks.c | 83 +--- firmware/quadruna/RSM/CMakeLists.txt | 2 +- firmware/quadruna/RSM/boot/cubemx/Src/main.c | 32 +- firmware/quadruna/RSM/src/tasks.c | 58 ++- firmware/quadruna/VC/CMakeLists.txt | 8 +- firmware/quadruna/VC/boot/cubemx/Src/main.c | 35 +- firmware/quadruna/VC/src/app/app_faultCheck.c | 1 - .../VC/src/app/states/app_allStates.c | 2 +- .../VC/src/app/states/app_driveState.c | 1 + firmware/quadruna/VC/src/cubemx/Inc/main.h | 11 +- firmware/quadruna/VC/src/cubemx/Src/main.c | 7 +- firmware/quadruna/VC/src/hw/hw_adcs.c | 4 +- .../quadruna/VC/src/hw/hw_chimeraConfig.c | 48 +++ firmware/quadruna/VC/src/hw/hw_gpios.c | 32 ++ firmware/quadruna/VC/src/hw/hw_gpios.h | 32 ++ firmware/quadruna/VC/src/hw/hw_sds.c | 5 + firmware/quadruna/VC/src/hw/hw_uarts.c | 7 + firmware/quadruna/VC/src/hw/hw_uarts.h | 8 + .../quadruna/VC/src/io/io_canQueueConfig.c | 24 ++ firmware/quadruna/VC/src/io/io_cans.c | 4 + firmware/quadruna/VC/src/io/io_cans.h | 4 + .../quadruna/VC/src/io/io_currentSensing.c | 19 +- .../quadruna/VC/src/io/io_currentSensing.h | 22 - firmware/quadruna/VC/src/io/io_efuse.c | 64 ++- firmware/quadruna/VC/src/io/io_efuse.h | 23 -- firmware/quadruna/VC/src/io/io_imu.c | 5 +- firmware/quadruna/VC/src/io/io_leds.c | 4 + firmware/quadruna/VC/src/io/io_leds.h | 5 + .../quadruna/VC/src/io/io_lowVoltageBattery.c | 22 +- .../quadruna/VC/src/io/io_lowVoltageBattery.h | 26 -- firmware/quadruna/VC/src/io/io_pcm.c | 12 +- firmware/quadruna/VC/src/io/io_pcm.h | 15 +- firmware/quadruna/VC/src/io/io_sbgEllipse.c | 13 +- firmware/quadruna/VC/src/io/io_sbgEllipse.h | 12 +- firmware/quadruna/VC/src/io/io_telemMessage.c | 54 ++- firmware/quadruna/VC/src/io/io_telemMessage.h | 21 +- firmware/quadruna/VC/src/io/io_vcShdn.c | 16 +- firmware/quadruna/VC/src/io/io_vcShdn.h | 22 +- firmware/quadruna/VC/src/jobs.c | 130 ++++++ firmware/quadruna/VC/src/jobs.h | 19 + firmware/quadruna/VC/src/tasks.c | 390 +++--------------- firmware/quintuna/CRIT/boot/cubemx/Src/main.c | 32 +- firmware/quintuna/RSM/CMakeLists.txt | 31 +- firmware/shared/src/hw/hw_can.c | 142 ------- firmware/shared/src/hw/hw_can.h | 59 --- firmware/shared/src/hw/hw_fdcan.c | 115 ------ firmware/shared/src/hw/hw_sd.c | 117 ++---- firmware/shared/src/hw/hw_sd.h | 22 +- firmware/shared/src/io/io_can.c | 185 +++++---- firmware/shared/src/io/io_can.h | 86 ++-- .../{io_canLogging.c => io_canLoggingQueue.c} | 109 ++--- .../{io_canLogging.h => io_canLoggingQueue.h} | 20 +- firmware/shared/src/io/io_canMsg.h | 13 + firmware/shared/src/io/io_canQueue.c | 97 +++++ firmware/shared/src/io/io_canQueue.h | 60 +++ firmware/shared/src/io/io_chimera.c | 43 +- firmware/shared/src/io/io_chimera.h | 5 +- firmware/shared/src/io/io_fdcan.c | 85 ++++ firmware/shared/src/io/io_fileSystem.h | 51 ++- firmware/shared/src/io/io_fileSystem_logfs.c | 107 ++--- firmware/shared/src/io/io_jsoncan.c | 27 +- firmware/shared/src/io/io_jsoncan.h | 26 +- firmware/shared/src/io/io_led.c | 4 +- firmware/shared/src/io/io_led.h | 6 +- firmware/shared/src/io/io_switch.h | 2 +- scripts/code_generation/jsoncan/jsoncan.cmake | 12 - 127 files changed, 1948 insertions(+), 2131 deletions(-) create mode 100644 firmware/quadruna/BMS/src/hw/hw_chimeraConfig.c create mode 100644 firmware/quadruna/BMS/src/hw/hw_gpios.c create mode 100644 firmware/quadruna/BMS/src/hw/hw_gpios.h create mode 100644 firmware/quadruna/BMS/src/hw/hw_sds.c create mode 100644 firmware/quadruna/BMS/src/hw/hw_uarts.c create mode 100644 firmware/quadruna/BMS/src/hw/hw_uarts.h create mode 100644 firmware/quadruna/BMS/src/io/io_canQueueConfig.c create mode 100644 firmware/quadruna/BMS/src/io/io_cans.c create mode 100644 firmware/quadruna/BMS/src/io/io_cans.h create mode 100644 firmware/quadruna/BMS/src/jobs.c create mode 100644 firmware/quadruna/BMS/src/jobs.h create mode 100644 firmware/quadruna/CRIT/src/hw/hw_gpios.c create mode 100644 firmware/quadruna/CRIT/src/hw/hw_gpios.h create mode 100644 firmware/quadruna/FSM/src/hw/hw_gpios.c create mode 100644 firmware/quadruna/FSM/src/hw/hw_gpios.h create mode 100644 firmware/quadruna/FSM/src/hw/hw_uarts.c create mode 100644 firmware/quadruna/FSM/src/hw/hw_uarts.h create mode 100644 firmware/quadruna/FSM/src/io/io_chimeraConfig.c create mode 100644 firmware/quadruna/VC/src/hw/hw_chimeraConfig.c create mode 100644 firmware/quadruna/VC/src/hw/hw_gpios.c create mode 100644 firmware/quadruna/VC/src/hw/hw_gpios.h create mode 100644 firmware/quadruna/VC/src/hw/hw_sds.c create mode 100644 firmware/quadruna/VC/src/hw/hw_uarts.c create mode 100644 firmware/quadruna/VC/src/hw/hw_uarts.h create mode 100644 firmware/quadruna/VC/src/io/io_canQueueConfig.c create mode 100644 firmware/quadruna/VC/src/io/io_cans.c create mode 100644 firmware/quadruna/VC/src/io/io_cans.h create mode 100644 firmware/quadruna/VC/src/io/io_leds.c create mode 100644 firmware/quadruna/VC/src/io/io_leds.h create mode 100644 firmware/quadruna/VC/src/jobs.c create mode 100644 firmware/quadruna/VC/src/jobs.h delete mode 100644 firmware/shared/src/hw/hw_can.c delete mode 100644 firmware/shared/src/hw/hw_can.h delete mode 100644 firmware/shared/src/hw/hw_fdcan.c rename firmware/shared/src/io/{io_canLogging.c => io_canLoggingQueue.c} (59%) rename firmware/shared/src/io/{io_canLogging.h => io_canLoggingQueue.h} (89%) create mode 100644 firmware/shared/src/io/io_canMsg.h create mode 100644 firmware/shared/src/io/io_canQueue.c create mode 100644 firmware/shared/src/io/io_canQueue.h create mode 100644 firmware/shared/src/io/io_fdcan.c diff --git a/firmware/boot/bootloader.c b/firmware/boot/bootloader.c index a7ad643432..db8c288e99 100644 --- a/firmware/boot/bootloader.c +++ b/firmware/boot/bootloader.c @@ -1,30 +1,49 @@ #include "bootloader.h" #include "bootloaderConfig.h" +#include "main.h" + #include #include + #include "cmsis_gcc.h" #include "cmsis_os.h" -#include "hw_hal.h" -#include "io_can.h" + +#include "app_commitInfo.h" +#include "io_canQueue.h" #include "io_log.h" -#include "hw_flash.h" + #include "hw_hardFaultHandler.h" +#include "hw_flash.h" #include "hw_utils.h" #include "hw_crc.h" -#include "main.h" -#include "hw_gpio.h" -#include "app_commitInfo.h" +#include "hw_hal.h" +#include "io_can.h" extern CRC_HandleTypeDef hcrc; extern TIM_HandleTypeDef htim6; +// Need these to be created an initialized elsewhere +extern CanHandle can; + +void canRxQueueOverflowCallBack(const uint32_t unused) +{ + UNUSED(unused); + BREAK_IF_DEBUGGER_CONNECTED(); +} + +void canTxQueueOverflowCallBack(const uint32_t unused) +{ + UNUSED(unused); + BREAK_IF_DEBUGGER_CONNECTED(); +} + // App code block. Start/size included from the linker script. -extern uint32_t __app_metadata_start__; -extern uint32_t __app_metadata_size__; +extern uint32_t __app_metadata_start__; // NOLINT(*-reserved-identifier) +extern uint32_t __app_metadata_size__; // NOLINT(*-reserved-identifier) // App metadata block. Start/size included from the linker script. -extern uint32_t __app_code_start__; -extern uint32_t __app_code_size__; +extern uint32_t __app_code_start__; // NOLINT(*-reserved-identifier) +extern uint32_t __app_code_size__; // NOLINT(*-reserved-identifier) // Info needed by the bootloader to boot safely. Currently takes up the the first kB // of flash allocated to the app. @@ -41,18 +60,6 @@ typedef enum BOOT_STATUS_NO_APP } BootStatus; -static void canRxOverflow(uint32_t unused) -{ - UNUSED(unused); - BREAK_IF_DEBUGGER_CONNECTED(); -} - -static void canTxOverflow(uint32_t unused) -{ - UNUSED(unused); - BREAK_IF_DEBUGGER_CONNECTED(); -} - _Noreturn static void modifyStackPointerAndStartApp(const uint32_t *address) { // Disable interrupts before jumping. @@ -110,24 +117,19 @@ static BootStatus verifyAppCodeChecksum(void) return BOOT_STATUS_NO_APP; } - Metadata *metadata = (Metadata *)&__app_metadata_start__; + const Metadata *metadata = (Metadata *)&__app_metadata_start__; if (metadata->size_bytes > (uint32_t)&__app_code_size__) { // App binary size field is invalid. return BOOT_STATUS_APP_INVALID; } - uint32_t calculated_checksum = hw_crc_calculate(&__app_code_start__, metadata->size_bytes / 4); + const uint32_t calculated_checksum = hw_crc_calculate(&__app_code_start__, metadata->size_bytes / 4); return calculated_checksum == metadata->checksum ? BOOT_STATUS_APP_VALID : BOOT_STATUS_APP_INVALID; } -static const CanConfig can_config = { - .rx_msg_filter = NULL, - .rx_overflow_callback = canRxOverflow, - .tx_overflow_callback = canTxOverflow, -}; - #ifndef BOOT_AUTO +#include "hw_gpio.h" static const Gpio bootloader_pin = { .port = nBOOT_EN_GPIO_Port, .pin = nBOOT_EN_Pin, @@ -149,7 +151,6 @@ void bootloader_init(void) // HW-level CAN should be initialized in main.c, since it is MCU-specific. hw_hardFaultHandler_init(); hw_crc_init(&hcrc); - io_can_init(&can_config); // This order is important! The bootloader starts the app when the bootloader // enable pin is high, which is caused by pullup resistors internal to each @@ -183,8 +184,7 @@ _Noreturn void bootloader_runInterfaceTask(void) { for (;;) { - CanMsg command; - io_can_popRxMsgFromQueue(&command); + const CanMsg command = io_canQueue_popRx(); if (command.std_id == START_UPDATE_ID) { @@ -193,13 +193,13 @@ _Noreturn void bootloader_runInterfaceTask(void) update_in_progress = true; // Send ACK message that programming has started. - CanMsg reply = { .std_id = UPDATE_ACK_ID, .dlc = 0 }; - io_can_pushTxMsgToQueue(&reply); + const CanMsg reply = { .std_id = UPDATE_ACK_ID, .dlc = 0 }; + io_canQueue_pushTx(&reply); } else if (command.std_id == ERASE_SECTOR_ID && update_in_progress) { // Erase a flash sector. - uint8_t sector = command.data[0]; + const uint8_t sector = command.data[0]; hw_flash_eraseSector(sector); // Erasing sectors takes a while, so reply when finished. @@ -207,7 +207,7 @@ _Noreturn void bootloader_runInterfaceTask(void) .std_id = ERASE_SECTOR_COMPLETE_ID, .dlc = 0, }; - io_can_pushTxMsgToQueue(&reply); + io_canQueue_pushTx(&reply); } else if (command.std_id == PROGRAM_ID && update_in_progress) { @@ -224,7 +224,7 @@ _Noreturn void bootloader_runInterfaceTask(void) .dlc = 1, }; reply.data[0] = (uint8_t)verifyAppCodeChecksum(); - io_can_pushTxMsgToQueue(&reply); + io_canQueue_pushTx(&reply); // Verify command doubles as exit programming state command. update_in_progress = false; @@ -245,7 +245,7 @@ _Noreturn void bootloader_runTickTask(void) status_msg.data[2] = (uint8_t)((0x00ff0000 & GIT_COMMIT_HASH) >> 16); status_msg.data[3] = (uint8_t)((0xff000000 & GIT_COMMIT_HASH) >> 24); status_msg.data[4] = (uint8_t)(verifyAppCodeChecksum() << 1) | GIT_COMMIT_CLEAN; - io_can_pushTxMsgToQueue(&status_msg); + io_canQueue_pushTx(&status_msg); bootloader_boardSpecific_tick(); @@ -258,9 +258,8 @@ _Noreturn void bootloader_runCanTxTask(void) { for (;;) { - CanMsg tx_msg; - io_can_popTxMsgFromQueue(&tx_msg); - io_can_transmitMsgFromQueue(&tx_msg); + CanMsg tx_msg = io_canQueue_popTx(); + io_can_transmit(&can, &tx_msg); } } diff --git a/firmware/cmake/bootlib.cmake b/firmware/cmake/bootlib.cmake index 5f828f9d91..000f806ba0 100644 --- a/firmware/cmake/bootlib.cmake +++ b/firmware/cmake/bootlib.cmake @@ -52,10 +52,11 @@ function(stm32f4_boot_binary # Add shared files. list(APPEND SRCS + "${SHARED_IO_INCLUDE_DIR}/io_canQueue.c" "${SHARED_IO_INCLUDE_DIR}/io_can.c" + "${SHARED_IO_INCLUDE_DIR}/io_time.c" "${SHARED_HW_INCLUDE_DIR}/hw_flash.c" "${SHARED_HW_INCLUDE_DIR}/hw_crc.c" - "${SHARED_HW_INCLUDE_DIR}/hw_can.c" "${SHARED_HW_INCLUDE_DIR}/hw_gpio.c" "${SHARED_HW_INCLUDE_DIR}/hw_hardFaultHandler.c" "${SHARED_HW_INCLUDE_DIR}/hw_crc.c" @@ -131,10 +132,11 @@ function(stm32h7_boot_binary # Add shared files. list(APPEND SRCS - "${SHARED_IO_INCLUDE_DIR}/io_can.c" + "${SHARED_IO_INCLUDE_DIR}/io_canQueue.c" + "${SHARED_IO_INCLUDE_DIR}/io_fdcan.c" + "${SHARED_IO_INCLUDE_DIR}/io_time.c" "${SHARED_HW_INCLUDE_DIR}/hw_flash.c" "${SHARED_HW_INCLUDE_DIR}/hw_crc.c" - "${SHARED_HW_INCLUDE_DIR}/hw_fdcan.c" "${SHARED_HW_INCLUDE_DIR}/hw_gpio.c" "${SHARED_HW_INCLUDE_DIR}/hw_hardFaultHandler.c" "${SHARED_HW_INCLUDE_DIR}/hw_crc.c" diff --git a/firmware/cmake/shared.cmake b/firmware/cmake/shared.cmake index e7c7729909..497512204d 100644 --- a/firmware/cmake/shared.cmake +++ b/firmware/cmake/shared.cmake @@ -35,20 +35,17 @@ function(commit_info_library OUTPUT_PATH ) commit_info_generate_sources(${BIND_TARGET} ${OUTPUT_PATH}) - IF("${TARGET}" STREQUAL "binary") + IF(${TARGET} STREQUAL "binary") embedded_interface_library( "${LIB_NAME}" "${COMMIT_INFO_SRC}" "${COMMIT_INFO_INCLUDE_DIR}" FALSE ) - ELSEIF("${TARGET}" STREQUAL "test") + ELSEIF(${TARGET} STREQUAL "test") get_filename_component(HEADER_DIR "${HEADER_OUTPUT_PATH}" DIRECTORY) - # TODO make this an interface library as well - add_library( - "${LIB_NAME}" INTERFACE - "${COMMIT_INFO_SRC}" - ) + add_library(${LIB_NAME} INTERFACE) + target_sources(${LIB_NAME} INTERFACE ${COMMIT_INFO_SRC}) target_include_directories("${LIB_NAME}" INTERFACE "${HEADER_DIR}") ENDIF() endfunction() diff --git a/firmware/dev/h7dev/CMakeLists.txt b/firmware/dev/h7dev/CMakeLists.txt index 7f56ce961d..1789e4115d 100644 --- a/firmware/dev/h7dev/CMakeLists.txt +++ b/firmware/dev/h7dev/CMakeLists.txt @@ -7,11 +7,11 @@ set(LINKER_SCRIPT "${LINKER_DIR}/stm32h733vgtx/stm32h733vgtx_app.ld") file(GLOB_RECURSE EMBEDDED_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c") list(APPEND EMBEDDED_SRCS - "${SHARED_IO_INCLUDE_DIR}/io_can.c" - "${SHARED_IO_INCLUDE_DIR}/io_canLogging.c" + "${SHARED_IO_INCLUDE_DIR}/io_canQueue.c" + "${SHARED_IO_INCLUDE_DIR}/io_fdcan.c" + "${SHARED_IO_INCLUDE_DIR}/io_canLoggingQueue.c" "${SHARED_IO_INCLUDE_DIR}/io_fileSystem_logfs.c" "${SHARED_HW_INCLUDE_DIR}/hw_hardFaultHandler.c" - "${SHARED_HW_INCLUDE_DIR}/hw_fdcan.c" "${SHARED_HW_INCLUDE_DIR}/hw_bootup.c" "${SHARED_HW_INCLUDE_DIR}/hw_uart.c" "${SHARED_HW_INCLUDE_DIR}/hw_sd.c" diff --git a/firmware/dev/h7dev/boot/cubemx/Src/main.c b/firmware/dev/h7dev/boot/cubemx/Src/main.c index 3d5042241e..b88aefdc8c 100644 --- a/firmware/dev/h7dev/boot/cubemx/Src/main.c +++ b/firmware/dev/h7dev/boot/cubemx/Src/main.c @@ -23,7 +23,7 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "bootloader.h" -#include "hw_can.h" +#include "io_canQueue.h" #include "io_can.h" /* USER CODE END Includes */ @@ -104,7 +104,7 @@ void runCanTxTask(void *argument); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ -CanHandle can = { .can = &hfdcan2, .can_msg_received_callback = io_can_pushRxMsgToQueue }; +CanHandle can = { .hcan = &hfdcan2 }; /* USER CODE END 0 */ /** @@ -138,7 +138,7 @@ int main(void) MX_CRC_Init(); MX_FDCAN2_Init(); /* USER CODE BEGIN 2 */ - hw_can_init(&can); + io_can_init(&can); bootloader_init(); /* USER CODE END 2 */ diff --git a/firmware/dev/h7dev/src/cubemx/Src/main.c b/firmware/dev/h7dev/src/cubemx/Src/main.c index c04f84a209..b532dabd04 100644 --- a/firmware/dev/h7dev/src/cubemx/Src/main.c +++ b/firmware/dev/h7dev/src/cubemx/Src/main.c @@ -26,14 +26,13 @@ #include "pb_decode.h" #include "sample.pb.h" #include "string.h" -#include "string.h" #include "hw_hardFaultHandler.h" -#include "hw_can.h" #include "hw_sd.h" #include "hw_bootup.h" #include "hw_uart.h" #include "io_can.h" -#include "io_canLogging.h" +#include "io_canQueue.h" +#include "io_canLoggingQueue.h" #include "io_fileSystem.h" #include "hw_gpio.h" #include "io_log.h" @@ -103,20 +102,14 @@ const osThreadAttr_t canRxTask_attributes = { }; /* USER CODE BEGIN PV */ -int write_num = 0; -int read_num = 0; -int overflow_num = 0; -static void callback(uint32_t i) -{ - overflow_num++; - // BREAK_IF_DEBUGGER_CONNECTED(); -} - -static CanConfig can_config = { - .rx_msg_filter = NULL, - .tx_overflow_callback = callback, - .rx_overflow_callback = callback, -}; +int write_num = 0; +int read_num = 0; +int overflow_num = 0; +// static void callback(uint32_t i) +// { +// overflow_num++; +// BREAK_IF_DEBUGGER_CONNECTED(); +// } /* USER CODE END PV */ @@ -132,14 +125,13 @@ void runCanTxTask(void *argument); void runCanRxTask(void *argument); /* USER CODE BEGIN PFP */ -static void can_msg_received_callback(CanMsg *rx_msg); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ -CanHandle can = { .can = &hfdcan2, .can_msg_received_callback = can_msg_received_callback }; -SdCard sd = { .hsd = &hsd1, .timeout = osWaitForever }; +CanHandle can = { .hcan = &hfdcan2 }; +SdCard sd1 = { .hsd = &hsd1, .timeout = osWaitForever }; Gpio sd_present = { .pin = GPIO_PIN_8, @@ -189,16 +181,16 @@ int main(void) /* USER CODE BEGIN 2 */ // __HAL_DBGMCU_FREEZE_IWDG(); - io_can_init(&can_config); hw_hardFaultHandler_init(); - hw_can_init(&can); + io_can_init(&can); + io_canQueue_init(); if (sd_inited) { - sd.hsd = &hsd1; - sd.timeout = osWaitForever; - int err = io_fileSystem_init(); - io_canLogging_init(&can_config); + sd1.hsd = &hsd1; + sd1.timeout = osWaitForever; + int err = io_fileSystem_init(); + io_canLogging_init(); } SEGGER_SYSVIEW_Conf(); @@ -449,7 +441,6 @@ static void MX_SDMMC1_SD_Init(void) } /* USER CODE BEGIN SDMMC1_Init 2 */ sd_inited = true; - hw_sd_init(&sd); /* USER CODE END SDMMC1_Init 2 */ } @@ -539,16 +530,33 @@ static void MX_GPIO_Init(void) } /* USER CODE BEGIN 4 */ - static void can_msg_received_callback(CanMsg *rx_msg) { // TODO: check gpio present static uint32_t id = 0; rx_msg->std_id = id; id++; - io_can_pushRxMsgToQueue(rx_msg); + io_canQueue_pushRx(rx_msg); io_canLogging_loggingQueuePush(rx_msg); } +void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, const uint32_t RxFifo0ITs) +{ + UNUSED(RxFifo0ITs); + CanMsg rx_msg; + if (!io_can_receive(&can, FDCAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + can_msg_received_callback(&rx_msg); +} +void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, const uint32_t RxFifo1ITs) +{ + UNUSED(RxFifo1ITs); + CanMsg rx_msg; + if (!io_can_receive(&can, FDCAN_RX_FIFO1, &rx_msg)) + // Early return if RX msg is unavailable. + return; + can_msg_received_callback(&rx_msg); +} /* USER CODE END 4 */ diff --git a/firmware/quadruna/BMS/CMakeLists.txt b/firmware/quadruna/BMS/CMakeLists.txt index 1097609ae8..bb307bde05 100644 --- a/firmware/quadruna/BMS/CMakeLists.txt +++ b/firmware/quadruna/BMS/CMakeLists.txt @@ -21,7 +21,8 @@ set(APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src/app" "${SHARED_APP_INCLUDE file(GLOB_RECURSE IO_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/io/*.c") set(IO_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src/io" "${SHARED_IO_INCLUDE_DIR}" "${SHARED_IO_INCLUDE_QUADRUNA_DIR}") list(APPEND IO_SRCS - "${SHARED_IO_INCLUDE_DIR}/io_can.c" + "${SHARED_IO_INCLUDE_DIR}/io_fdcan.c" + "${SHARED_IO_INCLUDE_DIR}/io_canQueue.c" "${SHARED_IO_INCLUDE_DIR}/io_jsoncan.c" "${SHARED_IO_INCLUDE_DIR}/io_time.c" "${SHARED_IO_INCLUDE_DIR}/io_chimera.c" @@ -36,7 +37,6 @@ file(GLOB_RECURSE HW_SRCS ) list(APPEND HW_SRCS "${SHARED_HW_INCLUDE_DIR}/hw_hardFaultHandler.c" - "${SHARED_HW_INCLUDE_DIR}/hw_fdcan.c" "${SHARED_HW_INCLUDE_DIR}/hw_adc.c" "${SHARED_HW_INCLUDE_DIR}/hw_bootup.c" "${SHARED_HW_INCLUDE_DIR}/hw_gpio.c" diff --git a/firmware/quadruna/BMS/boot/cubemx/Src/main.c b/firmware/quadruna/BMS/boot/cubemx/Src/main.c index daed004d9a..69a0acbd09 100644 --- a/firmware/quadruna/BMS/boot/cubemx/Src/main.c +++ b/firmware/quadruna/BMS/boot/cubemx/Src/main.c @@ -23,9 +23,12 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "bootloader.h" -#include "hw_can.h" #include "io_can.h" +#include "io_canQueue.h" +#include "hw_utils.h" #include "hw_error.h" + +#include /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -105,7 +108,29 @@ void runCanTxTask(void *argument); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ -CanHandle can = { .can = &hfdcan1, .can_msg_received_callback = io_can_pushRxMsgToQueue }; +CanHandle can = { .hcan = &hfdcan1 }; + +void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, const uint32_t RxFifo0ITs) +{ + assert(hfdcan == &hfdcan1); + UNUSED(RxFifo0ITs); + CanMsg rx_msg; + if (!io_can_receive(&can, FDCAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} + +void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, const uint32_t RxFifo1ITs) +{ + assert(hfdcan == &hfdcan1); + UNUSED(RxFifo1ITs); + CanMsg rx_msg; + if (!io_can_receive(&can, FDCAN_RX_FIFO1, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} /* USER CODE END 0 */ /** @@ -140,7 +165,7 @@ int main(void) MX_FDCAN1_Init(); /* USER CODE BEGIN 2 */ bootloader_init(); - hw_can_init(&can); + io_can_init(&can); /* USER CODE END 2 */ /* Init scheduler */ diff --git a/firmware/quadruna/BMS/src/app/app_globals.c b/firmware/quadruna/BMS/src/app/app_globals.c index 5d29602918..e3c6af83d9 100644 --- a/firmware/quadruna/BMS/src/app/app_globals.c +++ b/firmware/quadruna/BMS/src/app/app_globals.c @@ -5,11 +5,9 @@ Globals bms_globals; Globals *const globals = &bms_globals; -void app_globals_init(const GlobalsConfig *config) +void app_globals_init() { memset(globals, 0U, sizeof(Globals)); - globals->config = config; - app_timer_init(&globals->precharge_lower_bound_timer, PRECHARGE_COMPLETION_LOWER_BOUND); app_timer_init(&globals->precharge_upper_bound_timer, PRECHARGE_COMPLETION_UPPER_BOUND); globals->charger_connected_counter = 0; diff --git a/firmware/quadruna/BMS/src/app/app_globals.h b/firmware/quadruna/BMS/src/app/app_globals.h index 7071ea70de..1d0fd8176e 100644 --- a/firmware/quadruna/BMS/src/app/app_globals.h +++ b/firmware/quadruna/BMS/src/app/app_globals.h @@ -1,22 +1,10 @@ #pragma once #include -#include "io_faultLatch.h" -#include "io_thermistors.h" #include "app_timer.h" typedef struct { - const FaultLatch *bms_ok_latch; - const FaultLatch *imd_ok_latch; - const FaultLatch *bspd_ok_latch; -} GlobalsConfig; - -typedef struct -{ - // Config. - const GlobalsConfig *config; - // State variables. uint32_t cell_monitor_settle_count; uint32_t num_precharge_failures; @@ -36,4 +24,4 @@ extern Globals *const globals; * Initialize the globals module. * @param config Globals config. */ -void app_globals_init(const GlobalsConfig *config); +void app_globals_init(); diff --git a/firmware/quadruna/BMS/src/app/states/app_allStates.c b/firmware/quadruna/BMS/src/app/states/app_allStates.c index ea0ca40391..8d3c86415a 100644 --- a/firmware/quadruna/BMS/src/app/states/app_allStates.c +++ b/firmware/quadruna/BMS/src/app/states/app_allStates.c @@ -153,12 +153,12 @@ bool app_allStates_runOnTick100Hz(void) // Update CAN signals for BMS latch statuses. app_canTx_BMS_Soc_set(app_soc_getMinSocPercent()); - app_canTx_BMS_BmsOk_set(io_faultLatch_getCurrentStatus(globals->config->bms_ok_latch)); - app_canTx_BMS_ImdOk_set(io_faultLatch_getCurrentStatus(globals->config->imd_ok_latch)); - app_canTx_BMS_BspdOk_set(io_faultLatch_getCurrentStatus(globals->config->bspd_ok_latch)); - app_canTx_BMS_BmsLatchedFault_set(io_faultLatch_getLatchedStatus(globals->config->bms_ok_latch)); - app_canTx_BMS_ImdLatchedFault_set(io_faultLatch_getLatchedStatus(globals->config->imd_ok_latch)); - app_canTx_BMS_BspdLatchedFault_set(io_faultLatch_getLatchedStatus(globals->config->bspd_ok_latch)); + app_canTx_BMS_BmsOk_set(io_faultLatch_getCurrentStatus(&bms_ok_latch)); + app_canTx_BMS_ImdOk_set(io_faultLatch_getCurrentStatus(&imd_ok_latch)); + app_canTx_BMS_BspdOk_set(io_faultLatch_getCurrentStatus(&bspd_ok_latch)); + app_canTx_BMS_BmsLatchedFault_set(io_faultLatch_getLatchedStatus(&bms_ok_latch)); + app_canTx_BMS_ImdLatchedFault_set(io_faultLatch_getLatchedStatus(&imd_ok_latch)); + app_canTx_BMS_BspdLatchedFault_set(io_faultLatch_getLatchedStatus(&bspd_ok_latch)); // Wait for cell voltage and temperature measurements to settle. We expect to read back valid values from the // monitoring chips within 3 cycles diff --git a/firmware/quadruna/BMS/src/app/states/app_faultState.c b/firmware/quadruna/BMS/src/app/states/app_faultState.c index fd298beb81..bbfc8e4d9d 100644 --- a/firmware/quadruna/BMS/src/app/states/app_faultState.c +++ b/firmware/quadruna/BMS/src/app/states/app_faultState.c @@ -10,7 +10,7 @@ static void faultStateRunOnEntry(void) app_canAlerts_BMS_Fault_StateMachine_set(true); io_airs_openPositive(); - io_faultLatch_setCurrentStatus(globals->config->bms_ok_latch, false); + io_faultLatch_setCurrentStatus(&bms_ok_latch, false); } static void faultStateRunOnTick1Hz(void) diff --git a/firmware/quadruna/BMS/src/app/states/app_initState.c b/firmware/quadruna/BMS/src/app/states/app_initState.c index 53517969a6..850f44676b 100644 --- a/firmware/quadruna/BMS/src/app/states/app_initState.c +++ b/firmware/quadruna/BMS/src/app/states/app_initState.c @@ -14,7 +14,7 @@ static void initStateRunOnEntry(void) { app_canTx_BMS_State_set(BMS_INIT_STATE); app_accumulator_writeDefaultConfig(); - io_faultLatch_setCurrentStatus(globals->config->bms_ok_latch, true); + io_faultLatch_setCurrentStatus(&bms_ok_latch, true); // AIR+ opens upon entering init state // Should always be opened at this point from other states, this is only for redundancy since we really don't want diff --git a/firmware/quadruna/BMS/src/hw/hw_chimeraConfig.c b/firmware/quadruna/BMS/src/hw/hw_chimeraConfig.c new file mode 100644 index 0000000000..a0202b9bf9 --- /dev/null +++ b/firmware/quadruna/BMS/src/hw/hw_chimeraConfig.c @@ -0,0 +1,37 @@ +#include "hw_gpios.h" +#include "hw_adcs.h" +#include "hw_uarts.h" +#include "shared.pb.h" + +const Gpio *id_to_gpio[] = { [BMS_GpioNetName_ACCEL_BRAKE_OK_3V3] = &accel_brake_ok_pin, + [BMS_GpioNetName_AIR_P_EN] = &air_p_gpio, + [BMS_GpioNetName_AUX_TSENSE_MUX0] = &mux_0_gpio, + [BMS_GpioNetName_AUX_TSENSE_MUX1] = &mux_1_gpio, + [BMS_GpioNetName_AUX_TSENSE_MUX2] = &mux_2_gpio, + [BMS_GpioNetName_AUX_TSENSE_MUX3] = &mux_3_gpio, + [BMS_GpioNetName_BMS_LATCH] = &bms_ok_latch_status_gpio, + [BMS_GpioNetName_BMS_OK_3V3] = &bms_ok_current_status_gpio, + [BMS_GpioNetName_BSPD_LATCH] = &bspd_ok_latch_status_gpio, + [BMS_GpioNetName_BSPD_OK_3V3] = &bspd_ok_current_status_gpio, + [BMS_GpioNetName_BSPD_TEST_EN] = &test_enable_gpio, + [BMS_GpioNetName_HVD_SHDN_OK] = &air_n_gpio, + [BMS_GpioNetName_IMD_LATCH] = &imd_ok_latch_status_gpio, + [BMS_GpioNetName_IMD_OK_3V3] = &imd_ok_current_status_gpio, + [BMS_GpioNetName_LED] = &led_pin, + [BMS_GpioNetName_NCHIMERA] = &n_chimera_pin, + [BMS_GpioNetName_NHIGH_CURRENT_BSPD_3V3] = &n_high_current_gpio, + [BMS_GpioNetName_NPROGRAM_3V3] = &n_program_pin, + [BMS_GpioNetName_PRE_CHARGE_EN] = &precharge_gpio, + [BMS_GpioNetName_TS_ILCK_SHDN_OK] = &ts_ilck_shdn_pin, + [BMS_GpioNetName_TS_ISENSE_OCSC_OK_3V3] = &ts_isense_ocsc_ok_pin, + [BMS_GpioNetName_SD_CD] = &sd_cd_pin, + [BMS_GpioNetName_SPI_CS] = &spi_cs_pin }; + +const AdcChannel *id_to_adc[] = { + [BMS_AdcNetName_AUX_TSENSE] = &aux_tsns, [BMS_AdcNetName_TS_ISENSE_400A] = &ts_isns_400a, + [BMS_AdcNetName_TS_ISENSE_75A] = &ts_isns_75a, [BMS_AdcNetName_TS_VSENSE_P] = &ts_vsense_p, + [BMS_AdcNetName_TS_VSENSE_N] = &ts_vsense_n, +}; + +const UART *chimera_uart = &debug_uart; +const Gpio *n_chimera_gpio = &n_chimera_pin; \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/hw/hw_gpios.c b/firmware/quadruna/BMS/src/hw/hw_gpios.c new file mode 100644 index 0000000000..856ff8ba1e --- /dev/null +++ b/firmware/quadruna/BMS/src/hw/hw_gpios.c @@ -0,0 +1,28 @@ +#include "hw_gpios.h" +#include "main.h" + +const Gpio accel_brake_ok_pin = { .port = ACCEL_BRAKE_OK_3V3_GPIO_Port, .pin = ACCEL_BRAKE_OK_3V3_Pin }; +const Gpio led_pin = { .port = LED_GPIO_Port, .pin = LED_Pin }; +const Gpio n_chimera_pin = { .port = nCHIMERA_GPIO_Port, .pin = nCHIMERA_Pin }; +const Gpio n_program_pin = { .port = nPROGRAM_3V3_GPIO_Port, .pin = nPROGRAM_3V3_Pin }; +const Gpio ts_ilck_shdn_pin = { .port = TS_ILCK_SHDN_OK_GPIO_Port, .pin = TS_ILCK_SHDN_OK_Pin }; +const Gpio hvd_ok_shdn_pin = { .port = HVD_SHDN_OK_GPIO_Port, .pin = HVD_SHDN_OK_Pin }; +const Gpio ts_isense_ocsc_ok_pin = { .port = TS_ISENSE_OCSC_OK_3V3_GPIO_Port, .pin = TS_ISENSE_OCSC_OK_3V3_Pin }; +const Gpio sd_cd_pin = { .port = SD_CD_GPIO_Port, .pin = SD_CD_Pin }; +const Gpio spi_cs_pin = { .port = SPI_CS_GPIO_Port, .pin = SPI_CS_Pin }; +const Gpio air_p_gpio = { .port = AIR_P_EN_GPIO_Port, .pin = AIR_P_EN_Pin }; +const Gpio air_n_gpio = { .port = HVD_SHDN_OK_GPIO_Port, .pin = HVD_SHDN_OK_Pin }; +const Gpio precharge_gpio = { .port = PRE_CHARGE_EN_GPIO_Port, .pin = PRE_CHARGE_EN_Pin }; +const Gpio mux_0_gpio = { .port = AUX_TSENSE_MUX0_GPIO_Port, .pin = AUX_TSENSE_MUX0_Pin }; +const Gpio mux_1_gpio = { .port = AUX_TSENSE_MUX1_GPIO_Port, .pin = AUX_TSENSE_MUX1_Pin }; +const Gpio mux_2_gpio = { .port = AUX_TSENSE_MUX2_GPIO_Port, .pin = AUX_TSENSE_MUX2_Pin }; +const Gpio mux_3_gpio = { .port = AUX_TSENSE_MUX3_GPIO_Port, .pin = AUX_TSENSE_MUX3_Pin }; +const Gpio bms_ok_current_status_gpio = { .port = BMS_OK_3V3_GPIO_Port, .pin = BMS_OK_3V3_Pin }; +const Gpio bms_ok_latch_status_gpio = { .port = BMS_LATCH_GPIO_Port, .pin = BMS_LATCH_Pin }; +const Gpio imd_ok_current_status_gpio = { .port = IMD_OK_3V3_GPIO_Port, .pin = IMD_OK_3V3_Pin }; +const Gpio imd_ok_latch_status_gpio = { .port = IMD_LATCH_GPIO_Port, .pin = IMD_LATCH_Pin }; +const Gpio bspd_ok_current_status_gpio = { .port = BSPD_OK_3V3_GPIO_Port, .pin = BSPD_OK_3V3_Pin }; +const Gpio bspd_ok_latch_status_gpio = { .port = BSPD_LATCH_GPIO_Port, .pin = BSPD_LATCH_Pin }; +const Gpio test_enable_gpio = { .port = BSPD_TEST_EN_GPIO_Port, .pin = BSPD_TEST_EN_Pin }; +const Gpio n_high_current_gpio = { .port = nHIGH_CURRENT_BSPD_3V3_GPIO_Port, .pin = nHIGH_CURRENT_BSPD_3V3_Pin }; +const Gpio present_gpio = { .port = SD_CD_GPIO_Port, .pin = SD_CD_Pin }; \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/hw/hw_gpios.h b/firmware/quadruna/BMS/src/hw/hw_gpios.h new file mode 100644 index 0000000000..6b0ad618d6 --- /dev/null +++ b/firmware/quadruna/BMS/src/hw/hw_gpios.h @@ -0,0 +1,28 @@ +#pragma once +#include "hw_gpio.h" + +extern const Gpio accel_brake_ok_pin; +extern const Gpio led_pin; +extern const Gpio n_chimera_pin; +extern const Gpio n_program_pin; +extern const Gpio ts_ilck_shdn_pin; +extern const Gpio hvd_ok_shdn_pin; +extern const Gpio ts_isense_ocsc_ok_pin; +extern const Gpio sd_cd_pin; +extern const Gpio spi_cs_pin; +extern const Gpio air_p_gpio; +extern const Gpio air_n_gpio; +extern const Gpio precharge_gpio; +extern const Gpio mux_0_gpio; +extern const Gpio mux_1_gpio; +extern const Gpio mux_2_gpio; +extern const Gpio mux_3_gpio; +extern const Gpio bms_ok_current_status_gpio; +extern const Gpio bms_ok_latch_status_gpio; +extern const Gpio imd_ok_current_status_gpio; +extern const Gpio imd_ok_latch_status_gpio; +extern const Gpio bspd_ok_current_status_gpio; +extern const Gpio bspd_ok_latch_status_gpio; +extern const Gpio test_enable_gpio; +extern const Gpio n_high_current_gpio; +extern const Gpio present_gpio; \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/hw/hw_sds.c b/firmware/quadruna/BMS/src/hw/hw_sds.c new file mode 100644 index 0000000000..fef74b6a5d --- /dev/null +++ b/firmware/quadruna/BMS/src/hw/hw_sds.c @@ -0,0 +1,5 @@ +#include "hw_sd.h" +#include "main.h" +#include "hw_gpios.h" + +SdCard sd1 = { .hsd = &hsd1, .timeout = 0x20, .present_gpio = &present_gpio }; \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/hw/hw_uarts.c b/firmware/quadruna/BMS/src/hw/hw_uarts.c new file mode 100644 index 0000000000..c1d1278e41 --- /dev/null +++ b/firmware/quadruna/BMS/src/hw/hw_uarts.c @@ -0,0 +1,4 @@ +#include "hw_uarts.h" +#include "main.h" + +const UART debug_uart = { .handle = &huart1 }; diff --git a/firmware/quadruna/BMS/src/hw/hw_uarts.h b/firmware/quadruna/BMS/src/hw/hw_uarts.h new file mode 100644 index 0000000000..aa395d18b9 --- /dev/null +++ b/firmware/quadruna/BMS/src/hw/hw_uarts.h @@ -0,0 +1,4 @@ +#pragma once +#include "hw_uart.h" + +extern const UART debug_uart; \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/io/io_airs.c b/firmware/quadruna/BMS/src/io/io_airs.c index cf213aa609..dff681dca7 100644 --- a/firmware/quadruna/BMS/src/io/io_airs.c +++ b/firmware/quadruna/BMS/src/io/io_airs.c @@ -1,5 +1,8 @@ #include "io_airs.h" +#include "hw_gpios.h" +#include "hw_adcs.h" + #include // Shunt resistor used to measure AIR loop current @@ -16,44 +19,37 @@ // Value of shunt resistor #define AIR_LOOP_SHUNT_RES (1.0f / 75.0e-3f) -static const AirsConfig *config = NULL; - -void io_airs_init(const AirsConfig *airs_config) -{ - config = airs_config; -} - bool io_airs_isNegativeClosed(void) { - return hw_gpio_readPin(&config->air_n_gpio); + return hw_gpio_readPin(&air_n_gpio); } void io_airs_closePositive(void) { - hw_gpio_writePin(&config->air_p_gpio, true); + hw_gpio_writePin(&air_p_gpio, true); } void io_airs_openPositive(void) { - hw_gpio_writePin(&config->air_p_gpio, false); + hw_gpio_writePin(&air_p_gpio, false); } bool io_airs_isPositiveClosed(void) { - return hw_gpio_readPin(&config->air_p_gpio); + return hw_gpio_readPin(&air_p_gpio); } void io_airs_closePrecharge(void) { - hw_gpio_writePin(&config->precharge_gpio, true); + hw_gpio_writePin(&precharge_gpio, true); } void io_airs_openPrecharge(void) { - hw_gpio_writePin(&config->precharge_gpio, false); + hw_gpio_writePin(&precharge_gpio, false); } bool io_airs_isPrechargeClosed(void) { - return hw_gpio_readPin(&config->precharge_gpio); + return hw_gpio_readPin(&precharge_gpio); } diff --git a/firmware/quadruna/BMS/src/io/io_airs.h b/firmware/quadruna/BMS/src/io/io_airs.h index e47c2e55d3..291ec12bef 100644 --- a/firmware/quadruna/BMS/src/io/io_airs.h +++ b/firmware/quadruna/BMS/src/io/io_airs.h @@ -1,27 +1,6 @@ #pragma once #include -#include "app_utils.h" - -#ifdef TARGET_EMBEDDED -#include "hw_gpio.h" -#include "hw_adc.h" - -typedef struct -{ - const Gpio air_p_gpio; - const Gpio air_n_gpio; - const Gpio precharge_gpio; -} AirsConfig; -#else -EMPTY_STRUCT(AirsConfig); -#endif - -/** - * Initialize the AIRs driver. - * @param therm_config Config struct. - */ -void io_airs_init(const AirsConfig *airs_config); /** * Check if the AIR- is closed diff --git a/firmware/quadruna/BMS/src/io/io_bmsShdn.c b/firmware/quadruna/BMS/src/io/io_bmsShdn.c index 9848554359..ecc36105b5 100644 --- a/firmware/quadruna/BMS/src/io/io_bmsShdn.c +++ b/firmware/quadruna/BMS/src/io/io_bmsShdn.c @@ -1,18 +1,12 @@ #include "io_bmsShdn.h" - -static const BmsShdnConfig *shdn_config = NULL; - -void io_bmsShdn_init(const BmsShdnConfig *bms_shdn_config) -{ - shdn_config = bms_shdn_config; -} +#include "hw_gpios.h" bool io_bmsShdn_TS_ILCK_OK_get(void) { - return hw_gpio_readPin(&shdn_config->ts_ilck_ok_gpio); + return hw_gpio_readPin(&ts_ilck_shdn_pin); } bool io_bmsShdn_HVD_OK_get(void) { - return hw_gpio_readPin(&shdn_config->hvd_ok_gpio); + return hw_gpio_readPin(&hvd_ok_shdn_pin); } diff --git a/firmware/quadruna/BMS/src/io/io_bmsShdn.h b/firmware/quadruna/BMS/src/io/io_bmsShdn.h index 6e22e02109..6c1b5c0f15 100644 --- a/firmware/quadruna/BMS/src/io/io_bmsShdn.h +++ b/firmware/quadruna/BMS/src/io/io_bmsShdn.h @@ -1,24 +1,9 @@ #pragma once #include -#include "app_utils.h" - -#ifdef TARGET_EMBEDDED -#include "hw_gpio.h" - -typedef struct -{ - const Gpio ts_ilck_ok_gpio; - const Gpio hvd_ok_gpio; -} BmsShdnConfig; -#else -EMPTY_STRUCT(BmsShdnConfig); -#endif #define BMS_SHDN_NODE_COUNT 2 -void io_bmsShdn_init(const BmsShdnConfig *bms_shdn_config); - bool io_bmsShdn_TS_ILCK_OK_get(void); bool io_bmsShdn_HVD_OK_get(void); diff --git a/firmware/quadruna/BMS/src/io/io_bspdTest.c b/firmware/quadruna/BMS/src/io/io_bspdTest.c index 6d93524898..d4b4f932c3 100644 --- a/firmware/quadruna/BMS/src/io/io_bspdTest.c +++ b/firmware/quadruna/BMS/src/io/io_bspdTest.c @@ -1,18 +1,12 @@ #include "io_bspdTest.h" +#include "hw_gpios.h" -static const BSPDTestConfig *config = NULL; - -void io_bspdTest_init(const BSPDTestConfig *bspd_test_config) -{ - config = bspd_test_config; -} - -void io_bspdTest_enable(bool enable) +void io_bspdTest_enable(const bool enable) { - hw_gpio_writePin(&config->test_enable_gpio, enable); + hw_gpio_writePin(&test_enable_gpio, enable); } bool io_bspdTest_isCurrentThresholdExceeded(void) { - return !hw_gpio_readPin(&config->n_high_current_gpio); + return !hw_gpio_readPin(&n_high_current_gpio); } \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/io/io_bspdTest.h b/firmware/quadruna/BMS/src/io/io_bspdTest.h index 5fa357d973..8149aabbbd 100644 --- a/firmware/quadruna/BMS/src/io/io_bspdTest.h +++ b/firmware/quadruna/BMS/src/io/io_bspdTest.h @@ -2,21 +2,5 @@ #include -#include -#include "app_utils.h" - -#ifdef TARGET_EMBEDDED -#include "hw_gpio.h" - -typedef struct -{ - const Gpio test_enable_gpio; - const Gpio n_high_current_gpio; -} BSPDTestConfig; -#else -EMPTY_STRUCT(BSPDTestConfig); -#endif - -void io_bspdTest_init(const BSPDTestConfig *bspd_test_config); void io_bspdTest_enable(bool enable); bool io_bspdTest_isCurrentThresholdExceeded(void); \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/io/io_canQueueConfig.c b/firmware/quadruna/BMS/src/io/io_canQueueConfig.c new file mode 100644 index 0000000000..bb075c643b --- /dev/null +++ b/firmware/quadruna/BMS/src/io/io_canQueueConfig.c @@ -0,0 +1,27 @@ +#include "app_canTx.h" +#include "app_canAlerts.h" +#include "io_log.h" + +void rx_overflow_callback(uint32_t overflow_count) +{ + app_canTx_BMS_RxOverflowCount_set(overflow_count); + app_canAlerts_BMS_Warning_RxOverflow_set(true); + LOG_INFO("CAN RX QUEUE OVERFLOW, overflow_count = %d", overflow_count); +} + +void tx_overflow_callback(uint32_t overflow_count) +{ + app_canTx_BMS_TxOverflowCount_set(overflow_count); + app_canAlerts_BMS_Warning_TxOverflow_set(true); + LOG_INFO("CAN TX QUEUE OVERFLOW, overflow_count = %d", overflow_count); +} + +void tx_overflow_clear_callback(void) +{ + app_canAlerts_BMS_Warning_TxOverflow_set(false); +} + +void rx_overflow_clear_callback(void) +{ + app_canAlerts_BMS_Warning_RxOverflow_set(false); +} \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/io/io_cans.c b/firmware/quadruna/BMS/src/io/io_cans.c new file mode 100644 index 0000000000..a2350df3e0 --- /dev/null +++ b/firmware/quadruna/BMS/src/io/io_cans.c @@ -0,0 +1,4 @@ +#include "io_cans.h" +#include "main.h" + +const CanHandle can1 = { .hcan = &hfdcan1 }; diff --git a/firmware/quadruna/BMS/src/io/io_cans.h b/firmware/quadruna/BMS/src/io/io_cans.h new file mode 100644 index 0000000000..4b215d65c8 --- /dev/null +++ b/firmware/quadruna/BMS/src/io/io_cans.h @@ -0,0 +1,4 @@ +#pragma once +#include "io_can.h" + +extern const CanHandle can1; \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/io/io_faultLatch.c b/firmware/quadruna/BMS/src/io/io_faultLatch.c index ccbbacebb4..fe21736fa4 100644 --- a/firmware/quadruna/BMS/src/io/io_faultLatch.c +++ b/firmware/quadruna/BMS/src/io/io_faultLatch.c @@ -1,19 +1,35 @@ #include "io_faultLatch.h" -void io_faultLatch_setCurrentStatus(const FaultLatch *latch, bool status) +const FaultLatch bms_ok_latch = { + .current_status_gpio = &bms_ok_current_status_gpio, + .latch_status_gpio = &bms_ok_latch_status_gpio, + .read_only = false, +}; +const FaultLatch imd_ok_latch = { + .current_status_gpio = &imd_ok_current_status_gpio, + .latch_status_gpio = &imd_ok_latch_status_gpio, + .read_only = true, +}; +const FaultLatch bspd_ok_latch = { + .current_status_gpio = &bspd_ok_current_status_gpio, + .latch_status_gpio = &bspd_ok_latch_status_gpio, + .read_only = true, +}; + +void io_faultLatch_setCurrentStatus(const FaultLatch *latch, const bool status) { if (latch->read_only == false) { - hw_gpio_writePin(&latch->current_status_gpio, status); + hw_gpio_writePin(latch->current_status_gpio, status); } } bool io_faultLatch_getCurrentStatus(const FaultLatch *latch) { - return hw_gpio_readPin(&latch->current_status_gpio); + return hw_gpio_readPin(latch->current_status_gpio); } bool io_faultLatch_getLatchedStatus(const FaultLatch *latch) { - return !hw_gpio_readPin(&latch->latch_status_gpio); + return !hw_gpio_readPin(latch->latch_status_gpio); } diff --git a/firmware/quadruna/BMS/src/io/io_faultLatch.h b/firmware/quadruna/BMS/src/io/io_faultLatch.h index 695d6d7f70..c50aa3b46e 100644 --- a/firmware/quadruna/BMS/src/io/io_faultLatch.h +++ b/firmware/quadruna/BMS/src/io/io_faultLatch.h @@ -1,38 +1,42 @@ #pragma once #include -#include "app_utils.h" #ifdef TARGET_EMBEDDED -#include "hw_gpio.h" - +#include "hw_gpios.h" typedef struct { - const Gpio current_status_gpio; - const Gpio latch_status_gpio; - const bool read_only; // Certain fault latches can only be read from. + const Gpio *current_status_gpio; + const Gpio *latch_status_gpio; + const bool read_only; // Certain fault latches can only be read from. } FaultLatch; #else +#include "app_utils.h" EMPTY_STRUCT(FaultLatch); #endif +// latches to operate on +extern const FaultLatch bms_ok_latch; +extern const FaultLatch imd_ok_latch; +extern const FaultLatch bspd_ok_latch; + /** * Write a fault. * @param latch Fault latch instance. - * @param fault Whether or not to set a fault (true = OK, false = fault). + * @param status whether or not to set a fault (true = OK, false = fault). */ void io_faultLatch_setCurrentStatus(const FaultLatch *latch, bool status); /** * Return whether or not there is currently a fault. * @param latch Fault latch instance. - * @param fault True = there is currently NOT a fault. + * @returns True = there is currently NOT a fault. */ bool io_faultLatch_getCurrentStatus(const FaultLatch *latch); /** * Return whether or not a fault has been latched. * @param latch Fault latch instance. - * @param fault True = fault has NOT been latched. + * @returns True = fault has NOT been latched. */ bool io_faultLatch_getLatchedStatus(const FaultLatch *latch); \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/io/io_sd.h b/firmware/quadruna/BMS/src/io/io_sd.h index 4186cc8cd4..1e4f16f7ec 100644 --- a/firmware/quadruna/BMS/src/io/io_sd.h +++ b/firmware/quadruna/BMS/src/io/io_sd.h @@ -1,7 +1,6 @@ #pragma once #include -#include "app_utils.h" #ifdef TARGET_EMBEDDED #include "hw_gpio.h" @@ -11,6 +10,7 @@ typedef struct const Gpio sd_present; } SdGpio; #else +#include "app_utils.h" EMPTY_STRUCT(SdGpio); #endif diff --git a/firmware/quadruna/BMS/src/io/io_thermistors.c b/firmware/quadruna/BMS/src/io/io_thermistors.c index d2a40139c9..6cfed05801 100644 --- a/firmware/quadruna/BMS/src/io/io_thermistors.c +++ b/firmware/quadruna/BMS/src/io/io_thermistors.c @@ -1,5 +1,6 @@ #include "io_thermistors.h" -#include "hw_hal.h" +#include "hw_gpios.h" +#include "hw_adcs.h" #define SIZE_OF_TEMPERATURE_LUT (201U) #define BIAS_RESISTOR_OHM (10000.0f) @@ -7,8 +8,6 @@ #define THERM_INDEX_TO_DEGC (0.5f) #define THERM_LOOKUP_STARTING_TEMP (255.0f) -static const ThermistorsConfig *config = NULL; - // A 0-100°C temperature reverse lookup table with 0.5°C resolution for a Mitsubishi // DTN-V103J3T-DGS103V thermistor. The 0th index represents 0°C. Incrementing the // index represents a 0.5°C increase in temperature. @@ -30,22 +29,17 @@ static const float temp_resistance_lut[SIZE_OF_TEMPERATURE_LUT] = { 1381.1f, 1358.5f, 1336.4f, 1314.6f, 1293.3f, 1272.4f, 1251.8f }; -void io_thermistors_init(const ThermistorsConfig *therm_config) -{ - config = therm_config; -} - -void io_thermistors_muxSelect(uint8_t channel) +void io_thermistors_muxSelect(const uint8_t channel) { - hw_gpio_writePin(&config->mux_0_gpio, channel & 1 << 0); - hw_gpio_writePin(&config->mux_1_gpio, channel & 1 << 1); - hw_gpio_writePin(&config->mux_2_gpio, channel & 1 << 2); - hw_gpio_writePin(&config->mux_3_gpio, channel & 1 << 3); + hw_gpio_writePin(&mux_0_gpio, channel & 1 << 0); + hw_gpio_writePin(&mux_1_gpio, channel & 1 << 1); + hw_gpio_writePin(&mux_2_gpio, channel & 1 << 2); + hw_gpio_writePin(&mux_3_gpio, channel & 1 << 3); } float io_thermistors_readSelectedTemp(void) { - float raw_voltage = hw_adc_getVoltage(config->thermistor_adc_channel); + const float raw_voltage = hw_adc_getVoltage(&aux_tsns); // The following configuration is now the thermistor temperature is // calculated diff --git a/firmware/quadruna/BMS/src/io/io_thermistors.h b/firmware/quadruna/BMS/src/io/io_thermistors.h index e7a5c72531..91ab69f4e6 100644 --- a/firmware/quadruna/BMS/src/io/io_thermistors.h +++ b/firmware/quadruna/BMS/src/io/io_thermistors.h @@ -1,30 +1,6 @@ #pragma once #include -#include -#include "app_utils.h" - -#ifdef TARGET_EMBEDDED -#include "hw_gpio.h" -#include "hw_adc.h" - -typedef struct -{ - const Gpio mux_0_gpio; - const Gpio mux_1_gpio; - const Gpio mux_2_gpio; - const Gpio mux_3_gpio; - const AdcChannel *thermistor_adc_channel; -} ThermistorsConfig; -#else -EMPTY_STRUCT(ThermistorsConfig); -#endif - -/** - * Initialize the thermistors driver. - * @param therm_config Config struct. - */ -void io_thermistors_init(const ThermistorsConfig *therm_config); /** * Change the selected Mux Channel diff --git a/firmware/quadruna/BMS/src/io/io_tractiveSystem.h b/firmware/quadruna/BMS/src/io/io_tractiveSystem.h index 953d934a8c..1d791f8727 100644 --- a/firmware/quadruna/BMS/src/io/io_tractiveSystem.h +++ b/firmware/quadruna/BMS/src/io/io_tractiveSystem.h @@ -1,7 +1,5 @@ #pragma once -#include "app_utils.h" - #ifdef TARGET_EMBEDDED #include "hw_adc.h" @@ -13,6 +11,7 @@ typedef struct const AdcChannel *ts_isense_low_res_channel; } TractiveSystemConfig; #else +#include "app_utils.h" EMPTY_STRUCT(TractiveSystemConfig); #endif diff --git a/firmware/quadruna/BMS/src/jobs.c b/firmware/quadruna/BMS/src/jobs.c new file mode 100644 index 0000000000..bc84450448 --- /dev/null +++ b/firmware/quadruna/BMS/src/jobs.c @@ -0,0 +1,61 @@ +#include "jobs.h" + +#include "app_canTx.h" +#include "app_canRx.h" +#include "app_accumulator.h" +#include "app_soc.h" +#include "app_stateMachine.h" +#include "states/app_initState.h" +#include "app_commitInfo.h" +#include "app_heartbeatMonitors.h" + +#include "io_canMsg.h" +#include "io_canQueue.h" +#include "io_cans.h" +#include "io_jsoncan.h" + +static void jsoncan_transmit(const JsonCanMsg *tx_msg) +{ + const CanMsg msg = io_jsoncan_copyToCanMsg(tx_msg); + io_canQueue_pushTx(&msg); +} + +void jobs_init(void) +{ + io_can_init(&can1); + io_canQueue_init(); + io_canTx_init(jsoncan_transmit); + io_canTx_enableMode(CAN_MODE_DEFAULT, true); + + app_canTx_init(); + app_canRx_init(); + app_accumulator_init(); + app_tractiveSystem_init(); + // Re-enable if auxiliary thermistors installed + // app_thermistors_init(); + app_soc_init(); + + app_stateMachine_init(app_initState_get()); + app_heartbeatMonitor_init(&hb_monitor); + + // broadcast commit info + app_canTx_BMS_Hash_set(GIT_COMMIT_HASH); + app_canTx_BMS_Clean_set(GIT_COMMIT_CLEAN); +} +void jobs_run1Hz_tick(void) {} +void jobs_run100Hz_tick(void) {} +void jobs_run1kHz_tick(void) {} + +void jobs_runCanTx_tick(void) +{ + CanMsg tx_msg = io_canQueue_popTx(); + io_can_transmit(&can1, &tx_msg); +} + +void jobs_runCanRx_tick(void) +{ + const CanMsg rx_msg = io_canQueue_popRx(); + JsonCanMsg jsoncan_rx_msg = io_jsoncan_copyFromCanMsg(&rx_msg); + + io_canRx_updateRxTableWithMessage(&jsoncan_rx_msg); +} \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/jobs.h b/firmware/quadruna/BMS/src/jobs.h new file mode 100644 index 0000000000..03cf42d55a --- /dev/null +++ b/firmware/quadruna/BMS/src/jobs.h @@ -0,0 +1,19 @@ +/** + * This file is meant to help unit testing. + */ + +#pragma once + +/** + * Anything that needs to be initialized for unit testing must be put here + */ +void jobs_init(void); + +/** + * Anything that needs to run on periodic intervals in the unit test is to be placed here + */ +void jobs_run1Hz_tick(void); +void jobs_run100Hz_tick(void); +void jobs_run1kHz_tick(void); +void jobs_runCanTx_tick(void); +void jobs_runCanRx_tick(void); \ No newline at end of file diff --git a/firmware/quadruna/BMS/src/tasks.c b/firmware/quadruna/BMS/src/tasks.c index 9da0ed9281..5da4b04e03 100644 --- a/firmware/quadruna/BMS/src/tasks.c +++ b/firmware/quadruna/BMS/src/tasks.c @@ -1,10 +1,10 @@ #include "tasks.h" #include "main.h" +#include "jobs.h" #include "cmsis_os.h" -#include "hw_can.h" #include "hw_adcs.h" -#include "hw_gpio.h" +#include "hw_gpios.h" #include "hw_hardFaultHandler.h" #include "hw_bootup.h" #include "hw_utils.h" @@ -13,90 +13,27 @@ #include "hw_stackWaterMarkConfig.h" #include "hw_watchdogConfig.h" #include "hw_watchdog.h" -#include "hw_uart.h" +#include "hw_uarts.h" #include "hw_sd.h" #include "hw_crc.h" #include "io_canTx.h" -#include "io_canRx.h" -#include "io_jsoncan.h" -#include "io_can.h" -#include "io_airs.h" #include "io_sd.h" #include "io_faultLatch.h" #include "io_imd.h" #include "ltc6813/io_ltc6813Shared.h" -#include "io_thermistors.h" #include "io_tractiveSystem.h" #include "io_log.h" #include "io_chimera.h" #include "io_bmsShdn.h" -#include "io_bspdTest.h" -#include "app_canTx.h" #include "app_canRx.h" -#include "app_canAlerts.h" -#include "app_commitInfo.h" #include "app_accumulator.h" -#include "app_soc.h" #include "app_globals.h" -#include "states/app_initState.h" #include "app_stateMachine.h" #include "app_heartbeatMonitors.h" #include "shared.pb.h" -#include "BMS.pb.h" - -static void canRxQueueOverflowCallBack(uint32_t overflow_count) -{ - app_canTx_BMS_RxOverflowCount_set(overflow_count); - app_canAlerts_BMS_Warning_RxOverflow_set(true); - LOG_INFO("CAN RX QUEUE OVERFLOW, overflow_count = %d", overflow_count); -} - -static void canTxQueueOverflowCallBack(uint32_t overflow_count) -{ - app_canTx_BMS_TxOverflowCount_set(overflow_count); - app_canAlerts_BMS_Warning_TxOverflow_set(true); - LOG_INFO("CAN TX QUEUE OVERFLOW, overflow_count = %d", overflow_count); -} - -void canTxQueueOverflowClearCallback(void) -{ - app_canAlerts_BMS_Warning_TxOverflow_set(false); -} - -void canRxQueueOverflowClearCallback(void) -{ - app_canAlerts_BMS_Warning_RxOverflow_set(false); -} - -static const CanConfig can_config = { - .rx_msg_filter = io_canRx_filterMessageId, - .tx_overflow_callback = canTxQueueOverflowCallBack, - .rx_overflow_callback = canRxQueueOverflowCallBack, - .tx_overflow_clear_callback = canTxQueueOverflowClearCallback, - .rx_overflow_clear_callback = canRxQueueOverflowClearCallback, -}; - -// clang-format off -static const Gpio accel_brake_ok_pin = { .port = ACCEL_BRAKE_OK_3V3_GPIO_Port, .pin = ACCEL_BRAKE_OK_3V3_Pin }; -static const Gpio led_pin = { .port = LED_GPIO_Port, .pin = LED_Pin }; -static const Gpio n_chimera_pin = { .port = nCHIMERA_GPIO_Port, .pin = nCHIMERA_Pin }; -static const Gpio n_program_pin = { .port = nPROGRAM_3V3_GPIO_Port, .pin = nPROGRAM_3V3_Pin }; -static const Gpio ts_ilck_shdn_pin = { .port = TS_ILCK_SHDN_OK_GPIO_Port, .pin = TS_ILCK_SHDN_OK_Pin }; -static const Gpio hvd_ok_shdn_pin = { .port = HVD_SHDN_OK_GPIO_Port, .pin = HVD_SHDN_OK_Pin }; -static const Gpio ts_isense_ocsc_ok_pin = { .port = TS_ISENSE_OCSC_OK_3V3_GPIO_Port, .pin = TS_ISENSE_OCSC_OK_3V3_Pin }; -static const Gpio sd_cd_pin = { .port = SD_CD_GPIO_Port, .pin = SD_CD_Pin }; -static const Gpio spi_cs_pin = { .port = SPI_CS_GPIO_Port, .pin = SPI_CS_Pin }; -// clang-format on - -static SdCard sd = { - .hsd = &hsd1, - .timeout = 0x20, // osWaitForever, - // .sd_present = { .port = SD_CD_GPIO_Port, .pin = SD_CD_Pin }, - .sd_init_complete = false, -}; static const PwmInputConfig imd_pwm_input_config = { .htim = &htim1, @@ -105,8 +42,6 @@ static const PwmInputConfig imd_pwm_input_config = { .falling_edge_tim_channel = TIM_CHANNEL_2, }; -static const CanHandle can = { .can = &hfdcan1, .can_msg_received_callback = io_can_pushRxMsgToQueue }; - static const SpiInterface ltc6813_spi = { .spi_handle = &hspi2, .nss_port = SPI_CS_GPIO_Port, .nss_pin = SPI_CS_Pin, @@ -117,127 +52,10 @@ static const SdGpio sd_gpio = { .sd_present = { .pin = SD_CD_Pin, } }; -static const ThermistorsConfig thermistors_config = {.mux_0_gpio = { - .port = AUX_TSENSE_MUX0_GPIO_Port, - .pin = AUX_TSENSE_MUX0_Pin, - }, - .mux_1_gpio = { - .port = AUX_TSENSE_MUX1_GPIO_Port, - .pin = AUX_TSENSE_MUX1_Pin, - }, - .mux_2_gpio = { - .port = AUX_TSENSE_MUX2_GPIO_Port, - .pin = AUX_TSENSE_MUX2_Pin, - }, - .mux_3_gpio = { - .port = AUX_TSENSE_MUX3_GPIO_Port, - .pin = AUX_TSENSE_MUX3_Pin, - }, - .thermistor_adc_channel = &aux_tsns - }; - -static const AirsConfig airs_config = { .air_p_gpio = { - .port = AIR_P_EN_GPIO_Port, - .pin = AIR_P_EN_Pin, - }, - .air_n_gpio = { - .port = HVD_SHDN_OK_GPIO_Port, - .pin = HVD_SHDN_OK_Pin, - }, - .precharge_gpio = { - .port = PRE_CHARGE_EN_GPIO_Port, - .pin = PRE_CHARGE_EN_Pin, - } -}; - static const TractiveSystemConfig ts_config = { .ts_vsense_channel_P = &ts_vsense_p, .ts_vsense_channel_N = &ts_vsense_n, .ts_isense_high_res_channel = &ts_isns_75a, - .ts_isense_low_res_channel = &ts_isns_400a - -}; - -static const FaultLatch bms_ok_latch = { - .current_status_gpio = { - .port = BMS_OK_3V3_GPIO_Port, - .pin = BMS_OK_3V3_Pin, - }, - .latch_status_gpio = { - .port = BMS_LATCH_GPIO_Port, - .pin = BMS_LATCH_Pin, - }, - .read_only = false, -}; - -static const FaultLatch imd_ok_latch = { - .current_status_gpio = { - .port = IMD_OK_3V3_GPIO_Port, - .pin = IMD_OK_3V3_Pin, - }, - .latch_status_gpio = { - .port = IMD_LATCH_GPIO_Port, - .pin = IMD_LATCH_Pin, - }, - .read_only = true, -}; - -static const FaultLatch bspd_ok_latch = { - .current_status_gpio = { - .port = BSPD_OK_3V3_GPIO_Port, - .pin = BSPD_OK_3V3_Pin, - }, - .latch_status_gpio = { - .port = BSPD_LATCH_GPIO_Port, - .pin = BSPD_LATCH_Pin, - }, - .read_only = true, -}; - -static const BSPDTestConfig bspd_test_config = { - .test_enable_gpio = { .port = BSPD_TEST_EN_GPIO_Port, .pin = BSPD_TEST_EN_Pin }, - .n_high_current_gpio = { .port = nHIGH_CURRENT_BSPD_3V3_GPIO_Port, .pin = nHIGH_CURRENT_BSPD_3V3_Pin } -}; - -static const GlobalsConfig globals_config = { .bms_ok_latch = &bms_ok_latch, - .imd_ok_latch = &imd_ok_latch, - .bspd_ok_latch = &bspd_ok_latch }; - -const Gpio *id_to_gpio[] = { [BMS_GpioNetName_ACCEL_BRAKE_OK_3V3] = &accel_brake_ok_pin, - [BMS_GpioNetName_AIR_P_EN] = &airs_config.air_p_gpio, - [BMS_GpioNetName_AUX_TSENSE_MUX0] = &thermistors_config.mux_0_gpio, - [BMS_GpioNetName_AUX_TSENSE_MUX1] = &thermistors_config.mux_1_gpio, - [BMS_GpioNetName_AUX_TSENSE_MUX2] = &thermistors_config.mux_2_gpio, - [BMS_GpioNetName_AUX_TSENSE_MUX3] = &thermistors_config.mux_3_gpio, - [BMS_GpioNetName_BMS_LATCH] = &bms_ok_latch.latch_status_gpio, - [BMS_GpioNetName_BMS_OK_3V3] = &bms_ok_latch.current_status_gpio, - [BMS_GpioNetName_BSPD_LATCH] = &bspd_ok_latch.latch_status_gpio, - [BMS_GpioNetName_BSPD_OK_3V3] = &bspd_ok_latch.current_status_gpio, - [BMS_GpioNetName_BSPD_TEST_EN] = &bspd_test_config.test_enable_gpio, - [BMS_GpioNetName_HVD_SHDN_OK] = &airs_config.air_n_gpio, - [BMS_GpioNetName_IMD_LATCH] = &imd_ok_latch.latch_status_gpio, - [BMS_GpioNetName_IMD_OK_3V3] = &imd_ok_latch.current_status_gpio, - [BMS_GpioNetName_LED] = &led_pin, - [BMS_GpioNetName_NCHIMERA] = &n_chimera_pin, - [BMS_GpioNetName_NHIGH_CURRENT_BSPD_3V3] = &bspd_test_config.n_high_current_gpio, - [BMS_GpioNetName_NPROGRAM_3V3] = &n_program_pin, - [BMS_GpioNetName_PRE_CHARGE_EN] = &airs_config.precharge_gpio, - [BMS_GpioNetName_TS_ILCK_SHDN_OK] = &ts_ilck_shdn_pin, - [BMS_GpioNetName_TS_ISENSE_OCSC_OK_3V3] = &ts_isense_ocsc_ok_pin, - [BMS_GpioNetName_SD_CD] = &sd_cd_pin, - [BMS_GpioNetName_SPI_CS] = &spi_cs_pin }; - -const AdcChannel *id_to_adc[] = { - [BMS_AdcNetName_AUX_TSENSE] = &aux_tsns, [BMS_AdcNetName_TS_ISENSE_400A] = &ts_isns_400a, - [BMS_AdcNetName_TS_ISENSE_75A] = &ts_isns_75a, [BMS_AdcNetName_TS_VSENSE_P] = &ts_vsense_p, - [BMS_AdcNetName_TS_VSENSE_N] = &ts_vsense_n, -}; - -static const UART debug_uart = { .handle = &huart1 }; - -static const BmsShdnConfig bms_shdn_pin_config = { - .ts_ilck_ok_gpio = ts_ilck_shdn_pin, - .hvd_ok_gpio = hvd_ok_shdn_pin, -}; + .ts_isense_low_res_channel = &ts_isns_400a }; void tasks_preInit(void) { @@ -260,41 +78,16 @@ void tasks_init(void) hw_adcs_chipsInit(); hw_hardFaultHandler_init(); - hw_can_init(&can); - hw_sd_init(&sd); hw_crc_init(&hcrc); hw_watchdog_init(hw_watchdogConfig_refresh, hw_watchdogConfig_timeoutCallback); - io_canTx_init(io_jsoncan_pushTxMsgToQueue); - io_canTx_enableMode(CAN_MODE_DEFAULT, true); - io_can_init(&can_config); - io_bmsShdn_init(&bms_shdn_pin_config); io_tractiveSystem_init(&ts_config); - io_thermistors_init(&thermistors_config); io_ltc6813Shared_init(<c6813_spi); - io_airs_init(&airs_config); io_imd_init(&imd_pwm_input_config); - io_chimera_init(&debug_uart, GpioNetName_bms_net_name_tag, AdcNetName_bms_net_name_tag, &n_chimera_pin); + io_chimera_init(GpioNetName_bms_net_name_tag, AdcNetName_bms_net_name_tag); io_sdGpio_init(&sd_gpio); - io_bspdTest_init(&bspd_test_config); - - app_canTx_init(); - app_canRx_init(); - - app_accumulator_init(); - app_tractiveSystem_init(); - - // Re-enable if auxiliary thermistors installed - // app_thermistors_init(); - - app_soc_init(); - app_globals_init(&globals_config); - app_stateMachine_init(app_initState_get()); - app_heartbeatMonitor_init(&hb_monitor); - // broadcast commit info - app_canTx_BMS_Hash_set(GIT_COMMIT_HASH); - app_canTx_BMS_Clean_set(GIT_COMMIT_CLEAN); + app_globals_init(); } _Noreturn void tasks_run1Hz(void) @@ -388,11 +181,7 @@ _Noreturn void tasks_runCanTx(void) io_chimera_sleepTaskIfEnabled(); for (;;) - { - CanMsg tx_msg; - io_can_popTxMsgFromQueue(&tx_msg); - io_can_transmitMsgFromQueue(&tx_msg); - } + jobs_runCanTx_tick(); } _Noreturn void tasks_runCanRx(void) @@ -400,14 +189,7 @@ _Noreturn void tasks_runCanRx(void) io_chimera_sleepTaskIfEnabled(); for (;;) - { - CanMsg rx_msg; - io_can_popRxMsgFromQueue(&rx_msg); - - JsonCanMsg jsoncan_rx_msg; - io_jsoncan_copyFromCanMsg(&rx_msg, &jsoncan_rx_msg); - io_canRx_updateRxTableWithMessage(&jsoncan_rx_msg); - } + jobs_runCanRx_tick(); } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) diff --git a/firmware/quadruna/BMS/test/test_bmsBaseStateMachineTest.h b/firmware/quadruna/BMS/test/test_bmsBaseStateMachineTest.h index 171a4bf986..95f11c90b3 100644 --- a/firmware/quadruna/BMS/test/test_bmsBaseStateMachineTest.h +++ b/firmware/quadruna/BMS/test/test_bmsBaseStateMachineTest.h @@ -18,11 +18,8 @@ extern "C" { #include "app_canTx.h" #include "app_canRx.h" -#include "app_canAlerts.h" -#include "app_canUtils.h" #include "app_heartbeatMonitors.h" #include "app_stateMachine.h" -#include "app_utils.h" #include "states/app_initState.h" #include "states/app_prechargeState.h" #include "states/app_driveState.h" @@ -55,7 +52,7 @@ class BmsBaseStateMachineTest : public BaseStateMachineTest app_tractiveSystem_init(); app_thermistors_init(); app_soc_init(); - app_globals_init(&globals_config); + app_globals_init(); app_soc_resetSocCustomValue(100.0f); @@ -109,16 +106,8 @@ class BmsBaseStateMachineTest : public BaseStateMachineTest app_balancingState_get() }; } - const ThermistorsConfig thermistors_config = {}; - const AirsConfig airs_config = {}; - const TractiveSystemConfig ts_config = {}; - const FaultLatch bms_ok_latch = {}; - const FaultLatch imd_ok_latch = {}; - const FaultLatch bspd_ok_latch = {}; - - const GlobalsConfig globals_config = { - .bms_ok_latch = &bms_ok_latch, - .imd_ok_latch = &imd_ok_latch, - .bspd_ok_latch = &bspd_ok_latch, - }; -}; \ No newline at end of file + const TractiveSystemConfig ts_config = {}; +}; +inline const FaultLatch bms_ok_latch = {}; +inline const FaultLatch imd_ok_latch = {}; +inline const FaultLatch bspd_ok_latch = {}; diff --git a/firmware/quadruna/CRIT/CMakeLists.txt b/firmware/quadruna/CRIT/CMakeLists.txt index e23c408031..ddcefc8525 100644 --- a/firmware/quadruna/CRIT/CMakeLists.txt +++ b/firmware/quadruna/CRIT/CMakeLists.txt @@ -21,6 +21,7 @@ list(APPEND IO_SRCS "${SHARED_IO_INCLUDE_DIR}/io_led.c" "${SHARED_IO_INCLUDE_DIR}/io_switch.c" "${SHARED_IO_INCLUDE_DIR}/io_can.c" + "${SHARED_IO_INCLUDE_DIR}/io_canQueue.c" "${SHARED_IO_INCLUDE_DIR}/io_jsoncan.c" "${SHARED_IO_INCLUDE_DIR}/io_time.c" "${SHARED_IO_INCLUDE_DIR}/io_chimera.c" @@ -36,7 +37,6 @@ file(GLOB_RECURSE HW_SRCS list(APPEND HW_SRCS "${SHARED_HW_INCLUDE_DIR}/hw_hardFaultHandler.c" "${SHARED_HW_INCLUDE_DIR}/hw_adc.c" - "${SHARED_HW_INCLUDE_DIR}/hw_can.c" "${SHARED_HW_INCLUDE_DIR}/hw_bootup.c" "${SHARED_HW_INCLUDE_DIR}/hw_pwmInputFreqOnly.c" "${SHARED_HW_INCLUDE_DIR}/hw_watchdog.c" diff --git a/firmware/quadruna/CRIT/boot/cubemx/Src/main.c b/firmware/quadruna/CRIT/boot/cubemx/Src/main.c index 680f946f3c..965740773f 100644 --- a/firmware/quadruna/CRIT/boot/cubemx/Src/main.c +++ b/firmware/quadruna/CRIT/boot/cubemx/Src/main.c @@ -23,9 +23,12 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "bootloader.h" -#include "hw_can.h" +#include "io_canQueue.h" #include "io_can.h" #include "hw_error.h" +#include "hw_utils.h" + +#include /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -86,10 +89,27 @@ const osThreadAttr_t tickTask_attributes = { .priority = (osPriority_t)osPriorityNormal, }; /* USER CODE BEGIN PV */ -CanHandle can = { - .can = &hcan1, - .can_msg_received_callback = io_can_pushRxMsgToQueue, -}; +CanHandle can = { .hcan = &hcan1 }; + +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) +{ + assert(hcan == can.hcan); + CanMsg rx_msg; + if (!io_can_receive(&can, CAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} + +void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) +{ + assert(hcan == can.hcan); + CanMsg rx_msg; + if (!io_can_receive(&can, CAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ @@ -141,7 +161,7 @@ int main(void) MX_CRC_Init(); /* USER CODE BEGIN 2 */ bootloader_init(); - hw_can_init(&can); + io_can_init(&can); /* USER CODE END 2 */ /* Init scheduler */ diff --git a/firmware/quadruna/CRIT/src/hw/hw_gpios.c b/firmware/quadruna/CRIT/src/hw/hw_gpios.c new file mode 100644 index 0000000000..04a5e42e22 --- /dev/null +++ b/firmware/quadruna/CRIT/src/hw/hw_gpios.c @@ -0,0 +1,51 @@ +#include "hw_gpios.h" +#include "main.h" + +const Gpio ams_r_pin = { .port = AMS_R_GPIO_Port, .pin = AMS_R_Pin }; +const Gpio imd_r_pin = { .port = IMD_R_GPIO_Port, .pin = IMD_R_Pin }; +const Gpio bspd_r_pin = { .port = BSPD_R_GPIO_Port, .pin = BSPD_R_Pin }; +const Gpio shdn_r_pin = { .port = SHDN_R_GPIO_Port, .pin = SHDN_R_Pin }; +const Gpio shdn_g_pin = { .port = SHDN_G_GPIO_Port, .pin = SHDN_G_Pin }; + +const Gpio vc_r_pin = { .port = VC_R_GPIO_Port, .pin = VC_R_Pin }; +const Gpio vc_g_pin = { .port = VC_G_GPIO_Port, .pin = VC_G_Pin }; +const Gpio vc_b_pin = { .port = VC_B_GPIO_Port, .pin = VC_B_Pin }; + +const Gpio bms_r_pin = { .port = BMS_R_GPIO_Port, .pin = BMS_R_Pin }; +const Gpio bms_g_pin = { .port = BMS_G_GPIO_Port, .pin = BMS_G_Pin }; +const Gpio bms_b_pin = { .port = BMS_B_GPIO_Port, .pin = BMS_B_Pin }; + +const Gpio fsm_r_pin = { .port = FSM_R_GPIO_Port, .pin = FSM_R_Pin }; +const Gpio fsm_g_pin = { .port = FSM_G_GPIO_Port, .pin = FSM_G_Pin }; +const Gpio fsm_b_pin = { .port = FSM_B_GPIO_Port, .pin = FSM_B_Pin }; + +const Gpio rsm_r_pin = { .port = RSM_R_GPIO_Port, .pin = RSM_R_Pin }; +const Gpio rsm_g_pin = { .port = RSM_G_GPIO_Port, .pin = RSM_G_Pin }; +const Gpio rsm_b_pin = { .port = RSM_B_GPIO_Port, .pin = RSM_B_Pin }; + +const Gpio aux_r_pin = { .port = AUX_DB_R_GPIO_Port, .pin = AUX_DB_R_Pin }; +const Gpio aux_g_pin = { .port = AUX_DB_G_GPIO_Port, .pin = AUX_DB_G_Pin }; +const Gpio aux_b_pin = { .port = AUX_DB_B_GPIO_Port, .pin = AUX_DB_B_Pin }; + +const Gpio crit_r_pin = { .port = CRIT_DB_R_GPIO_Port, .pin = CRIT_DB_R_Pin }; +const Gpio crit_g_pin = { .port = CRIT_DB_G_GPIO_Port, .pin = CRIT_DB_G_Pin }; +const Gpio crit_b_pin = { .port = CRIT_DB_B_GPIO_Port, .pin = CRIT_DB_B_Pin }; + +const Gpio start_led_pin = { .port = START_LED_GPIO_Port, .pin = START_LED_Pin }; +const Gpio torque_vectoring_led_pin = { .port = TORQUE_VECTORING_LED_GPIO_Port, .pin = TORQUE_VECTORING_LED_Pin }; +const Gpio regen_led_pin = { .port = REGEN_LED_GPIO_Port, .pin = REGEN_LED_Pin }; +const Gpio led_pin = { .port = LED_GPIO_Port, .pin = LED_Pin }; + +const Gpio start_sig_pin = { .port = START_SIG_GPIO_Port, .pin = START_SIG_Pin }; +const Gpio torque_vectoring_sig_pin = { .port = TORQUE_VECTORING_SIG_GPIO_Port, .pin = TORQUE_VECTORING_SIG_Pin }; +const Gpio regen_sig_pin = { .port = REGEN_SIG_GPIO_Port, .pin = REGEN_SIG_Pin }; + +const Gpio n_drive_mode_0_pin = { .port = NDRIVE_MODE_0b_GPIO_Port, .pin = NDRIVE_MODE_0b_Pin }; +const Gpio n_drive_mode_1_pin = { .port = NDRIVE_MODE_1b_GPIO_Port, .pin = NDRIVE_MODE_1b_Pin }; +const Gpio n_drive_mode_2_pin = { .port = NDRIVE_MODE_2b_GPIO_Port, .pin = NDRIVE_MODE_2b_Pin }; +const Gpio n_drive_mode_3_pin = { .port = NDRIVE_MODE_3b_GPIO_Port, .pin = NDRIVE_MODE_3b_Pin }; + +const Gpio n_program_pin = { .port = NPROGRAM_3V3_GPIO_Port, .pin = NPROGRAM_3V3_Pin }; +const Gpio n_chimera_pin = { .port = NCHIMERA_GPIO_Port, .pin = NCHIMERA_Pin }; +const Gpio shdn_sen_pin = { .port = SHDN_SEN_GPIO_Port, .pin = SHDN_SEN_Pin }; +const Gpio inertia_sen_pin = { .port = INERTIA_SEN_GPIO_Port, .pin = INERTIA_SEN_Pin }; diff --git a/firmware/quadruna/CRIT/src/hw/hw_gpios.h b/firmware/quadruna/CRIT/src/hw/hw_gpios.h new file mode 100644 index 0000000000..d49a7b018a --- /dev/null +++ b/firmware/quadruna/CRIT/src/hw/hw_gpios.h @@ -0,0 +1,51 @@ +#pragma once +#include "hw_gpio.h" + +extern const Gpio ams_r_pin; +extern const Gpio imd_r_pin; +extern const Gpio bspd_r_pin; +extern const Gpio shdn_r_pin; +extern const Gpio shdn_g_pin; + +extern const Gpio vc_r_pin; +extern const Gpio vc_g_pin; +extern const Gpio vc_b_pin; + +extern const Gpio bms_r_pin; +extern const Gpio bms_g_pin; +extern const Gpio bms_b_pin; + +extern const Gpio fsm_r_pin; +extern const Gpio fsm_g_pin; +extern const Gpio fsm_b_pin; + +extern const Gpio rsm_r_pin; +extern const Gpio rsm_g_pin; +extern const Gpio rsm_b_pin; + +extern const Gpio aux_r_pin; +extern const Gpio aux_g_pin; +extern const Gpio aux_b_pin; + +extern const Gpio crit_r_pin; +extern const Gpio crit_g_pin; +extern const Gpio crit_b_pin; + +extern const Gpio start_led_pin; +extern const Gpio torque_vectoring_led_pin; +extern const Gpio regen_led_pin; +extern const Gpio led_pin; + +extern const Gpio start_sig_pin; +extern const Gpio torque_vectoring_sig_pin; +extern const Gpio regen_sig_pin; + +extern const Gpio n_drive_mode_0_pin; +extern const Gpio n_drive_mode_1_pin; +extern const Gpio n_drive_mode_2_pin; +extern const Gpio n_drive_mode_3_pin; + +extern const Gpio n_program_pin; +extern const Gpio n_chimera_pin; +extern const Gpio shdn_sen_pin; +extern const Gpio inertia_sen_pin; \ No newline at end of file diff --git a/firmware/quadruna/CRIT/src/io/io_critShdn.c b/firmware/quadruna/CRIT/src/io/io_critShdn.c index bffedede3a..9ed79ccdcc 100644 --- a/firmware/quadruna/CRIT/src/io/io_critShdn.c +++ b/firmware/quadruna/CRIT/src/io/io_critShdn.c @@ -9,10 +9,10 @@ void io_critShdn_init(const CritShdnConfig *crit_shdn_config) bool io_critShdn_COCKPIT_ESTOP_OK_get(void) { - return hw_gpio_readPin(&shdn_config->cockpit_estop_gpio); + return hw_gpio_readPin(shdn_config->cockpit_estop_gpio); } bool io_critShdn_get_INERTIA_SEN_OK_get(void) { - return hw_gpio_readPin(&shdn_config->inertia_sen_ok_gpio); + return hw_gpio_readPin(shdn_config->inertia_sen_ok_gpio); } diff --git a/firmware/quadruna/CRIT/src/io/io_critShdn.h b/firmware/quadruna/CRIT/src/io/io_critShdn.h index 0714cd4c8d..76db4a6d4b 100644 --- a/firmware/quadruna/CRIT/src/io/io_critShdn.h +++ b/firmware/quadruna/CRIT/src/io/io_critShdn.h @@ -1,17 +1,17 @@ #pragma once #include -#include "app_utils.h" #ifdef TARGET_EMBEDDED #include "hw_gpio.h" typedef struct { - const Gpio cockpit_estop_gpio; - const Gpio inertia_sen_ok_gpio; + const Gpio *cockpit_estop_gpio; + const Gpio *inertia_sen_ok_gpio; } CritShdnConfig; #else +#include "app_utils.h" EMPTY_STRUCT(CritShdnConfig); #endif diff --git a/firmware/quadruna/CRIT/src/io/io_driveMode.h b/firmware/quadruna/CRIT/src/io/io_driveMode.h index e47f692360..9982427dfb 100644 --- a/firmware/quadruna/CRIT/src/io/io_driveMode.h +++ b/firmware/quadruna/CRIT/src/io/io_driveMode.h @@ -1,7 +1,5 @@ #pragma once -#include -#include "app_utils.h" #include #ifdef TARGET_EMBEDDED @@ -15,6 +13,7 @@ typedef struct const Gpio *const n_drive_mode_3_pin; } DriveMode; #else +#include "app_utils.h" EMPTY_STRUCT(DriveMode); #endif diff --git a/firmware/quadruna/CRIT/src/tasks.c b/firmware/quadruna/CRIT/src/tasks.c index 7fdbb75793..1c4fc4dd52 100644 --- a/firmware/quadruna/CRIT/src/tasks.c +++ b/firmware/quadruna/CRIT/src/tasks.c @@ -17,6 +17,7 @@ #include "io_critShdn.h" #include "io_leds.h" #include "io_switches.h" +#include "io_canQueue.h" // can #include "io_jsoncan.h" #include "io_can.h" @@ -27,7 +28,7 @@ #include "app_canAlerts.h" #include "app_commitInfo.h" // hw -#include "hw_gpio.h" +#include "hw_gpios.h" #include "hw_adcs.h" #include "hw_uart.h" #include "hw_utils.h" @@ -37,7 +38,7 @@ #include "hw_stackWaterMarkConfig.h" #include "hw_hardFaultHandler.h" -static const CanHandle can = { .can = &hcan1, .can_msg_received_callback = io_can_pushRxMsgToQueue }; +static const CanHandle can = { .hcan = &hcan1 }; void canTxQueueOverflowCallback(uint32_t overflow_count) { @@ -63,36 +64,12 @@ void canRxQueueOverflowClearCallback(void) app_canAlerts_CRIT_Warning_RxOverflow_set(false); } -static const CanConfig can_config = { .rx_msg_filter = io_canRx_filterMessageId, - .tx_overflow_callback = canTxQueueOverflowCallback, - .rx_overflow_callback = canRxQueueOverflowCallback, - .tx_overflow_clear_callback = canTxQueueOverflowClearCallback, - .rx_overflow_clear_callback = canRxQueueOverflowClearCallback }; - -static const BinaryLed imd_led = { .gpio = { - .port = IMD_R_GPIO_Port, - .pin = IMD_R_Pin, - } }; -static const BinaryLed bspd_led = { .gpio = { - .port = BSPD_R_GPIO_Port, - .pin = BSPD_R_Pin, - } }; -static const BinaryLed ams_led = { .gpio = { - .port = AMS_R_GPIO_Port, - .pin = AMS_R_Pin, - } }; -static const BinaryLed start_led = { .gpio = { - .port = START_LED_GPIO_Port, - .pin = START_LED_Pin, - } }; -static const BinaryLed regen_led = { .gpio = { - .port = REGEN_LED_GPIO_Port, - .pin = REGEN_LED_Pin, - } }; -static const BinaryLed torquevec_led = { .gpio = { - .port = TORQUE_VECTORING_LED_GPIO_Port, - .pin = TORQUE_VECTORING_LED_Pin, - } }; +static const BinaryLed imd_led = { .gpio = &imd_r_pin }; +static const BinaryLed bspd_led = { .gpio = &bspd_r_pin }; +static const BinaryLed ams_led = { .gpio = &ams_r_pin }; +static const BinaryLed start_led = { .gpio = &start_led_pin }; +static const BinaryLed regen_led = { .gpio = ®en_led_pin }; +static const BinaryLed torquevec_led = { .gpio = &torque_vectoring_led_pin }; static const Switch start_switch = { .gpio = { @@ -222,57 +199,6 @@ static const RgbLed crit_status_led = { }, }; -// clang-format off -static const Gpio ams_r_pin = { .port = AMS_R_GPIO_Port, .pin = AMS_R_Pin }; -static const Gpio imd_r_pin = { .port = IMD_R_GPIO_Port, .pin = IMD_R_Pin }; -static const Gpio bspd_r_pin = { .port = BSPD_R_GPIO_Port, .pin = BSPD_R_Pin }; -static const Gpio shdn_r_pin = { .port = SHDN_R_GPIO_Port, .pin = SHDN_R_Pin }; -static const Gpio shdn_g_pin = { .port = SHDN_G_GPIO_Port, .pin = SHDN_G_Pin }; - -static const Gpio vc_r_pin = { .port = VC_R_GPIO_Port, .pin = VC_R_Pin }; -static const Gpio vc_g_pin = { .port = VC_G_GPIO_Port, .pin = VC_G_Pin }; -static const Gpio vc_b_pin = { .port = VC_B_GPIO_Port, .pin = VC_B_Pin }; - -static const Gpio bms_r_pin = { .port = BMS_R_GPIO_Port, .pin = BMS_R_Pin }; -static const Gpio bms_g_pin = { .port = BMS_G_GPIO_Port, .pin = BMS_G_Pin }; -static const Gpio bms_b_pin = { .port = BMS_B_GPIO_Port, .pin = BMS_B_Pin }; - -static const Gpio fsm_r_pin = { .port = FSM_R_GPIO_Port, .pin = FSM_R_Pin }; -static const Gpio fsm_g_pin = { .port = FSM_G_GPIO_Port, .pin = FSM_G_Pin }; -static const Gpio fsm_b_pin = { .port = FSM_B_GPIO_Port, .pin = FSM_B_Pin }; - -static const Gpio rsm_r_pin = { .port = RSM_R_GPIO_Port, .pin = RSM_R_Pin }; -static const Gpio rsm_g_pin = { .port = RSM_G_GPIO_Port, .pin = RSM_G_Pin }; -static const Gpio rsm_b_pin = { .port = RSM_B_GPIO_Port, .pin = RSM_B_Pin }; - -static const Gpio aux_r_pin = { .port = AUX_DB_R_GPIO_Port, .pin = AUX_DB_R_Pin }; -static const Gpio aux_g_pin = { .port = AUX_DB_G_GPIO_Port, .pin = AUX_DB_G_Pin }; -static const Gpio aux_b_pin = { .port = AUX_DB_B_GPIO_Port, .pin = AUX_DB_B_Pin }; - -static const Gpio crit_r_pin = { .port = CRIT_DB_R_GPIO_Port, .pin = CRIT_DB_R_Pin }; -static const Gpio crit_g_pin = { .port = CRIT_DB_G_GPIO_Port, .pin = CRIT_DB_G_Pin }; -static const Gpio crit_b_pin = { .port = CRIT_DB_B_GPIO_Port, .pin = CRIT_DB_B_Pin }; - -static const Gpio start_led_pin = { .port = START_LED_GPIO_Port, .pin = START_LED_Pin }; -static const Gpio torque_vectoring_led_pin = { .port = TORQUE_VECTORING_LED_GPIO_Port, .pin = TORQUE_VECTORING_LED_Pin }; -static const Gpio regen_led_pin = { .port = REGEN_LED_GPIO_Port, .pin = REGEN_LED_Pin }; -static const Gpio led_pin = { .port = LED_GPIO_Port, .pin = LED_Pin }; - -static const Gpio start_sig_pin = { .port = START_SIG_GPIO_Port, .pin = START_SIG_Pin }; -static const Gpio torque_vectoring_sig_pin = { .port = TORQUE_VECTORING_SIG_GPIO_Port, .pin = TORQUE_VECTORING_SIG_Pin }; -static const Gpio regen_sig_pin = { .port = REGEN_SIG_GPIO_Port, .pin = REGEN_SIG_Pin }; - -static const Gpio n_drive_mode_0_pin = { .port = NDRIVE_MODE_0b_GPIO_Port, .pin = NDRIVE_MODE_0b_Pin }; -static const Gpio n_drive_mode_1_pin = { .port = NDRIVE_MODE_1b_GPIO_Port, .pin = NDRIVE_MODE_1b_Pin }; -static const Gpio n_drive_mode_2_pin = { .port = NDRIVE_MODE_2b_GPIO_Port, .pin = NDRIVE_MODE_2b_Pin }; -static const Gpio n_drive_mode_3_pin = { .port = NDRIVE_MODE_3b_GPIO_Port, .pin = NDRIVE_MODE_3b_Pin }; - -static const Gpio n_program_pin = { .port = NPROGRAM_3V3_GPIO_Port, .pin = NPROGRAM_3V3_Pin }; -static const Gpio n_chimera_pin = { .port = NCHIMERA_GPIO_Port, .pin = NCHIMERA_Pin }; -static const Gpio shdn_sen_pin = { .port = SHDN_SEN_GPIO_Port, .pin = SHDN_SEN_Pin }; -static const Gpio inertia_sen_pin = { .port = INERTIA_SEN_GPIO_Port, .pin = INERTIA_SEN_Pin }; -// clang-format on - static const DriveMode drive_mode = { .n_drive_mode_0_pin = &n_drive_mode_0_pin, .n_drive_mode_1_pin = &n_drive_mode_1_pin, .n_drive_mode_2_pin = &n_drive_mode_2_pin, @@ -325,6 +251,9 @@ const AdcChannel *id_to_adc[] = { static const UART debug_uart = { .handle = &huart2 }; +const UART *chimera_uart = &debug_uart; +const Gpio *n_chimera_gpio = &n_chimera_pin; + static const Leds led_config = { .imd_led = &imd_led, .bspd_led = &bspd_led, @@ -347,14 +276,20 @@ static const Switches switch_config = { .torquevec_switch = &torquevec_switch, }; -static const CritShdnConfig crit_shdn_pin_config = { .cockpit_estop_gpio = shdn_sen_pin, - .inertia_sen_ok_gpio = inertia_sen_pin }; +static const CritShdnConfig crit_shdn_pin_config = { .cockpit_estop_gpio = &shdn_sen_pin, + .inertia_sen_ok_gpio = &inertia_sen_pin }; void tasks_preInit(void) { hw_bootup_enableInterruptsForApp(); } +static void jsoncan_transmit(const JsonCanMsg *tx_msg) +{ + const CanMsg msg = io_jsoncan_copyToCanMsg(tx_msg); + io_canQueue_pushTx(&msg); +} + void tasks_init(void) { // Configure and initialize SEGGER SystemView. @@ -365,19 +300,19 @@ void tasks_init(void) // Start DMA/TIM3 for the ADC. hw_adcs_chipsInit(); - io_chimera_init(&debug_uart, GpioNetName_crit_net_name_tag, AdcNetName_crit_net_name_tag, &n_chimera_pin); + io_chimera_init(GpioNetName_crit_net_name_tag, AdcNetName_crit_net_name_tag); // Re-enable watchdog. __HAL_DBGMCU_FREEZE_IWDG(); hw_hardFaultHandler_init(); - hw_can_init(&can); + io_can_init(&can); hw_watchdog_init(hw_watchdogConfig_refresh, hw_watchdogConfig_timeoutCallback); - io_canTx_init(io_jsoncan_pushTxMsgToQueue); + io_canTx_init(jsoncan_transmit); io_canTx_enableMode(CAN_MODE_DEFAULT, true); - io_can_init(&can_config); io_critShdn_init(&crit_shdn_pin_config); + io_canQueue_init(); io_led_init(&led_config); io_switches_init(&switch_config); @@ -427,9 +362,8 @@ _Noreturn void tasks_runCanTx(void) // Setup tasks. for (;;) { - CanMsg tx_msg; - io_can_popTxMsgFromQueue(&tx_msg); - io_can_transmitMsgFromQueue(&tx_msg); + CanMsg tx_msg = io_canQueue_popTx(); + io_can_transmit(&can, &tx_msg); } } @@ -440,11 +374,8 @@ _Noreturn void tasks_runCanRx(void) // Setup tasks. for (;;) { - CanMsg rx_msg; - io_can_popRxMsgFromQueue(&rx_msg); - - JsonCanMsg jsoncan_rx_msg; - io_jsoncan_copyFromCanMsg(&rx_msg, &jsoncan_rx_msg); + CanMsg rx_msg = io_canQueue_popRx(&rx_msg); + JsonCanMsg jsoncan_rx_msg = io_jsoncan_copyFromCanMsg(&rx_msg); io_canRx_updateRxTableWithMessage(&jsoncan_rx_msg); } } diff --git a/firmware/quadruna/FSM/CMakeLists.txt b/firmware/quadruna/FSM/CMakeLists.txt index 528e15d790..51840834f2 100644 --- a/firmware/quadruna/FSM/CMakeLists.txt +++ b/firmware/quadruna/FSM/CMakeLists.txt @@ -20,6 +20,7 @@ set(APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src/app" "${SHARED_APP_INCLUDE file(GLOB_RECURSE IO_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/io/*.c") list(APPEND IO_SRCS "${SHARED_IO_INCLUDE_DIR}/io_can.c" + "${SHARED_IO_INCLUDE_DIR}/io_canQueue.c" "${SHARED_IO_INCLUDE_DIR}/io_jsoncan.c" "${SHARED_IO_INCLUDE_DIR}/io_time.c" "${SHARED_IO_INCLUDE_DIR}/io_chimera.c" @@ -36,7 +37,6 @@ file(GLOB_RECURSE HW_SRCS list(APPEND HW_SRCS "${SHARED_HW_INCLUDE_DIR}/hw_hardFaultHandler.c" "${SHARED_HW_INCLUDE_DIR}/hw_adc.c" - "${SHARED_HW_INCLUDE_DIR}/hw_can.c" "${SHARED_HW_INCLUDE_DIR}/hw_bootup.c" "${SHARED_HW_INCLUDE_DIR}/hw_pwmInputFreqOnly.c" "${SHARED_HW_INCLUDE_DIR}/hw_watchdog.c" diff --git a/firmware/quadruna/FSM/boot/cubemx/Src/main.c b/firmware/quadruna/FSM/boot/cubemx/Src/main.c index 27efebfff7..447910549c 100644 --- a/firmware/quadruna/FSM/boot/cubemx/Src/main.c +++ b/firmware/quadruna/FSM/boot/cubemx/Src/main.c @@ -23,8 +23,11 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "bootloader.h" -#include "hw_can.h" +#include "io_canQueue.h" #include "io_can.h" +#include "hw_utils.h" + +#include /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -85,10 +88,27 @@ const osThreadAttr_t tickTask_attributes = { .priority = (osPriority_t)osPriorityNormal, }; /* USER CODE BEGIN PV */ -CanHandle can = { - .can = &hcan1, - .can_msg_received_callback = io_can_pushRxMsgToQueue, -}; +CanHandle can = { .hcan = &hcan1 }; + +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) +{ + assert(hcan == can.hcan); + CanMsg rx_msg; + if (!io_can_receive(&can, CAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} + +void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) +{ + assert(hcan == can.hcan); + CanMsg rx_msg; + if (!io_can_receive(&can, CAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ @@ -140,7 +160,7 @@ int main(void) MX_CRC_Init(); /* USER CODE BEGIN 2 */ bootloader_init(); - hw_can_init(&can); + io_can_init(&can); /* USER CODE END 2 */ /* Init scheduler */ diff --git a/firmware/quadruna/FSM/src/app/app_brake.c b/firmware/quadruna/FSM/src/app/app_brake.c index cc45909f31..14e88a53aa 100644 --- a/firmware/quadruna/FSM/src/app/app_brake.c +++ b/firmware/quadruna/FSM/src/app/app_brake.c @@ -3,6 +3,7 @@ #include "app_canTx.h" #include "app_canAlerts.h" #include "io_brake.h" +#include static const RangeCheck front_pressure_in_range_check = { .min_value = MIN_BRAKE_PRESSURE_PSI, .max_value = MAX_BRAKE_PRESSURE_PSI }; diff --git a/firmware/quadruna/FSM/src/hw/hw_gpios.c b/firmware/quadruna/FSM/src/hw/hw_gpios.c new file mode 100644 index 0000000000..574607b870 --- /dev/null +++ b/firmware/quadruna/FSM/src/hw/hw_gpios.c @@ -0,0 +1,9 @@ +#include "hw_gpios.h" +#include "main.h" + +const Gpio brake_ocsc_ok_3v3 = { .port = BRAKE_OCSC_OK_3V3_GPIO_Port, .pin = BRAKE_OCSC_OK_3V3_Pin }; +const Gpio n_chimera_pin = { .port = NCHIMERA_GPIO_Port, .pin = NCHIMERA_Pin }; +const Gpio led_gpio_pin = { .port = LED_GPIO_Port, .pin = LED_Pin }; +const Gpio nbspd_brake_pressed_3v3 = { .port = NBSPD_BRAKE_PRESSED_3V3_GPIO_Port, .pin = NBSPD_BRAKE_PRESSED_3V3_Pin }; +const Gpio nprogram_3v3 = { .port = NPROGRAM_3V3_GPIO_Port, .pin = NPROGRAM_3V3_Pin }; +const Gpio fsm_shdn = { .port = FSM_SHDN_GPIO_Port, .pin = FSM_SHDN_Pin }; diff --git a/firmware/quadruna/FSM/src/hw/hw_gpios.h b/firmware/quadruna/FSM/src/hw/hw_gpios.h new file mode 100644 index 0000000000..3e187aaec7 --- /dev/null +++ b/firmware/quadruna/FSM/src/hw/hw_gpios.h @@ -0,0 +1,9 @@ +#pragma once +#include "hw_gpio.h" + +extern const Gpio brake_ocsc_ok_3v3; +extern const Gpio n_chimera_pin; +extern const Gpio led_gpio_pin; +extern const Gpio nbspd_brake_pressed_3v3; +extern const Gpio nprogram_3v3; +extern const Gpio fsm_shdn; diff --git a/firmware/quadruna/FSM/src/hw/hw_uarts.c b/firmware/quadruna/FSM/src/hw/hw_uarts.c new file mode 100644 index 0000000000..c1d1278e41 --- /dev/null +++ b/firmware/quadruna/FSM/src/hw/hw_uarts.c @@ -0,0 +1,4 @@ +#include "hw_uarts.h" +#include "main.h" + +const UART debug_uart = { .handle = &huart1 }; diff --git a/firmware/quadruna/FSM/src/hw/hw_uarts.h b/firmware/quadruna/FSM/src/hw/hw_uarts.h new file mode 100644 index 0000000000..aa395d18b9 --- /dev/null +++ b/firmware/quadruna/FSM/src/hw/hw_uarts.h @@ -0,0 +1,4 @@ +#pragma once +#include "hw_uart.h" + +extern const UART debug_uart; \ No newline at end of file diff --git a/firmware/quadruna/FSM/src/io/io_apps.h b/firmware/quadruna/FSM/src/io/io_apps.h index 3f2a6da235..dab4c46432 100644 --- a/firmware/quadruna/FSM/src/io/io_apps.h +++ b/firmware/quadruna/FSM/src/io/io_apps.h @@ -1,7 +1,6 @@ #pragma once #include -#include "app_utils.h" #ifdef TARGET_EMBEDDED #include "hw_adc.h" @@ -13,6 +12,7 @@ typedef struct } AppsConfig; #else +#include "app_utils.h" EMPTY_STRUCT(AppsConfig) #endif /** diff --git a/firmware/quadruna/FSM/src/io/io_brake.h b/firmware/quadruna/FSM/src/io/io_brake.h index 03561469c1..c6fb313c22 100644 --- a/firmware/quadruna/FSM/src/io/io_brake.h +++ b/firmware/quadruna/FSM/src/io/io_brake.h @@ -1,7 +1,6 @@ #pragma once #include -#include "app_utils.h" #ifdef TARGET_EMBEDDED #include "hw_adc.h" @@ -16,6 +15,7 @@ typedef struct } BrakeConfig; #else +#include "app_utils.h" EMPTY_STRUCT(BrakeConfig) #endif diff --git a/firmware/quadruna/FSM/src/io/io_chimeraConfig.c b/firmware/quadruna/FSM/src/io/io_chimeraConfig.c new file mode 100644 index 0000000000..3ca1738eac --- /dev/null +++ b/firmware/quadruna/FSM/src/io/io_chimeraConfig.c @@ -0,0 +1,26 @@ +#include "FSM.pb.h" +#include "hw_gpios.h" +#include "hw_adcs.h" +#include "hw_uarts.h" + +const Gpio *const id_to_gpio[] = { [FSM_GpioNetName_BRAKE_OCSC_OK_3V3] = &brake_ocsc_ok_3v3, + [FSM_GpioNetName_NCHIMERA] = &n_chimera_pin, + [FSM_GpioNetName_LED] = &led_gpio_pin, + [FSM_GpioNetName_NBSPD_BRAKE_PRESSED_3V3] =  d_brake_pressed_3v3, + [FSM_GpioNetName_NPROGRAM_3V3] = &nprogram_3v3, + [FSM_GpioNetName_FSM_SHDN] = &fsm_shdn }; + +const AdcChannel *id_to_adc[] = { + [FSM_AdcNetName_SUSP_TRAVEL_FR_3V3] = &susp_travel_fr, + [FSM_AdcNetName_SUSP_TRAVEL_FL_3V3] = &susp_travel_fl, + [FSM_AdcNetName_LOAD_CELL_2_3V3] = &lc2, + [FSM_AdcNetName_APPS2_3V3] = &apps2, + [FSM_AdcNetName_BPS_F_3V3] = &bps_f, + [FSM_AdcNetName_BPS_B_3V3] = &bps_b, + [FSM_AdcNetName_LOAD_CELL_1_3V3] = &lc1, + [FSM_AdcNetName_APPS1_3V3] = &apps1, + [FSM_AdcNetName_SteeringAngle_3V3] = &steering_angle, +}; + +const UART *chimera_uart = &debug_uart; +const Gpio *n_chimera_gpio = &n_chimera_pin; \ No newline at end of file diff --git a/firmware/quadruna/FSM/src/io/io_fsmShdn.c b/firmware/quadruna/FSM/src/io/io_fsmShdn.c index c3fcf83e5b..b1163d8c30 100644 --- a/firmware/quadruna/FSM/src/io/io_fsmShdn.c +++ b/firmware/quadruna/FSM/src/io/io_fsmShdn.c @@ -1,13 +1,7 @@ #include "io_fsmShdn.h" - -static const FsmShdnConfig *shdn_config = NULL; - -void io_fsmShdn_init(const FsmShdnConfig *fsm_shdn_config) -{ - shdn_config = fsm_shdn_config; -} +#include "hw_gpios.h" bool io_fsmShdn_FSM_SHDN_OK_get(void) { - return hw_gpio_readPin(&shdn_config->fsm_shdn_ok_gpio); + return hw_gpio_readPin(&fsm_shdn); } diff --git a/firmware/quadruna/FSM/src/io/io_fsmShdn.h b/firmware/quadruna/FSM/src/io/io_fsmShdn.h index d0b96eb82a..c4264a631d 100644 --- a/firmware/quadruna/FSM/src/io/io_fsmShdn.h +++ b/firmware/quadruna/FSM/src/io/io_fsmShdn.h @@ -1,21 +1,7 @@ #pragma once #include -#include "app_utils.h" - -#ifdef TARGET_EMBEDDED -#include "hw_gpio.h" - -typedef struct -{ - const Gpio fsm_shdn_ok_gpio; -} FsmShdnConfig; -#else -EMPTY_STRUCT(FsmShdnConfig); -#endif #define FSM_SHDN_NODE_COUNT 1 -void io_fsmShdn_init(const FsmShdnConfig *fsm_shdn_config); - bool io_fsmShdn_FSM_SHDN_OK_get(void); diff --git a/firmware/quadruna/FSM/src/io/io_loadCell.h b/firmware/quadruna/FSM/src/io/io_loadCell.h index 982b5549e9..02cd226bf8 100644 --- a/firmware/quadruna/FSM/src/io/io_loadCell.h +++ b/firmware/quadruna/FSM/src/io/io_loadCell.h @@ -1,6 +1,5 @@ #pragma once #include -#include "app_utils.h" #ifdef TARGET_EMBEDDED #include "hw_adc.h" @@ -12,6 +11,7 @@ typedef struct } LoadCellConfig; #else +#include "app_utils.h" EMPTY_STRUCT(LoadCellConfig) #endif diff --git a/firmware/quadruna/FSM/src/io/io_steering.h b/firmware/quadruna/FSM/src/io/io_steering.h index 293e7fa746..b9b159be0d 100644 --- a/firmware/quadruna/FSM/src/io/io_steering.h +++ b/firmware/quadruna/FSM/src/io/io_steering.h @@ -1,6 +1,5 @@ #pragma once #include -#include "app_utils.h" #ifdef TARGET_EMBEDDED #include "hw_adc.h" @@ -11,6 +10,7 @@ typedef struct } SteeringConfig; #else +#include "app_utils.h" EMPTY_STRUCT(SteeringConfig) #endif diff --git a/firmware/quadruna/FSM/src/io/io_suspension.h b/firmware/quadruna/FSM/src/io/io_suspension.h index 78aa53b38f..ea7bc596fd 100644 --- a/firmware/quadruna/FSM/src/io/io_suspension.h +++ b/firmware/quadruna/FSM/src/io/io_suspension.h @@ -1,6 +1,5 @@ #pragma once #include -#include "app_utils.h" #ifdef TARGET_EMBEDDED #include "hw_adc.h" @@ -12,6 +11,7 @@ typedef struct } SuspensionConfig; #else +#include "app_utils.h" EMPTY_STRUCT(SuspensionConfig) #endif diff --git a/firmware/quadruna/FSM/src/tasks.c b/firmware/quadruna/FSM/src/tasks.c index b28f8bec4c..bcfc4c2adf 100644 --- a/firmware/quadruna/FSM/src/tasks.c +++ b/firmware/quadruna/FSM/src/tasks.c @@ -14,6 +14,7 @@ #include "io_canRx.h" #include "io_log.h" #include "io_can.h" +#include "io_canQueue.h" #include "io_led.h" #include "io_chimera.h" #include "io_steering.h" @@ -21,7 +22,6 @@ #include "io_brake.h" #include "io_suspension.h" #include "io_loadCell.h" -#include "io_fsmShdn.h" #include "io_apps.h" #include "hw_bootup.h" @@ -32,28 +32,21 @@ #include "hw_stackWaterMark.h" // TODO enable stackwatermark on the FSM #include "hw_stackWaterMarkConfig.h" #include "hw_adcs.h" -#include "hw_gpio.h" -#include "hw_uart.h" +#include "hw_gpios.h" +#include "hw_uarts.h" #include "hw_pwmInputFreqOnly.h" #include "shared.pb.h" -#include "FSM.pb.h" -extern ADC_HandleTypeDef hadc1; -extern TIM_HandleTypeDef htim3; -extern CAN_HandleTypeDef hcan1; -extern TIM_HandleTypeDef htim12; +static const CanHandle can = { .hcan = &hcan1 }; -static const CanHandle can = { .can = &hcan1, .can_msg_received_callback = io_can_pushRxMsgToQueue }; -extern UART_HandleTypeDef huart1; - -void canRxQueueOverflowCallBack(uint32_t overflow_count) +void canRxQueueOverflowCallBack(const uint32_t overflow_count) { app_canTx_FSM_RxOverflowCount_set(overflow_count); app_canAlerts_FSM_Warning_TxOverflow_set(true); } -void canTxQueueOverflowCallBack(uint32_t overflow_count) +void canTxQueueOverflowCallBack(const uint32_t overflow_count) { app_canTx_FSM_TxOverflowCount_set(overflow_count); app_canAlerts_FSM_Warning_TxOverflow_set(true); @@ -69,42 +62,7 @@ void canRxQueueOverflowClearCallback(void) app_canAlerts_FSM_Warning_RxOverflow_set(false); } -const CanConfig can_config = { - .rx_msg_filter = io_canRx_filterMessageId, - .tx_overflow_callback = canTxQueueOverflowCallBack, - .rx_overflow_callback = canRxQueueOverflowCallBack, - .tx_overflow_clear_callback = canTxQueueOverflowClearCallback, - .rx_overflow_clear_callback = canRxQueueOverflowClearCallback, -}; - -static const Gpio brake_ocsc_ok_3v3 = { .port = BRAKE_OCSC_OK_3V3_GPIO_Port, .pin = BRAKE_OCSC_OK_3V3_Pin }; -static const Gpio n_chimera_pin = { .port = NCHIMERA_GPIO_Port, .pin = NCHIMERA_Pin }; -static const BinaryLed led = { .gpio = { .port = LED_GPIO_Port, .pin = LED_Pin } }; -static const Gpio nbspd_brake_pressed_3v3 = { .port = NBSPD_BRAKE_PRESSED_3V3_GPIO_Port, - .pin = NBSPD_BRAKE_PRESSED_3V3_Pin }; -static const Gpio nprogram_3v3 = { .port = NPROGRAM_3V3_GPIO_Port, .pin = NPROGRAM_3V3_Pin }; -static const Gpio fsm_shdn = { .port = FSM_SHDN_GPIO_Port, .pin = FSM_SHDN_Pin }; - -const Gpio *const id_to_gpio[] = { [FSM_GpioNetName_BRAKE_OCSC_OK_3V3] = &brake_ocsc_ok_3v3, - [FSM_GpioNetName_NCHIMERA] = &n_chimera_pin, - [FSM_GpioNetName_LED] = &led.gpio, - [FSM_GpioNetName_NBSPD_BRAKE_PRESSED_3V3] =  d_brake_pressed_3v3, - [FSM_GpioNetName_NPROGRAM_3V3] = &nprogram_3v3, - [FSM_GpioNetName_FSM_SHDN] = &fsm_shdn }; - -const AdcChannel *id_to_adc[] = { - [FSM_AdcNetName_SUSP_TRAVEL_FR_3V3] = &susp_travel_fr, - [FSM_AdcNetName_SUSP_TRAVEL_FL_3V3] = &susp_travel_fl, - [FSM_AdcNetName_LOAD_CELL_2_3V3] = &lc2, - [FSM_AdcNetName_APPS2_3V3] = &apps2, - [FSM_AdcNetName_BPS_F_3V3] = &bps_f, - [FSM_AdcNetName_BPS_B_3V3] = &bps_b, - [FSM_AdcNetName_LOAD_CELL_1_3V3] = &lc1, - [FSM_AdcNetName_APPS1_3V3] = &apps1, - [FSM_AdcNetName_SteeringAngle_3V3] = &steering_angle, -}; - -static const UART debug_uart = { .handle = &huart1 }; +static const BinaryLed led = { .gpio = &led_gpio_pin }; static const AppsConfig apps_config = { .papps = &apps1, .sapps = &apps2 }; static const BrakeConfig brake_config = { .rear_brake = &bps_b, @@ -132,7 +90,11 @@ void tasks_preInit(void) hw_bootup_enableInterruptsForApp(); } -static const FsmShdnConfig fsm_shdn_pin_config = { .fsm_shdn_ok_gpio = fsm_shdn }; +static void jsoncan_transmit(const JsonCanMsg *tx_msg) +{ + const CanMsg msg = io_jsoncan_copyToCanMsg(tx_msg); + io_canQueue_pushTx(&msg); +} void tasks_init(void) { @@ -146,14 +108,13 @@ void tasks_init(void) hw_adcs_chipsInit(); hw_hardFaultHandler_init(); - hw_can_init(&can); + io_can_init(&can); hw_watchdog_init(hw_watchdogConfig_refresh, hw_watchdogConfig_timeoutCallback); - io_canTx_init(io_jsoncan_pushTxMsgToQueue); + io_canTx_init(jsoncan_transmit); io_canTx_enableMode(CAN_MODE_DEFAULT, true); - io_can_init(&can_config); - io_chimera_init(&debug_uart, GpioNetName_fsm_net_name_tag, AdcNetName_fsm_net_name_tag, &n_chimera_pin); - io_fsmShdn_init(&fsm_shdn_pin_config); + io_can_init(&can); + io_chimera_init(GpioNetName_fsm_net_name_tag, AdcNetName_fsm_net_name_tag); app_canTx_init(); app_canRx_init(); @@ -262,9 +223,8 @@ _Noreturn void tasks_runCanTx(void) for (;;) { - CanMsg tx_msg; - io_can_popTxMsgFromQueue(&tx_msg); - io_can_transmitMsgFromQueue(&tx_msg); + CanMsg tx_msg = io_canQueue_popTx(); + io_can_transmit(&can, &tx_msg); } } @@ -274,11 +234,8 @@ _Noreturn void tasks_runCanRx(void) for (;;) { - CanMsg rx_msg; - io_can_popRxMsgFromQueue(&rx_msg); - - JsonCanMsg jsoncan_rx_msg; - io_jsoncan_copyFromCanMsg(&rx_msg, &jsoncan_rx_msg); + CanMsg rx_msg = io_canQueue_popRx(); + JsonCanMsg jsoncan_rx_msg = io_jsoncan_copyFromCanMsg(&rx_msg); io_canRx_updateRxTableWithMessage(&jsoncan_rx_msg); } } diff --git a/firmware/quadruna/RSM/CMakeLists.txt b/firmware/quadruna/RSM/CMakeLists.txt index fe9c767594..4bd72ec416 100644 --- a/firmware/quadruna/RSM/CMakeLists.txt +++ b/firmware/quadruna/RSM/CMakeLists.txt @@ -20,6 +20,7 @@ set(APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src/app" "${SHARED_APP_INCLUDE file(GLOB_RECURSE IO_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/io/*.c") list(APPEND IO_SRCS "${SHARED_IO_INCLUDE_DIR}/io_can.c" + "${SHARED_IO_INCLUDE_DIR}/io_canQueue.c" "${SHARED_IO_INCLUDE_DIR}/io_jsoncan.c" "${SHARED_IO_INCLUDE_DIR}/io_time.c" "${SHARED_IO_INCLUDE_DIR}/io_chimera.c" @@ -37,7 +38,6 @@ list(APPEND HW_SRCS "${SHARED_HW_INCLUDE_DIR}/hw_hardFaultHandler.c" "${SHARED_HW_INCLUDE_DIR}/hw_gpio.c" "${SHARED_HW_INCLUDE_DIR}/hw_adc.c" - "${SHARED_HW_INCLUDE_DIR}/hw_can.c" "${SHARED_HW_INCLUDE_DIR}/hw_bootup.c" "${SHARED_HW_INCLUDE_DIR}/hw_pwmInputFreqOnly.c" "${SHARED_HW_INCLUDE_DIR}/hw_watchdog.c" diff --git a/firmware/quadruna/RSM/boot/cubemx/Src/main.c b/firmware/quadruna/RSM/boot/cubemx/Src/main.c index c25766b7e8..46ee3a002d 100644 --- a/firmware/quadruna/RSM/boot/cubemx/Src/main.c +++ b/firmware/quadruna/RSM/boot/cubemx/Src/main.c @@ -23,9 +23,12 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "bootloader.h" -#include "hw_can.h" +#include "io_canQueue.h" #include "io_can.h" #include "hw_error.h" +#include "hw_utils.h" + +#include /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -86,10 +89,27 @@ const osThreadAttr_t tickTask_attributes = { .priority = (osPriority_t)osPriorityNormal, }; /* USER CODE BEGIN PV */ -CanHandle can = { - .can = &hcan1, - .can_msg_received_callback = io_can_pushRxMsgToQueue, -}; +CanHandle can = { .hcan = &hcan1 }; + +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) +{ + assert(hcan == can.hcan); + CanMsg rx_msg; + if (!io_can_receive(&can, CAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} + +void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) +{ + assert(hcan == can.hcan); + CanMsg rx_msg; + if (!io_can_receive(&can, CAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ @@ -141,7 +161,7 @@ int main(void) MX_CRC_Init(); /* USER CODE BEGIN 2 */ bootloader_init(); - hw_can_init(&can); + io_can_init(&can); /* USER CODE END 2 */ /* Init scheduler */ diff --git a/firmware/quadruna/RSM/src/tasks.c b/firmware/quadruna/RSM/src/tasks.c index 1f9cf9475a..6819a48581 100644 --- a/firmware/quadruna/RSM/src/tasks.c +++ b/firmware/quadruna/RSM/src/tasks.c @@ -11,12 +11,14 @@ #include "app_heartbeatMonitors.h" #include "io_jsoncan.h" -#include "io_canRx.h" +#include "io_canTx.h" +#include "io_can.h" #include "io_log.h" #include "io_chimera.h" #include "io_coolant.h" #include "io_fans.h" #include "io_brake_light.h" +#include "io_canQueue.h" #include "hw_bootup.h" #include "hw_utils.h" @@ -32,7 +34,7 @@ #include "shared.pb.h" #include "RSM.pb.h" -static const CanHandle can = { .can = &hcan1, .can_msg_received_callback = io_can_pushRxMsgToQueue }; +static const CanHandle can = { .hcan = &hcan1 }; void canRxQueueOverflowCallBack(uint32_t overflow_count) { @@ -56,14 +58,6 @@ void canRxQueueOverflowClearCallback(void) app_canAlerts_RSM_Warning_RxOverflow_set(false); } -static const CanConfig can_config = { - .rx_msg_filter = io_canRx_filterMessageId, - .tx_overflow_callback = canTxQueueOverflowCallBack, - .rx_overflow_callback = canRxQueueOverflowCallBack, - .tx_overflow_clear_callback = canTxQueueOverflowClearCallback, - .rx_overflow_clear_callback = canRxQueueOverflowClearCallback, -}; - static const Gpio n_chimera_pin = { .port = NCHIMERA_GPIO_Port, .pin = NCHIMERA_Pin }; static const Gpio led_pin = { .port = LED_GPIO_Port, .pin = LED_Pin }; static const Gpio rad_fan_en_pin = { .port = RAD_FAN_EN_GPIO_Port, .pin = RAD_FAN_EN_Pin }; @@ -71,19 +65,11 @@ static const Gpio fr_stby_pin = { .port = FR_STBY_GPIO_Port, .pin = FR_ST static const Gpio brake_light_en_pin = { .port = BRAKE_LIGHT_EN_3V3_GPIO_Port, .pin = BRAKE_LIGHT_EN_3V3_Pin }; static const Gpio acc_fan_en_pin = { .port = ACC_FAN_EN_GPIO_Port, .pin = ACC_FAN_EN_Pin }; static const Gpio n_program_pin = { .port = NProgram_3V3_GPIO_Port, .pin = NProgram_3V3_Pin }; -static const Gpio acc_fan_pin = { - .port = ACC_FAN_EN_GPIO_Port, - .pin = RAD_FAN_EN_Pin, -}; -static const Gpio rad_fan_pin = { - .port = RAD_FAN_EN_GPIO_Port, - .pin = ACC_FAN_EN_Pin, -}; +static const Gpio acc_fan_pin = { .port = ACC_FAN_EN_GPIO_Port, .pin = RAD_FAN_EN_Pin }; +static const Gpio rad_fan_pin = { .port = RAD_FAN_EN_GPIO_Port, .pin = ACC_FAN_EN_Pin }; +static const Gpio brake_light_pin = { .port = BRAKE_LIGHT_EN_3V3_GPIO_Port, .pin = BRAKE_LIGHT_EN_3V3_Pin }; -static const BinaryLed brake_light = { .gpio = { - .port = BRAKE_LIGHT_EN_3V3_GPIO_Port, - .pin = BRAKE_LIGHT_EN_3V3_Pin, - } }; +static const BinaryLed brake_light = { .gpio = &brake_light_pin }; const Gpio *id_to_gpio[] = { [RSM_GpioNetName_NCHIMERA] = &n_chimera_pin, [RSM_GpioNetName_LED] = &led_pin, @@ -114,11 +100,20 @@ PwmInputFreqOnlyConfig coolant_config = { .htim = &htim3, static const UART debug_uart = { .handle = &huart1 }; +const UART *chimera_uart = &debug_uart; +const Gpio *n_chimera_gpio = &n_chimera_pin; + void tasks_preInit(void) { hw_bootup_enableInterruptsForApp(); } +static void jsoncan_transmit(const JsonCanMsg *tx_msg) +{ + const CanMsg msg = io_jsoncan_copyToCanMsg(tx_msg); + io_canQueue_pushTx(&msg); +} + void tasks_init(void) { // Configure and initialize SEGGER SystemView. @@ -131,13 +126,13 @@ void tasks_init(void) hw_adcs_chipsInit(); hw_hardFaultHandler_init(); - hw_can_init(&can); hw_watchdog_init(hw_watchdogConfig_refresh, hw_watchdogConfig_timeoutCallback); - io_canTx_init(io_jsoncan_pushTxMsgToQueue); + io_canTx_init(jsoncan_transmit); io_canTx_enableMode(CAN_MODE_DEFAULT, true); - io_can_init(&can_config); - io_chimera_init(&debug_uart, GpioNetName_rsm_net_name_tag, AdcNetName_rsm_net_name_tag, &n_chimera_pin); + io_can_init(&can); + io_canQueue_init(); + io_chimera_init(GpioNetName_rsm_net_name_tag, AdcNetName_rsm_net_name_tag); app_canTx_init(); app_canRx_init(); @@ -245,9 +240,8 @@ _Noreturn void tasks_runCanTx(void) for (;;) { - CanMsg tx_msg; - io_can_popTxMsgFromQueue(&tx_msg); - io_can_transmitMsgFromQueue(&tx_msg); + CanMsg tx_msg = io_canQueue_popTx(); + io_can_transmit(&can, &tx_msg); } } @@ -256,10 +250,8 @@ _Noreturn void tasks_runCanRx(void) io_chimera_sleepTaskIfEnabled(); for (;;) { - CanMsg rx_msg; - io_can_popRxMsgFromQueue(&rx_msg); - JsonCanMsg jsoncan_rx_msg; - io_jsoncan_copyFromCanMsg(&rx_msg, &jsoncan_rx_msg); + CanMsg rx_msg = io_canQueue_popRx(); + JsonCanMsg jsoncan_rx_msg = io_jsoncan_copyFromCanMsg(&rx_msg); io_canRx_updateRxTableWithMessage(&jsoncan_rx_msg); } } diff --git a/firmware/quadruna/VC/CMakeLists.txt b/firmware/quadruna/VC/CMakeLists.txt index d27af3a24e..d00d7dbd5c 100644 --- a/firmware/quadruna/VC/CMakeLists.txt +++ b/firmware/quadruna/VC/CMakeLists.txt @@ -18,8 +18,9 @@ set(APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src/app" "${CMAKE_CURRENT_SOUR file(GLOB_RECURSE IO_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/io/*.c") list(APPEND IO_SRCS - "${SHARED_IO_INCLUDE_DIR}/io_can.c" - "${SHARED_IO_INCLUDE_DIR}/io_canLogging.c" + "${SHARED_IO_INCLUDE_DIR}/io_fdcan.c" + "${SHARED_IO_INCLUDE_DIR}/io_canQueue.c" + "${SHARED_IO_INCLUDE_DIR}/io_canLoggingQueue.c" "${SHARED_IO_INCLUDE_DIR}/io_fileSystem_logfs.c" "${SHARED_IO_INCLUDE_DIR}/io_jsoncan.c" "${SHARED_IO_INCLUDE_DIR}/io_chimera.c" @@ -35,7 +36,6 @@ file(GLOB_RECURSE HW_SRCS ) list(APPEND HW_SRCS "${SHARED_HW_INCLUDE_DIR}/hw_hardFaultHandler.c" - "${SHARED_HW_INCLUDE_DIR}/hw_fdcan.c" "${SHARED_HW_INCLUDE_DIR}/hw_watchdog.c" "${SHARED_HW_INCLUDE_DIR}/hw_stackWaterMark.c" "${SHARED_HW_INCLUDE_DIR}/hw_gpio.c" @@ -175,7 +175,7 @@ ELSEIF ("${TARGET}" STREQUAL "test") # FakeIO set(HEADERS_TO_FAKE "${SHARED_IO_INCLUDE_DIR}/io_log.h" - "${SHARED_IO_INCLUDE_DIR}/io_canLogging.h" + "${SHARED_IO_INCLUDE_DIR}/io_canLoggingQueue.h" "${CMAKE_CURRENT_SOURCE_DIR}/src/io/io_sbgEllipse.h" "${CMAKE_CURRENT_SOURCE_DIR}/src/io/io_lowVoltageBattery.h" "${CMAKE_CURRENT_SOURCE_DIR}/src/io/io_efuse.h" diff --git a/firmware/quadruna/VC/boot/cubemx/Src/main.c b/firmware/quadruna/VC/boot/cubemx/Src/main.c index 72a6b97a36..4ba55ad7d3 100644 --- a/firmware/quadruna/VC/boot/cubemx/Src/main.c +++ b/firmware/quadruna/VC/boot/cubemx/Src/main.c @@ -23,8 +23,11 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "bootloader.h" -#include "hw_can.h" #include "io_can.h" +#include "hw_utils.h" +#include "io_canQueue.h" +#include "io_log.h" +#include /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -104,7 +107,29 @@ void runCanTxTask(void *argument); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ -CanHandle can = { .can = &hfdcan1, .can_msg_received_callback = io_can_pushRxMsgToQueue }; +CanHandle can = { .hcan = &hfdcan1 }; + +void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, const uint32_t RxFifo0ITs) +{ + assert(hfdcan == &hfdcan1); + UNUSED(RxFifo0ITs); + CanMsg rx_msg; + if (!io_can_receive(&can, FDCAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} + +void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, const uint32_t RxFifo1ITs) +{ + assert(hfdcan == &hfdcan1); + UNUSED(RxFifo1ITs); + CanMsg rx_msg; + if (!io_can_receive(&can, FDCAN_RX_FIFO1, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} /* USER CODE END 0 */ /** @@ -139,7 +164,8 @@ int main(void) MX_FDCAN1_Init(); /* USER CODE BEGIN 2 */ bootloader_init(); - hw_can_init(&can); + io_can_init(&can); + io_canQueue_init(); /* USER CODE END 2 */ /* Init scheduler */ @@ -431,6 +457,7 @@ static void MX_GPIO_Init(void) void runInterfaceTask(void *argument) { /* USER CODE BEGIN 5 */ + UNUSED(argument); bootloader_runInterfaceTask(); /* USER CODE END 5 */ } @@ -445,6 +472,7 @@ void runInterfaceTask(void *argument) void runTickTask(void *argument) { /* USER CODE BEGIN runTickTask */ + UNUSED(argument); bootloader_runTickTask(); /* USER CODE END runTickTask */ } @@ -459,6 +487,7 @@ void runTickTask(void *argument) void runCanTxTask(void *argument) { /* USER CODE BEGIN runCanTxTask */ + UNUSED(argument); bootloader_runCanTxTask(); /* USER CODE END runCanTxTask */ } diff --git a/firmware/quadruna/VC/src/app/app_faultCheck.c b/firmware/quadruna/VC/src/app/app_faultCheck.c index abd4770d3a..5b109ad53b 100644 --- a/firmware/quadruna/VC/src/app/app_faultCheck.c +++ b/firmware/quadruna/VC/src/app/app_faultCheck.c @@ -3,7 +3,6 @@ #include "app_canTx.h" #include "app_canRx.h" #include "app_signal.h" -#include "io_log.h" static Signal apps_brake_disagreement_signal; diff --git a/firmware/quadruna/VC/src/app/states/app_allStates.c b/firmware/quadruna/VC/src/app/states/app_allStates.c index 29ae1713f9..7408e24e3d 100644 --- a/firmware/quadruna/VC/src/app/states/app_allStates.c +++ b/firmware/quadruna/VC/src/app/states/app_allStates.c @@ -14,7 +14,7 @@ // io #include "io_sbgEllipse.h" #include "io_imu.h" -#include "io_canLogging.h" +#include "io_canLoggingQueue.h" #include "io_pcm.h" #include diff --git a/firmware/quadruna/VC/src/app/states/app_driveState.c b/firmware/quadruna/VC/src/app/states/app_driveState.c index 4b67e9008e..6fc2358b31 100644 --- a/firmware/quadruna/VC/src/app/states/app_driveState.c +++ b/firmware/quadruna/VC/src/app/states/app_driveState.c @@ -18,6 +18,7 @@ #include "app_regen.h" #include "app_units.h" #include "app_signal.h" +#include "app_utils.h" #define EFFICIENCY_ESTIMATE (0.80f) #define BUZZER_ON_DURATION_MS 2000 diff --git a/firmware/quadruna/VC/src/cubemx/Inc/main.h b/firmware/quadruna/VC/src/cubemx/Inc/main.h index 8d841f91e5..03167feb01 100644 --- a/firmware/quadruna/VC/src/cubemx/Inc/main.h +++ b/firmware/quadruna/VC/src/cubemx/Inc/main.h @@ -44,13 +44,18 @@ extern "C" /* USER CODE BEGIN EC */ extern ADC_HandleTypeDef hadc1; extern ADC_HandleTypeDef hadc3; + extern DMA_HandleTypeDef hdma_adc1; extern FDCAN_HandleTypeDef hfdcan1; - extern UART_HandleTypeDef huart7; + extern I2C_HandleTypeDef hi2c1; + extern I2C_HandleTypeDef hi2c2; + extern IWDG_HandleTypeDef hiwdg1; + extern SD_HandleTypeDef hsd1; extern TIM_HandleTypeDef htim3; - extern UART_HandleTypeDef huart2; + extern UART_HandleTypeDef huart7; extern UART_HandleTypeDef huart1; + extern UART_HandleTypeDef huart2; extern UART_HandleTypeDef huart3; - extern SD_HandleTypeDef hsd1; + extern DMA_HandleTypeDef hdma_usart2_rx; /* USER CODE END EC */ /* Exported macro ------------------------------------------------------------*/ diff --git a/firmware/quadruna/VC/src/cubemx/Src/main.c b/firmware/quadruna/VC/src/cubemx/Src/main.c index f4780da9b4..e06752b828 100644 --- a/firmware/quadruna/VC/src/cubemx/Src/main.c +++ b/firmware/quadruna/VC/src/cubemx/Src/main.c @@ -24,7 +24,7 @@ /* USER CODE BEGIN Includes */ #include "tasks.h" #include "hw_error.h" -#include "hw_gpio.h" +#include "hw_gpios.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -150,10 +150,7 @@ const osThreadAttr_t TaskTelem_attributes = { .priority = (osPriority_t)osPriorityLow, }; /* USER CODE BEGIN PV */ -Gpio sd_present = { - .pin = GPIO_PIN_8, - .port = GPIOA, -}; + /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ diff --git a/firmware/quadruna/VC/src/hw/hw_adcs.c b/firmware/quadruna/VC/src/hw/hw_adcs.c index 04e91ef259..016a927008 100644 --- a/firmware/quadruna/VC/src/hw/hw_adcs.c +++ b/firmware/quadruna/VC/src/hw/hw_adcs.c @@ -42,9 +42,9 @@ static uint8_t ADC3_PTR = 0; void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { - if (hadc == &hadc1) + if (hadc == adc1.hadc) hw_adcchip_updateCallback(&adc1); - else if (hadc == &hadc3) + else if (hadc == adc3.hadc) { /* On the STM32H733xx MCU, the ADC3 peripheral uses the BDMA peripheral to handle DMA transfers (not the regular DMA peripheral). Unfortunately, the BDMA can only transfer data to/from specific sections of memory (not regular diff --git a/firmware/quadruna/VC/src/hw/hw_chimeraConfig.c b/firmware/quadruna/VC/src/hw/hw_chimeraConfig.c new file mode 100644 index 0000000000..6c957b98a7 --- /dev/null +++ b/firmware/quadruna/VC/src/hw/hw_chimeraConfig.c @@ -0,0 +1,48 @@ +#include "shared.pb.h" +#include "hw_gpios.h" +#include "hw_adcs.h" +#include "hw_uarts.h" + +const Gpio *id_to_gpio[] = { [VC_GpioNetName_BUZZER_PWR_EN] = &buzzer_pwr_en, + [VC_GpioNetName_BAT_I_SNS_NFLT] = &bat_i_sns_nflt, + [VC_GpioNetName_LED] = &led_gpio, + [VC_GpioNetName_TELEM_PWR_EN] = &telem_pwr_en, + [VC_GpioNetName_NPCM_EN] = &npcm_en, + [VC_GpioNetName_ACC_I_SENSE_NFLT] = &acc_i_sns_nflt, + [VC_GpioNetName_PGOOD] = &pgood, + [VC_GpioNetName_LV_PWR_EN] = &lv_pwr_en, + [VC_GpioNetName_AUX_PWR_EN] = &aux_pwr_en, + [VC_GpioNetName_PUMP_PWR_EN] = &pump_pwr_en, + [VC_GpioNetName__900K_GPIO] = &_900k_gpio, + [VC_GpioNetName_NCHRG_FAULT] = &nchrg_fault, + [VC_GpioNetName_NCHRG] = &nchrg, + [VC_GpioNetName_INV_L_PWR_EN] = &inv_l_pwr_en, + [VC_GpioNetName_INV_R_PWR_EN] = &inv_r_pwr_en, + [VC_GpioNetName_SHDN_PWR_EN] = &shdn_pwr_en, + [VC_GpioNetName_FR_STBY1] = &fr_stby1, + [VC_GpioNetName_FR_STBY2] = &fr_stby2, + [VC_GpioNetName_FR_STBY3] = &fr_stby3, + [VC_GpioNetName_INV_L_PROGRAM] = &inv_l_program, + [VC_GpioNetName_INV_R_PROGRAM] = &inv_r_program, + [VC_GpioNetName_L_SHDN_SNS] = &l_shdn_sns, + [VC_GpioNetName_R_SHDN_SNS] = &r_shdn_sns, + [VC_GpioNetName_NCHIMERA] = &n_chimera_pin, + [VC_GpioNetName_NPROGRAM_3V3] = &nprogram_3v3, + [VC_GpioNetName_SB_ILCK_SHDN_SNS] = &sb_ilck_shdn_sns, + [VC_GpioNetName_TSMS_SHDN_SNS] = &tsms_shdn_sns }; + +const AdcChannel *id_to_adc[] = { + [VC_AdcNetName_INV_R_PWR_I_SNS] = &inv_r_pwr_i_sns, + [VC_AdcNetName_INV_L_PWR_I_SNS] = &inv_l_pwr_i_sns, + [VC_AdcNetName_AUX_PWR_I_SNS] = &aux_pwr_i_sns, + [VC_AdcNetName_SHDN_PWR_I_SNS] = &shdn_pwr_i_sns, + [VC_AdcNetName_VBAT_SENSE] = &vbat_sns, + [VC_AdcNetName__24V_ACC_SENSE] = &acc_24v_sns, + [VC_AdcNetName__22V_BOOST_SENSE] = &boost_22v_sns, + [VC_AdcNetName_LV_PWR_I_SNS] = &lv_pwr_i_sns, + [VC_AdcNetName_ACC_I_SENSE] = &acc_i_sns, + [VC_AdcNetName_PUMP_PWR_I_SNS] = &pump_pwr_i_sns, +}; + +const UART *chimera_uart = &debug_uart; +const Gpio *n_chimera_gpio = &n_chimera_pin; \ No newline at end of file diff --git a/firmware/quadruna/VC/src/hw/hw_gpios.c b/firmware/quadruna/VC/src/hw/hw_gpios.c new file mode 100644 index 0000000000..3eeeec4643 --- /dev/null +++ b/firmware/quadruna/VC/src/hw/hw_gpios.c @@ -0,0 +1,32 @@ +#include "hw_gpios.h" + +#include "main.h" + +const Gpio led_gpio = { .port = LED_GPIO_Port, .pin = LED_Pin }; +const Gpio sd_present = { .pin = SD_CD_Pin, .port = SD_CD_GPIO_Port }; +const Gpio buzzer_pwr_en = { .port = BUZZER_PWR_EN_GPIO_Port, .pin = BUZZER_PWR_EN_Pin }; +const Gpio bat_i_sns_nflt = { .port = BAT_I_SNS_nFLT_GPIO_Port, .pin = BAT_I_SNS_nFLT_Pin }; +const Gpio telem_pwr_en = { .port = TELEM_PWR_EN_GPIO_Port, .pin = TELEM_PWR_EN_Pin }; +const Gpio npcm_en = { .port = nPCM_EN_GPIO_Port, .pin = nPCM_EN_Pin }; +const Gpio acc_i_sns_nflt = { .port = ACC_I_SENSE_nFLT_GPIO_Port, .pin = ACC_I_SENSE_nFLT_Pin }; +const Gpio pgood = { .port = PGOOD_GPIO_Port, .pin = PGOOD_Pin }; +const Gpio lv_pwr_en = { .port = LV_PWR_EN_GPIO_Port, .pin = LV_PWR_EN_Pin }; +const Gpio aux_pwr_en = { .port = AUX_PWR_EN_GPIO_Port, .pin = AUX_PWR_EN_Pin }; +const Gpio pump_pwr_en = { .port = PUMP_PWR_EN_GPIO_Port, .pin = PUMP_PWR_EN_Pin }; +const Gpio _900k_gpio = { .port = _900K_GPIO_GPIO_Port, .pin = _900K_GPIO_Pin }; +const Gpio nchrg_fault = { .port = nCHRG_FAULT_GPIO_Port, .pin = nCHRG_FAULT_Pin }; +const Gpio nchrg = { .port = nCHRG_GPIO_Port, .pin = nCHRG_Pin }; +const Gpio inv_l_pwr_en = { .port = INV_L_PWR_EN_GPIO_Port, .pin = INV_L_PWR_EN_Pin }; +const Gpio inv_r_pwr_en = { .port = INV_R_PWR_EN_GPIO_Port, .pin = INV_R_PWR_EN_Pin }; +const Gpio shdn_pwr_en = { .port = SHDN_PWR_EN_GPIO_Port, .pin = SHDN_PWR_EN_Pin }; +const Gpio fr_stby1 = { .port = FR_STBY1_GPIO_Port, .pin = FR_STBY1_Pin }; +const Gpio fr_stby2 = { .port = FR_STBY2_GPIO_Port, .pin = FR_STBY2_Pin }; +const Gpio fr_stby3 = { .port = FR_STBY3_GPIO_Port, .pin = FR_STBY3_Pin }; +const Gpio inv_l_program = { .port = INV_L_PROGRAM_GPIO_Port, .pin = INV_L_PROGRAM_Pin }; +const Gpio inv_r_program = { .port = INV_R_PROGRAM_GPIO_Port, .pin = INV_R_PROGRAM_Pin }; +const Gpio l_shdn_sns = { .port = L_SHDN_SNS_GPIO_Port, .pin = L_SHDN_SNS_Pin }; +const Gpio r_shdn_sns = { .port = R_SHDN_SNS_GPIO_Port, .pin = R_SHDN_SNS_Pin }; +const Gpio n_chimera_pin = { .port = NCHIMERA_GPIO_Port, .pin = NCHIMERA_Pin }; +const Gpio nprogram_3v3 = { .port = NPROGRAM_3V3_GPIO_Port, .pin = NPROGRAM_3V3_Pin }; +const Gpio sb_ilck_shdn_sns = { .port = SB_ILCK_SHDN_SNS_GPIO_Port, .pin = SB_ILCK_SHDN_SNS_Pin }; +const Gpio tsms_shdn_sns = { .port = TSMS_SHDN_SNS_GPIO_Port, .pin = TSMS_SHDN_SNS_Pin }; diff --git a/firmware/quadruna/VC/src/hw/hw_gpios.h b/firmware/quadruna/VC/src/hw/hw_gpios.h new file mode 100644 index 0000000000..217efaf1dd --- /dev/null +++ b/firmware/quadruna/VC/src/hw/hw_gpios.h @@ -0,0 +1,32 @@ +#pragma once + +#include "hw_gpio.h" + +extern const Gpio led_gpio; +extern const Gpio sd_present; +extern const Gpio buzzer_pwr_en; +extern const Gpio bat_i_sns_nflt; +extern const Gpio telem_pwr_en; +extern const Gpio npcm_en; +extern const Gpio acc_i_sns_nflt; +extern const Gpio pgood; +extern const Gpio lv_pwr_en; +extern const Gpio aux_pwr_en; +extern const Gpio pump_pwr_en; +extern const Gpio _900k_gpio; +extern const Gpio nchrg_fault; +extern const Gpio nchrg; +extern const Gpio inv_l_pwr_en; +extern const Gpio inv_r_pwr_en; +extern const Gpio shdn_pwr_en; +extern const Gpio fr_stby1; +extern const Gpio fr_stby2; +extern const Gpio fr_stby3; +extern const Gpio inv_l_program; +extern const Gpio inv_r_program; +extern const Gpio l_shdn_sns; +extern const Gpio r_shdn_sns; +extern const Gpio n_chimera_pin; +extern const Gpio nprogram_3v3; +extern const Gpio sb_ilck_shdn_sns; +extern const Gpio tsms_shdn_sns; diff --git a/firmware/quadruna/VC/src/hw/hw_sds.c b/firmware/quadruna/VC/src/hw/hw_sds.c new file mode 100644 index 0000000000..60177ca4d0 --- /dev/null +++ b/firmware/quadruna/VC/src/hw/hw_sds.c @@ -0,0 +1,5 @@ +#include "hw_sd.h" +#include "main.h" +#include "hw_gpios.h" + +SdCard sd1 = { .hsd = &hsd1, .timeout = 1000, .present_gpio = &sd_present }; \ No newline at end of file diff --git a/firmware/quadruna/VC/src/hw/hw_uarts.c b/firmware/quadruna/VC/src/hw/hw_uarts.c new file mode 100644 index 0000000000..e0311e7abc --- /dev/null +++ b/firmware/quadruna/VC/src/hw/hw_uarts.c @@ -0,0 +1,7 @@ +#include "hw_uarts.h" +#include "main.h" + +const UART debug_uart = { .handle = &huart7 }; +const UART sbg_uart = { .handle = &huart2 }; +const UART modem2G4_uart = { .handle = &huart3 }; +const UART modem900_uart = { .handle = &huart1 }; diff --git a/firmware/quadruna/VC/src/hw/hw_uarts.h b/firmware/quadruna/VC/src/hw/hw_uarts.h new file mode 100644 index 0000000000..ac388a130a --- /dev/null +++ b/firmware/quadruna/VC/src/hw/hw_uarts.h @@ -0,0 +1,8 @@ +#pragma once + +#include "hw_uart.h" + +extern const UART debug_uart; +extern const UART sbg_uart; +extern const UART modem2G4_uart; +extern const UART modem900_uart; \ No newline at end of file diff --git a/firmware/quadruna/VC/src/io/io_canQueueConfig.c b/firmware/quadruna/VC/src/io/io_canQueueConfig.c new file mode 100644 index 0000000000..38c5c2aa35 --- /dev/null +++ b/firmware/quadruna/VC/src/io/io_canQueueConfig.c @@ -0,0 +1,24 @@ +#include "io_log.h" +#include "app_canAlerts.h" +#include "app_canTx.h" + +void tx_overflow_callback(const uint32_t overflow_count) +{ + app_canTx_VC_RxOverflowCount_set(overflow_count); + app_canAlerts_VC_Warning_RxOverflow_set(true); + LOG_INFO("CAN RX OVERFLOW"); +} +void rx_overflow_callback(const uint32_t overflow_count) +{ + app_canTx_VC_TxOverflowCount_set(overflow_count); + app_canAlerts_VC_Warning_TxOverflow_set(true); + LOG_INFO("CAN TX OVERFLOW"); +} +void tx_overflow_clear_callback(void) +{ + app_canAlerts_VC_Warning_TxOverflow_set(false); +} +void rx_overflow_clear_callback(void) +{ + app_canAlerts_VC_Warning_RxOverflow_set(false); +} diff --git a/firmware/quadruna/VC/src/io/io_cans.c b/firmware/quadruna/VC/src/io/io_cans.c new file mode 100644 index 0000000000..518b257d86 --- /dev/null +++ b/firmware/quadruna/VC/src/io/io_cans.c @@ -0,0 +1,4 @@ +#include "io_cans.h" +#include "main.h" + +const CanHandle can1 = { .hcan = &hfdcan1 }; \ No newline at end of file diff --git a/firmware/quadruna/VC/src/io/io_cans.h b/firmware/quadruna/VC/src/io/io_cans.h new file mode 100644 index 0000000000..8b17b07eac --- /dev/null +++ b/firmware/quadruna/VC/src/io/io_cans.h @@ -0,0 +1,4 @@ +#pragma once +#include "io_can.h" + +extern const CanHandle can1; diff --git a/firmware/quadruna/VC/src/io/io_currentSensing.c b/firmware/quadruna/VC/src/io/io_currentSensing.c index f422272d7c..734828cc72 100644 --- a/firmware/quadruna/VC/src/io/io_currentSensing.c +++ b/firmware/quadruna/VC/src/io/io_currentSensing.c @@ -1,35 +1,28 @@ #include "io_currentSensing.h" #include -#include "hw_gpio.h" -#include "hw_adc.h" +#include "hw_gpios.h" +#include "hw_adcs.h" // all constants in SI units #define AMPERAGE_PER_VOLTAGE (1.0f / (5.5e-2f)) #define MIN_VOLTAGE (3.3f / 2.0f) -static const CurrentSensingConfig *config = NULL; - -void io_currentSensing_init(const CurrentSensingConfig *current_sensing_config) -{ - config = current_sensing_config; -} - bool io_currentSensing_hasAccumulatorFault() { - return !hw_gpio_readPin(&config->acc_fault_gpio); + return !hw_gpio_readPin(&bat_i_sns_nflt); } bool io_currentSensing_hasBatteryFault() { - return !hw_gpio_readPin(&config->bat_fault_gpio); + return !hw_gpio_readPin(&acc_i_sns_nflt); } float io_currentSensing_getAccumulatorCurrent() { - return (hw_adc_getVoltage(config->acc_current_adc) - MIN_VOLTAGE) * AMPERAGE_PER_VOLTAGE; + return (hw_adc_getVoltage(&bat_i_sns) - MIN_VOLTAGE) * AMPERAGE_PER_VOLTAGE; } float io_currentSensing_getBatteryCurrent() { - return (hw_adc_getVoltage(config->bat_current_adc) - MIN_VOLTAGE) * AMPERAGE_PER_VOLTAGE; + return (hw_adc_getVoltage(&acc_i_sns) - MIN_VOLTAGE) * AMPERAGE_PER_VOLTAGE; } diff --git a/firmware/quadruna/VC/src/io/io_currentSensing.h b/firmware/quadruna/VC/src/io/io_currentSensing.h index 9d90f029ed..6888c41986 100644 --- a/firmware/quadruna/VC/src/io/io_currentSensing.h +++ b/firmware/quadruna/VC/src/io/io_currentSensing.h @@ -1,27 +1,5 @@ #pragma once #include -#include "app_utils.h" - -#ifdef TARGET_EMBEDDED -#include "hw_gpio.h" -#include "hw_adc.h" - -typedef struct -{ - const Gpio bat_fault_gpio; - const Gpio acc_fault_gpio; - const AdcChannel *bat_current_adc; - const AdcChannel *acc_current_adc; -} CurrentSensingConfig; -#else -EMPTY_STRUCT(CurrentSensingConfig); -#endif - -/* - * Initialize config for curent sensing pins - * @param current_sensing_config config with shutdown gpio pins - */ -void io_currentSensing_init(const CurrentSensingConfig *current_sensing_config); /** * Gets current from battery (BAT_I_SNS pin) diff --git a/firmware/quadruna/VC/src/io/io_efuse.c b/firmware/quadruna/VC/src/io/io_efuse.c index 74cd736a1f..99992a105d 100644 --- a/firmware/quadruna/VC/src/io/io_efuse.c +++ b/firmware/quadruna/VC/src/io/io_efuse.c @@ -1,19 +1,65 @@ #include "io_efuse.h" -#include -// TODO: Test ADC voltage -> output current transfer function -#define ADC_VOLTAGE_TO_CURRENT_A 1.720f +#include -static const EfuseConfig *configs = NULL; +#include "hw_gpios.h" +#include "hw_adcs.h" -void io_efuse_init(const EfuseConfig efuse_configs[NUM_EFUSE_CHANNELS]) +typedef struct { - configs = efuse_configs; -} + const Gpio *enable_gpio; + const Gpio *stby_reset_gpio; + const AdcChannel *cur_sns_adc_channel; +} EfuseConfig; +static const EfuseConfig configs[NUM_EFUSE_CHANNELS] = { + [EFUSE_CHANNEL_SHDN] = { + .enable_gpio = &shdn_pwr_en, + .stby_reset_gpio = &fr_stby1, + .cur_sns_adc_channel = &shdn_pwr_i_sns, + }, + [EFUSE_CHANNEL_LV] = { + .enable_gpio = &lv_pwr_en, + .stby_reset_gpio = &fr_stby1, + .cur_sns_adc_channel = &lv_pwr_i_sns, + }, + [EFUSE_CHANNEL_PUMP] = { + .enable_gpio = &pump_pwr_en, + .stby_reset_gpio = &fr_stby2, + .cur_sns_adc_channel = &pump_pwr_i_sns + }, + [EFUSE_CHANNEL_AUX] = { + .enable_gpio = &aux_pwr_en, + .stby_reset_gpio = &fr_stby2, + .cur_sns_adc_channel = &aux_pwr_i_sns + }, + [EFUSE_CHANNEL_INV_R] = { + .enable_gpio = &inv_r_pwr_en, + .stby_reset_gpio = &fr_stby3, + .cur_sns_adc_channel = &inv_r_pwr_i_sns + }, + [EFUSE_CHANNEL_INV_L] = { + .enable_gpio = &inv_l_pwr_en, + .stby_reset_gpio = &fr_stby3, + .cur_sns_adc_channel = &inv_l_pwr_i_sns + }, + [EFUSE_CHANNEL_TELEM] = { + .enable_gpio = &telem_pwr_en, + .stby_reset_gpio = NULL, + .cur_sns_adc_channel = NULL + }, + [EFUSE_CHANNEL_BUZZER] = { + .enable_gpio = &buzzer_pwr_en, + .stby_reset_gpio = NULL, + .cur_sns_adc_channel = NULL + } +}; + +// TODO: Test ADC voltage -> output current transfer function +#define ADC_VOLTAGE_TO_CURRENT_A 1.720f static bool enabled_channels[NUM_EFUSE_CHANNELS] = { false }; -void io_efuse_setChannel(EfuseChannel channel, bool enabled) +void io_efuse_setChannel(const EfuseChannel channel, const bool enabled) { assert(channel < NUM_EFUSE_CHANNELS); @@ -41,7 +87,7 @@ float io_efuse_getChannelCurrent(const EfuseChannel channel) return hw_adc_getVoltage(a) * ADC_VOLTAGE_TO_CURRENT_A; } -void io_efuse_standbyReset(EfuseChannel channel) +void io_efuse_standbyReset(const EfuseChannel channel) { assert(channel < NUM_EFUSE_CHANNELS); diff --git a/firmware/quadruna/VC/src/io/io_efuse.h b/firmware/quadruna/VC/src/io/io_efuse.h index 6acdeed0c2..94086d755b 100644 --- a/firmware/quadruna/VC/src/io/io_efuse.h +++ b/firmware/quadruna/VC/src/io/io_efuse.h @@ -1,21 +1,6 @@ #pragma once #include -#include "app_utils.h" - -#ifdef TARGET_EMBEDDED -#include "hw_gpio.h" -#include "hw_adc.h" - -typedef struct -{ - const Gpio *enable_gpio; - const Gpio *stby_reset_gpio; - const AdcChannel *cur_sns_adc_channel; -} EfuseConfig; -#else -EMPTY_STRUCT(EfuseConfig); -#endif typedef enum { @@ -38,14 +23,6 @@ typedef enum NUM_EFUSE_CHANNELS } EfuseChannel; -#ifdef TARGET_EMBEDDED -/** - * Initialize the efuses. - * @param configs Array of configs for each efuse, with indices corresponding to EfuseChannel values. - */ -void io_efuse_init(const EfuseConfig configs[NUM_EFUSE_CHANNELS]); -#endif - /** * Enable or disable the provided efuse channel. * @param channel Channel to enable/disable diff --git a/firmware/quadruna/VC/src/io/io_imu.c b/firmware/quadruna/VC/src/io/io_imu.c index f1e8908f1d..9e2f86f909 100644 --- a/firmware/quadruna/VC/src/io/io_imu.c +++ b/firmware/quadruna/VC/src/io/io_imu.c @@ -1,15 +1,14 @@ #include "io_imu.h" #include "hw_i2c.h" -#include #include +#include "main.h" // Default accelerometer sensitivity for LSM6DSM is 0.061 mg/digit const float ACCEL_SENSITIVITY = 0.061f; // Default gyroscope sensitivity for LSM6DSM is 8.75 mdeg/digit const float GYRO_SENSITIVITY = 8.75f; -extern I2C_HandleTypeDef hi2c2; -static I2cInterface imu = { .i2c_handle = &hi2c2, .target_address = 0x6B, .timeout_ms = 100 }; +static I2cInterface imu = { .i2c_handle = &hi2c2, .target_address = 0x6B, .timeout_ms = 100 }; bool io_imu_init() { diff --git a/firmware/quadruna/VC/src/io/io_leds.c b/firmware/quadruna/VC/src/io/io_leds.c new file mode 100644 index 0000000000..3cd43d7e14 --- /dev/null +++ b/firmware/quadruna/VC/src/io/io_leds.c @@ -0,0 +1,4 @@ +#include "io_leds.h" +#include "hw_gpios.h" + +const BinaryLed led = { .gpio = &led_gpio }; \ No newline at end of file diff --git a/firmware/quadruna/VC/src/io/io_leds.h b/firmware/quadruna/VC/src/io/io_leds.h new file mode 100644 index 0000000000..d9233e8e2d --- /dev/null +++ b/firmware/quadruna/VC/src/io/io_leds.h @@ -0,0 +1,5 @@ +#pragma once + +#include "io_led.h" + +const BinaryLed led; \ No newline at end of file diff --git a/firmware/quadruna/VC/src/io/io_lowVoltageBattery.c b/firmware/quadruna/VC/src/io/io_lowVoltageBattery.c index 8453216e84..a06ef7f54b 100644 --- a/firmware/quadruna/VC/src/io/io_lowVoltageBattery.c +++ b/firmware/quadruna/VC/src/io/io_lowVoltageBattery.c @@ -1,4 +1,6 @@ #include "io_lowVoltageBattery.h" +#include "hw_gpios.h" +#include "hw_adcs.h" // Percent error used to compensate for resistor errors. Determined from // testing with the HW @@ -11,40 +13,30 @@ #define VBOOST_VOLTAGE_DIV (3.1e3f / (20e3f + 3.1e3f)) #define VACC_VOLTAGE_DIV (3.1e3f / (20e3f + 3.1e3f)) -static const LvBatteryConfig *config = NULL; - -void io_lowVoltageBattery_init(const LvBatteryConfig *lv_batt_config) -{ - config = lv_batt_config; -} - bool io_lowVoltageBattery_hasChargeFault(void) { // FAULT pin on LT3650 2-cell Li-Ion battery charger is pulled low when the chip detects a fault. - return !hw_gpio_readPin(&config->lt3650_charger_fault_gpio); + return !hw_gpio_readPin(&nchrg_fault); } bool io_lowVoltageBattery_hasBoostControllerFault(void) { // PGOOD pin on LTC3786 boost converter is pulled low when the output voltage is more than ±10 % away from the // regulated output voltage. - return !hw_gpio_readPin(&config->ltc3786_boost_fault_gpio); + return !hw_gpio_readPin(&pgood); } float io_lowVoltageBattery_getBatVoltage(void) { - float adc_reading = hw_adc_getVoltage(config->vbat_vsense_adc_channel); - return adc_reading * VBAT_R_ERROR_COMPENSATION / VBAT_VOLTAGE_DIV; + return hw_adc_getVoltage(&vbat_sns) * VBAT_R_ERROR_COMPENSATION / VBAT_VOLTAGE_DIV; } float io_lowVoltageBattery_getBoostVoltage(void) { - float adc_reading = hw_adc_getVoltage(config->boost_vsense_adc_channel); - return adc_reading * VBOOST_R_ERROR_COMPENSATION / VBOOST_VOLTAGE_DIV; + return hw_adc_getVoltage(&boost_22v_sns) * VBOOST_R_ERROR_COMPENSATION / VBOOST_VOLTAGE_DIV; } float io_lowVoltageBattery_getAccVoltage(void) { - float adc_reading = hw_adc_getVoltage(config->acc_vsense_adc_channel); - return adc_reading * VACC_R_ERROR_COMPENSATION / VACC_VOLTAGE_DIV; + return hw_adc_getVoltage(&acc_24v_sns) * VACC_R_ERROR_COMPENSATION / VACC_VOLTAGE_DIV; } \ No newline at end of file diff --git a/firmware/quadruna/VC/src/io/io_lowVoltageBattery.h b/firmware/quadruna/VC/src/io/io_lowVoltageBattery.h index 3934e6c938..6b53a0fada 100644 --- a/firmware/quadruna/VC/src/io/io_lowVoltageBattery.h +++ b/firmware/quadruna/VC/src/io/io_lowVoltageBattery.h @@ -1,29 +1,6 @@ #pragma once #include -#include "app_utils.h" - -#ifdef TARGET_EMBEDDED -#include "hw_gpio.h" -#include "hw_adc.h" - -typedef struct -{ - const Gpio lt3650_charger_fault_gpio; - const Gpio ltc3786_boost_fault_gpio; - const AdcChannel *vbat_vsense_adc_channel; - const AdcChannel *boost_vsense_adc_channel; - const AdcChannel *acc_vsense_adc_channel; -} LvBatteryConfig; -#else -EMPTY_STRUCT(LvBatteryConfig); -#endif - -/** - * Initialize the LV battery IO module. - * @param config Config params. - */ -void io_lowVoltageBattery_init(const LvBatteryConfig *lv_batt_config); /** * Check if the charging IC for the given low voltage battery has a fault. @@ -42,21 +19,18 @@ bool io_lowVoltageBattery_hasBoostControllerFault(void); /** * Get the 2S1P 18650 battery voltage. - * @param low_voltage_battery the low voltage battery to read * @return 18650 series voltage, in volts. */ float io_lowVoltageBattery_getBatVoltage(void); /** * Get the boost converter voltage. - * @param low_voltage_battery the low voltage battery to get boost converter voltage for * @return Boost converter voltage, in volts. */ float io_lowVoltageBattery_getBoostVoltage(void); /** * Get the accumulator LV voltage. - * @param low_voltage_battery the low voltage battery to get accumulator voltage for * @return LV accumulator voltage, in volts. */ float io_lowVoltageBattery_getAccVoltage(void); \ No newline at end of file diff --git a/firmware/quadruna/VC/src/io/io_pcm.c b/firmware/quadruna/VC/src/io/io_pcm.c index 18cb12e246..1f36ae0969 100644 --- a/firmware/quadruna/VC/src/io/io_pcm.c +++ b/firmware/quadruna/VC/src/io/io_pcm.c @@ -1,13 +1,7 @@ #include "io_pcm.h" +#include "hw_gpios.h" -static const PcmConfig *config = NULL; - -void io_pcm_init(const PcmConfig *const in_config) -{ - config = in_config; -} - -void io_pcm_set(bool enable) +void io_pcm_set(const bool enable) { - hw_gpio_writePin(config->pcm_gpio, !enable); + hw_gpio_writePin(&npcm_en, !enable); } diff --git a/firmware/quadruna/VC/src/io/io_pcm.h b/firmware/quadruna/VC/src/io/io_pcm.h index 4aa6ebde82..b7ac2d1d52 100644 --- a/firmware/quadruna/VC/src/io/io_pcm.h +++ b/firmware/quadruna/VC/src/io/io_pcm.h @@ -1,16 +1,5 @@ -#ifdef TARGET_EMBEDDED -#include "hw_gpio.h" -typedef struct -{ - const Gpio *pcm_gpio; -} PcmConfig; - -/** - * Initialize the IO PCM module. - * @param in_config PCM config struct. - */ -void io_pcm_init(const PcmConfig *const in_config); -#endif +#pragma once +#include /** * Enable the PCM. diff --git a/firmware/quadruna/VC/src/io/io_sbgEllipse.c b/firmware/quadruna/VC/src/io/io_sbgEllipse.c index 0088076a42..c7a55dcfd7 100644 --- a/firmware/quadruna/VC/src/io/io_sbgEllipse.c +++ b/firmware/quadruna/VC/src/io/io_sbgEllipse.c @@ -3,8 +3,6 @@ #include #include "FreeRTOS.h" #include "cmsis_os.h" -#include "queue.h" - #include "main.h" #include "app_units.h" #include "sbgECom.h" @@ -14,6 +12,7 @@ #include "io_time.h" #include "io_log.h" +#include "hw_uarts.h" /* ------------------------------------ Defines ------------------------------------- */ @@ -21,9 +20,7 @@ #define QUEUE_MAX_SIZE 32 // 128 * 32 = 4096 which is SBG_ECOM_MAX_BUFFER_SIZE /* --------------------------------- Variables ---------------------------------- */ -extern UART_HandleTypeDef huart2; - -static const UART *uart = NULL; +static const UART *chimera_uart = &sbg_uart; static SbgInterface sbg_interface; // Handle for interface static SbgEComHandle com_handle; // Handle for comms static uint8_t uart_rx_buffer[UART_RX_PACKET_SIZE]; // Buffer to hold last RXed UART packet @@ -240,12 +237,10 @@ static void io_sbgEllipse_processMsg_EkfNavVelandPos(const SbgBinaryLogData *log /* ------------------------- Public Function Definitions -------------------------- */ -bool io_sbgEllipse_init(const UART *sbg_uart) +bool io_sbgEllipse_init() { memset(&sensor_data, 0, sizeof(SensorData)); - uart = sbg_uart; - // Initialize the SBG serial interface handle io_sbgEllipse_createSerialInterface(&sbg_interface); @@ -266,7 +261,7 @@ bool io_sbgEllipse_init(const UART *sbg_uart) assert(sensor_rx_queue_id != NULL); // Start waiting for UART packets - hw_uart_receiveDma(uart, uart_rx_buffer, UART_RX_PACKET_SIZE); + hw_uart_receiveDma(chimera_uart, uart_rx_buffer, UART_RX_PACKET_SIZE); return true; } diff --git a/firmware/quadruna/VC/src/io/io_sbgEllipse.h b/firmware/quadruna/VC/src/io/io_sbgEllipse.h index 653909e7ad..c5d7bff212 100644 --- a/firmware/quadruna/VC/src/io/io_sbgEllipse.h +++ b/firmware/quadruna/VC/src/io/io_sbgEllipse.h @@ -3,10 +3,6 @@ #include #include -#ifdef TARGET_EMBEDDED -#include "hw_uart.h" -#endif - /* ------------------------------------ Typedefs ------------------------------------- */ typedef struct @@ -78,13 +74,7 @@ typedef struct uint32_t ekf_solution_status; } SensorData; -#ifdef TARGET_EMBEDDED -#include "hw_uart.h" -/* - * Initialize the SBG Ellipse N sensor IO module. - */ -bool io_sbgEllipse_init(const UART *imu_uart); -#endif +bool io_sbgEllipse_init(); /* * Parse all logs which are currently residing in the UART RX buffer. diff --git a/firmware/quadruna/VC/src/io/io_telemMessage.c b/firmware/quadruna/VC/src/io/io_telemMessage.c index 74c8420ed1..3dd1682165 100644 --- a/firmware/quadruna/VC/src/io/io_telemMessage.c +++ b/firmware/quadruna/VC/src/io/io_telemMessage.c @@ -1,11 +1,9 @@ #include "io_telemMessage.h" #include "telem.pb.h" #include "pb_encode.h" -#include "pb_decode.h" -#include "io_time.h" #include "cmsis_os.h" -#include "queue.h" #include "io_log.h" +#include "hw_uarts.h" // create the truth table for now to decide which amount of things to use // create or grab the constants for the different modem and pins and such @@ -14,8 +12,13 @@ #define CAN_DATA_LENGTH 12 #define UART_LENGTH 1 #define QUEUE_SIZE 50 -static bool modem_900_choice; -static const Modem *modem = NULL; +static bool modem_900_choice; +typedef struct +{ + const UART *modem900M; + const UART *modem2_4G; +} Modem; +static const Modem modem = { .modem2_4G = &modem2G4_uart, .modem900M = &modem900_uart }; #define QUEUE_BYTES CAN_DATA_LENGTH *QUEUE_SIZE static bool proto_status; @@ -36,14 +39,13 @@ static const osMessageQueueAttr_t queue_attr = { .mq_size = QUEUE_BYTES, }; -void io_telemMessage_init(const Modem *m) +void io_telemMessage_init() { modem_900_choice = true; // if false, then using the 2.4GHz, - modem = m; message_queue_id = osMessageQueueNew(CAN_DATA_LENGTH, QUEUE_SIZE, &queue_attr); } -bool io_telemMessage_pushMsgtoQueue(CanMsg *rx_msg) +bool io_telemMessage_pushMsgtoQueue(const CanMsg *rx_msg) { uint8_t proto_buffer[QUEUE_SIZE] = { 0 }; @@ -59,17 +61,16 @@ bool io_telemMessage_pushMsgtoQueue(CanMsg *rx_msg) // Filling in fields if (rx_msg->dlc > 8) return false; - t_message.can_id = (int32_t)(rx_msg->std_id); - t_message.message_0 = rx_msg->data[0]; - t_message.message_1 = rx_msg->data[1]; - t_message.message_2 = rx_msg->data[2]; - t_message.message_3 = rx_msg->data[3]; - t_message.message_4 = rx_msg->data[4]; - t_message.message_5 = rx_msg->data[5]; - t_message.message_6 = rx_msg->data[6]; - t_message.message_7 = rx_msg->data[7]; - - t_message.time_stamp = (int32_t)io_time_getCurrentMs(); + t_message.can_id = (int32_t)(rx_msg->std_id); + t_message.message_0 = rx_msg->data[0]; + t_message.message_1 = rx_msg->data[1]; + t_message.message_2 = rx_msg->data[2]; + t_message.message_3 = rx_msg->data[3]; + t_message.message_4 = rx_msg->data[4]; + t_message.message_5 = rx_msg->data[5]; + t_message.message_6 = rx_msg->data[6]; + t_message.message_7 = rx_msg->data[7]; + t_message.time_stamp = (int32_t)rx_msg->timestamp; // encoding message proto_status = pb_encode(&stream, TelemMessage_fields, &t_message); @@ -94,22 +95,19 @@ bool io_telemMessage_broadcastMsgFromQueue(void) proto_out[49] = 0; // Start timing for measuring transmission speeds - uint32_t start_time = io_time_getCurrentMs(); - + SEGGER_SYSVIEW_MarkStart(0); if (modem_900_choice) { - hw_uart_transmitPoll(modem->modem900M, &proto_out_length, UART_LENGTH, UART_LENGTH); - hw_uart_transmitPoll(modem->modem900M, proto_out, (uint8_t)sizeof(proto_out), 100); + hw_uart_transmitPoll(modem.modem900M, &proto_out_length, UART_LENGTH, UART_LENGTH); + hw_uart_transmitPoll(modem.modem900M, proto_out, (uint8_t)sizeof(proto_out), 100); // hw_uart_transmitPoll(modem->modem900M, &zero_test, UART_LENGT/H, UART_LENGTH); } else { - hw_uart_transmitPoll(modem->modem2_4G, &proto_msg_length, UART_LENGTH, UART_LENGTH); - hw_uart_transmitPoll(modem->modem2_4G, proto_out, (uint8_t)sizeof(proto_out), 100); + hw_uart_transmitPoll(modem.modem2_4G, &proto_msg_length, UART_LENGTH, UART_LENGTH); + hw_uart_transmitPoll(modem.modem2_4G, proto_out, (uint8_t)sizeof(proto_out), 100); } - - uint32_t end_time = io_time_getCurrentMs(); - uint32_t transmission_time = end_time - start_time; + SEGGER_SYSVIEW_MarkStop(0); return true; } diff --git a/firmware/quadruna/VC/src/io/io_telemMessage.h b/firmware/quadruna/VC/src/io/io_telemMessage.h index d3bdb1bfb3..69f39ae4e9 100644 --- a/firmware/quadruna/VC/src/io/io_telemMessage.h +++ b/firmware/quadruna/VC/src/io/io_telemMessage.h @@ -1,29 +1,16 @@ #pragma once -#include "app_utils.h" -#include "io_can.h" - -#ifdef TARGET_EMBEDDED -#include "hw_uart.h" - -typedef struct -{ - UART const *modem900M; - UART const *modem2_4G; -} Modem; -#else -EMPTY_STRUCT(Modem); -#endif +#include "io_canMsg.h" +#include /** * Creates a new message queue for storing telem messages - * */ -void io_telemMessage_init(const Modem *m); +void io_telemMessage_init(); /** * Serializes the can msg and pushes it to the queue */ -bool io_telemMessage_pushMsgtoQueue(CanMsg *rx_msg); +bool io_telemMessage_pushMsgtoQueue(const CanMsg *rx_msg); /** * Pops message from the queue and passes over uart diff --git a/firmware/quadruna/VC/src/io/io_vcShdn.c b/firmware/quadruna/VC/src/io/io_vcShdn.c index 42a9a1edc3..f051ed4f9c 100644 --- a/firmware/quadruna/VC/src/io/io_vcShdn.c +++ b/firmware/quadruna/VC/src/io/io_vcShdn.c @@ -1,28 +1,22 @@ #include "io_vcShdn.h" - -static const VcShdnConfig *shdn_config = NULL; - -void io_vcShdn_init(const VcShdnConfig *shutdown_config) -{ - shdn_config = shutdown_config; -} +#include "hw_gpios.h" bool io_vcShdn_TsmsFault_get(void) { - return hw_gpio_readPin(shdn_config->tsms_gpio); + return hw_gpio_readPin(&tsms_shdn_sns); } bool io_vcShdn_LEStopFault_get(void) { - return hw_gpio_readPin(shdn_config->LE_stop_gpio); + return hw_gpio_readPin(&l_shdn_sns); } bool io_vcShdn_REStopFault_get(void) { - return hw_gpio_readPin(shdn_config->RE_stop_gpio); + return hw_gpio_readPin(&r_shdn_sns); } bool io_vcShdn_SplitterBoxInterlockFault_get(void) { - return hw_gpio_readPin(shdn_config->splitter_box_interlock_gpio); + return hw_gpio_readPin(&sb_ilck_shdn_sns); } diff --git a/firmware/quadruna/VC/src/io/io_vcShdn.h b/firmware/quadruna/VC/src/io/io_vcShdn.h index e1c58a1adf..e10ebcd911 100644 --- a/firmware/quadruna/VC/src/io/io_vcShdn.h +++ b/firmware/quadruna/VC/src/io/io_vcShdn.h @@ -1,29 +1,9 @@ #pragma once -#include "app_utils.h" -#ifdef TARGET_EMBEDDED -#include "hw_gpio.h" -#include "hw_adc.h" - -typedef struct -{ - const Gpio *tsms_gpio; - const Gpio *LE_stop_gpio; - const Gpio *RE_stop_gpio; - const Gpio *splitter_box_interlock_gpio; -} VcShdnConfig; -#else -EMPTY_STRUCT(VcShdnConfig); -#endif +#include #define VC_SHDN_NODE_COUNT 4 -/* - * Initialize config for shutdown gpio pins - * @param config with shutdown gpio pins - */ -void io_vcShdn_init(const VcShdnConfig *shutdown_config); - /* * Get the status of the tsms shutdown pin * @return the status of the tsms pin set in the shutdown config diff --git a/firmware/quadruna/VC/src/jobs.c b/firmware/quadruna/VC/src/jobs.c new file mode 100644 index 0000000000..8688c5e18c --- /dev/null +++ b/firmware/quadruna/VC/src/jobs.c @@ -0,0 +1,130 @@ +#include "jobs.h" + +#include "app_canDataCapture.h" + +#include "app_canTx.h" +#include "app_canRx.h" +#include "app_canAlerts.h" +#include "app_faultCheck.h" +#include "app_commitInfo.h" +#include "io_canTx.h" +#include "io_canRx.h" + +#include "app_stateMachine.h" +#include "states/app_initState.h" +#include "states/app_allStates.h" +#include "app_heartbeatMonitors.h" + +#include "io_time.h" +#include "io_log.h" +#include "io_sbgEllipse.h" +#include "io_imu.h" +#include "io_jsoncan.h" +#include "io_canQueue.h" +#include "io_telemMessage.h" +#include "io_canLoggingQueue.h" +#include "io_fileSystem.h" +#include "io_cans.h" + +static void jsoncan_transmit_func(const JsonCanMsg *tx_msg) +{ + const CanMsg c = io_jsoncan_copyToCanMsg(tx_msg); + io_canQueue_pushTx(&c); +} + +void jobs_init() +{ + app_canTx_init(); + app_canRx_init(); + app_canDataCapture_init(); + + // Empirically, mounting slows down (takes ~500ms) at 200 CAN logs on disk. + // This is not correlated to the size of each file. + app_canTx_VC_NumberOfCanDataLogs_set(io_canLogging_getCurrentLog()); + app_canAlerts_VC_Warning_HighNumberOfCanDataLogs_set(io_canLogging_getCurrentLog() > HIGH_NUMBER_OF_LOGS_THRESHOLD); + app_canAlerts_VC_Warning_CanLoggingSdCardNotPresent_set(!io_fileSystem_ready()); + + app_stateMachine_init(app_initState_get()); + app_heartbeatMonitor_init(&hb_monitor); + + app_canTx_VC_Hash_set(GIT_COMMIT_HASH); + app_canTx_VC_Clean_set(GIT_COMMIT_CLEAN); + + app_faultCheck_init(); + + if (!io_sbgEllipse_init()) + { + app_canAlerts_VC_Warning_SbgInitFailed_set(true); + LOG_INFO("Sbg initialization failed"); + } + if (!io_imu_init()) + { + app_canAlerts_VC_Warning_ImuInitFailed_set(true); + LOG_INFO("Imu initialization failed"); + } + + io_can_init(&can1); + io_canTx_init(jsoncan_transmit_func); + io_canTx_enableMode(CAN_MODE_DEFAULT, true); + io_canQueue_init(); + io_telemMessage_init(); +} + +void jobs_run1Hz_tick(void) +{ + // VERY IMPORTANT that allstates after state machine + // this is because there are fault overrides in allStates + app_stateMachine_tick1Hz(); + app_allStates_runOnTick1Hz(); + + const bool debug_mode_enabled = app_canRx_Debug_EnableDebugMode_get(); + io_canTx_enableMode(CAN_MODE_DEBUG, debug_mode_enabled); + io_canTx_enqueue1HzMsgs(); +} + +void jobs_run100Hz_tick(void) +{ + // VERY IMPORTANT that allstates after state machine + // this is because there are fault overrides in allStates + app_stateMachine_tick100Hz(); + app_allStates_runOnTick100Hz(); + + io_canTx_enqueue100HzMsgs(); +} + +void jobs_run1kHz_tick(void) +{ + const uint32_t task_start_ms = io_time_getCurrentMs(); + io_canTx_enqueueOtherPeriodicMsgs(task_start_ms); +} + +void jobs_runCanTx_tick(void) +{ + CanMsg tx_msg = io_canQueue_popTx(); + io_can_transmit(&can1, &tx_msg); // TODO make HW -> IO CAN + + // ReSharper disable once CppRedundantCastExpression + if (io_fileSystem_ready() && app_dataCapture_needsLog((uint16_t)tx_msg.std_id, tx_msg.timestamp)) + io_canLogging_loggingQueuePush(&tx_msg); + // ReSharper disable once CppRedundantCastExpression + if (app_dataCapture_needsTelem((uint16_t)tx_msg.std_id, tx_msg.timestamp)) + io_telemMessage_pushMsgtoQueue(&tx_msg); +} + +void jobs_runCanRx_tick(void) +{ + const CanMsg rx_msg = io_canQueue_popRx(); + if (io_canRx_filterMessageId(rx_msg.std_id)) + { + JsonCanMsg json_can_msg = io_jsoncan_copyFromCanMsg(&rx_msg); + io_canRx_updateRxTableWithMessage(&json_can_msg); + } + + // Log the message if it needs to be logged + // ReSharper disable once CppRedundantCastExpression + if (io_fileSystem_ready() && app_dataCapture_needsLog((uint16_t)rx_msg.std_id, rx_msg.timestamp)) + io_canLogging_loggingQueuePush(&rx_msg); // push to logging queue + // ReSharper disable once CppRedundantCastExpression + if (app_dataCapture_needsTelem((uint16_t)rx_msg.std_id, rx_msg.timestamp)) + io_telemMessage_pushMsgtoQueue(&rx_msg); +} \ No newline at end of file diff --git a/firmware/quadruna/VC/src/jobs.h b/firmware/quadruna/VC/src/jobs.h new file mode 100644 index 0000000000..0a8b68d56f --- /dev/null +++ b/firmware/quadruna/VC/src/jobs.h @@ -0,0 +1,19 @@ +/** + * This file is meant to help unit testing. + */ + +#pragma once + +/** + * Anything that needs to be initialized for unit testing must be put here + */ +void jobs_init(void); + +/** + * Anything that needs to run on periodic intervals in the unit test is to be placed here + */ +void jobs_run1Hz_tick(void); +void jobs_run100Hz_tick(void); +void jobs_run1kHz_tick(void); +void jobs_runCanTx_tick(void); +void jobs_runCanRx_tick(void); diff --git a/firmware/quadruna/VC/src/tasks.c b/firmware/quadruna/VC/src/tasks.c index c243b7b34f..c3fb3f0604 100644 --- a/firmware/quadruna/VC/src/tasks.c +++ b/firmware/quadruna/VC/src/tasks.c @@ -2,254 +2,31 @@ #include "main.h" #include "cmsis_os.h" #include "shared.pb.h" +#include "jobs.h" + +#include -#include "states/app_allStates.h" -#include "states/app_initState.h" -#include "app_canTx.h" -#include "app_canRx.h" #include "app_canAlerts.h" #include "app_canDataCapture.h" #include "app_commitInfo.h" #include "app_faultCheck.h" #include "app_heartbeatMonitors.h" -#include "io_jsoncan.h" #include "io_log.h" -#include "io_canRx.h" -#include "io_led.h" +#include "io_canLoggingQueue.h" +#include "io_telemMessage.h" #include "io_chimera.h" -#include "io_efuse.h" -#include "io_lowVoltageBattery.h" -#include "io_vcShdn.h" -#include "io_currentSensing.h" +#include "io_time.h" #include "io_sbgEllipse.h" -#include "io_canLogging.h" #include "io_fileSystem.h" -#include "io_imu.h" -#include "io_telemMessage.h" -#include "io_pcm.h" -#include "io_time.h" +#include "io_cans.h" +#include "io_canQueue.h" #include "hw_bootup.h" -#include "hw_utils.h" #include "hw_hardFaultHandler.h" -#include "hw_watchdog.h" #include "hw_watchdogConfig.h" -#include "hw_gpio.h" -#include "hw_stackWaterMarkConfig.h" -#include "hw_uart.h" #include "hw_adcs.h" -#include "hw_sd.h" - -static uint32_t can_logging_overflow_count = 0; -static uint32_t read_count = 0; // TODO debugging variables -static uint32_t write_count = 0; // TODO debugging variables -static bool sd_card_present = true; - -static void canRxCallback(CanMsg *rx_msg) -{ - io_can_pushRxMsgToQueue(rx_msg); // push to queue - - // Log the message if it needs to be logged - if (sd_card_present && app_dataCapture_needsLog((uint16_t)rx_msg->std_id, io_time_getCurrentMs())) - { - io_canLogging_loggingQueuePush(rx_msg); // push to logging queue - read_count++; - } -} - -SdCard sd = { .hsd = &hsd1, .timeout = 1000 }; -static const CanHandle can = { .can = &hfdcan1, .can_msg_received_callback = canRxCallback }; - -void canRxQueueOverflowCallBack(uint32_t overflow_count) -{ - app_canTx_VC_RxOverflowCount_set(overflow_count); - app_canAlerts_VC_Warning_RxOverflow_set(true); - LOG_INFO("CAN RX OVERFLOW"); -} - -void canTxQueueOverflowCallBack(uint32_t overflow_count) -{ - app_canTx_VC_TxOverflowCount_set(overflow_count); - app_canAlerts_VC_Warning_TxOverflow_set(true); - LOG_INFO("CAN TX OVERFLOW"); -} - -void canTxQueueOverflowClearCallback(void) -{ - app_canAlerts_VC_Warning_TxOverflow_set(false); -} - -void canRxQueueOverflowClearCallback(void) -{ - app_canAlerts_VC_Warning_RxOverflow_set(false); -} - -static const CanConfig io_can_config = { - .rx_msg_filter = io_canRx_filterMessageId, - .tx_overflow_callback = canTxQueueOverflowCallBack, - .rx_overflow_callback = canRxQueueOverflowCallBack, - .tx_overflow_clear_callback = canTxQueueOverflowClearCallback, - .rx_overflow_clear_callback = canRxQueueOverflowClearCallback, -}; - -static bool canLoggingFilter(uint32_t msg_id) -{ - return true; -} - -static void canLoggingQueueOverflowCallback(uint32_t f) -{ - can_logging_overflow_count++; -} - -static const CanConfig canLogging_config = { - .rx_msg_filter = canLoggingFilter, - .tx_overflow_callback = canLoggingQueueOverflowCallback, - .rx_overflow_callback = canLoggingQueueOverflowCallback, - .tx_overflow_clear_callback = NULL, - .rx_overflow_clear_callback = NULL, -}; - -extern Gpio sd_present; -static const Gpio buzzer_pwr_en = { .port = BUZZER_PWR_EN_GPIO_Port, .pin = BUZZER_PWR_EN_Pin }; -static const Gpio bat_i_sns_nflt = { .port = BAT_I_SNS_nFLT_GPIO_Port, .pin = BAT_I_SNS_nFLT_Pin }; -static const BinaryLed led = { .gpio = { .port = LED_GPIO_Port, .pin = LED_Pin } }; -static const Gpio telem_pwr_en = { .port = TELEM_PWR_EN_GPIO_Port, .pin = TELEM_PWR_EN_Pin }; -static const Gpio npcm_en = { .port = nPCM_EN_GPIO_Port, .pin = nPCM_EN_Pin }; -static const Gpio acc_i_sns_nflt = { .port = ACC_I_SENSE_nFLT_GPIO_Port, .pin = ACC_I_SENSE_nFLT_Pin }; -static const Gpio pgood = { .port = PGOOD_GPIO_Port, .pin = PGOOD_Pin }; -static const Gpio lv_pwr_en = { .port = LV_PWR_EN_GPIO_Port, .pin = LV_PWR_EN_Pin }; -static const Gpio aux_pwr_en = { .port = AUX_PWR_EN_GPIO_Port, .pin = AUX_PWR_EN_Pin }; -static const Gpio pump_pwr_en = { .port = PUMP_PWR_EN_GPIO_Port, .pin = PUMP_PWR_EN_Pin }; -static const Gpio _900k_gpio = { .port = _900K_GPIO_GPIO_Port, .pin = _900K_GPIO_Pin }; -static const Gpio nchrg_fault = { .port = nCHRG_FAULT_GPIO_Port, .pin = nCHRG_FAULT_Pin }; -static const Gpio nchrg = { .port = nCHRG_GPIO_Port, .pin = nCHRG_Pin }; -static const Gpio inv_l_pwr_en = { .port = INV_L_PWR_EN_GPIO_Port, .pin = INV_L_PWR_EN_Pin }; -static const Gpio inv_r_pwr_en = { .port = INV_R_PWR_EN_GPIO_Port, .pin = INV_R_PWR_EN_Pin }; -static const Gpio shdn_pwr_en = { .port = SHDN_PWR_EN_GPIO_Port, .pin = SHDN_PWR_EN_Pin }; -static const Gpio fr_stby1 = { .port = FR_STBY1_GPIO_Port, .pin = FR_STBY1_Pin }; -static const Gpio fr_stby2 = { .port = FR_STBY2_GPIO_Port, .pin = FR_STBY2_Pin }; -static const Gpio fr_stby3 = { .port = FR_STBY3_GPIO_Port, .pin = FR_STBY3_Pin }; -static const Gpio inv_l_program = { .port = INV_L_PROGRAM_GPIO_Port, .pin = INV_L_PROGRAM_Pin }; -static const Gpio inv_r_program = { .port = INV_R_PROGRAM_GPIO_Port, .pin = INV_R_PROGRAM_Pin }; -static const Gpio l_shdn_sns = { .port = L_SHDN_SNS_GPIO_Port, .pin = L_SHDN_SNS_Pin }; -static const Gpio r_shdn_sns = { .port = R_SHDN_SNS_GPIO_Port, .pin = R_SHDN_SNS_Pin }; -static const Gpio n_chimera_pin = { .port = NCHIMERA_GPIO_Port, .pin = NCHIMERA_Pin }; -static const Gpio nprogram_3v3 = { .port = NPROGRAM_3V3_GPIO_Port, .pin = NPROGRAM_3V3_Pin }; -static const Gpio sb_ilck_shdn_sns = { .port = SB_ILCK_SHDN_SNS_GPIO_Port, .pin = SB_ILCK_SHDN_SNS_Pin }; -static const Gpio tsms_shdn_sns = { .port = TSMS_SHDN_SNS_GPIO_Port, .pin = TSMS_SHDN_SNS_Pin }; - -const Gpio *id_to_gpio[] = { [VC_GpioNetName_BUZZER_PWR_EN] = &buzzer_pwr_en, - [VC_GpioNetName_BAT_I_SNS_NFLT] = &bat_i_sns_nflt, - [VC_GpioNetName_LED] = &led.gpio, - [VC_GpioNetName_TELEM_PWR_EN] = &telem_pwr_en, - [VC_GpioNetName_NPCM_EN] = &npcm_en, - [VC_GpioNetName_ACC_I_SENSE_NFLT] = &acc_i_sns_nflt, - [VC_GpioNetName_PGOOD] = &pgood, - [VC_GpioNetName_LV_PWR_EN] = &lv_pwr_en, - [VC_GpioNetName_AUX_PWR_EN] = &aux_pwr_en, - [VC_GpioNetName_PUMP_PWR_EN] = &pump_pwr_en, - [VC_GpioNetName__900K_GPIO] = &_900k_gpio, - [VC_GpioNetName_NCHRG_FAULT] = &nchrg_fault, - [VC_GpioNetName_NCHRG] = &nchrg, - [VC_GpioNetName_INV_L_PWR_EN] = &inv_l_pwr_en, - [VC_GpioNetName_INV_R_PWR_EN] = &inv_r_pwr_en, - [VC_GpioNetName_SHDN_PWR_EN] = &shdn_pwr_en, - [VC_GpioNetName_FR_STBY1] = &fr_stby1, - [VC_GpioNetName_FR_STBY2] = &fr_stby2, - [VC_GpioNetName_FR_STBY3] = &fr_stby3, - [VC_GpioNetName_INV_L_PROGRAM] = &inv_l_program, - [VC_GpioNetName_INV_R_PROGRAM] = &inv_r_program, - [VC_GpioNetName_L_SHDN_SNS] = &l_shdn_sns, - [VC_GpioNetName_R_SHDN_SNS] = &r_shdn_sns, - [VC_GpioNetName_NCHIMERA] = &n_chimera_pin, - [VC_GpioNetName_NPROGRAM_3V3] = &nprogram_3v3, - [VC_GpioNetName_SB_ILCK_SHDN_SNS] = &sb_ilck_shdn_sns, - [VC_GpioNetName_TSMS_SHDN_SNS] = &tsms_shdn_sns }; - -const AdcChannel *const id_to_adc[] = { - [VC_AdcNetName_INV_R_PWR_I_SNS] = &inv_r_pwr_i_sns, - [VC_AdcNetName_INV_L_PWR_I_SNS] = &inv_l_pwr_i_sns, - [VC_AdcNetName_AUX_PWR_I_SNS] = &aux_pwr_i_sns, - [VC_AdcNetName_SHDN_PWR_I_SNS] = &shdn_pwr_i_sns, - [VC_AdcNetName_VBAT_SENSE] = &vbat_sns, - [VC_AdcNetName__24V_ACC_SENSE] = &acc_24v_sns, - [VC_AdcNetName__22V_BOOST_SENSE] = &boost_22v_sns, - [VC_AdcNetName_LV_PWR_I_SNS] = &lv_pwr_i_sns, - [VC_AdcNetName_ACC_I_SENSE] = &acc_i_sns, - [VC_AdcNetName_PUMP_PWR_I_SNS] = &pump_pwr_i_sns, -}; - -static const CurrentSensingConfig current_sensing_config = { - .bat_fault_gpio = bat_i_sns_nflt, - .acc_fault_gpio = acc_i_sns_nflt, - .bat_current_adc = &bat_i_sns, - .acc_current_adc = &acc_i_sns, -}; - -static const VcShdnConfig shutdown_config = { .tsms_gpio = &tsms_shdn_sns, - .LE_stop_gpio = &l_shdn_sns, - .RE_stop_gpio = &r_shdn_sns, - .splitter_box_interlock_gpio = &sb_ilck_shdn_sns }; - -static const LvBatteryConfig lv_battery_config = { .lt3650_charger_fault_gpio = nchrg_fault, - .ltc3786_boost_fault_gpio = pgood, - .vbat_vsense_adc_channel = id_to_adc[VC_AdcNetName_VBAT_SENSE], - .boost_vsense_adc_channel = - id_to_adc[VC_AdcNetName__22V_BOOST_SENSE], - .acc_vsense_adc_channel = id_to_adc[VC_AdcNetName__24V_ACC_SENSE] }; - -static const EfuseConfig efuse_configs[NUM_EFUSE_CHANNELS] = { - [EFUSE_CHANNEL_SHDN] = { - .enable_gpio = &shdn_pwr_en, - .stby_reset_gpio = &fr_stby1, - .cur_sns_adc_channel = &shdn_pwr_i_sns, - }, - [EFUSE_CHANNEL_LV] = { - .enable_gpio = &lv_pwr_en, - .stby_reset_gpio = &fr_stby1, - .cur_sns_adc_channel = &lv_pwr_i_sns, - }, - [EFUSE_CHANNEL_PUMP] = { - .enable_gpio = &pump_pwr_en, - .stby_reset_gpio = &fr_stby2, - .cur_sns_adc_channel = &pump_pwr_i_sns - }, - [EFUSE_CHANNEL_AUX] = { - .enable_gpio = &aux_pwr_en, - .stby_reset_gpio = &fr_stby2, - .cur_sns_adc_channel = &aux_pwr_i_sns - }, - [EFUSE_CHANNEL_INV_R] = { - .enable_gpio = &inv_r_pwr_en, - .stby_reset_gpio = &fr_stby3, - .cur_sns_adc_channel = &inv_r_pwr_i_sns - }, - [EFUSE_CHANNEL_INV_L] = { - .enable_gpio = &inv_l_pwr_en, - .stby_reset_gpio = &fr_stby3, - .cur_sns_adc_channel = &inv_l_pwr_i_sns - }, - [EFUSE_CHANNEL_TELEM] = { - .enable_gpio = &telem_pwr_en, - .stby_reset_gpio = NULL, - .cur_sns_adc_channel = NULL - }, - [EFUSE_CHANNEL_BUZZER] = { - .enable_gpio = &buzzer_pwr_en, - .stby_reset_gpio = NULL, - .cur_sns_adc_channel = NULL - } -}; - -static const PcmConfig pcm_config = { .pcm_gpio = &npcm_en }; - -static const UART debug_uart = { .handle = &huart7 }; -static const UART sbg_uart = { .handle = &huart2 }; -static const UART modem2G4_uart = { .handle = &huart3 }; -static const UART modem900_uart = { .handle = &huart1 }; -static const Modem modem = { .modem2_4G = &modem2G4_uart, .modem900M = &modem900_uart }; +#include "hw_stackWaterMarkConfig.h" void tasks_preInit(void) { @@ -258,20 +35,8 @@ void tasks_preInit(void) void tasks_preInitWatchdog(void) { - hw_sd_init(&sd); - - sd_card_present = !hw_gpio_readPin(&sd_present); - if (sd_card_present) - { - if (io_fileSystem_init() == FILE_OK) - { - io_canLogging_init(&canLogging_config); - } - else - { - sd_card_present = false; - } - } + if (io_fileSystem_init() == FILE_OK) + io_canLogging_init(); } void tasks_init(void) @@ -282,61 +47,17 @@ void tasks_init(void) LOG_INFO("VC reset!"); __HAL_DBGMCU_FREEZE_IWDG1(); - hw_hardFaultHandler_init(); - hw_can_init(&can); hw_watchdog_init(hw_watchdogConfig_refresh, hw_watchdogConfig_timeoutCallback); - hw_adcs_chipsInit(); - // Start interrupt mode for ADC3, since we can't use DMA (see `firmware/quadruna/VC/src/hw/hw_adc.c` for a more // in-depth comment). HAL_ADC_Start_IT(&hadc3); - io_canTx_init(io_jsoncan_pushTxMsgToQueue); - io_canTx_enableMode(CAN_MODE_DEFAULT, true); - io_can_init(&io_can_config); - io_chimera_init(&debug_uart, GpioNetName_vc_net_name_tag, AdcNetName_vc_net_name_tag, &n_chimera_pin); - - io_lowVoltageBattery_init(&lv_battery_config); - io_vcShdn_init(&shutdown_config); - io_currentSensing_init(¤t_sensing_config); - io_efuse_init(efuse_configs); - io_pcm_init(&pcm_config); - - if (!io_sbgEllipse_init(&sbg_uart)) - { - app_canAlerts_VC_Warning_SbgInitFailed_set(true); - LOG_INFO("Sbg initialization failed"); - } - if (!io_imu_init()) - { - app_canAlerts_VC_Warning_ImuInitFailed_set(true); - LOG_INFO("Imu initialization failed"); - } - - app_canTx_init(); - app_canRx_init(); - app_canDataCapture_init(); + // TODO hw_chimera?? + io_chimera_init(GpioNetName_vc_net_name_tag, AdcNetName_vc_net_name_tag); - // Empirically, mounting slows down (takes ~500ms) at 200 CAN logs on disk. - // This is not correlated to the size of each file. - app_canTx_VC_NumberOfCanDataLogs_set(io_canLogging_getCurrentLog()); - app_canAlerts_VC_Warning_HighNumberOfCanDataLogs_set(io_canLogging_getCurrentLog() > HIGH_NUMBER_OF_LOGS_THRESHOLD); - app_canAlerts_VC_Warning_CanLoggingSdCardNotPresent_set(!sd_card_present); - - app_heartbeatMonitor_init(&hb_monitor); - app_stateMachine_init(app_initState_get()); - io_telemMessage_init(&modem); - - io_lowVoltageBattery_init(&lv_battery_config); - io_currentSensing_init(¤t_sensing_config); - io_efuse_init(efuse_configs); - - app_canTx_VC_Hash_set(GIT_COMMIT_HASH); - app_canTx_VC_Clean_set(GIT_COMMIT_CLEAN); - - app_faultCheck_init(); + jobs_init(); // enable these for inverter programming // hw_gpio_writePin(&inv_l_program, true); @@ -357,11 +78,7 @@ _Noreturn void tasks_run1Hz(void) for (;;) { hw_stackWaterMarkConfig_check(); - app_stateMachine_tick1Hz(); - - const bool debug_mode_enabled = app_canRx_Debug_EnableDebugMode_get(); - io_canTx_enableMode(CAN_MODE_DEBUG, debug_mode_enabled); - io_canTx_enqueue1HzMsgs(); + jobs_run1Hz_tick(); // Watchdog check-in must be the last function called before putting the // task to sleep. @@ -385,9 +102,7 @@ _Noreturn void tasks_run100Hz(void) for (;;) { - app_allStates_runOnTick100Hz(); - app_stateMachine_tick100Hz(); - io_canTx_enqueue100HzMsgs(); + jobs_run100Hz_tick(); // Watchdog check-in must be the last function called before putting the // task to sleep. @@ -411,18 +126,16 @@ _Noreturn void tasks_run1kHz(void) for (;;) { - hw_watchdog_checkForTimeouts(); + const uint32_t task_start_ms = io_time_getCurrentMs(); - const uint32_t task_start_ms = TICK_TO_MS(osKernelGetTickCount()); - io_canTx_enqueueOtherPeriodicMsgs(task_start_ms); + hw_watchdog_checkForTimeouts(); + jobs_run1kHz_tick(); // Watchdog check-in must be the last function called before putting the // task to sleep. Prevent check in if the elapsed period is greater or // equal to the period ms - if ((TICK_TO_MS(osKernelGetTickCount()) - task_start_ms) <= period_ms) - { + if (io_time_getCurrentMs() - task_start_ms <= period_ms) hw_watchdog_checkIn(watchdog); - } start_ticks += period_ms; osDelayUntil(start_ticks); @@ -435,50 +148,37 @@ _Noreturn void tasks_runCanTx(void) for (;;) { - CanMsg tx_msg; - io_can_popTxMsgFromQueue(&tx_msg); - io_telemMessage_pushMsgtoQueue(&tx_msg); - - if (sd_card_present) - { - io_canLogging_loggingQueuePush(&tx_msg); - } - - io_can_transmitMsgFromQueue(&tx_msg); + jobs_runCanTx_tick(); } } -_Noreturn void tasks_runTelem(void) +_Noreturn void tasks_runCanRx(void) { + io_chimera_sleepTaskIfEnabled(); + for (;;) { - io_telemMessage_broadcastMsgFromQueue(); + jobs_runCanRx_tick(); } } -_Noreturn void tasks_runCanRx(void) +_Noreturn void tasks_runTelem(void) { - io_chimera_sleepTaskIfEnabled(); - for (;;) { - CanMsg rx_msg; - io_can_popRxMsgFromQueue(&rx_msg); - io_telemMessage_pushMsgtoQueue(&rx_msg); - - JsonCanMsg jsoncan_rx_msg; - io_jsoncan_copyFromCanMsg(&rx_msg, &jsoncan_rx_msg); - io_canRx_updateRxTableWithMessage(&jsoncan_rx_msg); + io_telemMessage_broadcastMsgFromQueue(); } } _Noreturn void tasks_runLogging(void) { - if (!sd_card_present) + if (!io_fileSystem_ready()) { + // queue shouldn't populate, so this is just an extra precaution osThreadSuspend(osThreadGetId()); } + static uint32_t write_count = 0; static uint32_t message_batch_count = 0; for (;;) { @@ -493,9 +193,13 @@ _Noreturn void tasks_runLogging(void) } } +/* + * INTERRUPTS + */ + void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { - if (huart == debug_uart.handle) + if (huart == &huart1) { io_chimera_msgRxCallback(); } @@ -504,3 +208,27 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) io_sbgEllipse_msgRxCallback(); } } + +void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, const uint32_t RxFifo0ITs) +{ + UNUSED(RxFifo0ITs); + CanMsg rx_msg; + + assert(hfdcan == &hfdcan1); + if (!io_can_receive(&can1, FDCAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} + +void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, const uint32_t RxFifo1ITs) +{ + UNUSED(RxFifo1ITs); + CanMsg rx_msg; + + assert(hfdcan == &hfdcan1); + if (!io_can_receive(&can1, FDCAN_RX_FIFO1, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} diff --git a/firmware/quintuna/CRIT/boot/cubemx/Src/main.c b/firmware/quintuna/CRIT/boot/cubemx/Src/main.c index fa9d6b0c37..2e539fc829 100644 --- a/firmware/quintuna/CRIT/boot/cubemx/Src/main.c +++ b/firmware/quintuna/CRIT/boot/cubemx/Src/main.c @@ -23,9 +23,12 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "bootloader.h" -#include "hw_can.h" +#include "io_canQueue.h" #include "io_can.h" #include "hw_error.h" +#include "hw_utils.h" + +#include /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -86,10 +89,27 @@ const osThreadAttr_t tickTask_attributes = { .priority = (osPriority_t)osPriorityNormal, }; /* USER CODE BEGIN PV */ -CanHandle can = { - .can = &hcan1, - .can_msg_received_callback = io_can_pushRxMsgToQueue, -}; +CanHandle can = { .hcan = &hcan1 }; + +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) +{ + assert(hcan == can.hcan); + CanMsg rx_msg; + if (!io_can_receive(&can, CAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} + +void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) +{ + assert(hcan == can.hcan); + CanMsg rx_msg; + if (!io_can_receive(&can, CAN_RX_FIFO0, &rx_msg)) + // Early return if RX msg is unavailable. + return; + io_canQueue_pushRx(&rx_msg); +} /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ @@ -142,7 +162,7 @@ int main(void) MX_CRC_Init(); /* USER CODE BEGIN 2 */ bootloader_init(); - hw_can_init(&can); + io_can_init(&can); /* USER CODE END 2 */ /* Init scheduler */ diff --git a/firmware/quintuna/RSM/CMakeLists.txt b/firmware/quintuna/RSM/CMakeLists.txt index 069fe4688f..9671151ad9 100644 --- a/firmware/quintuna/RSM/CMakeLists.txt +++ b/firmware/quintuna/RSM/CMakeLists.txt @@ -62,21 +62,21 @@ if ("${TARGET}" STREQUAL "binary") set(STM32_HAL_SRCS "stm32f4xx_hal_adc_ex.c" - "stm32f4xx_hal_adc.c" - "stm32f4xx_hal_cortex.c" - "stm32f4xx_hal_dma_ex.c" - "stm32f4xx_hal_dma.c" - "stm32f4xx_hal_exti.c" - "stm32f4xx_hal_can.c" - "stm32f4xx_hal_gpio.c" - "stm32f4xx_hal_iwdg.c" - "stm32f4xx_hal_pwr_ex.c" - "stm32f4xx_hal_rcc_ex.c" - "stm32f4xx_hal_rcc.c" - "stm32f4xx_hal_tim_ex.c" - "stm32f4xx_hal_tim.c" - "stm32f4xx_hal_uart.c" - "stm32f4xx_hal.c" + "stm32f4xx_hal_adc.c" + "stm32f4xx_hal_cortex.c" + "stm32f4xx_hal_dma_ex.c" + "stm32f4xx_hal_dma.c" + "stm32f4xx_hal_exti.c" + "stm32f4xx_hal_can.c" + "stm32f4xx_hal_gpio.c" + "stm32f4xx_hal_iwdg.c" + "stm32f4xx_hal_pwr_ex.c" + "stm32f4xx_hal_rcc_ex.c" + "stm32f4xx_hal_rcc.c" + "stm32f4xx_hal_tim_ex.c" + "stm32f4xx_hal_tim.c" + "stm32f4xx_hal_uart.c" + "stm32f4xx_hal.c" ) stm32f412rx_cube_library( @@ -88,7 +88,6 @@ if ("${TARGET}" STREQUAL "binary") FALSE ) - # JSONCAN # JSONCAN jsoncan_embedded_library(RSM quintuna "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/firmware/shared/src/hw/hw_can.c b/firmware/shared/src/hw/hw_can.c deleted file mode 100644 index 22889513af..0000000000 --- a/firmware/shared/src/hw/hw_can.c +++ /dev/null @@ -1,142 +0,0 @@ -#include "hw_can.h" -#undef NDEBUG -#include -#include "io_can.h" - -// The following filter IDs/masks must be used with 16-bit Filter Scale -// (FSCx = 0) and Identifier Mask Mode (FBMx = 0). In this mode, the identifier -// registers are associated with mask registers specifying which bits of the -// identifier are handled as "don't care" or as "must match". For each bit in -// the mask registers, 0 = Don't Care and 1 = Must Match. -// -// Bit mapping of a 16-bit identifier register and mask register: -// Standard CAN ID [15:5] RTR[4] IDE[3] Extended CAN ID [2:0] -// -// For example, with the following filter IDs/mask: -// ======================================================= -// Identifier Register: [000 0000 0000] [0] [0] [000] -// Mask Register: [111 1110 0000] [1] [1] [000] -// ======================================================= -// The filter will accept incoming messages that match the following criteria: -// [000 000x xxxx] [0] [0] [xxx] -// Standard CAN ID RTR IDE Extended CAN ID -#define INIT_MASKMODE_16BIT_FiRx(std_id, rtr, ide, ext_id) \ - ((((uint32_t)(std_id) << 5U) & 0xFFE0) | (((uint32_t)(rtr) << 4U) & 0x0010) | (((uint32_t)(ide) << 3U) & 0x0008) | \ - (((uint32_t)(ext_id) << 0U) & 0x0007)) - -// Open CAN filter that accepts any CAN message as long as it uses Standard CAN -// ID and is a data frame. -#define CAN_ExtID_NULL 0 // Set CAN Extended ID to 0 because we are not using it. -#define MASKMODE_16BIT_ID_OPEN INIT_MASKMODE_16BIT_FiRx(0x0, CAN_ID_STD, CAN_RTR_DATA, CAN_ExtID_NULL) -#define MASKMODE_16BIT_MASK_OPEN INIT_MASKMODE_16BIT_FiRx(0x0, 0x1, 0x1, 0x0) - -static const CanHandle *handle; - -void hw_can_init(const CanHandle *can_handle) -{ - handle = can_handle; - - // Configure a single filter bank that accepts any message. - CAN_FilterTypeDef filter; - filter.FilterMode = CAN_FILTERMODE_IDMASK; - filter.FilterScale = CAN_FILTERSCALE_16BIT; - filter.FilterActivation = CAN_FILTER_ENABLE; - filter.FilterIdLow = MASKMODE_16BIT_ID_OPEN; - filter.FilterMaskIdLow = MASKMODE_16BIT_MASK_OPEN; - filter.FilterIdHigh = MASKMODE_16BIT_ID_OPEN; - filter.FilterMaskIdHigh = MASKMODE_16BIT_MASK_OPEN; - filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; - filter.FilterBank = 0; - - // Configure and initialize hardware filter. - assert(HAL_CAN_ConfigFilter(handle->can, &filter) == HAL_OK); - - // Configure interrupt mode for CAN peripheral. - assert( - HAL_CAN_ActivateNotification( - handle->can, CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING) == - HAL_OK); - - // Start the CAN peripheral. - assert(HAL_CAN_Start(handle->can) == HAL_OK); -} - -void hw_can_deinit(void) -{ - assert(HAL_CAN_Stop(handle->can) == HAL_OK); - assert(HAL_CAN_DeInit(handle->can) == HAL_OK); -} - -bool hw_can_transmit(const CanMsg *msg) -{ - CAN_TxHeaderTypeDef tx_header; - - tx_header.DLC = msg->dlc; - tx_header.StdId = msg->std_id; - - // The standard 11-bit CAN identifier is more than sufficient, so we disable - // Extended CAN IDs by setting this field to zero. - tx_header.ExtId = CAN_ExtID_NULL; - - // This field can be either Standard CAN or Extended CAN. See .ExtID to see - // why we don't want Extended CAN. - tx_header.IDE = CAN_ID_STD; - - // This field can be either Data Frame or Remote Frame. For our - // purpose, we only ever transmit Data Frames. - tx_header.RTR = CAN_RTR_DATA; - - // Enabling this gives us a tick-based timestamp which we do not need. Plus, - // it would take up 2 bytes of the CAN payload. So we disable the timestamp. - tx_header.TransmitGlobalTime = DISABLE; - - // Spin until a TX mailbox becomes available. - while (HAL_CAN_GetTxMailboxesFreeLevel(handle->can) == 0U) - ; - - // Indicates the mailbox used for transmission, not currently used. - uint32_t mailbox = 0; - const HAL_StatusTypeDef return_status = HAL_CAN_AddTxMessage(handle->can, &tx_header, msg->data, &mailbox); - return return_status == HAL_OK; -} - -bool hw_can_receive(uint32_t rx_fifo, CanMsg *msg) -{ - CAN_RxHeaderTypeDef header; - if (HAL_CAN_GetRxMessage(handle->can, rx_fifo, &header, msg->data) != HAL_OK) - { - return false; - } - - // Copy metadata from HAL's CAN message struct into our custom CAN - // message struct - msg->std_id = header.StdId; - msg->dlc = header.DLC; - return true; -} - -void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) -{ - UNUSED(hcan); - CanMsg rx_msg; - if (!hw_can_receive(CAN_RX_FIFO0, &rx_msg)) - { - // Early return if RX msg is unavailable. - return; - } - - handle->can_msg_received_callback(&rx_msg); -} - -void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) -{ - UNUSED(hcan); - CanMsg rx_msg; - if (!hw_can_receive(CAN_RX_FIFO1, &rx_msg)) - { - // Early return if RX msg is unavailable. - return; - } - - handle->can_msg_received_callback(&rx_msg); -} diff --git a/firmware/shared/src/hw/hw_can.h b/firmware/shared/src/hw/hw_can.h deleted file mode 100644 index cc95d31727..0000000000 --- a/firmware/shared/src/hw/hw_can.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include -#include -#include "hw_hal.h" - -#define CAN_PAYLOAD_BYTES 8 - -typedef struct -{ - uint32_t std_id; - uint32_t dlc; // data length range : [0, 8] - uint8_t data[CAN_PAYLOAD_BYTES]; -} CanMsg; - -typedef void (*MsgReceivedCallback)(CanMsg *rx_msg); - -#ifdef CANFD -// STM32 HAL CAN FD handle. -typedef struct -{ - FDCAN_HandleTypeDef *can; - MsgReceivedCallback can_msg_received_callback; -} CanHandle; -#else -// STM32 HAL CAN handle. -typedef struct -{ - CAN_HandleTypeDef *can; - MsgReceivedCallback can_msg_received_callback; -} CanHandle; -#endif - -/** - * Initialize CAN driver. - * @param can_handle STM32 HAL CAN handle. - */ -void hw_can_init(const CanHandle *can_handle); - -/** - * Stop and deinitialize the CAN peripheral. - */ -void hw_can_deinit(void); - -/** - * Transmit a CAN msg on the bus, blocking until completed. - * @param msg CAN msg to be TXed. - * @return Whether or not the transmission was successful. - */ -bool hw_can_transmit(const CanMsg *msg); - -/** - * Receive a CAN msg from the bus, returning whether or not a message is available. - * This function also passes up the CanMsg to a callback function. - * @param msg CAN msg to be RXed. - * @param rx_fifo Which RX FIFO to receive a message from. - * @return Whether or not the reception was successful. - */ -bool hw_can_receive(uint32_t rx_fifo, CanMsg *msg); diff --git a/firmware/shared/src/hw/hw_fdcan.c b/firmware/shared/src/hw/hw_fdcan.c deleted file mode 100644 index d1c15331e2..0000000000 --- a/firmware/shared/src/hw/hw_fdcan.c +++ /dev/null @@ -1,115 +0,0 @@ -#include "hw_can.h" -#include "io_can.h" -#undef NDEBUG -#include -#include "io_log.h" - -static const CanHandle *handle; - -void hw_can_init(const CanHandle *can_handle) -{ - handle = can_handle; - - // Configure a single filter bank that accepts any message. - FDCAN_FilterTypeDef filter; - filter.IdType = FDCAN_STANDARD_ID; // 11 bit ID - filter.FilterIndex = 0; - filter.FilterType = FDCAN_FILTER_MASK; - filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; - filter.FilterID1 = 0; // Standard CAN ID bits [10:0] - filter.FilterID2 = 0x1FFFFFFF; // Mask bits for Standard CAN ID - - // Configure and initialize hardware filter. - assert(HAL_FDCAN_ConfigFilter(handle->can, &filter) == HAL_OK); - - // Configure interrupt mode for CAN peripheral. - assert( - HAL_FDCAN_ActivateNotification(handle->can, FDCAN_IT_RX_FIFO0_NEW_MESSAGE | FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0) == - HAL_OK); - assert(HAL_FDCAN_ActivateNotification(handle->can, FDCAN_IT_BUS_OFF, 0) == HAL_OK); - - // Start the FDCAN peripheral. - assert(HAL_FDCAN_Start(handle->can) == HAL_OK); -} - -void hw_can_deinit(void) -{ - assert(HAL_FDCAN_Stop(handle->can) == HAL_OK); - assert(HAL_FDCAN_DeInit(handle->can) == HAL_OK); -} - -bool hw_can_transmit(const CanMsg *msg) -{ - FDCAN_TxHeaderTypeDef tx_header; - tx_header.Identifier = msg->std_id; - tx_header.IdType = FDCAN_STANDARD_ID; - tx_header.TxFrameType = FDCAN_DATA_FRAME; - tx_header.DataLength = msg->dlc << 16; // Data length code needs to be shifted by 16 bits. - tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; - tx_header.BitRateSwitch = FDCAN_BRS_OFF; - tx_header.FDFormat = FDCAN_CLASSIC_CAN; - tx_header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; - tx_header.MessageMarker = 0; - - while (HAL_FDCAN_GetTxFifoFreeLevel(handle->can) == 0U) - ; - - return HAL_FDCAN_AddMessageToTxFifoQ(handle->can, &tx_header, (uint8_t *)msg->data) == HAL_OK; -} - -bool hw_can_receive(uint32_t rx_fifo, CanMsg *msg) -{ - FDCAN_RxHeaderTypeDef header; - if (HAL_FDCAN_GetRxMessage(handle->can, rx_fifo, &header, msg->data) != HAL_OK) - { - return false; - } - - msg->std_id = header.Identifier; - msg->dlc = header.DataLength >> 16; // Data length code needs to be un-shifted by 16 bits. - - return true; -} - -void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) -{ - assert(hfdcan == handle->can); - UNUSED(RxFifo0ITs); - CanMsg rx_msg; - if (!hw_can_receive(FDCAN_RX_FIFO0, &rx_msg) && handle->can_msg_received_callback != NULL) - { - // Early return if RX msg is unavailable. - return; - } - - handle->can_msg_received_callback(&rx_msg); -} - -void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs) -{ - assert(hfdcan == handle->can); - UNUSED(RxFifo1ITs); - CanMsg rx_msg; - if (!hw_can_receive(FDCAN_RX_FIFO1, &rx_msg) && handle->can_msg_received_callback != NULL) - { - // Early return if RX msg is unavailable. - return; - } - - handle->can_msg_received_callback(&rx_msg); -} - -void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs) -{ - assert(hfdcan == handle->can); - LOG_INFO("FDCAN detected an error"); - if ((ErrorStatusITs & FDCAN_IT_BUS_OFF) != RESET) - { - FDCAN_ProtocolStatusTypeDef protocolStatus; - HAL_FDCAN_GetProtocolStatus(hfdcan, &protocolStatus); - if (protocolStatus.BusOff) - { - CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT); - } - } -} diff --git a/firmware/shared/src/hw/hw_sd.c b/firmware/shared/src/hw/hw_sd.c index 0001afca7c..16ee324b90 100644 --- a/firmware/shared/src/hw/hw_sd.c +++ b/firmware/shared/src/hw/hw_sd.c @@ -1,135 +1,94 @@ - // interface read write // using HAL layer #include "hw_sd.h" #include "hw_utils.h" -#include -#include + +#include #include static volatile bool dma_tx_completed = true; -static SdCard *sd; +#define OFFSET_SIZE_VALID(offset, size) (offset % HW_DEVICE_SECTOR_SIZE == 0 && size % HW_DEVICE_SECTOR_SIZE == 0) -void hw_sd_init(SdCard *sd_config) -{ - sd = sd_config; -} +/** + * @attention This must be constructed in some translation unit in each ECU which uses includes file + * @note create this object in hw_sds.c for your ECU + */ +extern SdCard sd1; -SdCardStatus hw_sd_read(uint8_t *pdata, uint32_t block_addr, uint32_t num_blocks) +SdCardStatus hw_sd_read(uint8_t *pdata, const uint32_t block_addr, const uint32_t num_blocks) { - if (sd == NULL) - { - return SD_CARD_ERROR; - } - while (HAL_SD_GetCardState(sd->hsd) != HAL_SD_CARD_TRANSFER) + while (HAL_SD_GetCardState(sd1.hsd) != HAL_SD_CARD_TRANSFER) ; - HAL_StatusTypeDef status = HAL_SD_ReadBlocks(sd->hsd, pdata, block_addr, num_blocks, sd->timeout); - - return (SdCardStatus)status; + return (SdCardStatus)HAL_SD_ReadBlocks(sd1.hsd, pdata, block_addr, num_blocks, sd1.timeout); } -SdCardStatus hw_sd_readOffset(uint8_t *pdata, uint32_t block_addr, uint32_t offset, uint32_t size) +SdCardStatus hw_sd_readOffset(uint8_t *pdata, const uint32_t block_addr, const uint32_t offset, const uint32_t size) { - SdCardStatus status = SD_CARD_OK; - - if (sd == NULL) - { - return SD_CARD_ERROR; - } if (size == 0) - { return SD_CARD_OK; - } - - if (((offset % HW_DEVICE_SECTOR_SIZE) == 0) && (size % HW_DEVICE_SECTOR_SIZE == 0)) // easy case - { - status = hw_sd_read(pdata, block_addr + offset / HW_DEVICE_SECTOR_SIZE, size / HW_DEVICE_SECTOR_SIZE); - return (SdCardStatus)status; - } - + if (OFFSET_SIZE_VALID(offset, size)) // easy case + return hw_sd_read(pdata, block_addr + offset / HW_DEVICE_SECTOR_SIZE, size / HW_DEVICE_SECTOR_SIZE); return SD_CARD_ERROR; } -SdCardStatus hw_sd_write(uint8_t *pdata, uint32_t block_addr, uint32_t num_blocks) +SdCardStatus hw_sd_write(uint8_t *pdata, const uint32_t block_addr, const uint32_t num_blocks) { - if (sd == NULL) - { - return SD_CARD_ERROR; - } - while (HAL_SD_GetCardState(sd->hsd) != HAL_SD_CARD_TRANSFER) + while (HAL_SD_GetCardState(sd1.hsd) != HAL_SD_CARD_TRANSFER) ; - - HAL_StatusTypeDef status = HAL_SD_WriteBlocks(sd->hsd, pdata, block_addr, num_blocks, sd->timeout); - - return (SdCardStatus)status; + return (SdCardStatus)HAL_SD_WriteBlocks(sd1.hsd, pdata, block_addr, num_blocks, sd1.timeout); } -SdCardStatus hw_sd_writeOffset(uint8_t *pdata, uint32_t block_addr, uint32_t offset, uint32_t size) +SdCardStatus hw_sd_writeOffset(uint8_t *pdata, const uint32_t block_addr, const uint32_t offset, const uint32_t size) { - if (sd == NULL) - { - return SD_CARD_ERROR; - } - SdCardStatus status = SD_CARD_OK; if (size == 0) - { - return status; - } - - if (((offset % HW_DEVICE_SECTOR_SIZE) == 0) && (size % HW_DEVICE_SECTOR_SIZE == 0)) // easy case - { - status = hw_sd_write(pdata, block_addr + offset / HW_DEVICE_SECTOR_SIZE, size / HW_DEVICE_SECTOR_SIZE); - return status; - } - + return SD_CARD_OK; + if (OFFSET_SIZE_VALID(offset, size)) // easy case + return hw_sd_write(pdata, block_addr + offset / HW_DEVICE_SECTOR_SIZE, size / HW_DEVICE_SECTOR_SIZE); return SD_CARD_ERROR; } -SdCardStatus hw_sd_erase(uint32_t start_addr, uint32_t end_addr) +SdCardStatus hw_sd_erase(const uint32_t start_addr, const uint32_t end_addr) { - if (sd == NULL) - { - return SD_CARD_ERROR; - } - while (HAL_SD_GetCardState(sd->hsd) != HAL_SD_CARD_TRANSFER) + while (HAL_SD_GetCardState(sd1.hsd) != HAL_SD_CARD_TRANSFER) ; - - HAL_StatusTypeDef status = HAL_SD_Erase(sd->hsd, start_addr, end_addr); - - return (SdCardStatus)status; + return (SdCardStatus)HAL_SD_Erase(sd1.hsd, start_addr, end_addr); } -SdCardStatus hw_sd_writeDma(uint8_t *pdata, uint32_t block_addr, uint32_t num_blocks) +SdCardStatus hw_sd_writeDma(uint8_t *pdata, const uint32_t block_addr, const uint32_t num_blocks) { - if (sd == NULL) - { - return SD_CARD_ERROR; - } while (!dma_tx_completed) ; - while (HAL_SD_GetCardState(sd->hsd) != HAL_SD_CARD_TRANSFER) + while (HAL_SD_GetCardState(sd1.hsd) != HAL_SD_CARD_TRANSFER) ; - dma_tx_completed = false; - HAL_StatusTypeDef status = HAL_SD_WriteBlocks_DMA(sd->hsd, pdata, block_addr, num_blocks); - return (SdCardStatus)status; + dma_tx_completed = false; + return (SdCardStatus)HAL_SD_WriteBlocks_DMA(sd1.hsd, pdata, block_addr, num_blocks); } void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd) { + assert(hsd == sd1.hsd); dma_tx_completed = true; } void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd) { + assert(hsd == sd1.hsd); dma_tx_completed = true; } void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd) { + assert(hsd == sd1.hsd); dma_tx_completed = true; } void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd) { + assert(hsd == sd1.hsd); dma_tx_completed = true; -} \ No newline at end of file +} + +bool hw_sd_present() +{ + return hw_gpio_readPin(sd1.present_gpio); +} diff --git a/firmware/shared/src/hw/hw_sd.h b/firmware/shared/src/hw/hw_sd.h index de4b6f079e..505d77a976 100644 --- a/firmware/shared/src/hw/hw_sd.h +++ b/firmware/shared/src/hw/hw_sd.h @@ -2,21 +2,17 @@ #include "hw_hal.h" #include "hw_gpio.h" -#include #include - -// Check here for documentation about the type defined by HAL -// https://www.disca.upv.es/aperles/arm_cortex_m3/llibre/st/STM32F439xx_User_Manual/structsd__handletypedef.html +#include #define HW_DEVICE_SECTOR_SIZE 512 typedef struct { - SD_HandleTypeDef *hsd; // the HAL SD handle that will hold the state of the SD card - uint32_t timeout; // the timeout for the SD card operations - // const Gpio sd_present; // GPIO to detect if SD card installed - bool sd_init_complete; -} SdCard; // struct that included all the state about SDIO and SD card + SD_HandleTypeDef *hsd; // the HAL SD handle that will hold the state of the SD card + uint32_t timeout; // the timeout for the SD card operations + const Gpio *present_gpio; // gpio for sd_cd +} SdCard; // struct that included all the state about SDIO and SD card typedef enum { @@ -26,12 +22,6 @@ typedef enum SD_CARD_TIMEOUT = HAL_TIMEOUT } SdCardStatus; // wrapper of HAL status for better interface -/** - * @brief Initialize Static SD Card structure - * @param sd_config SD Card Configuration - */ -void hw_sd_init(SdCard *sd_config); - /** * @brief Read from sd card. The data size will be num_blocks * BlockSize * @param sd the state struct of sd card @@ -92,3 +82,5 @@ SdCardStatus hw_sd_writeOffset(uint8_t *pdata, uint32_t block_addr, uint32_t off * @return SD_card_status the status of the opeation */ SdCardStatus hw_sd_erase(uint32_t start_addr, uint32_t end_addr); + +bool hw_sd_present(); \ No newline at end of file diff --git a/firmware/shared/src/io/io_can.c b/firmware/shared/src/io/io_can.c index ce7de01ccf..8c7d7bde9d 100644 --- a/firmware/shared/src/io/io_can.c +++ b/firmware/shared/src/io/io_can.c @@ -1,111 +1,114 @@ #include "io_can.h" -#include +#undef NDEBUG // TODO remove this in favour of always_assert (we would write this) #include -#include "cmsis_os.h" - -// Sizes of CAN TX and RX queues. -#define TX_QUEUE_SIZE 128 -#define RX_QUEUE_SIZE 128 -#define TX_QUEUE_BYTES sizeof(CanMsg) * TX_QUEUE_SIZE -#define RX_QUEUE_BYTES sizeof(CanMsg) * RX_QUEUE_SIZE - -// Private globals. -static const CanConfig *config; - -static osMessageQueueId_t tx_queue_id; -static osMessageQueueId_t rx_queue_id; -static StaticQueue_t tx_queue_control_block; -static StaticQueue_t rx_queue_control_block; -static uint8_t tx_queue_buf[TX_QUEUE_BYTES]; -static uint8_t rx_queue_buf[RX_QUEUE_BYTES]; - -static const osMessageQueueAttr_t tx_queue_attr = { - .name = "CAN TX Queue", - .attr_bits = 0, - .cb_mem = &tx_queue_control_block, - .cb_size = sizeof(StaticQueue_t), - .mq_mem = tx_queue_buf, - .mq_size = TX_QUEUE_BYTES, -}; -static const osMessageQueueAttr_t rx_queue_attr = { - .name = "CAN RX Queue", - .attr_bits = 0, - .cb_mem = &rx_queue_control_block, - .cb_size = sizeof(StaticQueue_t), - .mq_mem = rx_queue_buf, - .mq_size = RX_QUEUE_BYTES, -}; - -void io_can_init(const CanConfig *can_config) -{ - assert(can_config != NULL); - config = can_config; +#include "io_time.h" - // Initialize CAN queues. - tx_queue_id = osMessageQueueNew(TX_QUEUE_SIZE, sizeof(CanMsg), &tx_queue_attr); - rx_queue_id = osMessageQueueNew(RX_QUEUE_SIZE, sizeof(CanMsg), &rx_queue_attr); -} +// The following filter IDs/masks must be used with 16-bit Filter Scale +// (FSCx = 0) and Identifier Mask Mode (FBMx = 0). In this mode, the identifier +// registers are associated with mask registers specifying which bits of the +// identifier are handled as "don't care" or as "must match". For each bit in +// the mask registers, 0 = Don't Care and 1 = Must Match. +// +// Bit mapping of a 16-bit identifier register and mask register: +// Standard CAN ID [15:5] RTR[4] IDE[3] Extended CAN ID [2:0] +// +// For example, with the following filter IDs/mask: +// ======================================================= +// Identifier Register: [000 0000 0000] [0] [0] [000] +// Mask Register: [111 1110 0000] [1] [1] [000] +// ======================================================= +// The filter will accept incoming messages that match the following criteria: +// [000 000x xxxx] [0] [0] [xxx] +// Standard CAN ID RTR IDE Extended CAN ID +#define INIT_MASKMODE_16BIT_FiRx(std_id, rtr, ide, ext_id) \ + ((((uint32_t)(std_id) << 5U) & 0xFFE0) | (((uint32_t)(rtr) << 4U) & 0x0010) | (((uint32_t)(ide) << 3U) & 0x0008) | \ + (((uint32_t)(ext_id) << 0U) & 0x0007)) + +// Open CAN filter that accepts any CAN message as long as it uses Standard CAN +// ID and is a data frame. +#define CAN_ExtID_NULL 0 // Set CAN Extended ID to 0 because we are not using it. +#define MASKMODE_16BIT_ID_OPEN INIT_MASKMODE_16BIT_FiRx(0x0, CAN_ID_STD, CAN_RTR_DATA, CAN_ExtID_NULL) +#define MASKMODE_16BIT_MASK_OPEN INIT_MASKMODE_16BIT_FiRx(0x0, 0x1, 0x1, 0x0) -void io_can_pushTxMsgToQueue(const CanMsg *msg) +void io_can_init(const CanHandle *can_handle) { - static uint32_t tx_overflow_count = 0; + // Configure a single filter bank that accepts any message. + CAN_FilterTypeDef filter; + filter.FilterMode = CAN_FILTERMODE_IDMASK; + filter.FilterScale = CAN_FILTERSCALE_16BIT; + filter.FilterActivation = CAN_FILTER_ENABLE; + filter.FilterIdLow = MASKMODE_16BIT_ID_OPEN; + filter.FilterMaskIdLow = MASKMODE_16BIT_MASK_OPEN; + filter.FilterIdHigh = MASKMODE_16BIT_ID_OPEN; + filter.FilterMaskIdHigh = MASKMODE_16BIT_MASK_OPEN; + filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; + filter.FilterBank = 0; - const osStatus_t s = osMessageQueuePut(tx_queue_id, msg, 0, 0); - if (s != osOK) - { - // If pushing to the queue failed, the queue is full. Discard the msg and invoke the TX overflow callback. - if (config->tx_overflow_callback) - config->tx_overflow_callback(++tx_overflow_count); - } - else - { - if (config->tx_overflow_clear_callback) - config->tx_overflow_clear_callback(); - } -} + // Configure and initialize hardware filter. + assert(HAL_CAN_ConfigFilter(can_handle->hcan, &filter) == HAL_OK); -void io_can_popTxMsgFromQueue(CanMsg *msg) -{ - // Pop a msg of the TX queue - const osStatus_t s = osMessageQueueGet(tx_queue_id, msg, NULL, osWaitForever); - assert(s == osOK); + // Configure interrupt mode for CAN peripheral. + assert( + HAL_CAN_ActivateNotification( + can_handle->hcan, CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING) == + HAL_OK); + + // Start the CAN peripheral. + assert(HAL_CAN_Start(can_handle->hcan) == HAL_OK); } -void io_can_transmitMsgFromQueue(CanMsg *msg) +void io_can_deinit(const CanHandle *can_handle) { - // Transmit the tx_msg onto the bus. - hw_can_transmit(msg); + assert(HAL_CAN_Stop(can_handle->hcan) == HAL_OK); + assert(HAL_CAN_DeInit(can_handle->hcan) == HAL_OK); } -void io_can_popRxMsgFromQueue(CanMsg *msg) +bool io_can_transmit(const CanHandle *can_handle, CanMsg *msg) { - // Pop a message off the RX queue. - const osStatus_t s = osMessageQueueGet(rx_queue_id, msg, NULL, osWaitForever); - assert(s == osOK); + CAN_TxHeaderTypeDef tx_header; + + tx_header.DLC = msg->dlc; + tx_header.StdId = msg->std_id; + + // The standard 11-bit CAN identifier is more than sufficient, so we disable + // Extended CAN IDs by setting this field to zero. + tx_header.ExtId = CAN_ExtID_NULL; + + // This field can be either Standard CAN or Extended CAN. See .ExtID to see + // why we don't want Extended CAN. + tx_header.IDE = CAN_ID_STD; + + // This field can be either Data Frame or Remote Frame. For our + // purpose, we only ever transmit Data Frames. + tx_header.RTR = CAN_RTR_DATA; + + // Enabling this gives us a tick-based timestamp which we do not need. Plus, + // it would take up 2 bytes of the CAN payload. So we disable the timestamp. + tx_header.TransmitGlobalTime = DISABLE; + + // Spin until a TX mailbox becomes available. + while (HAL_CAN_GetTxMailboxesFreeLevel(can_handle->hcan) == 0U) + ; + + // Indicates the mailbox used for transmission, not currently used. + uint32_t mailbox = 0; + const HAL_StatusTypeDef return_status = HAL_CAN_AddTxMessage(can_handle->hcan, &tx_header, msg->data, &mailbox); + return return_status == HAL_OK; } -void io_can_pushRxMsgToQueue(CanMsg *rx_msg) +bool io_can_receive(const CanHandle *can_handle, const uint32_t rx_fifo, CanMsg *msg) { - static uint32_t rx_overflow_count = 0; - - assert(config != NULL); - if (config->rx_msg_filter != NULL && !config->rx_msg_filter(rx_msg->std_id)) + CAN_RxHeaderTypeDef header; + if (HAL_CAN_GetRxMessage(can_handle->hcan, rx_fifo, &header, msg->data) != HAL_OK) { - // Early return if we don't care about this msg via configured filter func. - return; + return false; } - // We defer reading the CAN RX message to another task by storing the - // message on the CAN RX queue. - if (osMessageQueuePut(rx_queue_id, rx_msg, 0, 0) != osOK) - { - // If pushing to the queue failed, the queue is full. Discard the msg and invoke the RX overflow callback. - if (config->rx_overflow_callback != NULL) - config->rx_overflow_callback(++rx_overflow_count); - } - else - { - if (config->rx_overflow_clear_callback != NULL) - config->rx_overflow_clear_callback(); - } + // Copy metadata from HAL's CAN message struct into our custom CAN + // message struct + msg->std_id = header.StdId; + msg->dlc = header.DLC; + msg->timestamp = io_time_getCurrentMs(); + + return true; } diff --git a/firmware/shared/src/io/io_can.h b/firmware/shared/src/io/io_can.h index 44d873b3fa..e1f7ff85c3 100644 --- a/firmware/shared/src/io/io_can.h +++ b/firmware/shared/src/io/io_can.h @@ -2,82 +2,48 @@ #include #include -#ifdef TARGET_EMBEDDED -#include "hw_can.h" -#endif - -/** - * This module is a CAN driver which manages CAN msg transmission (TX) and reception (RX) via FreeRTOS queues: One for - * TX, and one for RX. - * - * Transmission: - * 1. Enqueue msgs via `io_can_enqueueTxMsg`. If the TX queue is full, the `tx_overflow_callback` function is called. - * 2. Pop msgs off the TX queue and transmit them via `io_can_transmitTxMsg`. After popping a msg off the TX queue, - * `io_can_transmitTxMsg` spins until a CAN TX mailbox becomes available (STM32F412x MCUs have 3) and adds it to a - * mailbox. After adding to the mailbox, the CAN peripheral hardware will put the msg on the bus. - * - * Receiving: - * 1. When a CAN msg is received, it is passed through a hardware filter (currently configured to accept all msgs with a - * standard 11-bit identifier) and an interrupt is fired (`HAL_CAN_RxFifo0MsgPendingCallback` or - * `HAL_CAN_RxFifo1MsgPendingCallback`, depending on the RX hardware FIFO). - * 2. Both interrupts invoke a callback, which filters by msg ID via an optional `rx_msg_filter` function. If accepted, - * the RX msg is placed on the RX queue. - * 3. Pop msgs off the RX queue via `io_can_dequeueRxMsg`, which blocks until a CAN RX msg is successfully dequeued. - */ +#include "hw_hal.h" +#include "io_canMsg.h" +#ifdef CANFD +// STM32 HAL CAN FD handle. typedef struct { - bool (*const rx_msg_filter)(uint32_t); // Optional func to filter RX msgs by ID. - void (*const tx_overflow_callback)(uint32_t); // Callback on TX queue overflow. - void (*const rx_overflow_callback)(uint32_t); // Callback on RX queue overflow. - void (*const tx_overflow_clear_callback)(); // Callback on TX queue overflow clear. - void (*const rx_overflow_clear_callback)(); // Callback on RX queue overflow clear. -} CanConfig; - -#define CAN_PAYLOAD_BYTES 8 // TODO: grab from the same place perhaps - -#ifdef TARGET_TEST + FDCAN_HandleTypeDef *hcan; +} CanHandle; +#else +// STM32 HAL CAN handle. typedef struct { - uint32_t std_id; - uint32_t dlc; // data length range : [0, 8] - uint8_t data[CAN_PAYLOAD_BYTES]; -} CanMsg; + CAN_HandleTypeDef *hcan; +} CanHandle; #endif /** - * Initialize and start the CAN peripheral. - * @param can_config Config struct. + * Initialize CAN driver. + * @param can_handle STM32 HAL CAN handle. */ -void io_can_init(const CanConfig *can_config); +void io_can_init(const CanHandle *can_handle); /** - * Enqueue a CAN msg to be transmitted on the bus. - * Does not block, calls `tx_overflow_callback` if queue is full. - * @param msg CAN msg to be TXed. + * Stop and deinitialize the CAN peripheral. */ -void io_can_pushTxMsgToQueue(const CanMsg *msg); +void io_can_deinit(const CanHandle *can_handle); /** - * Pops a CAN msg from the TX queue. Blocks until a msg exists in the queue. - */ -void io_can_popTxMsgFromQueue(CanMsg *msg); - -/** - * Transmit a single CAN msg onto the bus. + * Transmit a CAN msg on the bus, blocking until completed. + * @param can_handle Can handle to transmit from + * @param msg CAN msg to be TXed. + * @return Whether or not the transmission was successful. */ -void io_can_transmitMsgFromQueue(CanMsg *msg); +bool io_can_transmit(const CanHandle *can_handle, CanMsg *msg); /** - * Dequeue a received CAN msg. Blocks until a msg can be dequeued. + * Receive a CAN msg from the bus, returning whether or not a message is available. + * This function also passes up the CanMsg to a callback function. + * @param can_handle Can handle to receive from + * @param msg CAN msg to be RXed. * @param rx_fifo Which RX FIFO to receive a message from. + * @return Whether or not the reception was successful. */ -void io_can_popRxMsgFromQueue(CanMsg *msg); - -#ifdef TARGET_EMBEDDED -/** - * Callback fired by config-specific interrupts to receive a message from a given FIFO. - * @param msg CAN msg to be populated by RXed msg. - */ -void io_can_pushRxMsgToQueue(CanMsg *rx_msg); -#endif +bool io_can_receive(const CanHandle *can_handle, uint32_t rx_fifo, CanMsg *msg); diff --git a/firmware/shared/src/io/io_canLogging.c b/firmware/shared/src/io/io_canLoggingQueue.c similarity index 59% rename from firmware/shared/src/io/io_canLogging.c rename to firmware/shared/src/io/io_canLoggingQueue.c index 436be4388c..ea3bab4525 100644 --- a/firmware/shared/src/io/io_canLogging.c +++ b/firmware/shared/src/io/io_canLoggingQueue.c @@ -1,21 +1,16 @@ +#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wconversion" +#include "io_canLoggingQueue.h" #include #include #include #include + #include "cmsis_os.h" -#include "queue.h" -#include "hw_gpio.h" -#include "io_canLogging.h" #include "io_fileSystem.h" -#include "io_time.h" - -// Private globals. -static const CanConfig *config; // batch message buffer - #define BATCH_SIZE 10 struct CanMsgBatch { @@ -26,18 +21,17 @@ static uint32_t batch_count = 0; // Message Queue configuration #define QUEUE_SIZE 256 -#define QUEUE_BYTES sizeof(CanMsgLog) * QUEUE_SIZE *BATCH_SIZE #define PATH_LENGTH 8 +#define QUEUE_BYTES sizeof(CanMsgLog) * QUEUE_SIZE *BATCH_SIZE + +// State static osMessageQueueId_t message_queue_id; static StaticQueue_t queue_control_block; static uint8_t queue_buf[QUEUE_BYTES]; - -// filesystem globals -static uint32_t current_bootcount; -static int log_fd; // fd for the log file -static char current_path[10]; - -static uint8_t logging_error_remaining = 10; // number of times to error before stopping logging +static uint32_t current_bootcount; +static int log_fd; // fd for the log file +static char current_path[10]; +static uint8_t logging_error_remaining = 10; // number of times to error before stopping logging static const osMessageQueueAttr_t queue_attr = { .name = "CAN Logging Queue", @@ -48,44 +42,27 @@ static const osMessageQueueAttr_t queue_attr = { .mq_size = QUEUE_BYTES, }; -// assume the filesystem is already inited -static int initLoggingFileSystem(void) -{ - current_bootcount = io_fileSystem_getBootCount(); - - // create new folder for this boot - sprintf(current_path, "/%lu.txt", current_bootcount); - log_fd = io_fileSystem_open(current_path); - if (log_fd < 0) - { - logging_error_remaining = 0; - return 1; - } - - return 0; -} - static void convertCanMsgToLog(const CanMsg *msg, CanMsgLog *log) { log->id = msg->std_id; log->dlc = msg->dlc; - log->timestamp = io_time_getCurrentMs(); + log->timestamp = msg->timestamp; memcpy(log->data, msg->data, 8); } static bool isLoggingEnabled(void) { - return logging_error_remaining > 0 && config != NULL; + return logging_error_remaining > 0; } // Push a message to the buffer // return true and reset the batch counter if the buffer is full after pushing // return false otherwise -static bool pushToBuffer(CanMsgLog *msg) +static bool pushToBuffer(const CanMsgLog *msg) { // the buffer should always have space for the message assert(batch_count < BATCH_SIZE); - memcpy(&batch_buf.msg[batch_count], msg, sizeof(CanMsg)); + batch_buf.msg[batch_count] = *msg; batch_count++; if (batch_count >= BATCH_SIZE) { @@ -95,34 +72,31 @@ static bool pushToBuffer(CanMsgLog *msg) return false; } -int io_canLogging_init(const CanConfig *can_config) +int io_canLogging_init() { - assert(can_config != NULL); - if (config != NULL) - { - return 1; // return 1 if already initialized - } - - config = can_config; - message_queue_id = osMessageQueueNew(QUEUE_SIZE, sizeof(CanMsg) * BATCH_SIZE, &queue_attr); // create new folder for this boot - return initLoggingFileSystem(); + current_bootcount = io_fileSystem_getBootCount(); + sprintf(current_path, "/%lu.txt", current_bootcount); + log_fd = io_fileSystem_open(current_path); + if (log_fd < 0) + { + logging_error_remaining = 0; + return 1; + } + return 0; } int io_canLogging_recordMsgFromQueue(void) { if (!isLoggingEnabled()) - { return 1; - } struct CanMsgBatch tx_msg; osMessageQueueGet(message_queue_id, &tx_msg, NULL, osWaitForever); - int err = io_fileSystem_write(log_fd, &tx_msg, sizeof(tx_msg.msg)); - if (err < 0 && logging_error_remaining > 0) + if (io_fileSystem_write(log_fd, &tx_msg, sizeof(tx_msg.msg)) < 0 && logging_error_remaining > 0) { logging_error_remaining--; return 1; @@ -130,48 +104,31 @@ int io_canLogging_recordMsgFromQueue(void) return 0; } -void io_canLogging_loggingQueuePush(CanMsg *msg) +bool io_canLogging_loggingQueuePush(const CanMsg *rx_msg) { if (!isLoggingEnabled()) - { - return; - } - - if (config->rx_msg_filter != NULL && !config->rx_msg_filter(msg->std_id)) - { - // Early return if we don't care about this msg via configured filter func. - return; - } + return false; static uint32_t overflow_count = 0; CanMsgLog msg_log; - convertCanMsgToLog(msg, &msg_log); + convertCanMsgToLog(rx_msg, &msg_log); // cache the message to the buffer first if (!pushToBuffer(&msg_log)) - { - return; - } + return false; // We defer reading the CAN RX message to another task by storing the // message on the CAN RX queue. - if (osMessageQueuePut(message_queue_id, &batch_buf.msg, 0, 0) != osOK && config->rx_overflow_callback != NULL) - { - // If pushing to the queue failed, the queue is full. Discard the msg and invoke the RX overflow callback. - config->rx_overflow_callback(++overflow_count); - } + return osMessageQueuePut(message_queue_id, &batch_buf.msg, 0, 0) == osOK; } int io_canLogging_sync(void) { if (!isLoggingEnabled()) - { return 1; - } - // SAVe the seek before close - int err = io_fileSystem_sync(log_fd); - if (err < 0 && logging_error_remaining > 0) + // Save the seek before close + if (io_fileSystem_sync(log_fd) < 0 && logging_error_remaining > 0) { logging_error_remaining--; return 1; @@ -188,3 +145,5 @@ uint32_t io_canLogging_errorsRemaining(void) { return logging_error_remaining; } + +#pragma GCC diagnostic pop \ No newline at end of file diff --git a/firmware/shared/src/io/io_canLogging.h b/firmware/shared/src/io/io_canLoggingQueue.h similarity index 89% rename from firmware/shared/src/io/io_canLogging.h rename to firmware/shared/src/io/io_canLoggingQueue.h index af421c1e96..9f16ca92e0 100644 --- a/firmware/shared/src/io/io_canLogging.h +++ b/firmware/shared/src/io/io_canLoggingQueue.h @@ -1,10 +1,8 @@ #pragma once -#include "io_can.h" - -#ifdef TARGET_EMBEDDED -#include "hw_sd.h" -#endif +#include +#include +#include "io_canMsg.h" // Empirically determined number which corresponds to the time to mount the filesystem, plus the time to create a new // blank CAN log, taking approximately 500ms. This was found using logfs (not littlefs, there is probably a different @@ -30,20 +28,20 @@ typedef struct /** * Create a new message queue for can logging message * Create a new file for this boot for record message - * @param can_config - * */ -int io_canLogging_init(const CanConfig *can_config); +int io_canLogging_init(void); + +/** + * Populate queue with another item + */ +bool io_canLogging_loggingQueuePush(const CanMsg *rx_msg); /** * write the can message to the sdcard * pop the massage from queue - * */ int io_canLogging_recordMsgFromQueue(void); -void io_canLogging_loggingQueuePush(CanMsg *rx_msg); - int io_canLogging_sync(void); /** diff --git a/firmware/shared/src/io/io_canMsg.h b/firmware/shared/src/io/io_canMsg.h new file mode 100644 index 0000000000..f8f2e0ca8c --- /dev/null +++ b/firmware/shared/src/io/io_canMsg.h @@ -0,0 +1,13 @@ +#pragma once +#include + +#define CAN_PAYLOAD_BYTES 8 + +typedef struct +{ + uint32_t std_id; + uint32_t dlc; // data length range : [0, 8] + uint32_t timestamp; + uint8_t data[CAN_PAYLOAD_BYTES]; + uint8_t bus; +} CanMsg; diff --git a/firmware/shared/src/io/io_canQueue.c b/firmware/shared/src/io/io_canQueue.c new file mode 100644 index 0000000000..da7dde005f --- /dev/null +++ b/firmware/shared/src/io/io_canQueue.c @@ -0,0 +1,97 @@ +#include "io_canQueue.h" + +#include +#include +#include +#include + +#include "cmsis_os.h" +#define TX_QUEUE_SIZE 128 +#define RX_QUEUE_SIZE 128 +#define TX_QUEUE_BYTES sizeof(CanMsg) * TX_QUEUE_SIZE +#define RX_QUEUE_BYTES sizeof(CanMsg) * RX_QUEUE_SIZE +char *tx_name; +char *rx_name; +osMessageQueueId_t tx_queue_id; +osMessageQueueId_t rx_queue_id; +StaticQueue_t tx_queue_control_block; +StaticQueue_t rx_queue_control_block; +uint8_t tx_queue_buf[TX_QUEUE_BYTES]; +uint8_t rx_queue_buf[RX_QUEUE_BYTES]; +const osMessageQueueAttr_t tx_queue_attr = { + .name = "CAN TX Queue", + .attr_bits = 0, + .cb_mem = &tx_queue_control_block, + .cb_size = sizeof(StaticQueue_t), + .mq_mem = tx_queue_buf, + .mq_size = TX_QUEUE_BYTES, +}; +const osMessageQueueAttr_t rx_queue_attr = { + .name = "CAN RX Queue", + .attr_bits = 0, + .cb_mem = &rx_queue_control_block, + .cb_size = sizeof(StaticQueue_t), + .mq_mem = rx_queue_buf, + .mq_size = RX_QUEUE_BYTES, +}; + +static bool init_complete = false; + +__weak void canTxQueueOverflowCallBack(const uint32_t overflow_count) {} +__weak void canTxQueueOverflowClearCallback() {} +__weak void canRxQueueOverflowCallBack(const uint32_t overflow_count) {} +__weak void canRxQueueOverflowClearCallback() {} + +void io_canQueue_init() +{ + // Initialize CAN queues. + tx_queue_id = osMessageQueueNew(TX_QUEUE_SIZE, sizeof(CanMsg), &tx_queue_attr); + rx_queue_id = osMessageQueueNew(RX_QUEUE_SIZE, sizeof(CanMsg), &rx_queue_attr); + init_complete = true; +} + +void io_canQueue_pushTx(const CanMsg *tx_msg) +{ + assert(init_complete); + static uint32_t tx_overflow_count = 0; + const osStatus_t s = osMessageQueuePut(tx_queue_id, tx_msg, 0, 0); + + if (s != osOK) + // If pushing to the queue failed, the queue is full. Discard the tx_msg and invoke the TX overflow callback. + canTxQueueOverflowCallBack(++tx_overflow_count); + else + canTxQueueOverflowClearCallback(); +} + +CanMsg io_canQueue_popTx() +{ + assert(init_complete); + CanMsg msg; + // Pop a msg of the TX queue + const osStatus_t s = osMessageQueueGet(tx_queue_id, &msg, NULL, osWaitForever); + assert(s == osOK); + return msg; +} + +void io_canQueue_pushRx(const CanMsg *rx_msg) +{ + assert(init_complete); + static uint32_t rx_overflow_count = 0; + + // We defer reading the CAN RX message to another task by storing the message on the CAN RX queue. + if (osMessageQueuePut(rx_queue_id, rx_msg, 0, 0) != osOK) + // If pushing to the queue failed, the queue is full. Discard the msg and invoke the RX overflow callback. + canRxQueueOverflowCallBack(++rx_overflow_count); + else + canRxQueueOverflowClearCallback(); +} + +CanMsg io_canQueue_popRx() +{ + assert(init_complete); + CanMsg msg; + // Pop a message off the RX queue. + const osStatus_t s = osMessageQueueGet(rx_queue_id, &msg, NULL, osWaitForever); + assert(s == osOK); + return msg; +} diff --git a/firmware/shared/src/io/io_canQueue.h b/firmware/shared/src/io/io_canQueue.h new file mode 100644 index 0000000000..6e560fee43 --- /dev/null +++ b/firmware/shared/src/io/io_canQueue.h @@ -0,0 +1,60 @@ +#pragma once + +#include + +#include "io_canMsg.h" + +/** + * This module is a CAN driver which manages CAN msg transmission (TX) and reception (RX) via FreeRTOS queues: One for + * TX, and one for RX. + * + * Transmission: + * 1. Enqueue msgs via `io_can_enqueueTxMsg`. If the TX queue is full, the `tx_overflow_callback` function is called. + * 2. Pop msgs off the TX queue and transmit them via `io_can_transmitTxMsg`. After popping a msg off the TX queue, + * `io_can_transmitTxMsg` spins until a CAN TX mailbox becomes available (STM32F412x MCUs have 3) and adds it to a + * mailbox. After adding to the mailbox, the CAN peripheral hardware will put the msg on the bus. + * + * Receiving: + * 1. When a CAN msg is received, it is passed through a hardware filter (currently configured to accept all msgs with a + * standard 11-bit identifier) and an interrupt is fired (`HAL_CAN_RxFifo0MsgPendingCallback` or + * `HAL_CAN_RxFifo1MsgPendingCallback`, depending on the RX hardware FIFO). + * 2. Both interrupts invoke a callback, which filters by msg ID via an optional `rx_msg_filter` function. If accepted, + * the RX msg is placed on the RX queue. + * 3. Pop msgs off the RX queue via `io_can_dequeueRxMsg`, which blocks until a CAN RX msg is successfully dequeued. + */ + +// typedef struct +// { +// void (*tx_overflow_callback)(uint32_t); // Callback on TX queue overflow. +// void (*rx_overflow_callback)(uint32_t); // Callback on RX queue overflow. +// void (*tx_overflow_clear_callback)(void); // Callback on TX queue overflow clear. +// void (*rx_overflow_clear_callback)(void); // Callback on RX queue overflow clear. +// } CanQueue; + +/** + * Initialize and start the CAN peripheral. + */ +void io_canQueue_init(); + +/** + * Enqueue a CAN msg to be transmitted on the bus. + * Does not block, calls `tx_overflow_callback` if queue is full. + * @param tx_msg CAN msg to be TXed. + */ +void io_canQueue_pushTx(const CanMsg *tx_msg); + +/** + * Pops a CAN msg from the TX queue. Blocks until a msg exists in the queue. + */ +CanMsg io_canQueue_popTx(); + +/** + * Callback fired by config-specific interrupts to receive a message from a given FIFO. + * @param rx_msg CAN msg to be populated by RXed msg. + */ +void io_canQueue_pushRx(const CanMsg *rx_msg); + +/** + * Dequeue a received CAN msg. Blocks until a msg can be dequeued. + */ +CanMsg io_canQueue_popRx(); diff --git a/firmware/shared/src/io/io_chimera.c b/firmware/shared/src/io/io_chimera.c index 521304ef1f..3a9b8e965e 100644 --- a/firmware/shared/src/io/io_chimera.c +++ b/firmware/shared/src/io/io_chimera.c @@ -6,6 +6,8 @@ #include "cmsis_os.h" #include "hw_adcs.h" +#include "hw_gpio.h" +#include "hw_uart.h" #include "shared.pb.h" #include "VC.pb.h" @@ -13,18 +15,20 @@ #define MAX_DEBUG_BUF_SIZE 100 #define DEBUG_SIZE_MSG_BUF_SIZE 1 -extern const Gpio *const id_to_gpio[]; -extern const AdcChannel *const id_to_adc[]; - -static const UART *uart; -static bool is_mid_debug_msg; -static uint8_t data[MAX_DEBUG_BUF_SIZE]; -static uint8_t rx_packet_size; -static uint32_t net_name_gpio; -static uint32_t net_name_adc; -static bool chimera_button_pressed; - -static const Gpio *n_chimera_gpio; +/** + * Required to be provided by hw_chimeraConfig.c + */ +extern const Gpio *const id_to_gpio[]; // TODO make these proper functions, rather than implicit list indexing? +extern const AdcChannel *const id_to_adc[]; // TODO make these proper functions, rather than implicit list indexing? +extern const UART *chimera_uart; +extern const Gpio *n_chimera_gpio; + +static bool is_mid_debug_msg; +static uint8_t data[MAX_DEBUG_BUF_SIZE]; +static uint8_t rx_packet_size; +static uint32_t net_name_gpio; +static uint32_t net_name_adc; +static bool chimera_button_pressed; static const Gpio *io_chimera_parseNetLabelGpio(const GpioNetName *net_name) { @@ -53,7 +57,7 @@ static const Gpio *io_chimera_parseNetLabelGpio(const GpioNetName *net_name) default: { assert(false); - return 0U; + return NULL; } } } @@ -90,22 +94,19 @@ static const AdcChannel *io_chimera_parseNetLabelAdc(const AdcNetName *net_name) } } -void io_chimera_init(const UART *serial_uart, uint32_t name_gpio, uint32_t name_adc, const Gpio *bootup_gpio) +void io_chimera_init(const uint32_t name_gpio, const uint32_t name_adc) { - uart = serial_uart; is_mid_debug_msg = false; rx_packet_size = 0; net_name_gpio = name_gpio; net_name_adc = name_adc; - n_chimera_gpio = bootup_gpio; - // Button is active low chimera_button_pressed = hw_gpio_readPin(n_chimera_gpio) ? false : true; if (chimera_button_pressed) { - hw_uart_receiveIt(uart, data, DEBUG_SIZE_MSG_BUF_SIZE); + hw_uart_receiveIt(chimera_uart, data, DEBUG_SIZE_MSG_BUF_SIZE); } } @@ -160,8 +161,8 @@ void io_chimera_msgRxCallback(void) assert(pb_encode(&out_stream, DebugMessage_fields, &msg)); uint8_t tx_packet_size = (uint8_t)out_stream.bytes_written; - hw_uart_transmitPoll(uart, &tx_packet_size, DEBUG_SIZE_MSG_BUF_SIZE, osWaitForever); - hw_uart_transmitPoll(uart, data, tx_packet_size, osWaitForever); + hw_uart_transmitPoll(chimera_uart, &tx_packet_size, DEBUG_SIZE_MSG_BUF_SIZE, osWaitForever); + hw_uart_transmitPoll(chimera_uart, data, tx_packet_size, osWaitForever); // Wait for next length message (1 byte). rx_packet_size = DEBUG_SIZE_MSG_BUF_SIZE; @@ -176,5 +177,5 @@ void io_chimera_msgRxCallback(void) // Start receiving data in interrupt mode again so this interrupt will get fired if // more data is recieved. - hw_uart_receiveIt(uart, data, rx_packet_size); + hw_uart_receiveIt(chimera_uart, data, rx_packet_size); } diff --git a/firmware/shared/src/io/io_chimera.h b/firmware/shared/src/io/io_chimera.h index e4eb7280f4..b4406988ad 100644 --- a/firmware/shared/src/io/io_chimera.h +++ b/firmware/shared/src/io/io_chimera.h @@ -1,8 +1,7 @@ #pragma once -#include "hw_uart.h" -#include "hw_gpio.h" +#include -void io_chimera_init(const UART *serial_uart, uint32_t net_name_gpio, uint32_t net_name_adc, const Gpio *bootup_gpio); +void io_chimera_init(uint32_t name_gpio, uint32_t name_adc); void io_chimera_msgRxCallback(void); void io_chimera_sleepTaskIfEnabled(void); diff --git a/firmware/shared/src/io/io_fdcan.c b/firmware/shared/src/io/io_fdcan.c new file mode 100644 index 0000000000..14754e5e34 --- /dev/null +++ b/firmware/shared/src/io/io_fdcan.c @@ -0,0 +1,85 @@ +#include "io_can.h" +#undef NDEBUG +#include +#include "io_log.h" +#include "io_time.h" + +void io_can_init(const CanHandle *can_handle) +{ + // Configure a single filter bank that accepts any message. + FDCAN_FilterTypeDef filter; + filter.IdType = FDCAN_STANDARD_ID; // 11 bit ID + filter.FilterIndex = 0; + filter.FilterType = FDCAN_FILTER_MASK; + filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; + filter.FilterID1 = 0; // Standard CAN ID bits [10:0] + filter.FilterID2 = 0x1FFFFFFF; // Mask bits for Standard CAN ID + + // Configure and initialize hardware filter. + assert(HAL_FDCAN_ConfigFilter(can_handle->hcan, &filter) == HAL_OK); + + // Configure interrupt mode for CAN peripheral. + assert( + HAL_FDCAN_ActivateNotification( + can_handle->hcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE | FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0) == HAL_OK); + assert(HAL_FDCAN_ActivateNotification(can_handle->hcan, FDCAN_IT_BUS_OFF, 0) == HAL_OK); + + // Start the FDCAN peripheral. + assert(HAL_FDCAN_Start(can_handle->hcan) == HAL_OK); +} + +void io_can_deinit(const CanHandle *can_handle) +{ + assert(HAL_FDCAN_Stop(can_handle->hcan) == HAL_OK); + assert(HAL_FDCAN_DeInit(can_handle->hcan) == HAL_OK); +} + +bool io_can_transmit(const CanHandle *can_handle, CanMsg *msg) +{ + FDCAN_TxHeaderTypeDef tx_header; + tx_header.Identifier = msg->std_id; + tx_header.IdType = FDCAN_STANDARD_ID; + tx_header.TxFrameType = FDCAN_DATA_FRAME; + tx_header.DataLength = msg->dlc << 16; // Data length code needs to be shifted by 16 bits. + tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; + tx_header.BitRateSwitch = FDCAN_BRS_OFF; + tx_header.FDFormat = FDCAN_CLASSIC_CAN; + tx_header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; + tx_header.MessageMarker = 0; + + while (HAL_FDCAN_GetTxFifoFreeLevel(can_handle->hcan) == 0U) + ; + + return HAL_FDCAN_AddMessageToTxFifoQ(can_handle->hcan, &tx_header, msg->data) == HAL_OK; +} + +bool io_can_receive(const CanHandle *can_handle, const uint32_t rx_fifo, CanMsg *msg) +{ + FDCAN_RxHeaderTypeDef header; + if (HAL_FDCAN_GetRxMessage(can_handle->hcan, rx_fifo, &header, msg->data) != HAL_OK) + { + return false; + } + + msg->std_id = header.Identifier; + msg->dlc = header.DataLength >> 16; // Data length code needs to be un-shifted by 16 bits. + msg->timestamp = io_time_getCurrentMs(); + + return true; +} + +// ReSharper disable once CppParameterMayBeConst +void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs) +{ + // assert(hfdcan == can_handle->hcan); + LOG_INFO("FDCAN detected an error"); + if ((ErrorStatusITs & FDCAN_IT_BUS_OFF) != RESET) + { + FDCAN_ProtocolStatusTypeDef protocolStatus; + HAL_FDCAN_GetProtocolStatus(hfdcan, &protocolStatus); + if (protocolStatus.BusOff) + { + CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT); + } + } +} diff --git a/firmware/shared/src/io/io_fileSystem.h b/firmware/shared/src/io/io_fileSystem.h index 8d38c37903..a27e9a44d6 100644 --- a/firmware/shared/src/io/io_fileSystem.h +++ b/firmware/shared/src/io/io_fileSystem.h @@ -1,5 +1,7 @@ +#pragma once #include #include +#include typedef enum { @@ -12,23 +14,56 @@ typedef enum FILE_ERROR_BAD_ARG = -6, // Invalid argument passed in } FileSystemError; -// init the file system -// config the file system -// mount the file system +/** + * init the file system + * config the file system + * mount the file system + * @return success of operation + */ FileSystemError io_fileSystem_init(void); -// open a file and return the file descriptor +/** + * open a file and return the file descriptor + * @param path path in question + * @return a file descriptor + */ int io_fileSystem_open(const char *path); -// write return error code +/** + * writes to file descriptor for some size into the buffer + * @param fd file descriptor in question + * @param buf buffer in question + * @param size size in questino + * @return + */ FileSystemError io_fileSystem_write(int fd, void *buf, size_t size); -// given fd, buf, size, return error code +/** + * reads from file descriptor for some size into the buffer + * @param fd file descriptor in question + * @param buf buffer in question + * @param size size in questino + * @return success of operation + */ FileSystemError io_fileSystem_read(int fd, void *buf, size_t size); -// close file + +/** + * Closes file given file descriptor + * @param fd file descriptor in question + * @return success of operation + */ FileSystemError io_fileSystem_close(int fd); +/** + * @return The bootcount of a given file system + */ uint32_t io_fileSystem_getBootCount(void); -// do the concrete write operation to the hardware +/** + * do the concrete write operation to the hardware + * @param fd on this file descriptor + * @return success of operation + */ FileSystemError io_fileSystem_sync(int fd); + +bool io_fileSystem_ready(); diff --git a/firmware/shared/src/io/io_fileSystem_logfs.c b/firmware/shared/src/io/io_fileSystem_logfs.c index 42ec16234f..1e870bee2c 100644 --- a/firmware/shared/src/io/io_fileSystem_logfs.c +++ b/firmware/shared/src/io/io_fileSystem_logfs.c @@ -3,13 +3,16 @@ #include "hw_sd.h" #include -#define MAX_FILE_NUMBER 3 +// Note: this code assumes that sd card is either in at the start (removable later) +// or never in at all. Furthermore, if the sd card is removed, this cannot be recovered. -extern Gpio sd_present; +// config +#define MAX_FILE_NUMBER 3 static LogFsErr logfsCfgRead(const LogFsCfg *cfg, uint32_t block, void *buf); static LogFsErr logfsCfgWrite(const LogFsCfg *cfg, uint32_t block, void *buf); +// state static uint8_t cache[HW_DEVICE_SECTOR_SIZE]; static const LogFsCfg fs_cfg = { .block_count = 1024 * 1024 * 15, // ~7.5GB @@ -31,14 +34,12 @@ static LogFsFile bootcount_file; static uint8_t bootcount_cache[HW_DEVICE_SECTOR_SIZE]; static LogFsFileCfg bootcount_cfg = { .cache = bootcount_cache, .path = "/bootcount.txt" }; -static bool sdCardReady() -{ - return !hw_gpio_readPin(&sd_present); -} +static bool ready = false; -static LogFsErr logfsCfgRead(const LogFsCfg *cfg, uint32_t block, void *buf) +static LogFsErr logfsCfgRead(const LogFsCfg *cfg, const uint32_t block, void *buf) { - if (!sdCardReady()) + UNUSED(cfg); + if (!io_fileSystem_ready()) { return LOGFS_ERR_IO; } @@ -51,9 +52,10 @@ static LogFsErr logfsCfgRead(const LogFsCfg *cfg, uint32_t block, void *buf) return LOGFS_ERR_OK; } -static LogFsErr logfsCfgWrite(const LogFsCfg *cfg, uint32_t block, void *buf) +static LogFsErr logfsCfgWrite(const LogFsCfg *cfg, const uint32_t block, void *buf) { - if (!sdCardReady()) + UNUSED(cfg); + if (!io_fileSystem_ready()) { return LOGFS_ERR_IO; } @@ -66,7 +68,10 @@ static LogFsErr logfsCfgWrite(const LogFsCfg *cfg, uint32_t block, void *buf) return LOGFS_ERR_OK; } -static int logfsErrorToFsError(int err) +/** + * Converts logfs errors to firmware filesystem error + */ +static FileSystemError logfsErrorToFsError(const LogFsErr err) { switch (err) { @@ -89,6 +94,10 @@ static int logfsErrorToFsError(int err) } } +/** + * Allocates a file descriptor. + * @return a valid fd + */ static int allocateFd(void) { for (int i = 0; i < MAX_FILE_NUMBER; i++) @@ -103,13 +112,18 @@ static int allocateFd(void) return -1; } -static bool isValidFd(int fd) -{ - return fd >= 0 && fd < MAX_FILE_NUMBER && files_opened[fd]; -} +/** + * Checks the file descriptor to make sure it's valid, if not returns FILE_ERROR + * @param fd file descriptor in question + */ +#define CHECK_FILE_DESCRIPTOR(fd) \ + if (!(fd >= 0 && fd < MAX_FILE_NUMBER && files_opened[fd])) \ + return FILE_ERROR; FileSystemError io_fileSystem_init(void) { + if (!hw_sd_present()) + return FILE_ERROR_IO; LogFsErr err = logfs_mount(&fs, &fs_cfg); if (err != LOGFS_ERR_OK) { @@ -140,37 +154,31 @@ FileSystemError io_fileSystem_init(void) return logfsErrorToFsError(err); } + ready = true; return FILE_OK; } int io_fileSystem_open(const char *path) { - int fd = allocateFd(); + const int fd = allocateFd(); if (fd < 0) { return FILE_NOT_FOUND; } - files_cfg[fd].path = path; - LogFsErr err = logfs_open(&fs, &files[fd], &files_cfg[fd], LOGFS_OPEN_RD_WR | LOGFS_OPEN_CREATE); - if (err != LOGFS_ERR_OK) + if (logfs_open(&fs, &files[fd], &files_cfg[fd], LOGFS_OPEN_RD_WR | LOGFS_OPEN_CREATE) != LOGFS_ERR_OK) { files_opened[fd] = false; - return logfsErrorToFsError(err); + return logfsErrorToFsError(logfs_open(&fs, &files[fd], &files_cfg[fd], LOGFS_OPEN_RD_WR | LOGFS_OPEN_CREATE)); } - return fd; } -FileSystemError io_fileSystem_read(int fd, void *buffer, size_t size) +FileSystemError io_fileSystem_read(const int fd, void *buf, const size_t size) { - if (!isValidFd(fd)) - { - return FILE_NOT_FOUND; - } - - uint32_t num_read; - LogFsErr err = logfs_read(&fs, &files[fd], buffer, size, LOGFS_READ_END, &num_read); + CHECK_FILE_DESCRIPTOR(fd) + uint32_t num_read; + const LogFsErr err = logfs_read(&fs, &files[fd], buf, size, LOGFS_READ_END, &num_read); if (err != LOGFS_ERR_OK || num_read != size) { return logfsErrorToFsError(err); @@ -179,21 +187,17 @@ FileSystemError io_fileSystem_read(int fd, void *buffer, size_t size) return FILE_OK; } -FileSystemError io_fileSystem_write(int fd, void *buffer, size_t size) +FileSystemError io_fileSystem_write(const int fd, void *buf, const size_t size) { - if (!isValidFd(fd)) - { - return FILE_ERROR; - } - - return logfsErrorToFsError(logfs_write(&fs, &files[fd], buffer, size)); + CHECK_FILE_DESCRIPTOR(fd) + return logfsErrorToFsError(logfs_write(&fs, &files[fd], buf, size)); } uint32_t io_fileSystem_getBootCount(void) { - uint32_t bootcount; - uint32_t num_read; - LogFsErr err = logfs_readMetadata(&fs, &bootcount_file, &bootcount, sizeof(bootcount), &num_read); + uint32_t bootcount; + uint32_t num_read; + const LogFsErr err = logfs_readMetadata(&fs, &bootcount_file, &bootcount, sizeof(bootcount), &num_read); if (err != LOGFS_ERR_OK || num_read != sizeof(bootcount)) { bootcount = 0; @@ -204,14 +208,10 @@ uint32_t io_fileSystem_getBootCount(void) return bootcount; } -FileSystemError io_fileSystem_close(int fd) +FileSystemError io_fileSystem_close(const int fd) { - if (!isValidFd(fd)) - { - return FILE_ERROR; - } - - LogFsErr err = logfs_close(&fs, &files[fd]); + CHECK_FILE_DESCRIPTOR(fd) + const LogFsErr err = logfs_close(&fs, &files[fd]); if (err != LOGFS_ERR_OK) { return logfsErrorToFsError(err); @@ -221,12 +221,15 @@ FileSystemError io_fileSystem_close(int fd) return FILE_OK; } -FileSystemError io_fileSystem_sync(int fd) +FileSystemError io_fileSystem_sync(const int fd) { - if (!isValidFd(fd)) - { - return FILE_ERROR; - } - + CHECK_FILE_DESCRIPTOR(fd) return logfsErrorToFsError(logfs_sync(&fs, &files[fd])); } + +bool io_fileSystem_ready() +{ + // TODO recheck ready conditions + ready &= hw_sd_present(); + return ready; +} diff --git a/firmware/shared/src/io/io_jsoncan.c b/firmware/shared/src/io/io_jsoncan.c index f904d1ad0b..f4201c37e7 100644 --- a/firmware/shared/src/io/io_jsoncan.c +++ b/firmware/shared/src/io/io_jsoncan.c @@ -1,25 +1,20 @@ #include "io_jsoncan.h" -#include "hw_can.h" #include -void io_jsoncan_pushTxMsgToQueue(const JsonCanMsg *msg) +JsonCanMsg io_jsoncan_copyFromCanMsg(const CanMsg *msg) { - CanMsg tx_msg; + JsonCanMsg tx_msg; memcpy(tx_msg.data, msg->data, sizeof(tx_msg.data)); - io_jsoncan_copyToCanMsg(msg, &tx_msg); - io_can_pushTxMsgToQueue(&tx_msg); -} - -void io_jsoncan_copyToCanMsg(const JsonCanMsg *src, CanMsg *dest) -{ - dest->std_id = src->std_id; - dest->dlc = src->dlc; - memcpy(dest->data, src->data, sizeof(dest->data)); + tx_msg.std_id = msg->std_id; + tx_msg.dlc = msg->dlc; + return tx_msg; } -void io_jsoncan_copyFromCanMsg(const CanMsg *src, JsonCanMsg *dest) +CanMsg io_jsoncan_copyToCanMsg(const JsonCanMsg *msg) { - dest->std_id = src->std_id; - dest->dlc = src->dlc; - memcpy(dest->data, src->data, sizeof(dest->data)); + CanMsg tx_msg; + memcpy(tx_msg.data, msg->data, sizeof(tx_msg.data)); + tx_msg.std_id = msg->std_id; + tx_msg.dlc = msg->dlc; + return tx_msg; } diff --git a/firmware/shared/src/io/io_jsoncan.h b/firmware/shared/src/io/io_jsoncan.h index a27c2155ea..6336131559 100644 --- a/firmware/shared/src/io/io_jsoncan.h +++ b/firmware/shared/src/io/io_jsoncan.h @@ -1,7 +1,7 @@ #pragma once -#include "io_can.h" -#include "io_canTx.h" +#include "io_canRx.h" +#include "io_canMsg.h" /** * Helper functions to interface our hw-level CAN driver (hw_can.h/c) @@ -11,23 +11,13 @@ */ /** - * Enqueue a jsoncan msg to be transmitted on the bus. - * This just invokes io_can_pushTxMsgToQueue, but we need this intermediate - * function since jsoncan defines its own CAN message struct. - * @param msg CAN msg to be TXed. - */ -void io_jsoncan_pushTxMsgToQueue(const JsonCanMsg *msg); - -/** - * Convert a jsoncan message to our own driver-level CAN message type. - * @param src Pointer to jsoncan message to be copied from. - * @param dest Pointer to CAN message to be copied to. + * Convert own driver-level CAN message type to a jsoncan message. + * @param msg message to convert */ -void io_jsoncan_copyToCanMsg(const JsonCanMsg *src, CanMsg *dest); +JsonCanMsg io_jsoncan_copyFromCanMsg(const CanMsg *msg); /** - * Convert own driver-level CAN message type to a jsoncan message. - * @param src Pointer to CAN message to be copied from. - * @param dest Pointer to jsoncan message to be copied to. + * Convert a jsoncan message to own driver-level CAN message type. + * @param msg message to convert */ -void io_jsoncan_copyFromCanMsg(const CanMsg *src, JsonCanMsg *dest); +CanMsg io_jsoncan_copyToCanMsg(const JsonCanMsg *msg); diff --git a/firmware/shared/src/io/io_led.c b/firmware/shared/src/io/io_led.c index cde2b30d61..af1596fccf 100644 --- a/firmware/shared/src/io/io_led.c +++ b/firmware/shared/src/io/io_led.c @@ -1,6 +1,6 @@ #include "io_led.h" -void io_led_enable(const BinaryLed *led, bool on) +void io_led_enable(const BinaryLed *led, const bool on) { - hw_gpio_writePin(&led->gpio, on); + hw_gpio_writePin(led->gpio, on); } diff --git a/firmware/shared/src/io/io_led.h b/firmware/shared/src/io/io_led.h index bfd21881dc..42199c77c3 100644 --- a/firmware/shared/src/io/io_led.h +++ b/firmware/shared/src/io/io_led.h @@ -1,21 +1,21 @@ #pragma once #include -#include "app_utils.h" #ifdef TARGET_EMBEDDED #include "hw_gpio.h" - typedef struct { - const Gpio gpio; + const Gpio *gpio; } BinaryLed; #else +#include "app_utils.h" EMPTY_STRUCT(BinaryLed); #endif /** * Turn an LED on or off. + * @param led led to modify * @param on Whether or not to turn LED on. */ void io_led_enable(const BinaryLed *led, bool on); diff --git a/firmware/shared/src/io/io_switch.h b/firmware/shared/src/io/io_switch.h index 5998066b29..e293a5e4bb 100644 --- a/firmware/shared/src/io/io_switch.h +++ b/firmware/shared/src/io/io_switch.h @@ -1,7 +1,6 @@ #pragma once #include -#include "app_utils.h" #ifdef TARGET_EMBEDDED #include "hw_gpio.h" @@ -12,6 +11,7 @@ typedef struct const bool closed_state; // GPIO state that indicates closed. } Switch; #else +#include "app_utils.h" EMPTY_STRUCT(Switch); #endif diff --git a/scripts/code_generation/jsoncan/jsoncan.cmake b/scripts/code_generation/jsoncan/jsoncan.cmake index eeacb1cdd3..07c77a5972 100644 --- a/scripts/code_generation/jsoncan/jsoncan.cmake +++ b/scripts/code_generation/jsoncan/jsoncan.cmake @@ -60,19 +60,12 @@ function(jsoncan_sources JSONCAN_PY_BOARD OUTPUT_DIR USE_IO CAR) IF (${USE_IO}) set(CAN_SRCS ${APP_CAN_TX_SRC_OUTPUT} - ${APP_CAN_TX_HEADER_OUTPUT} ${IO_CAN_TX_SRC_OUTPUT} - ${IO_CAN_TX_HEADER_OUTPUT} ${APP_CAN_RX_SRC_OUTPUT} - ${APP_CAN_RX_HEADER_OUTPUT} ${IO_CAN_RX_SRC_OUTPUT} - ${IO_CAN_RX_HEADER_OUTPUT} ${APP_CAN_UTILS_SRC_OUTPUT} - ${APP_CAN_UTILS_HEADER_OUTPUT} ${APP_CAN_ALERTS_SRC_OUTPUT} - ${APP_CAN_ALERTS_HEADER_OUTPUT} ${APP_CAN_DATA_CAPTURE_SRC_OUTPUT} - ${APP_CAN_DATA_CAPTURE_HEADER_OUTPUT} PARENT_SCOPE ) set(CAN_INCLUDE_DIRS @@ -83,15 +76,10 @@ function(jsoncan_sources JSONCAN_PY_BOARD OUTPUT_DIR USE_IO CAR) ELSE () set(CAN_SRCS ${APP_CAN_TX_SRC_OUTPUT} - ${APP_CAN_TX_HEADER_OUTPUT} ${APP_CAN_RX_SRC_OUTPUT} - ${APP_CAN_RX_HEADER_OUTPUT} ${APP_CAN_UTILS_SRC_OUTPUT} - ${APP_CAN_UTILS_HEADER_OUTPUT} ${APP_CAN_ALERTS_SRC_OUTPUT} - ${APP_CAN_ALERTS_HEADER_OUTPUT} ${APP_CAN_DATA_CAPTURE_SRC_OUTPUT} - ${APP_CAN_DATA_CAPTURE_HEADER_OUTPUT} PARENT_SCOPE ) set(CAN_INCLUDE_DIRS