diff --git a/.github/workflows/hepa_uv.yaml b/.github/workflows/hepa_uv.yaml new file mode 100644 index 000000000..a275be301 --- /dev/null +++ b/.github/workflows/hepa_uv.yaml @@ -0,0 +1,122 @@ +name: "HEPA/UV build/test" +on: + pull_request: + paths: + - "hepa-uv/**" + - "common/**" + - "can/**" + - "include/**" + - "!include/pipettes/**" + - "!include/gantry/**" + - "!include/head/**" + - "cmake/*" + - "!cmake/Arduino*" + - "CMakeLists.txt" + - "hepa-uv/CMakeLists.txt" + - "CMakePresets.json" + - ".clang-format" + - ".clang-tidy" + push: + paths: + - "hepa-uv/**" + - "common/**" + - "can/**" + - "spi/**" + - "include/**" + - "!include/pipettes/**" + - "!include/gantry/**" + - "!include/head/**" + - "cmake/*" + - "!cmake/Arduino*" + - "CMakeLists.txt" + - "hepa-uv/CMakeLists.txt" + - "CMakePresets.json" + - ".clang-format" + - ".clang-tidy" + - ".github/workflows/hepa_uv.yaml" + branches: + - "*" + tags: + - "hepa_uv@*" + workflow_dispatch: + +env: + ci: 1 + +defaults: + run: + shell: bash + +jobs: + cross-compile-check: + name: "Cross-Compile/Check" + runs-on: "ubuntu-20.04" + timeout-minutes: 20 + steps: + - uses: "actions/checkout@v2" + with: + fetch-depth: 0 + - uses: "actions/cache@v3" + with: + path: "./stm32-tools" + key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} + - name: "Configure" + run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=RelWithDebInfo + - name: "Format" + run: cmake --build ./build-cross --target hepa-uv-format-ci + - name: "Build" + run: cmake --build ./build-cross --target hepa-uv-images hepa-uv-applications + - name: "Lint" + run: cmake --build ./build-cross --target hepa-uv-lint + + host-compile-test: + name: "Host-Compile/Test" + runs-on: "ubuntu-20.04" + timeout-minutes: 10 + steps: + - name: Update and install gcc-10 & g++-10 + run: | + sudo apt update + sudo apt install gcc-10 g++-10 + + - name: Checkout ot3-firmware repository + uses: "actions/checkout@v2" + with: + fetch-depth: 0 + path: ot3-firmware + + - name: Checkout opentrons repository + uses: actions/checkout@v3 + with: + repository: "Opentrons/opentrons" + path: opentrons + + - name: Cache stm32-tools + uses: "actions/cache@v3" + with: + path: "./stm32-tools" + key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} + + - name: "Configure" + run: cmake --preset=host-gcc10 . + working-directory: ot3-firmware + + - name: 'Build and test' + run: cmake --build ./build-host --target hepa-uv-build-and-test + working-directory: ot3-firmware + + - name: 'Setup state_manager' + run: cmake --build ./build-host/ --target state-manager-setup + working-directory: ot3-firmware + + - name: 'Build simulator' + run: cmake --build ./build-host --target hepa-uv-simulator + working-directory: ot3-firmware + + - name: "Upload artifacts" + if: github.event_name != 'pull_request' + uses: actions/upload-artifact@v3 + with: + name: "hepa-uv-simulator-${{github.ref_name}}" + path: | + build-host/hepa-uv/simulator/hepa-uv-simulator diff --git a/CMakeLists.txt b/CMakeLists.txt index bef77ac12..65aa199ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,7 @@ add_subdir_for_archs(SUBDIR gantry ARCHS cortex-m4) add_subdir_for_archs(SUBDIR head ARCHS cortex-m4) add_subdir_for_archs(SUBDIR gripper ARCHS cortex-m4) add_subdir_for_archs(SUBDIR pipettes ARCHS cortex-m4 cortex-m33) +add_subdir_for_archs(SUBDIR hepa-uv ARCHS cortex-m4) list(REMOVE_DUPLICATES LINT_TARGETS) message(VERBOSE "Checking if cross-compiling.") @@ -141,6 +142,7 @@ file(GLOB_RECURSE SOURCES_FOR_FORMAT ./spi/*.hpp ./spi/*.cpp ./eeprom/*.hpp ./eeprom/*.cpp ./rear-panel/*.hpp ./rear-panel/*.cpp + ./hepa-uv/*.cpp ) # Targets for formatting. These are here rather than in individual target CMakeLists (e.g. diff --git a/CMakePresets.json b/CMakePresets.json index 18cf67ffb..5246dbadd 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -139,6 +139,17 @@ "gripper" ] }, + { + "name": "hepa-uv", + "displayName": "hepa-uv binary", + "description": "Build the hepa-uv cross binary", + "configurePreset": "cross", + "jobs": 4, + "targets": [ + "hepa-uv" + ] + }, + { "name": "gantry", "displayName": "gantry binaries", @@ -212,7 +223,8 @@ "bootloader-gripper-applications", "bootloader-pipettes-single-applications", "bootloader-pipettes-multi-applications", - "bootloader-pipettes-96-applications" + "bootloader-pipettes-96-applications", + "bootloader-hepa-uv-applications" ] }, { @@ -230,7 +242,8 @@ "pipettes-single-simulator", "pipettes-multi-simulator", "pipettes-96-simulator", - "gripper-simulator" + "gripper-simulator", + "hepa-uv-simulator" ] }, { @@ -248,7 +261,8 @@ "pipettes-single-simulator", "pipettes-multi-simulator", "pipettes-96-simulator", - "gripper-simulator" + "gripper-simulator", + "hepa-uv-simulator" ] } ] diff --git a/bootloader/firmware/stm32G4/CMakeLists.txt b/bootloader/firmware/stm32G4/CMakeLists.txt index 27520bfc5..8664cd97a 100644 --- a/bootloader/firmware/stm32G4/CMakeLists.txt +++ b/bootloader/firmware/stm32G4/CMakeLists.txt @@ -156,6 +156,25 @@ foreach_revision( NO_CREATE_INSTALL_RULES ) +set(hepauv_sources ${_g4_sources}) + +macro(hepauv_bootloader_loop) + target_link_libraries(${REVISION_TARGET} + PUBLIC STM32G491RETx_bootloader + STM32G4xx_Drivers_Bootloader + bootloader-core) + + target_compile_definitions(${REVISION_TARGET} PUBLIC node_id_hepa_uv) +endmacro() + +foreach_revision( + PROJECT_NAME bootloader-hepa-uv + CALL_FOREACH_REV hepauv_bootloader_loop + REVISIONS b1 + SOURCES hepauv_sources + NO_CREATE_IMAGE_HEX + NO_CREATE_INSTALL_RULES + ) target_include_directories(STM32G4xx_Drivers_Bootloader PUBLIC .) diff --git a/bootloader/firmware/stm32G4/node_id_stm32g4xx.c b/bootloader/firmware/stm32G4/node_id_stm32g4xx.c index 8e1ec9826..f2cf9629d 100644 --- a/bootloader/firmware/stm32G4/node_id_stm32g4xx.c +++ b/bootloader/firmware/stm32G4/node_id_stm32g4xx.c @@ -73,9 +73,11 @@ CANNodeId get_node_id(void) { #elif defined(node_id_pipette_left) return can_nodeid_pipette_left_bootloader; #elif defined(node_id_pipette_right) - return can_nodeid_pipette_right_bootloader + return can_nodeid_pipette_right_bootloader; #elif defined(node_id_pipette_dynamic) return get_dynamic_nodeid(); +#elif defined(node_id_hepa_uv) + return can_nodeid_hepa_uv_bootloader; #else #error "No node id" #endif diff --git a/common/firmware/gpio.c b/common/firmware/gpio.c index e58412d18..6a79511be 100644 --- a/common/firmware/gpio.c +++ b/common/firmware/gpio.c @@ -42,4 +42,4 @@ __attribute__((section( ".ccmram" ))) #endif bool gpio_is_set(void* port, uint16_t pin, uint8_t active_setting) { return HAL_GPIO_ReadPin(port, pin) == active_setting; -} +} \ No newline at end of file diff --git a/common/firmware/gpio.cpp b/common/firmware/gpio.cpp index fb4c58c2e..a6fafced2 100644 --- a/common/firmware/gpio.cpp +++ b/common/firmware/gpio.cpp @@ -24,4 +24,4 @@ __attribute__((section( ".ccmram" ))) auto gpio::is_set(const gpio::PinConfig& pc) -> bool { return gpio_is_set(pc.port, pc.pin, pc.active_setting); -} +} \ No newline at end of file diff --git a/hepa-uv/CMakeLists.txt b/hepa-uv/CMakeLists.txt new file mode 100644 index 000000000..bc76be1a0 --- /dev/null +++ b/hepa-uv/CMakeLists.txt @@ -0,0 +1,33 @@ +# hepa-uv source tree + +add_subdirectory(core) + +if (${CMAKE_CROSSCOMPILING}) + if (${ARM_ARCH_TYPE} STREQUAL "cortex-m4") + add_subdirectory(firmware) + endif () +else () + add_subdirectory(simulator) + add_subdirectory(tests) +endif () + +file(GLOB_RECURSE HEPA_SOURCES_FOR_FORMAT ./*.cpp ./*.hpp ../include/hepa-uv/*.hpp) + +# Targets for formatting. These are here rather than in individual target CMakeLists (e.g. +# the ones in tests/ or firmware/) because they don't have semantic reasoning involved and +# can therefore operate on file globs, unlike lint/static analysis + +# Target for use during dev - edits files +add_custom_target( + hepa-uv-format + ALL + COMMAND ${Clang_CLANGFORMAT_EXECUTABLE} -style=file -i ${HEPA_SOURCES_FOR_FORMAT} +) + +# Target for use in ci - warnings are errors, doesn't edit files +add_custom_target( + hepa-uv-format-ci + COMMAND ${Clang_CLANGFORMAT_EXECUTABLE} -style=file -Werror --ferror-limit=0 -n ${HEPA_SOURCES_FOR_FORMAT} +) + +set(LINT_TARGETS ${LINT_TARGETS} PARENT_SCOPE) diff --git a/hepa-uv/core/CMakeLists.txt b/hepa-uv/core/CMakeLists.txt new file mode 100644 index 000000000..b1474e65a --- /dev/null +++ b/hepa-uv/core/CMakeLists.txt @@ -0,0 +1,8 @@ +function(target_hepa_uv_core TARGET) + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/can_tasks.cpp + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tasks.cpp) + target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR}) + target_link_libraries(${TARGET} PUBLIC common-core) + target_include_directories(${TARGET} INTERFACE ${CMAKE_SOURCE_DIR}/cpp-utils/include) +endfunction() diff --git a/hepa-uv/core/can_tasks.cpp b/hepa-uv/core/can_tasks.cpp new file mode 100644 index 000000000..73d1e1b73 --- /dev/null +++ b/hepa-uv/core/can_tasks.cpp @@ -0,0 +1,126 @@ +#include + +#include "hepa-uv/core/can_task.hpp" + +using namespace can::dispatch; + +static auto& main_queues = hepauv_tasks::get_main_queues(); + +auto can_sender_queue = freertos_message_queue::FreeRTOSMessageQueue< + can::message_writer_task::TaskMessage>{}; + +/** Handler of system messages. */ +static auto system_message_handler = + can::message_handlers::system::SystemMessageHandler{ + main_queues, + version_get()->version, + version_get()->flags, + std::span(std::cbegin(version_get()->sha), + std::cend(version_get()->sha)), + revision_get()->primary, + revision_get()->secondary}; +static auto system_dispatch_target = + can_task::SystemDispatchTarget{system_message_handler}; + +struct CheckForNodeId { + can::ids::NodeId node_id; + auto operator()(uint32_t arbitration_id) const { + auto arb = can::arbitration_id::ArbitrationId(arbitration_id); + auto _node_id = arb.node_id(); + return ((_node_id == node_id) || + (_node_id == can::ids::NodeId::broadcast) || + (_node_id == can::ids::NodeId::hepa_uv)); + } +}; + +/** Dispatcher to the various handlers */ +static auto main_dispatcher = can::dispatch::Dispatcher( + [](uint32_t arbitration_id) -> bool { + auto arb = can::arbitration_id::ArbitrationId(arbitration_id); + auto node_id = arb.node_id(); + return ((node_id == can::ids::NodeId::broadcast) || + (node_id == can::ids::NodeId::hepa_uv)); + }, + system_dispatch_target); + +auto static reader_message_buffer = + freertos_message_buffer::FreeRTOSMessageBuffer<1024>{}; +static auto reader_message_buffer_writer = + can::message_buffer::CanMessageBufferWriter(reader_message_buffer); + +/** + * New CAN message callback. + * + * @param identifier Arbitration id + * @param data Message data + * @param length Message data length + */ +void callback(void*, uint32_t identifier, uint8_t* data, uint8_t length) { + reader_message_buffer_writer.send_from_isr(identifier, data, + data + length); // NOLINT +} + +/** + * Entry point for the reader task. + * TODO (2021-12-15, AL): Most of what happens in this task should be moved out + * when we move to separate motor tasks. + */ +[[noreturn]] void can_task::CanMessageReaderTask::operator()( + can::bus::CanBus* can_bus) { + can_bus->set_incoming_message_callback(nullptr, callback); + + auto filter = can::arbitration_id::ArbitrationId(); + + // Accept broadcast + filter.node_id(can::ids::NodeId::broadcast); + can_bus->add_filter(CanFilterType::mask, CanFilterConfig::to_fifo0, filter, + can::arbitration_id::ArbitrationId::node_id_bit_mask); + + // TODO: add HEPA/UV filter + filter.node_id(can::ids::NodeId::hepa_uv); + can_bus->add_filter(CanFilterType::mask, CanFilterConfig::to_fifo1, filter, + can::arbitration_id::ArbitrationId::node_id_bit_mask); + + // Reject everything else. + can_bus->add_filter(CanFilterType::mask, CanFilterConfig::reject, 0, 0); + + auto poller = can::freertos_dispatch::FreeRTOSCanBufferPoller( + reader_message_buffer, main_dispatcher); + poller(); +} + +auto static reader_task = can_task::CanMessageReaderTask{}; +auto static writer_task = can_task::CanMessageWriterTask{can_sender_queue}; + +auto static reader_task_control = + freertos_task::FreeRTOSTask<512, can_task::CanMessageReaderTask>{ + reader_task}; +auto static writer_task_control = + freertos_task::FreeRTOSTask<512, can_task::CanMessageWriterTask>{ + writer_task}; + +/** + * Start the can reader task + * @param canbus The can bus reference + * @return The task entry point. + */ +auto can_task::start_reader(can::bus::CanBus& canbus) + -> can_task::CanMessageReaderTask& { + LOG("Starting the CAN reader task"); + + reader_task_control.start(5, "can reader task", &canbus); + return reader_task; +} + +/** + * Start the can writer task + * @param canbus The can bus reference + * @return The task entry point + */ +auto can_task::start_writer(can::bus::CanBus& canbus) + -> can_task::CanMessageWriterTask& { + LOG("Starting the CAN writer task"); + + writer_task_control.start(5, "can writer task", &canbus); + return writer_task; +} diff --git a/hepa-uv/core/tasks.cpp b/hepa-uv/core/tasks.cpp new file mode 100644 index 000000000..224cf90fc --- /dev/null +++ b/hepa-uv/core/tasks.cpp @@ -0,0 +1,36 @@ +#include "hepa-uv/core/tasks.hpp" + +#include "common/core/freertos_task.hpp" +#include "common/core/freertos_timer.hpp" +#include "hepa-uv/core/can_task.hpp" + +#pragma GCC diagnostic push +// NOLINTNEXTLINE(clang-diagnostic-unknown-warning-option) + +static auto tasks = hepauv_tasks::AllTask{}; +static auto queues = hepauv_tasks::QueueClient{can::ids::NodeId::hepa_uv}; + +/** + * 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); + tasks.can_writer = &can_writer; + queues.set_queue(&can_writer.get_queue()); +} + +hepauv_tasks::QueueClient::QueueClient(can::ids::NodeId this_fw) + : can::message_writer::MessageWriter{this_fw} {} + +/** + * Access to the tasks singleton + * @return + */ +auto hepauv_tasks::get_all_tasks() -> AllTask& { return tasks; } + +/** + * Access to the queues singleton + * @return + */ +auto hepauv_tasks::get_main_queues() -> QueueClient& { return queues; } diff --git a/hepa-uv/firmware/CMakeLists.txt b/hepa-uv/firmware/CMakeLists.txt new file mode 100644 index 000000000..d2056eb75 --- /dev/null +++ b/hepa-uv/firmware/CMakeLists.txt @@ -0,0 +1,87 @@ +# This CMakeLists.txt handles everything that is compiled only when +# cross-compiling, like the board support packages and special options. +find_package(STM32G4xx) +include(RevisionHandling) +include(ClangTidy) + +set(COMMON_EXECUTABLE_DIR "${CMAKE_SOURCE_DIR}/common/firmware") +set(CAN_FW_DIR "${CMAKE_SOURCE_DIR}/can/firmware") + +set(REVISIONS hepa-rev1) + +# Add source files that should be checked by clang-tidy here +set(HEPA_UV_FW_LINTABLE_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/freertos_idle_timer_task.cpp + ${COMMON_EXECUTABLE_DIR}/system/iwdg.cpp + ${CAN_FW_DIR}/hal_can_bus.cpp + ${CAN_FW_DIR}/utils.c + ${CAN_FW_DIR}/hal_can.c + ) + +set(HEPAUV_FW_NON_LINTABLE_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/system_stm32g4xx.c + ${CMAKE_CURRENT_SOURCE_DIR}/stm32g4xx_it.c + ${CMAKE_CURRENT_SOURCE_DIR}/clocking.c + ${CMAKE_CURRENT_SOURCE_DIR}/utility_gpio.c + ${CMAKE_CURRENT_SOURCE_DIR}/can.c + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_setup.c + ${COMMON_EXECUTABLE_DIR}/errors/errors.c + ${COMMON_EXECUTABLE_DIR}/system/app_update.c + ${COMMON_EXECUTABLE_DIR}/system/iwdg.c + ) + +set(HEPAUV_SRCS_B1 + ${HEPA_UV_FW_LINTABLE_SRCS} + ${HEPAUV_FW_NON_LINTABLE_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/main_rev1.cpp +) +set(HEPAUV_SRCS_C1 ${HEPAUV_SRCS_B1}) +set(HEPAUV_SRCS_C2 ${HEPAUV_SRCS_C1}) + +macro(hepa_uv_loop) + set(_driver_suffix ${PROJECT_NAME}_${REVISION}) + add_STM32G4_driver(${_driver_suffix}) + add_STM32G4_freertos(${_driver_suffix}) + + target_include_directories(STM32G4xx_Drivers_${_driver_suffix} + PUBLIC .) + target_include_directories(STM32G4xx_FreeRTOS_${_driver_suffix} + PUBLIC .) + + target_compile_definitions(STM32G4xx_Drivers_${_driver_suffix} + PUBLIC STM32G491xx) + target_compile_definitions(STM32G4xx_FreeRTOS_${_driver_suffix} + PUBLIC STM32G491xx) + + set_target_properties( + STM32G4xx_FreeRTOS_${_driver_suffix} + PROPERTIES FREERTOS_HEAP_IMPLEMENTATION "heap_5") + + target_hepa_uv_core(${REVISION_TARGET}) + target_ot_motor_control(${REVISION_TARGET}) + + target_i2c_firmware(${REVISION_TARGET}) + + target_link_libraries(${REVISION_TARGET} + PUBLIC STM32G491RETx + STM32G4xx_Drivers_${_driver_suffix} STM32G4xx_FreeRTOS_${_driver_suffix} + can-core) + install_if_latest_revision( + FILENAME ${REVISION_HEX_IMAGE_FILE} + COMPONENT hepauv-images + THISREVISION ${REVISION} + REVISIONS ${REVISIONS} + ) +endmacro() + +foreach_revision( + PROJECT_NAME hepa-uv + REVISIONS b1 + SOURCES HEPAUV_SRCS_B1 + CALL_FOREACH_REV hepa_uv_loop) + +alias_for_revision(PROJECT_NAME hepa-uv REVISION b1 REVISION_ALIAS rev1) + +add_clang_tidy_target( + TARGET_NAME hepa-uv-lint + LINT_SOURCES ${HEPA_UV_FW_LINTABLE_SRCS}) diff --git a/hepa-uv/firmware/FreeRTOSConfig.h b/hepa-uv/firmware/FreeRTOSConfig.h new file mode 100644 index 000000000..be6b09bf3 --- /dev/null +++ b/hepa-uv/firmware/FreeRTOSConfig.h @@ -0,0 +1,175 @@ +/* + * FreeRTOS Kernel V10.0.1 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * this is a template configuration files + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * These parameters and more are described within the 'configuration' section of + *the FreeRTOS API documentation available on the FreeRTOS.org web site. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* Ensure stdint is only used by the compiler, and not the assembler. */ +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) +#include +extern uint32_t SystemCoreClock; +#endif + +/* CMSIS-RTOSv2 defines 56 levels of priorities. To be able to use them + * all and avoid application misbehavior, + * configUSE_PORT_OPTIMISED_TASK_SELECTION must be set to 0 and + * configMAX_PRIORITIES to 56 + * + */ +/* #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0*/ +/* #define configMAX_PRIORITIES ( 56 ) */ +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configMAX_PRIORITIES (7) +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configCPU_CLOCK_HZ (SystemCoreClock) +#define configTICK_RATE_HZ ((TickType_t)1000) +#define configMINIMAL_STACK_SIZE ((uint16_t)128) +#define configTOTAL_HEAP_SIZE ((size_t)(15 * 1024)) +#define configMAX_TASK_NAME_LEN (16) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 8 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES (2) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (6) +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 0 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 + +/*------------- CMSIS-RTOS V2 specific defines -----------*/ +/* When using CMSIS-RTOSv2 set configSUPPORT_STATIC_ALLOCATION to 1 + * is mandatory to avoid compile errors. + * CMSIS-RTOS V2 implmentation requires the following defines + * +#define configSUPPORT_STATIC_ALLOCATION 1 <-- cmsis_os threads are +created using xTaskCreateStatic() API #define configMAX_PRIORITIES (56) <-- +Priority range in CMSIS-RTOS V2 is [0 .. 56] #define +configUSE_PORT_OPTIMISED_TASK_SELECTION 0 <-- when set to 1, +configMAX_PRIORITIES can't be more than 32 which is not suitable for the new +CMSIS-RTOS v2 priority range +*/ + +/* the CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation +used + * by the application thus the correct define need to be enabled from the list + * below + * +//define USE_FreeRTOS_HEAP_1 +//define USE_FreeRTOS_HEAP_2 +//define USE_FreeRTOS_HEAP_3 +//define USE_FreeRTOS_HEAP_4 +//define USE_FreeRTOS_HEAP_5 +*/ + +/* Cortex-M specific definitions. */ +#ifdef __NVIC_PRIO_BITS +/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ +#define configPRIO_BITS __NVIC_PRIO_BITS +#else +#define configPRIO_BITS 4 /* 15 priority levels */ +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" +function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY \ + (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY \ + (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +#define configASSERT(x) \ + if ((x) == 0) { \ + taskDISABLE_INTERRUPTS(); \ + for (;;) \ + ; \ + } + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS + standard names. */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler + +/* IMPORTANT: FreeRTOS is using the SysTick as internal time base, thus make + sure the system and peripherials are using a different time base (TIM based + for example). + */ +#define xPortSysTickHandler FreeRTOS_SysTick_Handler + +#endif /* FREERTOS_CONFIG_H */ diff --git a/hepa-uv/firmware/can.c b/hepa-uv/firmware/can.c new file mode 100644 index 000000000..cd7d8a9c9 --- /dev/null +++ b/hepa-uv/firmware/can.c @@ -0,0 +1,85 @@ +#include "common/firmware/can.h" + +/** + * Initialize a connection to FDCAN1 + * + * @param handle Pointer to an FDCAN handle + * @return HAL_OK on success + */ +HAL_StatusTypeDef MX_FDCAN1_Init( + FDCAN_HandleTypeDef* handle, + uint8_t clock_divider, + uint8_t segment_1_tqs, + uint8_t segment_2_tqs, + uint8_t max_sync_jump_width) { + handle->Instance = FDCAN1; + handle->Init.ClockDivider = FDCAN_CLOCK_DIV1; + handle->Init.FrameFormat = FDCAN_FRAME_FD_NO_BRS; + handle->Init.Mode = FDCAN_MODE_NORMAL; + handle->Init.AutoRetransmission = ENABLE; + handle->Init.TransmitPause = DISABLE; + handle->Init.ProtocolException = DISABLE; + handle->Init.NominalPrescaler = clock_divider; + handle->Init.NominalSyncJumpWidth = max_sync_jump_width; + handle->Init.NominalTimeSeg1 = segment_1_tqs; + handle->Init.NominalTimeSeg2 = segment_2_tqs; + handle->Init.DataPrescaler = clock_divider; + handle->Init.DataSyncJumpWidth = max_sync_jump_width; + handle->Init.DataTimeSeg1 = segment_1_tqs; + handle->Init.DataTimeSeg2 = segment_2_tqs; + handle->Init.StdFiltersNbr = 20; + handle->Init.ExtFiltersNbr = 20; + handle->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; + return HAL_FDCAN_Init(handle); +} + + +/** + * @brief FDCAN MSP Initialization + * This function configures the hardware resources used in this example + * @param hfdcan: FDCAN handle pointer + * @retval None + */ +void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if (hfdcan->Instance == FDCAN1) { + /* Peripheral clock enable */ + __HAL_RCC_FDCAN_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**FDCAN1 GPIO Configuration + PA11 ------> FDCAN1_RX + PA12 ------> FDCAN1_TX + */ + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + // Priority is 0-15 (highest to lowest). Use lowest priority until we + // believe it is too low. + HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 15, 15); + HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn); + } +} + +/** + * @brief FDCAN MSP De-Initialization + * This function freeze the hardware resources used in this example + * @param hfdcan: FDCAN handle pointer + * @retval None + */ +void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* hfdcan) { + if (hfdcan->Instance == FDCAN1) { + /* Peripheral clock disable */ + __HAL_RCC_FDCAN_CLK_DISABLE(); + + /**FDCAN1 GPIO Configuration + PA11 ------> FDCAN1_RX + PA12 ------> FDCAN1_TX + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11 | GPIO_PIN_12); + } +} diff --git a/hepa-uv/firmware/clocking.c b/hepa-uv/firmware/clocking.c new file mode 100644 index 000000000..efe930690 --- /dev/null +++ b/hepa-uv/firmware/clocking.c @@ -0,0 +1,19 @@ +#include "common/firmware/clocking.h" + +#include "common/firmware/errors.h" +#include "stm32g4xx_hal_conf.h" + +void RCC_Peripheral_Clock_Select() { + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + PeriphClkInit.PeriphClockSelection = + RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_FDCAN | RCC_PERIPHCLK_I2C2 | + RCC_PERIPHCLK_I2C3; + PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2; + PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL; + PeriphClkInit.I2c2ClockSelection = RCC_I2C2CLKSOURCE_PCLK1; + PeriphClkInit.I2c3ClockSelection = RCC_I2C3CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { + Error_Handler(); + } +} diff --git a/hepa-uv/firmware/freertos_idle_timer_task.cpp b/hepa-uv/firmware/freertos_idle_timer_task.cpp new file mode 100644 index 000000000..39cf620f8 --- /dev/null +++ b/hepa-uv/firmware/freertos_idle_timer_task.cpp @@ -0,0 +1,42 @@ +/* + * Configuration for the FreeRTOS idle task, which is necessary when we told it + * we're using static allocation. Provides the same configuration as the other + * stacks, but in callback form (vApplicationGetIdleTaskMemory is called by the + * RTOS internals) + */ + +#include + +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" + +StaticTask_t + idle_task_tcb; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +StaticTask_t + idle_timer_tcb; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +std::array + idle_task_stack; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +std::array + idle_timer_stack; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +// This is a callback defined in a C file so it has to be linked as such +extern "C" void vApplicationGetIdleTaskMemory( + StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, + uint32_t *pulIdleTaskStackSize) { + // Same configuration as in the other tasks, but a smaller stack + *ppxIdleTaskTCBBuffer = &idle_task_tcb; + *ppxIdleTaskStackBuffer = idle_task_stack.data(); + *pulIdleTaskStackSize = idle_task_stack.size(); +} + +extern "C" void vApplicationGetTimerTaskMemory( + StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, + uint32_t *pulTimerTaskStackSize) { + *ppxTimerTaskTCBBuffer = &idle_timer_tcb; + *ppxTimerTaskStackBuffer = idle_timer_stack.data(); + *pulTimerTaskStackSize = idle_timer_stack.size(); +} diff --git a/hepa-uv/firmware/i2c_setup.c b/hepa-uv/firmware/i2c_setup.c new file mode 100644 index 000000000..2c31b5e51 --- /dev/null +++ b/hepa-uv/firmware/i2c_setup.c @@ -0,0 +1,173 @@ +#include "hepa-uv/firmware/i2c_setup.h" + +#include "common/firmware/errors.h" +#include "platform_specific_hal_conf.h" + +#define EEPROM_GPIO_BANK GPIOC +#define EEPROM_GPIO_PIN GPIO_PIN_12 + +static I2C_HandleTypeDef hi2c2; +static I2C_HandleTypeDef hi2c3; + +void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + __HAL_RCC_GPIOC_CLK_ENABLE(); + + if (hi2c->Instance == I2C2) { + // PIN PC4 is SCL + // PIN PA8 is SDA + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitStruct.Pin = GPIO_PIN_8; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C2; + HAL_GPIO_Init( + GPIOA, // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + &GPIO_InitStruct); // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + + GPIO_InitStruct.Pin = GPIO_PIN_4; + HAL_GPIO_Init( + GPIOC, // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + &GPIO_InitStruct); // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + __HAL_RCC_I2C2_CLK_ENABLE(); + + HAL_NVIC_SetPriority(I2C2_EV_IRQn, 7, 0); + HAL_NVIC_EnableIRQ(I2C2_EV_IRQn); + HAL_NVIC_SetPriority(I2C2_ER_IRQn, 7, 0); + HAL_NVIC_EnableIRQ(I2C2_ER_IRQn); + } + + if (hi2c->Instance == I2C3) { + // PIN PC8 is SCL + // PIN PC9 is SDA + GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF8_I2C3; + HAL_GPIO_Init( + GPIOC, // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + &GPIO_InitStruct); // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + __HAL_RCC_I2C3_CLK_ENABLE(); + + HAL_NVIC_SetPriority(I2C3_EV_IRQn, 7, 0); + HAL_NVIC_EnableIRQ(I2C3_EV_IRQn); + HAL_NVIC_SetPriority(I2C3_ER_IRQn, 7, 0); + HAL_NVIC_EnableIRQ(I2C3_ER_IRQn); + } +} + +HAL_I2C_HANDLE MX_I2C2_Init() { + hi2c2.Instance = I2C2; + hi2c2.Init.Timing = 0x10C0ECFF; + hi2c2.Init.OwnAddress1 = 0; + hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c2.Init.OwnAddress2 = 0; + hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK; + hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c2) != HAL_OK) { + Error_Handler(); + } + /** Configure Analogue filter + */ + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != + HAL_OK) { + Error_Handler(); + } + /** Configure Digital filter + */ + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK) { + Error_Handler(); + } + return &hi2c2; +} + +HAL_I2C_HANDLE MX_I2C3_Init() { + hi2c3.Instance = I2C3; + hi2c3.Init.Timing = 0x10C0ECFF; + hi2c3.Init.OwnAddress1 = 0; + hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c3.Init.OwnAddress2 = 0; + hi2c3.Init.OwnAddress2Masks = I2C_OA2_NOMASK; + hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c3) != HAL_OK) { + Error_Handler(); + } + /** Configure Analogue filter + */ + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c3, I2C_ANALOGFILTER_ENABLE) != + HAL_OK) { + Error_Handler(); + } + /** Configure Digital filter + */ + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c3, 0) != HAL_OK) { + Error_Handler(); + } + return &hi2c3; +} + +/** + * @brief enable the eeprom write protect pin. + */ +void eeprom_write_protect_init(void) { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + + /*Configure GPIO pin : C12 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = EEPROM_GPIO_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(EEPROM_GPIO_BANK, &GPIO_InitStruct); +} + +/** + * @brief enable writing to the eeprom. + */ +void enable_eeprom_write() { + HAL_GPIO_WritePin(GPIOC, EEPROM_GPIO_PIN, GPIO_PIN_RESET); +} + +/** + * @brief disable writing to the eeprom. + */ +void disable_eeprom_write() { + HAL_GPIO_WritePin(GPIOC, EEPROM_GPIO_PIN, GPIO_PIN_SET); +} + +void i2c_setup(I2CHandlerStruct* i2c_handles) { + HAL_I2C_HANDLE i2c2 = MX_I2C2_Init(); + i2c_handles->i2c2 = i2c2; + HAL_I2C_HANDLE i2c3 = MX_I2C3_Init(); + i2c_handles->i2c3 = i2c3; + eeprom_write_protect_init(); + + // write protect the eeprom. + disable_eeprom_write(); +} + +void I2C2_EV_IRQHandler(void) +{ + HAL_I2C_EV_IRQHandler(&hi2c2); +} + +void I2C2_ER_IRQHandler(void) +{ + HAL_I2C_ER_IRQHandler(&hi2c2); +} + +void I2C3_EV_IRQHandler(void) +{ + HAL_I2C_EV_IRQHandler(&hi2c3); +} + +void I2C3_ER_IRQHandler(void) +{ + HAL_I2C_ER_IRQHandler(&hi2c3); +} diff --git a/hepa-uv/firmware/main_rev1.cpp b/hepa-uv/firmware/main_rev1.cpp new file mode 100644 index 000000000..ccd9e8b13 --- /dev/null +++ b/hepa-uv/firmware/main_rev1.cpp @@ -0,0 +1,70 @@ +#include + +// clang-format off +#include "FreeRTOS.h" +#include "task.h" +#include "system_stm32g4xx.h" +#include "hepa-uv/firmware/i2c_setup.h" +// clang-format on +#pragma GCC diagnostic push +// NOLINTNEXTLINE(clang-diagnostic-unknown-warning-option) +#pragma GCC diagnostic ignored "-Wvolatile" +#include "stm32g4xx_hal.h" +#pragma GCC diagnostic pop + +#include "can/core/bit_timings.hpp" +#include "can/firmware/hal_can.h" +#include "can/firmware/hal_can_bus.hpp" +#include "common/core/app_update.h" +#include "common/firmware/clocking.h" +#include "common/firmware/gpio.hpp" +#include "common/firmware/iwdg.hpp" +#include "common/firmware/utility_gpio.h" +#include "hepa-uv/core/tasks.hpp" +#include "hepa-uv/firmware/utility_gpio.h" + +static auto iWatchdog = iwdg::IndependentWatchDog{}; + +/** + * The can bus. + */ +static auto canbus = can::hal::bus::HalCanBus( + can_get_device_handle(), + gpio::PinConfig{// NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) + .port = LED_DRIVE_PORT, + .pin = LED_DRIVE_PIN, + .active_setting = GPIO_PIN_RESET}); +// Unfortunately, these numbers need to be literals or defines +// to get the compile-time checks to work so we can't actually +// correctly rely on the hal to get these numbers - they need +// to be checked against current configuration. However, they are +// - clock input is 85MHz assuming the CAN is clocked from PCLK1 +// which has a clock divider of 2, and the system clock is 170MHZ +// - 50ns requested time quantum yields a 235ns actual +// - 250KHz bitrate requested yields 250312KHz actual +// - 88.3% sample point +// Should drive +// segment 1 = 73 quanta +// segment 2 = 11 quanta +// +// For the exact timing values these generate see +// can/tests/test_bit_timings.cpp +static constexpr auto can_bit_timings = + can::bit_timings::BitTimings<170 * can::bit_timings::MHZ, 100, + 500 * can::bit_timings::KHZ, 800>{}; + +auto main() -> int { + HardwareInit(); + RCC_Peripheral_Clock_Select(); + utility_gpio_init(); + + app_update_clear_flags(); + + canbus.start(can_bit_timings); + + hepauv_tasks::start_tasks(canbus); + + iWatchdog.start(6); + + vTaskStartScheduler(); +} diff --git a/hepa-uv/firmware/stm32g4xx_hal_conf.h b/hepa-uv/firmware/stm32g4xx_hal_conf.h new file mode 100644 index 000000000..791bd60e6 --- /dev/null +++ b/hepa-uv/firmware/stm32g4xx_hal_conf.h @@ -0,0 +1,396 @@ +/** + ****************************************************************************** + * @file stm32g4xx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32g4xx_hal_conf.h. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32G4xx_HAL_CONF_H +#define STM32G4xx_HAL_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_COMP_MODULE_ENABLED +#define HAL_CORDIC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_FDCAN_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_FMAC_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_HRTIM_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_NAND_MODULE_ENABLED +#define HAL_NOR_MODULE_ENABLED +#define HAL_OPAMP_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_QSPI_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SAI_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_SMBUS_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_SRAM_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED + +/* ########################## Register Callbacks selection + * ############################## */ +/** + * @brief This is the list of modules where register callback can be used + */ + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U +#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U +#define USE_HAL_EXTI_REGISTER_CALLBACKS 0U +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U +#define USE_HAL_FMAC_REGISTER_CALLBACKS 0U +#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U +#define USE_HAL_UART_REGISTER_CALLBACKS 0U +#define USE_HAL_USART_REGISTER_CALLBACKS 0U +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U + +/* ########################## Oscillator Values adaptation + * ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your + * application. This value is used by the RCC HAL module to compute the system + * frequency (when HSE is used as system clock source, directly or through the + * PLL). + */ +#if !defined(HSE_VALUE) +#define HSE_VALUE (16000000UL) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined(HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT (100UL) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system + * frequency (when HSI is used as system clock source, directly or through the + * PLL). + */ +#if !defined(HSI_VALUE) +#define HSI_VALUE (16000000UL) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS and RNG. + * This internal oscillator is mainly dedicated to provide a high + * precision clock to the USB peripheral by means of a special Clock Recovery + * System (CRS) circuitry. When the CRS is not used, the HSI48 RC oscillator + * runs on it default frequency which is subject to manufacturing process + * variations. + */ +#if !defined(HSI48_VALUE) +#define HSI48_VALUE \ + (48000000UL) /*!< Value of the Internal High Speed oscillator for USB \ + FS/RNG in Hz. The real value my vary depending on \ + manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined(LSI_VALUE) +/*!< Value of the Internal Low Speed oscillator in Hz +The real value may vary depending on the variations in voltage and +temperature.*/ +#define LSI_VALUE (32000UL) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system + * frequency + */ +#if !defined(LSE_VALUE) +#define LSE_VALUE (32768UL) /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined(LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT (5000UL) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S and SAI peripherals + * This value is used by the I2S and SAI HAL modules to compute the I2S + * and SAI clock source frequency, this source is inserted directly through + * I2S_CKIN pad. + */ +#if !defined(EXTERNAL_CLOCK_VALUE) +#define EXTERNAL_CLOCK_VALUE \ + (48000UL) /*!< Value of the External clock source in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ + +#define VDD_VALUE (3300UL) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY \ + (0UL) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ + +#define USE_SPI_CRC 1U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32g4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32g4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32g4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32g4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32g4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32g4xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CORDIC_MODULE_ENABLED +#include "stm32g4xx_hal_cordic.h" +#endif /* HAL_CORDIC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32g4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32g4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32g4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32g4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_FDCAN_MODULE_ENABLED +#include "stm32g4xx_hal_fdcan.h" +#endif /* HAL_FDCAN_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32g4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_FMAC_MODULE_ENABLED +#include "stm32g4xx_hal_fmac.h" +#endif /* HAL_FMAC_MODULE_ENABLED */ + +#ifdef HAL_HRTIM_MODULE_ENABLED +#include "stm32g4xx_hal_hrtim.h" +#endif /* HAL_HRTIM_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32g4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32g4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32g4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED +#include "stm32g4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32g4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32g4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32g4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32g4xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32g4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32g4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED +#include "stm32g4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32g4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32g4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED +#include "stm32g4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32g4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED +#include "stm32g4xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32g4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32g4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32g4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32g4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32g4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32g4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) \ + ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions + ------------------------------------------------------- */ +void assert_failed(uint8_t *file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32G4xx_HAL_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hepa-uv/firmware/stm32g4xx_it.c b/hepa-uv/firmware/stm32g4xx_it.c new file mode 100644 index 000000000..ee1a3295b --- /dev/null +++ b/hepa-uv/firmware/stm32g4xx_it.c @@ -0,0 +1,152 @@ +/** + ****************************************************************************** + * @file Templates/Src/stm32g4xx_it.c + * @author MCD Application Team + * @brief Main Interrupt Service Routines. + * This file provides template for all exceptions handler and + * peripherals interrupt service routine. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32g4xx_it.h" + +#include "FreeRTOSConfig.h" +#include "can/firmware/hal_can.h" +#include "stm32g4xx_hal.h" + +/** @addtogroup STM32G4xx_HAL_Examples + * @{ + */ + +/** @addtogroup Templates + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/* External variables --------------------------------------------------------*/ +DMA_HandleTypeDef hdma_spi1_tx; +DMA_HandleTypeDef hdma_spi1_rx; + +/******************************************************************************/ +/* Cortex-M4 Processor Exceptions Handlers */ +/******************************************************************************/ + +/** + * @brief This function handles NMI exception. + * @param None + * @retval None + */ +void NMI_Handler(void) {} + +/** + * @brief This function handles Hard Fault exception. + * @param None + * @retval None + */ +void HardFault_Handler(void) { + /* Go to infinite loop when Hard Fault exception occurs */ + while (1) { + } +} + +/** + * @brief This function handles Memory Manage exception. + * @param None + * @retval None + */ +void MemManage_Handler(void) { + /* Go to infinite loop when Memory Manage exception occurs */ + while (1) { + } +} + +/** + * @brief This function handles Bus Fault exception. + * @param None + * @retval None + */ +void BusFault_Handler(void) { + /* Go to infinite loop when Bus Fault exception occurs */ + while (1) { + } +} + +/** + * @brief This function handles Usage Fault exception. + * @param None + * @retval None + */ +void UsageFault_Handler(void) { + /* Go to infinite loop when Usage Fault exception occurs */ + while (1) { + } +} + +/** + * @brief This function handles Debug Monitor exception. + * @param None + * @retval None + */ +void DebugMon_Handler(void) {} + +/******************************************************************************/ +/* STM32G4xx Peripherals Interrupt Handlers */ +/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ +/* available peripheral interrupt handler's name please refer to the startup */ +/* file (startup_stm32g4xxxx.s). */ +/******************************************************************************/ + +/** + * @brief This function handles PPP interrupt request. + * @param None + * @retval None + */ +/*void PPP_IRQHandler(void) +{ +}*/ +/** + * @brief This function handles DMA1 channel2 global interrupt. + */ + __attribute__((section(".ccmram"))) +void DMA1_Channel2_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_spi1_rx); } + +/** + * @brief This function handles DMA1 channel3 global interrupt. + */ + __attribute__((section(".ccmram"))) +void DMA1_Channel3_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_spi1_tx); } + +/** + * @brief This function handles FDCAN1 interrupt 0. + */ + __attribute__((section(".ccmram"))) +void FDCAN1_IT0_IRQHandler(void) { + HAL_FDCAN_IRQHandler(can_get_device_handle()); +} + +extern void xPortSysTickHandler(void); +void SysTick_Handler(void) { + HAL_IncTick(); + xPortSysTickHandler(); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hepa-uv/firmware/stm32g4xx_it.h b/hepa-uv/firmware/stm32g4xx_it.h new file mode 100644 index 000000000..42e65e4a2 --- /dev/null +++ b/hepa-uv/firmware/stm32g4xx_it.h @@ -0,0 +1,53 @@ +/** + ****************************************************************************** + * @file Templates/Inc/stm32g4xx_it.h + * @author MCD Application Team + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32G4xx_IT_H +#define STM32G4xx_IT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macros -----------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); +void DMA1_Channel2_IRQHandler(void); +void DMA1_Channel3_IRQHandler(void); +void FDCAN1_IT0_IRQHandler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* STM32G4xx_IT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hepa-uv/firmware/system_stm32g4xx.c b/hepa-uv/firmware/system_stm32g4xx.c new file mode 100644 index 000000000..8c35abc77 --- /dev/null +++ b/hepa-uv/firmware/system_stm32g4xx.c @@ -0,0 +1,342 @@ +/** + ****************************************************************************** + * @file system_stm32g4xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32g4xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be + *used by the user application to setup the SysTick timer or configure other + *parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * After each device reset the HSI (16 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32g4xx.s" file, to + * configure the system clock before to branch to main program. + * + * This file configures the system clock as follows: + *============================================================================= + *----------------------------------------------------------------------------- + * System Clock source | HSI + *----------------------------------------------------------------------------- + * SYSCLK(Hz) | 16000000 + *----------------------------------------------------------------------------- + * HCLK(Hz) | 16000000 + *----------------------------------------------------------------------------- + * AHB Prescaler | 1 + *----------------------------------------------------------------------------- + * APB1 Prescaler | 1 + *----------------------------------------------------------------------------- + * APB2 Prescaler | 1 + *----------------------------------------------------------------------------- + * PLL_M | 1 + *----------------------------------------------------------------------------- + * PLL_N | 16 + *----------------------------------------------------------------------------- + * PLL_P | 7 + *----------------------------------------------------------------------------- + * PLL_Q | 2 + *----------------------------------------------------------------------------- + * PLL_R | 2 + *----------------------------------------------------------------------------- + * Require 48MHz for RNG | Disabled + *----------------------------------------------------------------------------- + *============================================================================= + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32g4xx_system + * @{ + */ + +/** @addtogroup STM32G4xx_System_Private_Includes + * @{ + */ + +#include "system_stm32g4xx.h" + +#include "stm32g4xx.h" +#include "stm32g4xx_hal.h" + +#include "common/firmware/errors.h" +#include "bootloader/firmware/constants.h" + +#if !defined(HSE_VALUE) +#define HSE_VALUE 16000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined(HSI_VALUE) +#define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_Defines + * @{ + */ + +/** + * The vector table is offset by the space reserved for our bootloader. This must + * align with the value in the linker script. + */ +#define VECT_TAB_OFFSET APP_OFFSET + +/******************************************************************************/ +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_Variables + * @{ + */ +/* The SystemCoreClock variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock + frequency Note: If you use this function to configure the system clock; then + there is no need to call the 2 first functions listed above, since + SystemCoreClock variable is updated automatically. +*/ +uint32_t SystemCoreClock = HSE_VALUE; + +const uint8_t AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, + 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U}; +const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U}; + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system. + * @param None + * @retval None + */ + +void SystemInit(void) { +/* FPU settings ------------------------------------------------------------*/ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << (10 * 2)) | + (3UL << (11 * 2))); /* set CP10 and CP11 Full Access */ +#endif + + /* Configure the Vector Table location add offset address + * ------------------*/ +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | + VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#else + SCB->VTOR = FLASH_BASE | + VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +#endif +} + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * System Clock source = PLL (HSE) + * SYSCLK(Hz) = 72000000 + * HCLK(Hz) = 72000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 2 + * APB2 Prescaler = 1 + * HSE Frequency(Hz) = 8000000 + * PREDIV = RCC_PREDIV_DIV1 (1) + * PLLMUL = RCC_PLL_MUL9 (9) + * Flash Latency(WS) = 2 + * @param None + * @retval None + */ +void SystemClock_Config(void) { + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + /** Configure the main internal regulator output voltage + */ + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.HSIState = RCC_HSI_OFF; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4; + RCC_OscInitStruct.PLL.PLLN = 85; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | + RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); + PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or + * configure other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any + * configuration based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the + * HSI_VALUE(**) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the + * HSE_VALUE(***) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the + * HSE_VALUE(***) or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (**) HSI_VALUE is a constant defined in stm32g4xx_hal.h file (default + * value 16 MHz) but the real value may vary depending on the variations in + * voltage and temperature. + * + * (***) HSE_VALUE is a constant defined in stm32g4xx_hal.h file + * (default value 24 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using + * fractional value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) { + uint32_t tmp, pllvco, pllr, pllsource, pllm; + + /* Get SYSCLK source + * -------------------------------------------------------*/ + switch (RCC->CFGR & RCC_CFGR_SWS) { + case 0x04: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + + case 0x08: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + + case 0x0C: /* PLL used as system clock source */ + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); + pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> 4) + 1U; + if (pllsource == 0x02UL) /* HSI used as PLL clock source */ + { + pllvco = (HSI_VALUE / pllm); + } else /* HSE used as PLL clock source */ + { + pllvco = (HSE_VALUE / pllm); + } + pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 8); + pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 25) + 1U) * 2U; + SystemCoreClock = pllvco / pllr; + break; + + default: + break; + } + /* Compute HCLK clock frequency + * --------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; +} + +void HardwareInit(void) { + HAL_Init(); + SystemClock_Config(); + SystemCoreClockUpdate(); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hepa-uv/firmware/system_stm32g4xx.h b/hepa-uv/firmware/system_stm32g4xx.h new file mode 100644 index 000000000..106ecdec0 --- /dev/null +++ b/hepa-uv/firmware/system_stm32g4xx.h @@ -0,0 +1,108 @@ +/** + ****************************************************************************** + * @file system_stm32g4xx.h + * @author MCD Application Team + * @brief CMSIS Cortex-M4 Device System Source File for STM32G4xx devices. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32g4xx_system + * @{ + */ + +/** + * @brief Define to prevent recursive inclusion + */ +#include + +#ifndef __SYSTEM_STM32G4XX_H +#define __SYSTEM_STM32G4XX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup STM32G4xx_System_Includes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Exported_Variables + * @{ + */ +/* The SystemCoreClock variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetSysClockFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock + frequency Note: If you use this function to configure the system clock; then + there is no need to call the 2 first functions listed above, since + SystemCoreClock variable is updated automatically. +*/ +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + +extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */ +extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Exported_Functions + * @{ + */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +void HardwareInit(void); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__SYSTEM_STM32G4XX_H */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hepa-uv/firmware/utility_gpio.c b/hepa-uv/firmware/utility_gpio.c new file mode 100644 index 000000000..c4a8f0fb4 --- /dev/null +++ b/hepa-uv/firmware/utility_gpio.c @@ -0,0 +1,110 @@ +#include "hepa-uv/firmware/utility_gpio.h" + +#include "platform_specific_hal_conf.h" +#include "stm32g4xx_hal_gpio.h" + +/** + * @brief LED Drive Initialization Function + * @param None + * @retval None +*/ +void LED_drive_gpio_init() { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + /*Configure GPIO pin LED_DRIVE : PA1 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = LED_DRIVE_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LED_DRIVE_PORT, &GPIO_InitStruct); +} + +/** + * @brief Door Open GPIO Initialization Function + * @param None + * @retval None +*/ +void door_open_input_gpio_init() { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + /*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.Pull = GPIO_NOPULL; + HAL_GPIO_Init(DOOR_OPEN_MCU_PORT, &GPIO_InitStruct); +} + +/** + * @brief Reed Switch GPIO Initialization Function + * @param None + * @retval None +*/ +void reed_switch_input_gpio_init() { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + /*Configure GPIO pin DOOR_OPEN_MCU : PC11 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = REED_SW_MCU_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(REED_SW_MCU_PORT, &GPIO_InitStruct); +} + +/** + * @brief AUX ID Initialization Function + * @param None + * @retval None +*/ +void aux_input_gpio_init(void) { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOB_CLK_ENABLE(); + /*Configure GPIO pin AUX_ID_MCU : PC12 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = AUX_ID_MCU_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + HAL_GPIO_Init(AUX_ID_MCU_PORT, &GPIO_InitStruct); +} + +/** + * @brief Hepa Push Button GPIO Initialization Function + * @param None + * @retval None +*/ +void hepa_push_button_input_gpio_init(void) { + /*Configure Ports Clock Enable*/ + __HAL_RCC_GPIOB_CLK_ENABLE(); + /*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.Pull = GPIO_NOPULL; + HAL_GPIO_Init(HEPA_NO_MCU_PORT, &GPIO_InitStruct); +} + +/** + * @brief UV Push Button GPIO Initialization Function + * @param None + * @retval None +*/ +void uv_push_button_gpio_init(void) { + /*Configure Ports Clock Enable*/ + __HAL_RCC_GPIOB_CLK_ENABLE(); + /*Configure GPIO pin UV_NO_MCU : PC2 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = UV_NO_MCU_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(UV_NO_MCU_PORT, &GPIO_InitStruct); +} + +void utility_gpio_init(void) { + LED_drive_gpio_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(); +} diff --git a/hepa-uv/simulator/CMakeLists.txt b/hepa-uv/simulator/CMakeLists.txt new file mode 100644 index 000000000..9634114b8 --- /dev/null +++ b/hepa-uv/simulator/CMakeLists.txt @@ -0,0 +1,62 @@ +# Load free for the posix port +find_package(FreeRTOS) + +# Set up the include directories +include_directories( + . + ${CMAKE_CURRENT_SOURCE_DIR}/../../include + ${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/include + ${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/portable/ThirdParty/GCC/Posix + ${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/utils + +) + +# Create the FreeRTOS source file list +FILE( + GLOB FREERTOS_SOURCES + ${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/*.c +) + +# Add the posix port files +list(APPEND FREERTOS_SOURCES "${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/portable/MemMang/heap_3.c") +list(APPEND FREERTOS_SOURCES "${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c") +list(APPEND FREERTOS_SOURCES "${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/port.c") + + +# Create the freertos lib +add_library(freertos-hepa-uv STATIC ${FREERTOS_SOURCES}) + +set(HEPA_UV_SIMULATOR_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/freertos_idle_timer_task.cpp + ) + +add_executable( + hepa-uv-simulator + ${HEPA_UV_SIMULATOR_SRC} +) + +add_revision(TARGET hepa-uv-simulator REVISION a1) + + +if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux" AND DEFINED ENV{USE_SOCKETCAN}) + target_compile_definitions(hepa-uv-simulator PUBLIC USE_SOCKETCAN) +endif () + +target_compile_definitions(hepa-uv-simulator PUBLIC ENABLE_LOGGING) + +target_can_simlib(hepa-uv-simulator) + +target_hepa_uv_core(hepa-uv-simulator) + +target_ot_motor_control(hepa-uv-simulator) + +target_i2c_simlib(hepa-uv-simulator) + +target_link_libraries(hepa-uv-simulator PRIVATE can-core common-simulation freertos-hepa-uv pthread Boost::boost Boost::program_options state_manager) + +set_target_properties(hepa-uv-simulator + PROPERTIES CXX_STANDARD 20 + CXX_STANDARD_REQUIRED TRUE + C_STANDARD 11 + C_STANDARD_REQUIRED TRUE) diff --git a/hepa-uv/simulator/FreeRTOSConfig.h b/hepa-uv/simulator/FreeRTOSConfig.h new file mode 100644 index 000000000..ea2403deb --- /dev/null +++ b/hepa-uv/simulator/FreeRTOSConfig.h @@ -0,0 +1,182 @@ +/* + * FreeRTOS Kernel V10.0.1 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +/** + * This file is only present to support the FreeRTOS POSIX Port. + * + * TODO (AmitL, 2021-08-17): This file is entirely lifted from our FW projects. + * It should be specialized for the POSIX port. + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * this is a template configuration files + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * These parameters and more are described within the 'configuration' section of + *the FreeRTOS API documentation available on the FreeRTOS.org web site. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* Ensure stdint is only used by the compiler, and not the assembler. */ +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) +#include +extern uint32_t SystemCoreClock; +#endif + +/* CMSIS-RTOSv2 defines 56 levels of priorities. To be able to use them + * all and avoid application misbehavior, + * configUSE_PORT_OPTIMISED_TASK_SELECTION must be set to 0 and + * configMAX_PRIORITIES to 56 + * + */ +/* #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0*/ +/* #define configMAX_PRIORITIES ( 56 ) */ +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configMAX_PRIORITIES (7) +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configCPU_CLOCK_HZ (SystemCoreClock) +#define configTICK_RATE_HZ ((TickType_t)1000) +#define configMINIMAL_STACK_SIZE ((uint16_t)128) +#define configTOTAL_HEAP_SIZE ((size_t)(64 * 1024)) +#define configMAX_TASK_NAME_LEN (16) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configGENERATE_RUN_TIME_STATS 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 8 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES (2) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (6) +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 0 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 + +/*------------- CMSIS-RTOS V2 specific defines -----------*/ +/* When using CMSIS-RTOSv2 set configSUPPORT_STATIC_ALLOCATION to 1 + * is mandatory to avoid compile errors. + * CMSIS-RTOS V2 implmentation requires the following defines + * +#define configSUPPORT_STATIC_ALLOCATION 1 <-- cmsis_os threads are +created using xTaskCreateStatic() API #define configMAX_PRIORITIES (56) <-- +Priority range in CMSIS-RTOS V2 is [0 .. 56] #define +configUSE_PORT_OPTIMISED_TASK_SELECTION 0 <-- when set to 1, +configMAX_PRIORITIES can't be more than 32 which is not suitable for the new +CMSIS-RTOS v2 priority range +*/ + +/* the CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation +used + * by the application thus the correct define need to be enabled from the list + * below + * +//define USE_FreeRTOS_HEAP_1 +//define USE_FreeRTOS_HEAP_2 +//define USE_FreeRTOS_HEAP_3 +//define USE_FreeRTOS_HEAP_4 +//define USE_FreeRTOS_HEAP_5 +*/ + +/* Cortex-M specific definitions. */ +#ifdef __NVIC_PRIO_BITS +/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ +#define configPRIO_BITS __NVIC_PRIO_BITS +#else +#define configPRIO_BITS 4 /* 15 priority levels */ +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" +function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY \ + (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY \ + (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +#define configASSERT(x) \ + if ((x) == 0) { \ + taskDISABLE_INTERRUPTS(); \ + for (;;) \ + ; \ + } + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS + standard names. */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler + +/* IMPORTANT: FreeRTOS is using the SysTick as internal time base, thus make + sure the system and peripherials are using a different time base (TIM based + for example). + */ +#define xPortSysTickHandler SysTick_Handler + +#endif /* FREERTOS_CONFIG_H */ diff --git a/hepa-uv/simulator/freertos_idle_timer_task.cpp b/hepa-uv/simulator/freertos_idle_timer_task.cpp new file mode 100644 index 000000000..87b80a629 --- /dev/null +++ b/hepa-uv/simulator/freertos_idle_timer_task.cpp @@ -0,0 +1,43 @@ +/* + * Configuration for the FreeRTOS idle task, which is necessary when we told it + * we're using static allocation. Provides the same configuration as the other + * stacks, but in callback form (vApplicationGetIdleTaskMemory is called by the + * RTOS internals) + * + * This file is only present to support the FreeRTOS POSIX Port. + */ + +#include + +#include "FreeRTOS.h" +#include "task.h" + +StaticTask_t + idle_task_tcb; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +std::array + idle_task_stack; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +StaticTask_t + timer_task_tcb; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +std::array + timer_task_stack; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +// This is a callback defined in a C file so it has to be linked as such +extern "C" void vApplicationGetIdleTaskMemory( + StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, + uint32_t *pulIdleTaskStackSize) { + // Same configuration as in the other tasks, but a smaller stack + *ppxIdleTaskTCBBuffer = &idle_task_tcb; + *ppxIdleTaskStackBuffer = idle_task_stack.data(); + *pulIdleTaskStackSize = idle_task_stack.size(); +} + +extern "C" void vApplicationGetTimerTaskMemory( + StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, + uint32_t *pulTimerTaskStackSize) { + *ppxTimerTaskTCBBuffer = &timer_task_tcb; + *ppxTimerTaskStackBuffer = timer_task_stack.data(); + *pulTimerTaskStackSize = timer_task_stack.size(); +} diff --git a/hepa-uv/simulator/main.cpp b/hepa-uv/simulator/main.cpp new file mode 100644 index 000000000..1902098d1 --- /dev/null +++ b/hepa-uv/simulator/main.cpp @@ -0,0 +1,86 @@ +#include + +#include +#include +#include + +#include "FreeRTOS.h" +#include "boost/program_options.hpp" +#include "can/simlib/sim_canbus.hpp" +#include "common/core/freertos_synchronization.hpp" +#include "common/core/freertos_task.hpp" +#include "common/simulation/state_manager.hpp" +#include "hepa-uv/core/tasks.hpp" +#include "task.h" + +namespace po = boost::program_options; + +void signal_handler(int signum) { + LOG("Interrupt signal (%d) received.", signum); + exit(signum); +} + +/** + * The CAN bus. + */ + +static std::shared_ptr> + state_manager_connection; + +static auto state_manager_task = state_manager::StateManagerTask< + freertos_synchronization::FreeRTOSCriticalSection>{}; + +static auto state_manager_task_control = + freertos_task::FreeRTOSTask<512, decltype(state_manager_task)>{ + state_manager_task}; + +auto handle_options(int argc, char** argv) -> po::variables_map { + auto cmdlinedesc = + po::options_description("simulator for the Flex HEPA/UV module."); + auto envdesc = po::options_description(""); + cmdlinedesc.add_options()("help,h", "Show this help message."); + auto can_arg_xform = can::sim::transport::add_options(cmdlinedesc, envdesc); + auto state_mgr_arg_xform = state_manager::add_options(cmdlinedesc, envdesc); + + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, cmdlinedesc), vm); + if (vm.count("help")) { + std::cout << cmdlinedesc << std::endl; + std::exit(0); + } + po::store(po::parse_environment( + envdesc, + [can_arg_xform, state_mgr_arg_xform]( + const std::string& input_val) -> std::string { + auto can_xformed = can_arg_xform(input_val); + if (can_xformed != "") { + return can_xformed; + } + auto state_mgr_xformed = state_mgr_arg_xform(input_val); + return state_mgr_xformed; + }), + vm); + po::notify(vm); + return vm; +} + +int main(int argc, char** argv) { + signal(SIGINT, signal_handler); + + LOG_INIT("HEPA/UV", []() -> const char* { + return pcTaskGetName(xTaskGetCurrentTaskHandle()); + }); + auto options = handle_options(argc, argv); + + state_manager_connection = state_manager::create< + freertos_synchronization::FreeRTOSCriticalSection>(options); + state_manager_task_control.start(5, "state mgr task", + &state_manager_connection); + + static auto canbus = + can::sim::bus::SimCANBus(can::sim::transport::create(options)); + hepauv_tasks::start_tasks(canbus); + + vTaskStartScheduler(); +} diff --git a/hepa-uv/tests/CMakeLists.txt b/hepa-uv/tests/CMakeLists.txt new file mode 100644 index 000000000..97a2bcba0 --- /dev/null +++ b/hepa-uv/tests/CMakeLists.txt @@ -0,0 +1,40 @@ +# this CMakeLists.txt file is only used when host-compiling to build tests + +find_package(Catch2 REQUIRED) +include(CTest) +include(Catch) +include(AddBuildAndTestTarget) + +add_executable( + hepa-uv + test_main.cpp + test_leds.cpp +) + +target_include_directories(hepa-uv PUBLIC ${CMAKE_SOURCE_DIR}/include) +set_target_properties(hepa-uv + PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED TRUE) + +target_compile_options(hepa-uv + PUBLIC + -Wall + -Werror + -Wextra + -Wno-missing-field-initializers + $<$:-Weffc++> + $<$:-Wreorder> + $<$:-Wsign-promo> + $<$:-Wextra-semi> + $<$:-Wctor-dtor-privacy> + $<$:-fno-rtti> +) +add_revision(TARGET hepa-uv REVISION b1) + +target_link_libraries(hepa-uv Catch2::Catch2) + +catch_discover_tests(hepa-uv) +add_build_and_test_target(hepa-uv) + +add_coverage(hepa-uv) diff --git a/hepa-uv/tests/test_leds.cpp b/hepa-uv/tests/test_leds.cpp new file mode 100644 index 000000000..cf8dc1ed1 --- /dev/null +++ b/hepa-uv/tests/test_leds.cpp @@ -0,0 +1,4 @@ +#include "catch2/catch.hpp" + +// Just a dummy test case for CI. +TEST_CASE("Holder Test Case") { REQUIRE(true); } \ No newline at end of file diff --git a/hepa-uv/tests/test_main.cpp b/hepa-uv/tests/test_main.cpp new file mode 100644 index 000000000..62bf7476a --- /dev/null +++ b/hepa-uv/tests/test_main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch2/catch.hpp" diff --git a/include/bootloader/core/ids.h b/include/bootloader/core/ids.h index 71ee3a3dc..6bc462a0e 100644 --- a/include/bootloader/core/ids.h +++ b/include/bootloader/core/ids.h @@ -124,12 +124,14 @@ typedef enum { can_nodeid_gripper = 0x20, can_nodeid_gripper_z = 0x21, can_nodeid_gripper_g = 0x22, + can_nodeid_hepa_uv = 0x32, can_nodeid_pipette_left_bootloader = 0x6f, can_nodeid_pipette_right_bootloader = 0x7f, can_nodeid_gantry_x_bootloader = 0x3f, can_nodeid_gantry_y_bootloader = 0x4f, can_nodeid_head_bootloader = 0x5f, can_nodeid_gripper_bootloader = 0x2f, + can_nodeid_hepa_uv_bootloader = 0x3e, } CANNodeId; /** Common error codes. */ diff --git a/include/can/core/ids.hpp b/include/can/core/ids.hpp index 3633df880..4f51179ae 100644 --- a/include/can/core/ids.hpp +++ b/include/can/core/ids.hpp @@ -126,12 +126,14 @@ enum class NodeId { gripper = 0x20, gripper_z = 0x21, gripper_g = 0x22, + hepa_uv = 0x32, pipette_left_bootloader = 0x6f, pipette_right_bootloader = 0x7f, gantry_x_bootloader = 0x3f, gantry_y_bootloader = 0x4f, head_bootloader = 0x5f, gripper_bootloader = 0x2f, + hepa_uv_bootloader = 0x3e, }; /** Common error codes. */ diff --git a/include/hepa-uv/core/can_task.hpp b/include/hepa-uv/core/can_task.hpp new file mode 100644 index 000000000..9c6e01a09 --- /dev/null +++ b/include/hepa-uv/core/can_task.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include "can/core/freertos_can_dispatch.hpp" +#include "can/core/message_handlers/system.hpp" +#include "common/core/freertos_message_queue.hpp" +#include "hepa-uv/core/tasks.hpp" + +namespace can_task { + +using namespace hepauv_tasks; + +using SystemDispatchTarget = can::dispatch::DispatchParseTarget< + can::message_handlers::system::SystemMessageHandler< + hepauv_tasks::QueueClient>, + can::messages::DeviceInfoRequest, can::messages::InitiateFirmwareUpdate, + can::messages::FirmwareUpdateStatusRequest, can::messages::TaskInfoRequest>; + +auto constexpr reader_message_buffer_size = 1024; + +struct CanMessageReaderTask { + [[noreturn]] void operator()(can::bus::CanBus* can_bus); +}; + +/** + * Create the can message reader task. + * + * @param canbus reference to the can bus + * @return The task. + */ +auto start_reader(can::bus::CanBus& canbus) -> CanMessageReaderTask&; + +using CanMessageWriterTask = can::message_writer_task::MessageWriterTask< + freertos_message_queue::FreeRTOSMessageQueue>; + +/** + * Create the can message writer task. + * + * @param canbus reference to the can bus + * @return The task. + */ +auto start_writer(can::bus::CanBus& canbus) -> CanMessageWriterTask&; + +} // namespace can_task diff --git a/include/hepa-uv/core/tasks.hpp b/include/hepa-uv/core/tasks.hpp new file mode 100644 index 000000000..bcff5abb6 --- /dev/null +++ b/include/hepa-uv/core/tasks.hpp @@ -0,0 +1,41 @@ +#pragma once +#include "can/core/message_writer.hpp" +#include "common/core/freertos_timer.hpp" + +namespace hepauv_tasks { + +/** + * Start hepa-uv tasks. + */ +void start_tasks(can::bus::CanBus& can_bus); + +/** + * Access to all the message queues in the system. + */ +struct QueueClient : can::message_writer::MessageWriter { + QueueClient(can::ids::NodeId this_fw); +}; + +/** + * Access to all tasks in the system. + */ +struct AllTask { + can::message_writer_task::MessageWriterTask< + freertos_message_queue::FreeRTOSMessageQueue>* can_writer{nullptr}; +}; + +/** + * Access to the tasks singleton + * @return + */ +[[nodiscard]] auto get_all_tasks() -> AllTask&; + +/** + * Access to the queues singleton + * @return + */ +[[nodiscard]] auto get_main_queues() -> QueueClient&; + +[[nodiscard]] auto get_queues() -> QueueClient&; + +} // namespace hepauv_tasks diff --git a/include/hepa-uv/firmware/gpio_drive_hardware.hpp b/include/hepa-uv/firmware/gpio_drive_hardware.hpp new file mode 100644 index 000000000..65e621219 --- /dev/null +++ b/include/hepa-uv/firmware/gpio_drive_hardware.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "common/firmware/gpio.hpp" + +namespace gpio_drive_hardware { + +struct GpioDrivePins { + gpio::PinConfig push_button_led; + gpio::PinConfig push_button; + gpio::PinConfig reed_switch; + gpio::PinConfig door_open; +}; + +} // namespace gpio_drive_hardware \ No newline at end of file diff --git a/include/hepa-uv/firmware/i2c_setup.h b/include/hepa-uv/firmware/i2c_setup.h new file mode 100644 index 000000000..ebeef3e92 --- /dev/null +++ b/include/hepa-uv/firmware/i2c_setup.h @@ -0,0 +1,27 @@ +#pragma once +#include "i2c/firmware/i2c.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +typedef struct HandlerStruct { + HAL_I2C_HANDLE i2c2; + HAL_I2C_HANDLE i2c3; +} I2CHandlerStruct; + +void i2c_setup(I2CHandlerStruct* i2c_handles); + +/** + * enable writing to the eeprom. + */ +void enable_eeprom_write(); + +/** + * disable writing to the eeprom. + */ +void disable_eeprom_write(); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/include/hepa-uv/firmware/utility_gpio.h b/include/hepa-uv/firmware/utility_gpio.h new file mode 100644 index 000000000..a3c03f136 --- /dev/null +++ b/include/hepa-uv/firmware/utility_gpio.h @@ -0,0 +1,97 @@ +#pragma once +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void utility_gpio_init(); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +/* The Following variables sometimes complain since some are unused + * some are only used in the c side or just the c++ + */ + +#pragma GCC diagnostic push +// NOLINTNEXTLINE(clang-diagnostic-unknown-warning-option) +#pragma GCC diagnostic ignored "-Wunused-variable" + + +/* ---- Generic Pins ---- */ + +// LED_DRIVE PA1 +#define LED_DRIVE_PORT GPIOA +#define LED_DRIVE_PIN GPIO_PIN_1 +#define LED_DRIVE_AS GPIO_PIN_SET +// DOOR_OPEN_MCU PC7 +#define DOOR_OPEN_MCU_PORT GPIOC +#define DOOR_OPEN_MCU_PIN GPIO_PIN_7 +#define DOOR_OPEN_MCU_AS GPIO_PIN_SET +// REED_SW_MCU PC11 +#define REED_SW_MCU_PORT GPIOC +#define REED_SW_MCU_PIN GPIO_PIN_11 +#define REED_SW_MCU_AS GPIO_PIN_SET +// AUX_ID_MCU PC12 +#define AUX_ID_MCU_PORT GPIOC +#define AUX_ID_MCU_PIN GPIO_PIN_12 +// CAN_RXD + + +/* ---- Hepa Pins ---- */ + +// HEPA_NO_MCU PB10 +#define HEPA_NO_MCU_PORT GPIOB +#define HEPA_NO_MCU_PIN GPIO_PIN_10 +// HEPA_FG_MCU PA5 +#define HEPA_FG_MCU_PORT GPIOA +#define HEPA_FG_MCU_PIN GPIO_PIN_5 +// HEPA_PWM PA6 +#define HEPA_PWM_PORT GPIOA +#define HEPA_PWM_PIN GPIO_PIN_6 +// HEPA_ON/OFF PA7 +#define HEPA_ON_OFF_PORT GPIOA +#define HEPA_ON_OFF_PIN GPIO_PIN_7 +// HEPA_R_CTRL PA9 +#define HEPA_R_CTRL_PORT GPIOA +#define HEPA_R_CTRL_PIN GPIO_PIN_9 +// HEPA_W_CTRL PA10 +#define HEPA_W_CTRL_PORT GPIOA +#define HEPA_W_CTRL_PIN GPIO_PIN_10 +// HEPA_G_CTRL PC6 +#define HEPA_G_CTRL_PORT GPIOC +#define HEPA_G_CTRL_PIN GPIO_PIN_6 +// HEPA_B_CTRL PB4 +#define HEPA_B_CTRL_PORT GPIOB +#define HEPA_B_CTRL_PIN GPIO_PIN_4 + + +/* ---- UV Pins ---- */ + +// UV_SNS_MCU PA0 +#define UV_SNS_MCU_PORT GPIOA +#define UV_SNS_MCU_PIN GPIO_PIN_0 +// UV_ON_OFF_MCU PA4 +#define UV_ON_OFF_MCU_PORT GPIOA +#define UV_ON_OFF_MCU_PIN GPIO_PIN_4 +// UV_NO_MCU PC2 +#define UV_NO_MCU_PORT GPIOC +#define UV_NO_MCU_PIN GPIO_PIN_2 +// UV_ADC PA3 +#define UV_ADC_PORT GPIOC +#define UV_ADC_PIN GPIO_PIN_3 +// UV_B_CTRL PC5 +#define UV_B_CTRL_PORT GPIOC +#define UV_B_CTRL_PIN GPIO_PIN_5 +// UV_G_CTRL PB0 +#define UV_G_CTRL_PORT GPIOB +#define UV_G_CTRL_PIN GPIO_PIN_0 +// UV_R_CTRL PB1 +#define UV_R_CTRL_PORT GPIOB +#define UV_R_CTRL_PIN GPIO_PIN_1 +// UV_W_CTRL PB2 +#define UV_W_CTRL_PORT GPIOB +#define UV_W_CTRL_PIN GPIO_PIN_2 \ No newline at end of file diff --git a/motor-control/firmware/stepper_motor/motor_hardware.cpp b/motor-control/firmware/stepper_motor/motor_hardware.cpp index ec422b22b..412175689 100644 --- a/motor-control/firmware/stepper_motor/motor_hardware.cpp +++ b/motor-control/firmware/stepper_motor/motor_hardware.cpp @@ -23,6 +23,7 @@ void MotorHardware::activate_motor() { void MotorHardware::deactivate_motor() { if (pins.ebrake.has_value()) { gpio::set(pins.ebrake.value()); + motor_hardware_delay(10); } motor_hardware_delay(10); gpio::reset(pins.enable);