Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✅ (dac): Add CoreSTM32HalBasicTimer_test #1418

Open
wants to merge 1 commit into
base: yann/feature/haptic/halbasictimer
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions drivers/CoreDAC/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,9 @@ target_link_libraries(CoreDAC
mbed-os
CoreSTM32Hal
)

if(${CMAKE_PROJECT_NAME} STREQUAL "LekaOSUnitTests")
leka_unit_tests_sources(
tests/CoreSTM32HalBasicTimer_test.cpp
)
endif()
200 changes: 200 additions & 0 deletions drivers/CoreDAC/tests/CoreSTM32HalBasicTimer_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
// Leka - LekaOS
// Copyright 2024 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#include "CoreSTM32HalBasicTimer.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "mocks/leka/CoreSTM32Hal.h"
#include "mocks/leka/STM32HalBasicTimer.h"

using namespace leka;

using testing::_;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::MockFunction;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::SaveArgPointee;

class CoreSTM32HalBasicTimerTest : public ::testing::Test
{
protected:
void SetUp() override
{
basic_timer.registerCallback(callback.AsStdFunction());

EXPECT_CALL(halmock, HAL_TIM_RegisterCallback(_, HAL_TIM_BASE_MSPINIT_CB_ID, _))
.WillOnce(DoAll(SaveArg<2>(&mspinit_callback), Return(HAL_StatusTypeDef::HAL_OK)));
EXPECT_CALL(halmock, HAL_TIM_RegisterCallback(_, HAL_TIM_BASE_MSPDEINIT_CB_ID, _))
.WillOnce(DoAll(SaveArg<2>(&mspdeinit_callback), Return(HAL_StatusTypeDef::HAL_OK)));
EXPECT_CALL(halmock, HAL_TIM_RegisterCallback(_, HAL_TIM_PERIOD_ELAPSED_CB_ID, _))
.WillOnce(DoAll(SaveArg<2>(&period_elapsed_callback), Return(HAL_StatusTypeDef::HAL_OK)));

EXPECT_CALL(halmock, HAL_TIM_Base_Init);
EXPECT_CALL(halmock, HAL_TIMEx_MasterConfigSynchronization)
.WillOnce(DoAll(SaveArgPointee<1>(&basic_timer_master_config), Return(HAL_StatusTypeDef::HAL_OK)));

basic_timer.initialize();
}
// void TearDown() override {}

mock::CoreSTM32Hal halmock;

CoreSTM32HalBasicTimer basic_timer {halmock};
TIM_MasterConfigTypeDef basic_timer_master_config {};

MockFunction<void()> callback;

std::function<void(TIM_HandleTypeDef *)> mspinit_callback = [](TIM_HandleTypeDef *) {};
std::function<void(TIM_HandleTypeDef *)> mspdeinit_callback = [](TIM_HandleTypeDef *) {};
std::function<void(TIM_HandleTypeDef *)> period_elapsed_callback = [](TIM_HandleTypeDef *) {};
};

TEST_F(CoreSTM32HalBasicTimerTest, initializationDefault)
{
EXPECT_NE(&basic_timer, nullptr);

auto handle = basic_timer.getHandle();
EXPECT_NE(&handle, nullptr);
auto allowed_instance = handle.Instance == TIM6 || handle.Instance == TIM7;
EXPECT_TRUE(allowed_instance);
}

TEST_F(CoreSTM32HalBasicTimerTest, initialize)
{
{
InSequence seq;

{
EXPECT_CALL(halmock, HAL_TIM_RegisterCallback(_, HAL_TIM_BASE_MSPINIT_CB_ID, _));
EXPECT_CALL(halmock, HAL_TIM_RegisterCallback(_, HAL_TIM_BASE_MSPDEINIT_CB_ID, _));
} // MSP callbacks

{
EXPECT_CALL(halmock, HAL_TIM_Base_Init);
EXPECT_CALL(halmock, HAL_TIMEx_MasterConfigSynchronization);
} // BasicTimer config

{
EXPECT_CALL(halmock, HAL_TIM_RegisterCallback(_, HAL_TIM_PERIOD_ELAPSED_CB_ID, _));
} // Callback on event
}

basic_timer.initialize();
}

TEST_F(CoreSTM32HalBasicTimerTest, initializeMspInit)
{
auto *basic_timer_instance = basic_timer.getHandle().Instance;

if (basic_timer_instance == TIM6) {
EXPECT_CALL(halmock, HAL_RCC_TIM6_CLK_ENABLE);
EXPECT_CALL(halmock, HAL_NVIC_SetPriority(TIM6_DAC_IRQn, _, _));
EXPECT_CALL(halmock, HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn));
} else if (basic_timer_instance == TIM7) {
EXPECT_CALL(halmock, HAL_RCC_TIM7_CLK_ENABLE);
EXPECT_CALL(halmock, HAL_NVIC_SetPriority(TIM7_IRQn, _, _));
EXPECT_CALL(halmock, HAL_NVIC_EnableIRQ(TIM7_IRQn));
} else {
FAIL(); // Only timers 6 and 7 can be used as Basic Timer
}

