diff --git a/config/mbed_app.json b/config/mbed_app.json index 952996d9ef..8e56ae60fc 100644 --- a/config/mbed_app.json +++ b/config/mbed_app.json @@ -4,6 +4,10 @@ "USE_HAL_JPEG_REGISTER_CALLBACKS": { "macro_name": "USE_HAL_JPEG_REGISTER_CALLBACKS", "value": "1U" + }, + "USE_HAL_TIM_REGISTER_CALLBACKS": { + "macro_name": "USE_HAL_TIM_REGISTER_CALLBACKS", + "value": "1U" } }, "target_overrides": { diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 4282cae5cf..daa3090cc5 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory(${DRIVERS_DIR}/CoreBufferedSerial) add_subdirectory(${DRIVERS_DIR}/CoreEventFlags) add_subdirectory(${DRIVERS_DIR}/CoreEventQueue) +add_subdirectory(${DRIVERS_DIR}/CoreDAC) add_subdirectory(${DRIVERS_DIR}/CoreI2C) add_subdirectory(${DRIVERS_DIR}/CoreInterruptIn) add_subdirectory(${DRIVERS_DIR}/CoreLL) diff --git a/drivers/CoreDAC/CMakeLists.txt b/drivers/CoreDAC/CMakeLists.txt new file mode 100644 index 0000000000..c50cf4348a --- /dev/null +++ b/drivers/CoreDAC/CMakeLists.txt @@ -0,0 +1,27 @@ +# Leka - LekaOS +# Copyright 2024 APF France handicap +# SPDX-License-Identifier: Apache-2.0 + +add_library(CoreDAC STATIC) + +target_include_directories(CoreDAC + PUBLIC + include +) + +target_sources(CoreDAC + PRIVATE + source/CoreSTM32HalBasicTimer.cpp +) + +if(NOT(${CMAKE_PROJECT_NAME} STREQUAL "LekaOSUnitTests")) + target_sources(CoreDAC + PUBLIC + source/HAL_IRQHandlers.cpp + ) +endif() + +target_link_libraries(CoreDAC + mbed-os + CoreSTM32Hal +) diff --git a/drivers/CoreDAC/include/CoreSTM32HalBasicTimer.h b/drivers/CoreDAC/include/CoreSTM32HalBasicTimer.h new file mode 100644 index 0000000000..b389ad6d4e --- /dev/null +++ b/drivers/CoreDAC/include/CoreSTM32HalBasicTimer.h @@ -0,0 +1,41 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +#include "interface/drivers/STM32HalBasicTimer.h" + +namespace leka { + +class CoreSTM32HalBasicTimer : public interface::STM32HalBasicTimer +{ + static constexpr float DEFAULT_AUDIO_FILE_SAMPLE_RATE = 44'100; + + public: + CoreSTM32HalBasicTimer(interface::STM32Hal &hal); + + [[nodiscard]] auto getHandle() -> TIM_HandleTypeDef & final; + + void registerCallback(std::function const &callback); + void linkDACTimer(DAC_ChannelConfTypeDef *config) final; + + void initialize(float frequency = DEFAULT_AUDIO_FILE_SAMPLE_RATE) final; + void terminate() final; + + void start() final; + void stop() final; + + private: + void _registerMspCallbacks(); + + interface::STM32Hal &_hal; + + TIM_HandleTypeDef _htim {}; + + std::function _callback {}; +}; + +} // namespace leka diff --git a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp new file mode 100644 index 0000000000..bb54da1113 --- /dev/null +++ b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp @@ -0,0 +1,86 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#include "CoreSTM32HalBasicTimer.h" +#include + +using namespace leka; + +CoreSTM32HalBasicTimer::CoreSTM32HalBasicTimer(interface::STM32Hal &hal) : _hal(hal) +{ + _htim.Instance = TIM6; +} + +auto CoreSTM32HalBasicTimer::getHandle() -> TIM_HandleTypeDef & +{ + return _htim; +} + +void CoreSTM32HalBasicTimer::registerCallback(std::function const &callback) +{ + _callback = callback; +} + +void CoreSTM32HalBasicTimer::initialize(float frequency) +{ + _registerMspCallbacks(); + + // CK_Timer = CK_INT / ((Prescaler + 1) * (Period + 1)) + const auto CK_INT = float {108'000'000.0}; + auto divider = static_cast(std::round(CK_INT / frequency)); + + _htim.Init.Prescaler = 0; + _htim.Init.Period = divider - 1; // ? min 1 + _htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + _hal.HAL_TIM_Base_Init(&_htim); + + auto timerMasterConfig = TIM_MasterConfigTypeDef {}; + timerMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; + _hal.HAL_TIMEx_MasterConfigSynchronization(&_htim, &timerMasterConfig); + + static const auto &self = *this; + _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_PERIOD_ELAPSED_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { + if (self._callback != nullptr) { + self._callback(); + } + }); +} + +void CoreSTM32HalBasicTimer::_registerMspCallbacks() +{ + static const auto &self = *this; + + _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_BASE_MSPINIT_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { + self._hal.HAL_RCC_TIM6_CLK_ENABLE(); + + self._hal.HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0x00, 0x00); + self._hal.HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); + }); + + _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_BASE_MSPDEINIT_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { + self._hal.HAL_RCC_TIM6_CLK_DISABLE(); + }); +} + +void CoreSTM32HalBasicTimer::linkDACTimer(DAC_ChannelConfTypeDef *config) +{ + if (config != nullptr) { + config->DAC_Trigger = DAC_TRIGGER_T6_TRGO; + } +} + +void CoreSTM32HalBasicTimer::terminate() +{ + _hal.HAL_TIM_Base_DeInit(&_htim); +} + +void CoreSTM32HalBasicTimer::start() +{ + _hal.HAL_TIM_Base_Start_IT(&_htim); +} + +void CoreSTM32HalBasicTimer::stop() +{ + _hal.HAL_TIM_Base_Stop_IT(&_htim); +} diff --git a/drivers/CoreDAC/source/HAL_IRQHandlers.cpp b/drivers/CoreDAC/source/HAL_IRQHandlers.cpp new file mode 100644 index 0000000000..a2e695b99f --- /dev/null +++ b/drivers/CoreDAC/source/HAL_IRQHandlers.cpp @@ -0,0 +1,19 @@ +#include "CoreSTM32HalBasicTimer.h" + +extern "C" { + +namespace audio::internal { + extern leka::CoreSTM32HalBasicTimer hal_timer; +} + +void TIM6_DAC_IRQHandler() +{ + HAL_TIM_IRQHandler(&audio::internal::hal_timer.getHandle()); +} + +void TIM7_DAC_IRQHandler() +{ + HAL_TIM_IRQHandler(&audio::internal::hal_timer.getHandle()); +} + +} // extern "C" diff --git a/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h b/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h index 7daa41772a..0d552636b5 100644 --- a/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h +++ b/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h @@ -22,6 +22,11 @@ class CoreSTM32Hal : public interface::STM32Hal void HAL_RCC_GPIOI_CLK_ENABLE() final; void HAL_RCC_GPIOJ_CLK_ENABLE() final; + void HAL_RCC_TIM6_CLK_ENABLE() final; + void HAL_RCC_TIM6_CLK_DISABLE() final; + void HAL_RCC_TIM7_CLK_ENABLE() final; + void HAL_RCC_TIM7_CLK_DISABLE() final; + void HAL_RCC_FMC_CLK_ENABLE() final; void HAL_RCC_DMA2_CLK_ENABLE() final; @@ -104,6 +109,15 @@ class CoreSTM32Hal : public interface::STM32Hal auto HAL_JPEG_Pause(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelection) -> HAL_StatusTypeDef final; auto HAL_JPEG_Resume(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelection) -> HAL_StatusTypeDef final; + + auto HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef final; + auto HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, TIM_MasterConfigTypeDef *sMasterConfig) + -> HAL_StatusTypeDef final; + auto HAL_TIM_RegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID, + pTIM_CallbackTypeDef pCallback) -> HAL_StatusTypeDef final; + auto HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef final; + auto HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef final; + auto HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef final; }; } // namespace leka diff --git a/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp b/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp index c9352501ad..50a925207e 100644 --- a/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp +++ b/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp @@ -41,6 +41,26 @@ void CoreSTM32Hal::HAL_RCC_GPIOJ_CLK_ENABLE() __HAL_RCC_GPIOJ_CLK_ENABLE(); // NOLINT } +void CoreSTM32Hal::HAL_RCC_TIM6_CLK_ENABLE() +{ + __HAL_RCC_TIM6_CLK_ENABLE(); // NOLINT +} + +void CoreSTM32Hal::HAL_RCC_TIM6_CLK_DISABLE() +{ + __HAL_RCC_TIM6_CLK_DISABLE(); // NOLINT +} + +void CoreSTM32Hal::HAL_RCC_TIM7_CLK_ENABLE() +{ + __HAL_RCC_TIM7_CLK_ENABLE(); // NOLINT +} + +void CoreSTM32Hal::HAL_RCC_TIM7_CLK_DISABLE() +{ + __HAL_RCC_TIM7_CLK_DISABLE(); // NOLINT +} + void CoreSTM32Hal::HAL_RCC_FMC_CLK_ENABLE() { __HAL_RCC_FMC_CLK_ENABLE(); // NOLINT @@ -311,4 +331,36 @@ auto CoreSTM32Hal::HAL_JPEG_Resume(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelec return ::HAL_JPEG_Resume(hjpeg, XferSelection); } +auto CoreSTM32Hal::HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef +{ + return ::HAL_TIM_Base_Init(htim); +} + +auto CoreSTM32Hal::HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, + TIM_MasterConfigTypeDef *sMasterConfig) -> HAL_StatusTypeDef +{ + return ::HAL_TIMEx_MasterConfigSynchronization(htim, sMasterConfig); +} + +auto CoreSTM32Hal::HAL_TIM_RegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID, + pTIM_CallbackTypeDef pCallback) -> HAL_StatusTypeDef +{ + return ::HAL_TIM_RegisterCallback(htim, CallbackID, pCallback); +} + +auto CoreSTM32Hal::HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef +{ + return ::HAL_TIM_Base_Start_IT(htim); +} + +auto CoreSTM32Hal::HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef +{ + return ::HAL_TIM_Base_Stop_IT(htim); +} + +auto CoreSTM32Hal::HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef +{ + return ::HAL_TIM_Base_DeInit(htim); +} + } // namespace leka diff --git a/include/interface/drivers/STM32Hal.h b/include/interface/drivers/STM32Hal.h index b70089f827..79417cc996 100644 --- a/include/interface/drivers/STM32Hal.h +++ b/include/interface/drivers/STM32Hal.h @@ -21,6 +21,12 @@ class STM32Hal virtual void HAL_RCC_GPIOI_CLK_ENABLE() = 0; virtual void HAL_RCC_GPIOJ_CLK_ENABLE() = 0; + virtual void HAL_RCC_TIM6_CLK_ENABLE() = 0; + virtual void HAL_RCC_TIM6_CLK_DISABLE() = 0; + + virtual void HAL_RCC_TIM7_CLK_ENABLE() = 0; + virtual void HAL_RCC_TIM7_CLK_DISABLE() = 0; + virtual void HAL_RCC_FMC_CLK_ENABLE() = 0; virtual void HAL_RCC_DMA2_CLK_ENABLE() = 0; @@ -106,6 +112,15 @@ class STM32Hal virtual auto HAL_JPEG_Pause(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelection) -> HAL_StatusTypeDef = 0; virtual auto HAL_JPEG_Resume(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelection) -> HAL_StatusTypeDef = 0; + + virtual auto HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef = 0; + virtual auto HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, TIM_MasterConfigTypeDef *sMasterConfig) + -> HAL_StatusTypeDef = 0; + virtual auto HAL_TIM_RegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID, + pTIM_CallbackTypeDef pCallback) -> HAL_StatusTypeDef = 0; + virtual auto HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef = 0; + virtual auto HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef = 0; + virtual auto HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef = 0; }; } // namespace leka::interface diff --git a/include/interface/drivers/STM32HalBasicTimer.h b/include/interface/drivers/STM32HalBasicTimer.h new file mode 100644 index 0000000000..73fee09ee3 --- /dev/null +++ b/include/interface/drivers/STM32HalBasicTimer.h @@ -0,0 +1,27 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "interface/drivers/STM32Hal.h" + +namespace leka::interface { + +class STM32HalBasicTimer +{ + public: + virtual ~STM32HalBasicTimer() = default; + + [[nodiscard]] virtual auto getHandle() -> TIM_HandleTypeDef & = 0; + + virtual void linkDACTimer(DAC_ChannelConfTypeDef *config) = 0; + + virtual void initialize(float frequency) = 0; + virtual void terminate() = 0; + + virtual void start() = 0; + virtual void stop() = 0; +}; + +} // namespace leka::interface diff --git a/tests/unit/headers/mbed/mbed_config.h b/tests/unit/headers/mbed/mbed_config.h index e7fee6c006..5ff7967da5 100644 --- a/tests/unit/headers/mbed/mbed_config.h +++ b/tests/unit/headers/mbed/mbed_config.h @@ -288,6 +288,7 @@ #define SMP_DB_MAX_DEVICES 3 // set by library:cordio #define TARGET_LSE_DRIVE_LOAD_LEVEL RCC_LSEDRIVE_LOW // set by target:MCU_STM32F7 #define USE_HAL_JPEG_REGISTER_CALLBACKS 1U // set by application +#define USE_HAL_TIM_REGISTER_CALLBACKS 1U // set by application // Macros #define WSF_MS_PER_TICK 1 // defined by library:cordio #define _RTE_ // defined by library:rtos diff --git a/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h b/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h index 2d950de3e7..d72b263f4d 100644 --- a/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h +++ b/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h @@ -19,7 +19,10 @@ class CoreSTM32Hal : public interface::STM32Hal MOCK_METHOD(void, HAL_RCC_GPIOH_CLK_ENABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_GPIOI_CLK_ENABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_GPIOJ_CLK_ENABLE, (), (override)); - + MOCK_METHOD(void, HAL_RCC_TIM6_CLK_ENABLE, (), (override)); + MOCK_METHOD(void, HAL_RCC_TIM6_CLK_DISABLE, (), (override)); + MOCK_METHOD(void, HAL_RCC_TIM7_CLK_ENABLE, (), (override)); + MOCK_METHOD(void, HAL_RCC_TIM7_CLK_DISABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_FMC_CLK_ENABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_DMA2_CLK_ENABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_JPEG_CLK_ENABLE, (), (override)); @@ -113,6 +116,15 @@ class CoreSTM32Hal : public interface::STM32Hal MOCK_METHOD(HAL_StatusTypeDef, HAL_JPEG_Pause, (JPEG_HandleTypeDef *, uint32_t), (override)); MOCK_METHOD(HAL_StatusTypeDef, HAL_JPEG_Resume, (JPEG_HandleTypeDef *, uint32_t), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_Base_Init, (TIM_HandleTypeDef * htim), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIMEx_MasterConfigSynchronization, + (TIM_HandleTypeDef * htim, TIM_MasterConfigTypeDef *sMasterConfig), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_RegisterCallback, + (TIM_HandleTypeDef * htim, HAL_TIM_CallbackIDTypeDef CallbackID, pTIM_CallbackTypeDef pCallback), + (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_Base_Start_IT, (TIM_HandleTypeDef * htim), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_Base_Stop_IT, (TIM_HandleTypeDef * htim), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_Base_DeInit, (TIM_HandleTypeDef * htim), (override)); }; } // namespace leka::mock diff --git a/tests/unit/mocks/mocks/leka/STM32HalBasicTimer.h b/tests/unit/mocks/mocks/leka/STM32HalBasicTimer.h new file mode 100644 index 0000000000..fef8693733 --- /dev/null +++ b/tests/unit/mocks/mocks/leka/STM32HalBasicTimer.h @@ -0,0 +1,26 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "gmock/gmock.h" +#include "interface/drivers/STM32HalBasicTimer.h" + +namespace leka::mock { + +class STM32HalBasicTimer : public interface::STM32HalBasicTimer +{ + public: + MOCK_METHOD(TIM_HandleTypeDef &, getHandle, (), (override)); + + MOCK_METHOD(void, linkDACTimer, (DAC_ChannelConfTypeDef *), (override)); + + MOCK_METHOD(void, initialize, (float), (override)); + MOCK_METHOD(void, terminate, (), (override)); + + MOCK_METHOD(void, start, (), (override)); + MOCK_METHOD(void, stop, (), (override)); +}; + +} // namespace leka::mock