From e7eee709690e43e9145730d781df62a9400222e7 Mon Sep 17 00:00:00 2001 From: vegano1 Date: Wed, 17 Jan 2024 11:06:41 -0500 Subject: [PATCH] - Added irq router for door_open, reed_switch, hepa_push_button, and uv_push_button - Added HepaTask that is responsible for handeling irq events received on its message queue to turn the hepa fan on/off - Fixed up gpio init settings for door_open, reed_switch and others --- hepa-uv/core/tasks.cpp | 51 ++++++++++ hepa-uv/firmware/main_rev1.cpp | 20 ++++ hepa-uv/firmware/stm32g4xx_it.c | 28 ++++-- hepa-uv/firmware/stm32g4xx_it.h | 3 + hepa-uv/firmware/utility_gpio.c | 56 +++++++++-- include/hepa-uv/core/hepa_task.hpp | 92 +++++++++++++++++++ include/hepa-uv/core/messages.hpp | 19 ++++ include/hepa-uv/core/tasks.hpp | 12 ++- .../hepa-uv/firmware/gpio_drive_hardware.hpp | 8 +- include/hepa-uv/firmware/utility_gpio.h | 6 +- 10 files changed, 270 insertions(+), 25 deletions(-) create mode 100644 include/hepa-uv/core/hepa_task.hpp create mode 100644 include/hepa-uv/core/messages.hpp diff --git a/hepa-uv/core/tasks.cpp b/hepa-uv/core/tasks.cpp index 224cf90fc..9e8516b03 100644 --- a/hepa-uv/core/tasks.cpp +++ b/hepa-uv/core/tasks.cpp @@ -3,26 +3,77 @@ #include "common/core/freertos_task.hpp" #include "common/core/freertos_timer.hpp" #include "hepa-uv/core/can_task.hpp" +#include "hepa-uv/firmware/gpio_drive_hardware.hpp" +#include "hepa-uv/firmware/utility_gpio.h" + #pragma GCC diagnostic push // NOLINTNEXTLINE(clang-diagnostic-unknown-warning-option) +#pragma GCC diagnostic ignored "-Wvolatile" +#include "platform_specific_hal_conf.h" +#pragma GCC diagnostic pop static auto tasks = hepauv_tasks::AllTask{}; static auto queues = hepauv_tasks::QueueClient{can::ids::NodeId::hepa_uv}; +static auto gpio_drive_pins = gpio_drive_hardware::GpioDrivePins { + .door_open = gpio::PinConfig{ + .port = DOOR_OPEN_MCU_PORT, + .pin = DOOR_OPEN_MCU_PIN, + .active_setting = DOOR_OPEN_MCU_AS + }, + .reed_switch = gpio::PinConfig{ + .port = REED_SW_MCU_PORT, + .pin = REED_SW_MCU_PIN, + .active_setting = REED_SW_MCU_AS + }, + .hepa_push_button = gpio::PinConfig{ + .port = HEPA_NO_MCU_PORT, + .pin = HEPA_NO_MCU_PIN, + }, + .uv_push_button = gpio::PinConfig{ + .port = UV_NO_MCU_PORT, + .pin = UV_NO_MCU_PIN, + }, + .hepa_on_off = gpio::PinConfig{ + .port = HEPA_ON_OFF_PORT, + .pin = HEPA_ON_OFF_PIN, + .active_setting = HEPA_ON_OFF_AS + }, + .uv_on_off = gpio::PinConfig{ + .port = UV_ON_OFF_MCU_PORT, + .pin = UV_ON_OFF_MCU_PIN, + .active_setting = UV_ON_OFF_AS + } +}; + +static auto hepa_task_builder = + freertos_task::TaskStarter<512, hepa_task::HepaTask>{}; + /** * Start hepa_uv tasks. */ void hepauv_tasks::start_tasks(can::bus::CanBus& can_bus) { auto& can_writer = can_task::start_writer(can_bus); can_task::start_reader(can_bus); + + auto& hepa_task = hepa_task_builder.start(5, "hepa_fan", gpio_drive_pins); + + tasks.hepa_task_handler = &hepa_task; tasks.can_writer = &can_writer; + queues.set_queue(&can_writer.get_queue()); + queues.hepa_queue = &hepa_task.get_queue(); } hepauv_tasks::QueueClient::QueueClient(can::ids::NodeId this_fw) : can::message_writer::MessageWriter{this_fw} {} +void hepauv_tasks::QueueClient::send_interrupt_message( + const hepa_task::TaskMessage& m) { + hepa_queue->try_write(m); +} + /** * Access to the tasks singleton * @return diff --git a/hepa-uv/firmware/main_rev1.cpp b/hepa-uv/firmware/main_rev1.cpp index ccd9e8b13..3438e7c1c 100644 --- a/hepa-uv/firmware/main_rev1.cpp +++ b/hepa-uv/firmware/main_rev1.cpp @@ -22,6 +22,7 @@ #include "common/firmware/utility_gpio.h" #include "hepa-uv/core/tasks.hpp" #include "hepa-uv/firmware/utility_gpio.h" +#include "hepa-uv/core/messages.hpp" static auto iWatchdog = iwdg::IndependentWatchDog{}; @@ -53,6 +54,25 @@ static constexpr auto can_bit_timings = can::bit_timings::BitTimings<170 * can::bit_timings::MHZ, 100, 500 * can::bit_timings::KHZ, 800>{}; +static auto& hepa_queue_client = hepauv_tasks::get_main_queues(); + +extern "C" void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { + switch (GPIO_Pin) { + case DOOR_OPEN_MCU_PIN: + case REED_SW_MCU_PIN: + case HEPA_NO_MCU_PIN: + case UV_NO_MCU_PIN: + if (hepa_queue_client.hepa_queue != nullptr) { + static_cast(hepa_queue_client.hepa_queue->try_write_isr( + interrupt_task_messages::GPIOInterruptChanged{.pin = GPIO_Pin })); + } + // send to uv queue here + break; + default: + break; + } +} + auto main() -> int { HardwareInit(); RCC_Peripheral_Clock_Select(); diff --git a/hepa-uv/firmware/stm32g4xx_it.c b/hepa-uv/firmware/stm32g4xx_it.c index ee1a3295b..207ea169b 100644 --- a/hepa-uv/firmware/stm32g4xx_it.c +++ b/hepa-uv/firmware/stm32g4xx_it.c @@ -115,14 +115,26 @@ void DebugMon_Handler(void) {} /* file (startup_stm32g4xxxx.s). */ /******************************************************************************/ -/** - * @brief This function handles PPP interrupt request. - * @param None - * @retval None - */ -/*void PPP_IRQHandler(void) -{ -}*/ +void EXTI2_IRQHandler(void) { + if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_2)) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); + } +} + +void EXTI9_5_IRQHandler(void) { + if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_7)) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7); + } +} + +void EXTI15_10_IRQHandler(void) { + if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_10)) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10); + } else if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_11)) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11); + } +} + /** * @brief This function handles DMA1 channel2 global interrupt. */ diff --git a/hepa-uv/firmware/stm32g4xx_it.h b/hepa-uv/firmware/stm32g4xx_it.h index 42e65e4a2..152c80265 100644 --- a/hepa-uv/firmware/stm32g4xx_it.h +++ b/hepa-uv/firmware/stm32g4xx_it.h @@ -43,6 +43,9 @@ void SysTick_Handler(void); void DMA1_Channel2_IRQHandler(void); void DMA1_Channel3_IRQHandler(void); void FDCAN1_IT0_IRQHandler(void); +void EXTI2_IRQHandler(void); +void EXTI9_5_IRQHandler(void); +void EXTI15_10_IRQHandler(void); #ifdef __cplusplus } diff --git a/hepa-uv/firmware/utility_gpio.c b/hepa-uv/firmware/utility_gpio.c index 47d5b275d..9bba75704 100644 --- a/hepa-uv/firmware/utility_gpio.c +++ b/hepa-uv/firmware/utility_gpio.c @@ -31,7 +31,7 @@ void door_open_input_gpio_init() { /*Configure GPIO pin DOOR_OPEN_MCU : PC7 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = DOOR_OPEN_MCU_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(DOOR_OPEN_MCU_PORT, &GPIO_InitStruct); } @@ -47,7 +47,7 @@ void reed_switch_input_gpio_init() { /*Configure GPIO pin REED_SW_MCU : PC11 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = REED_SW_MCU_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(REED_SW_MCU_PORT, &GPIO_InitStruct); } @@ -59,7 +59,7 @@ void reed_switch_input_gpio_init() { */ void aux_input_gpio_init(void) { /* GPIO Ports Clock Enable */ - __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); /*Configure GPIO pin AUX_ID_MCU : PC12 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = AUX_ID_MCU_PIN; @@ -79,7 +79,7 @@ void hepa_push_button_input_gpio_init(void) { /*Configure GPIO pin HEPA_NO_MCU : PB10 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = HEPA_NO_MCU_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(HEPA_NO_MCU_PORT, &GPIO_InitStruct); } @@ -89,9 +89,9 @@ void hepa_push_button_input_gpio_init(void) { * @param None * @retval None */ -void uv_push_button_gpio_init(void) { +void uv_push_button_input_gpio_init(void) { /*Configure Ports Clock Enable*/ - __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); /*Configure GPIO pin UV_NO_MCU : PC2 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = UV_NO_MCU_PIN; @@ -100,6 +100,40 @@ void uv_push_button_gpio_init(void) { HAL_GPIO_Init(UV_NO_MCU_PORT, &GPIO_InitStruct); } +/** + * @brief HEPA ON/OFF GPIO Initialization Function + * @param None + * @retval None +*/ +void hepa_on_off_output_init() { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + /*Configure GPIO pin LED_DRIVE : PA7 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = HEPA_ON_OFF_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(HEPA_ON_OFF_PORT, &GPIO_InitStruct); +} + +/** + * @brief UV ON/OFF GPIO Initialization Function + * @param None + * @retval None +*/ +void uv_on_off_output_init() { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + /*Configure GPIO pin LED_DRIVE : PA4 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = UV_ON_OFF_MCU_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(UV_ON_OFF_MCU_PORT, &GPIO_InitStruct); +} + /** * @brief NVIC EXTI interrupt priority Initialization * @param None @@ -115,21 +149,23 @@ static void nvic_priority_enable_init() { /* EXTI interrupt init HEPA_NO_MCU : PB10*/ // PC11 -> GPIO_EXTI11 (EXTI15_10_IRQn) // PB11 -> GPIO_EXTI11 (EXTI15_10_IRQn) - HAL_NVIC_SetPriority(EXTI15_10_IRQn, 7, 0); + HAL_NVIC_SetPriority(EXTI15_10_IRQn, 5, 0); HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); /* EXTI interrupt init UV_NO_MCU : PC2*/ // PC2 -> GPIO_EXTI2 (EXTI2_IRQn) - HAL_NVIC_SetPriority(EXTI2_IRQn, 7, 0); + HAL_NVIC_SetPriority(EXTI2_IRQn, 5, 0); HAL_NVIC_EnableIRQ(EXTI2_IRQn); } void utility_gpio_init(void) { LED_drive_gpio_init(); + nvic_priority_enable_init(); door_open_input_gpio_init(); reed_switch_input_gpio_init(); aux_input_gpio_init(); hepa_push_button_input_gpio_init(); - uv_push_button_gpio_init(); - nvic_priority_enable_init(); + uv_push_button_input_gpio_init(); + hepa_on_off_output_init(); + uv_on_off_output_init(); } diff --git a/include/hepa-uv/core/hepa_task.hpp b/include/hepa-uv/core/hepa_task.hpp new file mode 100644 index 000000000..8eb4850a1 --- /dev/null +++ b/include/hepa-uv/core/hepa_task.hpp @@ -0,0 +1,92 @@ +#pragma once + +#include "can/core/ids.hpp" +#include "common/core/bit_utils.hpp" +#include "common/core/logging.h" +#include "common/core/message_queue.hpp" +#include "messages.hpp" +#include "hepa-uv/firmware/gpio_drive_hardware.hpp" + +namespace hepa_task { + +using TaskMessage = interrupt_task_messages::TaskMessage; + +class HepaMessageHandler { + public: + explicit HepaMessageHandler( + gpio_drive_hardware::GpioDrivePins& drive_pins) + : drive_pins{drive_pins} {} + HepaMessageHandler(const HepaMessageHandler &) = delete; + HepaMessageHandler(const HepaMessageHandler &&) = delete; + auto operator=(const HepaMessageHandler &) + -> HepaMessageHandler & = delete; + auto operator=(const HepaMessageHandler &&) + -> HepaMessageHandler && = delete; + ~HepaMessageHandler() { } + + void handle_message(const TaskMessage &m) { + std::visit([this](auto o) { this->visit(o); }, m); + } + + private: + void visit(const std::monostate &) {} + + // Handle GPIO EXTI Interrupts here + void visit(const interrupt_task_messages::GPIOInterruptChanged &m) { + if (m.pin == drive_pins.hepa_push_button.pin) { + hepa_push_button = !hepa_push_button; + // handle state changes here + if (hepa_push_button) { + gpio::set(drive_pins.hepa_on_off); + } else { + gpio::reset(drive_pins.hepa_on_off); + } + } + + // TODO: send CAN message to host + } + + // state tracking variables + bool hepa_push_button = false; + bool hepa_fan_on = false; + + gpio_drive_hardware::GpioDrivePins& drive_pins; +}; + +/** + * The task type. + */ +template