mspinit_callback(&basic_timer.getHandle());
}

TEST_F(CoreSTM32HalBasicTimerTest, initializeMspDeinit)
{
auto *basic_timer_instance = basic_timer.getHandle().Instance;

if (basic_timer_instance == TIM6) {
EXPECT_CALL(halmock, HAL_RCC_TIM6_CLK_DISABLE);
} else if (basic_timer_instance == TIM7) {
EXPECT_CALL(halmock, HAL_RCC_TIM7_CLK_DISABLE);
} else {
FAIL(); // Only timers 6 and 7 can be used as Basic Timer
}

mspdeinit_callback(&basic_timer.getHandle());
}

TEST_F(CoreSTM32HalBasicTimerTest, initializeConfig)
{
auto timer_handle = basic_timer.getHandle();

auto CK_INT = float(108'000'000.0);
auto default_sample_rate = float(44'100.0);
auto divider = std::round(CK_INT / default_sample_rate);

// The prescaler can divide the counter clock frequency by any factor between 1 and 65536, see 28.3.1 of RM
auto prescaler = timer_handle.Init.Prescaler;
EXPECT_LE(prescaler, 0xFFF);

// The counter counts from 0 to the auto-reload value, see 28.3.2 of RM
auto auto_reload_value = timer_handle.Init.Period;
EXPECT_GE(auto_reload_value, 1);
EXPECT_LE(auto_reload_value, 0xFFF);

// To fit required frequency (default sample rate), multiplying prescaler and auto-reload value must give
// approximately the divider
EXPECT_NEAR((prescaler + 1) * (auto_reload_value + 1), divider, 1);

// Disable shadow write
EXPECT_EQ(timer_handle.Init.AutoReloadPreload, TIM_AUTORELOAD_PRELOAD_DISABLE);

// The update event is selected as a trigger output, see 28.4.2 of RM
EXPECT_EQ(basic_timer_master_config.MasterOutputTrigger, TIM_TRGO_UPDATE);

// ? Config not available for BasicTimer (TIM6 and TIM7)
// _htim.Init.CounterMode;
// _htim.Init.ClockDivision;
// _htim.Init.RepetitionCounter;
// timerMasterConfig.MasterSlaveMode;
}

TEST_F(CoreSTM32HalBasicTimerTest, initializePeriodElapsedCallback)
{
EXPECT_CALL(callback, Call);
period_elapsed_callback(&basic_timer.getHandle());
}

TEST_F(CoreSTM32HalBasicTimerTest, linkDACTimer)
{
basic_timer.linkDACTimer(nullptr);

DAC_ChannelConfTypeDef dac_config {};

basic_timer.linkDACTimer(&dac_config);

auto *basic_timer_instance = basic_timer.getHandle().Instance;
if (basic_timer_instance == TIM6) {
EXPECT_EQ(dac_config.DAC_Trigger, DAC_TRIGGER_T6_TRGO);
} else if (basic_timer_instance == TIM7) {
EXPECT_EQ(dac_config.DAC_Trigger, DAC_TRIGGER_T7_TRGO);
} else {
FAIL(); // Only timers 6 and 7 can be used as DAC Timer
}
}

TEST_F(CoreSTM32HalBasicTimerTest, terminate)
{
EXPECT_CALL(halmock, HAL_TIM_Base_DeInit);

basic_timer.terminate();
}

TEST_F(CoreSTM32HalBasicTimerTest, start)
{
EXPECT_CALL(halmock, HAL_TIM_Base_Start_IT);

basic_timer.start();
}

TEST_F(CoreSTM32HalBasicTimerTest, stop)
{
EXPECT_CALL(halmock, HAL_TIM_Base_Stop_IT);

basic_timer.stop();
}
3 changes: 2 additions & 1 deletion tests/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ add_subdirectory(template)
# Register drivers
leka_register_unit_tests_for_driver(CoreBattery)
leka_register_unit_tests_for_driver(CoreBufferedSerial)
leka_register_unit_tests_for_driver(CoreQDAC)
leka_register_unit_tests_for_driver(CoreDAC)
leka_register_unit_tests_for_driver(CoreEventFlags)
leka_register_unit_tests_for_driver(CoreEventQueue)
leka_register_unit_tests_for_driver(CoreFlashMemory)
Expand All @@ -270,6 +270,7 @@ leka_register_unit_tests_for_driver(CoreMicrophone)
leka_register_unit_tests_for_driver(CoreMotor)
leka_register_unit_tests_for_driver(CoreMutex)
leka_register_unit_tests_for_driver(CorePwm)
leka_register_unit_tests_for_driver(CoreQDAC)
leka_register_unit_tests_for_driver(CoreQSPI)
leka_register_unit_tests_for_driver(CoreRFIDReader)
leka_register_unit_tests_for_driver(CoreSPI)
Expand Down
Loading