blob: f150da12357c06e3885657f7341119055b18dc95 [file]
/*
* STM32F405 timer tests
*
* Copyright (c) 2026 Manuele Conti <manuele.conti@archimede-energia.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "libqtest-single.h"
#define TIM2_BASE 0x40000000
#define TIM_CR1 (TIM2_BASE + 0x00)
#define TIM_DIER (TIM2_BASE + 0x0c)
#define TIM_SR (TIM2_BASE + 0x10)
#define TIM_EGR (TIM2_BASE + 0x14)
#define TIM_CNT (TIM2_BASE + 0x24)
#define TIM_PSC (TIM2_BASE + 0x28)
#define TIM_ARR (TIM2_BASE + 0x2c)
#define TIM_CR1_CEN (1U << 0)
#define TIM_DIER_UIE (1U << 0)
#define TIM_SR_UIF (1U << 0)
#define TIM_EGR_UG (1U << 0)
static void timer_reset(void)
{
qtest_system_reset(global_qtest);
}
static void test_period_and_update(void)
{
timer_reset();
writel(TIM_PSC, 0);
writel(TIM_ARR, 4);
writel(TIM_CNT, 0);
writel(TIM_DIER, TIM_DIER_UIE);
writel(TIM_CR1, TIM_CR1_CEN);
clock_step(4);
g_assert_cmphex(readl(TIM_CNT), ==, 4);
g_assert_cmphex(readl(TIM_SR), ==, 0);
clock_step(1);
g_assert_cmphex(readl(TIM_CNT), ==, 0);
g_assert_cmphex(readl(TIM_SR), ==, TIM_SR_UIF);
writel(TIM_SR, 0);
g_assert_cmphex(readl(TIM_SR), ==, 0);
}
static void test_prescaler(void)
{
timer_reset();
writel(TIM_PSC, 9);
writel(TIM_ARR, 4);
writel(TIM_CNT, 0);
writel(TIM_CR1, TIM_CR1_CEN);
clock_step(40);
g_assert_cmphex(readl(TIM_CNT), ==, 4);
clock_step(10);
g_assert_cmphex(readl(TIM_CNT), ==, 0);
}
static void test_stopped_counter(void)
{
timer_reset();
writel(TIM_ARR, 100);
writel(TIM_CNT, 200);
g_assert_cmphex(readl(TIM_CNT), ==, 200);
writel(TIM_CNT, 37);
writel(TIM_CR1, TIM_CR1_CEN);
clock_step(10);
g_assert_cmphex(readl(TIM_CNT), ==, 47);
writel(TIM_CR1, 0);
clock_step(100);
g_assert_cmphex(readl(TIM_CNT), ==, 47);
writel(TIM_CR1, TIM_CR1_CEN);
clock_step(1);
g_assert_cmphex(readl(TIM_CNT), ==, 48);
}
static void test_arr_zero(void)
{
timer_reset();
writel(TIM_ARR, 0);
writel(TIM_CNT, 0);
writel(TIM_DIER, TIM_DIER_UIE);
writel(TIM_CR1, TIM_CR1_CEN);
clock_step(1);
g_assert_cmphex(readl(TIM_CNT), ==, 0);
g_assert_cmphex(readl(TIM_SR), ==, TIM_SR_UIF);
}
static void test_update_and_reset(void)
{
timer_reset();
writel(TIM_ARR, 20);
writel(TIM_CNT, 12);
writel(TIM_EGR, TIM_EGR_UG);
g_assert_cmphex(readl(TIM_CNT), ==, 0);
writel(TIM_DIER, TIM_DIER_UIE);
writel(TIM_CR1, TIM_CR1_CEN);
qtest_system_reset(global_qtest);
clock_step(100);
g_assert_cmphex(readl(TIM_CR1), ==, 0);
g_assert_cmphex(readl(TIM_SR), ==, 0);
}
int main(int argc, char **argv)
{
int ret;
g_test_init(&argc, &argv, NULL);
qtest_add_func("/stm32f405/timer/period-and-update",
test_period_and_update);
qtest_add_func("/stm32f405/timer/prescaler", test_prescaler);
qtest_add_func("/stm32f405/timer/stopped-counter",
test_stopped_counter);
qtest_add_func("/stm32f405/timer/arr-zero", test_arr_zero);
qtest_add_func("/stm32f405/timer/update-and-reset",
test_update_and_reset);
qtest_start("-machine olimex-stm32-h405");
ret = g_test_run();
qtest_end();
return ret;
}