Files
arcs/arcs-sdk/drivers/lisa_hwtimer/arcs_dual_timer.c
2026-08-13 16:50:52 +08:00

395 lines
12 KiB
C

/*
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file arcs_dual_timer.c
* @brief Dual Timer 适配 LISA硬件定时器驱动框架
*/
#include "lisa_hwtimer.h"
#include "Driver_DUAL_TIMER.h"
#include "ClockManager.h"
#include <string.h>
#include <lisa_mutex.h>
#define LOG_TAG "arcs_dual_timer"
#include <lisa_log.h>
#define DEVICE_LOCK(priv) \
do { \
if (priv->mutex) { \
lisa_mutex_lock(priv->mutex, LISA_OS_WAIT_FOREVER); \
} \
} while (0)
#define DEVICE_UNLOCK(priv) \
do { \
if (priv->mutex) { \
lisa_mutex_unlock(priv->mutex); \
} \
} while (0)
#define DUAL_TIMER_SOURCE_CLK 16000
#define DUAL_TIMER_CHANNEL_COUNT 2
/* Dual Timer 支持的分频系数 */
#define DUAL_TIMER_PRESCALE_DIV_1 1
#define DUAL_TIMER_PRESCALE_DIV_16 16
#define DUAL_TIMER_PRESCALE_DIV_256 256
/* Dual Timer 支持的定时器频率 */
#define DUAL_TIMER_FREQ_DIV_1 (DUAL_TIMER_SOURCE_CLK / DUAL_TIMER_PRESCALE_DIV_1) /* 16000 Hz */
#define DUAL_TIMER_FREQ_DIV_16 (DUAL_TIMER_SOURCE_CLK / DUAL_TIMER_PRESCALE_DIV_16) /* 1000 Hz */
#define DUAL_TIMER_FREQ_DIV_256 (DUAL_TIMER_SOURCE_CLK / DUAL_TIMER_PRESCALE_DIV_256) /* 62 Hz */
/* Dual Timer 通道私有数据结构 */
typedef struct {
lisa_hwtimer_callback_t callback;
void *user_data;
uint32_t frequency_hz; /* 当前设置的频率 */
bool is_running;
uint32_t count; /* 保存的计数值,用于重置 */
lisa_hwtimer_mode_t mode; /* 保存的模式,用于重置 */
} dual_timer_channel_data_t;
/* Dual Timer 设备私有数据结构 */
typedef struct {
void *dual_timer_handler;
dual_timer_channel_data_t channels[DUAL_TIMER_CHANNEL_COUNT];
uint32_t base_clock_hz; /* 基准时钟频率 */
lisa_mutex_t *mutex; /* 互斥锁 */
} lisa_hwtimer_dual_data_t;
/* 静态实例数据 */
static lisa_hwtimer_dual_data_t dual_timer_priv = {
.base_clock_hz = DUAL_TIMER_SOURCE_CLK
};
/* Dual Timer 事件回调 */
static void dual_timer_event_callback(uint32_t event, void *workspace)
{
lisa_hwtimer_dual_data_t *data = (lisa_hwtimer_dual_data_t *)workspace;
if (!data) {
return;
}
/* 根据事件判断是哪个通道触发 */
uint8_t channel = 0;
if (event & CSK_TIMER_EVENT_ONESTEP_COMPLETE_CH0) {
channel = 0;
} else if (event & CSK_TIMER_EVENT_ONESTEP_COMPLETE_CH1) {
channel = 1;
} else {
return;
}
dual_timer_channel_data_t *ch_data = &data->channels[channel];
if (ch_data->callback) {
ch_data->callback(ch_data->user_data);
}
}
/* 获取硬件能力 */
static int dual_timer_get_capabilities(lisa_device_t *dev, lisa_hwtimer_capabilities_t *caps)
{
if (!lisa_device_is_initialized(dev) || !caps) {
return LISA_DEVICE_ERR_INVALID;
}
caps->channel_count = DUAL_TIMER_CHANNEL_COUNT; /* Dual Timer 有2个通道 */
caps->max_count = 0xFFFFFFFF; /* 32位计数器 */
caps->min_count = 1;
caps->max_freq_hz = DUAL_TIMER_FREQ_DIV_1; /* 最大频率: 16000 Hz (分频/1) */
caps->min_freq_hz = DUAL_TIMER_FREQ_DIV_256; /* 最小频率: 62 Hz (分频/256) */
caps->support_oneshot = true; /* 支持单次模式 */
caps->support_periodic = true; /* 支持周期模式 */
return 0;
}
/* 设置频率 */
static int dual_timer_set_frequency(lisa_device_t *dev, uint8_t channel, uint32_t freq_hz)
{
if (!lisa_device_is_initialized(dev)) {
return LISA_DEVICE_ERR_INVALID;
}
lisa_hwtimer_dual_data_t *data = (lisa_hwtimer_dual_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel >= DUAL_TIMER_CHANNEL_COUNT) {
return LISA_DEVICE_ERR_RANGE;
}
/*
* Dual Timer 内部时钟源固定为 16000Hz
* 分频系数只支持: /1, /16, /256
* 因此支持的频率为: 16000Hz, 1000Hz, 62.5Hz
*/
if (freq_hz != DUAL_TIMER_FREQ_DIV_1 &&
freq_hz != DUAL_TIMER_FREQ_DIV_16 &&
freq_hz != DUAL_TIMER_FREQ_DIV_256) {
LISA_LOGE(LOG_TAG, "Unsupported frequency %d Hz. Only support %d, %d, %d Hz",
freq_hz, DUAL_TIMER_FREQ_DIV_1, DUAL_TIMER_FREQ_DIV_16, DUAL_TIMER_FREQ_DIV_256);
return LISA_DEVICE_ERR_RANGE;
}
DEVICE_LOCK(data);
data->channels[channel].frequency_hz = freq_hz;
DEVICE_UNLOCK(data);
return 0;
}
/* 根据目标频率计算分频系数 */
static uint32_t calculate_prescale(uint32_t target_freq)
{
/*
* Dual Timer 内部时钟源固定为 DUAL_TIMER_SOURCE_CLK (16000Hz)
* 只支持三种分频: /1, /16, /256
*/
if (target_freq == DUAL_TIMER_FREQ_DIV_1) {
return CSK_TIMER_PRESCALE_Divide_1;
} else if (target_freq == DUAL_TIMER_FREQ_DIV_16) {
return CSK_TIMER_PRESCALE_Divide_16;
} else if (target_freq == DUAL_TIMER_FREQ_DIV_256) {
return CSK_TIMER_PRESCALE_Divide_256;
}
/* 不应该到达这里,因为 set_frequency 已经做了检查 */
LISA_LOGW(LOG_TAG, "Unsupported frequency %d Hz. Using default frequency %d Hz",
target_freq, DUAL_TIMER_FREQ_DIV_1);
return CSK_TIMER_PRESCALE_Divide_1;
}
/* 内部启动定时器函数(假设已持有锁) */
static int dual_timer_start_internal(lisa_device_t *dev, uint8_t channel, uint32_t count, lisa_hwtimer_mode_t mode)
{
lisa_hwtimer_dual_data_t *data = (lisa_hwtimer_dual_data_t *)dev->priv_data;
dual_timer_channel_data_t *ch_data = &data->channels[channel];
/* 检查是否设置了回调函数,如果没有设置则不允许启动定时器
* 避免 HAL 库中断处理时的空指针访问 */
if (!ch_data->callback) {
LISA_LOGE(LOG_TAG, "Callback not set for channel %d, cannot start timer", channel);
return LISA_DEVICE_ERR_INVALID;
}
/* 计算分频系数 */
uint32_t prescale = calculate_prescale(ch_data->frequency_hz);
/* 配置定时器模式 */
uint32_t control = prescale | CSK_TIMER_SIZE_32Bit | CSK_TIMER_INTERRUPT_Enabled;
if (mode == LISA_HWTIMER_MODE_ONESHOT) {
control |= CSK_TIMER_MODE_OneShot;
} else {
control |= CSK_TIMER_MODE_Periodic;
}
DUALTIMERS_Control(data->dual_timer_handler, control, channel);
/* 设置回调(每个通道独立设置) */
DUALTIMERS_SetTimerCallback(data->dual_timer_handler, channel, dual_timer_event_callback, data);
/* 设置计数周期 */
DUALTIMERS_SetTimerPeriodByCount(data->dual_timer_handler, channel, count);
/* 启动定时器 */
DUALTIMERS_StartTimer(data->dual_timer_handler, channel);
ch_data->is_running = true;
ch_data->count = count; /* 保存计数值,用于重置 */
ch_data->mode = mode; /* 保存模式,用于重置 */
return 0;
}
/* 启动定时器 */
static int dual_timer_start(lisa_device_t *dev, uint8_t channel, uint32_t count, lisa_hwtimer_mode_t mode)
{
if (!lisa_device_is_initialized(dev)) {
return LISA_DEVICE_ERR_INVALID;
}
lisa_hwtimer_dual_data_t *data = (lisa_hwtimer_dual_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel >= DUAL_TIMER_CHANNEL_COUNT) {
return LISA_DEVICE_ERR_RANGE;
}
DEVICE_LOCK(data);
int ret = dual_timer_start_internal(dev, channel, count, mode);
DEVICE_UNLOCK(data);
return ret;
}
/* 停止定时器 */
static int dual_timer_stop(lisa_device_t *dev, uint8_t channel)
{
if (!lisa_device_is_initialized(dev)) {
return LISA_DEVICE_ERR_INVALID;
}
lisa_hwtimer_dual_data_t *data = (lisa_hwtimer_dual_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel >= DUAL_TIMER_CHANNEL_COUNT) {
return LISA_DEVICE_ERR_RANGE;
}
DEVICE_LOCK(data);
if (!data->channels[channel].is_running) {
DEVICE_UNLOCK(data);
return LISA_DEVICE_ERR_INVALID;
}
DUALTIMERS_StopTimer(data->dual_timer_handler, channel);
data->channels[channel].is_running = false;
DEVICE_UNLOCK(data);
return 0;
}
/* 重置定时器 */
static int dual_timer_reset(lisa_device_t *dev, uint8_t channel)
{
if (!lisa_device_is_initialized(dev)) {
return LISA_DEVICE_ERR_INVALID;
}
lisa_hwtimer_dual_data_t *data = (lisa_hwtimer_dual_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel >= DUAL_TIMER_CHANNEL_COUNT) {
return LISA_DEVICE_ERR_RANGE;
}
DEVICE_LOCK(data);
dual_timer_channel_data_t *ch_data = &data->channels[channel];
/* 如果定时器未运行,无需重置 */
if (!ch_data->is_running) {
DEVICE_UNLOCK(data);
return LISA_DEVICE_ERR_INVALID;
}
/* 停止定时器 */
DUALTIMERS_StopTimer(data->dual_timer_handler, channel);
/* 使用保存的配置参数重新启动定时器 */
int ret = dual_timer_start_internal(dev, channel, ch_data->count, ch_data->mode);
DEVICE_UNLOCK(data);
return ret;
}
/* 获取当前计数值 */
static int dual_timer_get_value(lisa_device_t *dev, uint8_t channel, uint32_t *count)
{
if (!lisa_device_is_initialized(dev) || !count) {
return LISA_DEVICE_ERR_INVALID;
}
lisa_hwtimer_dual_data_t *data = (lisa_hwtimer_dual_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel >= DUAL_TIMER_CHANNEL_COUNT) {
return LISA_DEVICE_ERR_RANGE;
}
DUALTIMERS_ReadTimerCount(data->dual_timer_handler, channel, count);
return 0;
}
/* 设置回调函数 */
static int dual_timer_set_callback(lisa_device_t *dev, uint8_t channel,
lisa_hwtimer_callback_t callback, void *user_data)
{
if (!lisa_device_is_initialized(dev)) {
return LISA_DEVICE_ERR_INVALID;
}
lisa_hwtimer_dual_data_t *data = (lisa_hwtimer_dual_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel >= DUAL_TIMER_CHANNEL_COUNT) {
return LISA_DEVICE_ERR_RANGE;
}
DEVICE_LOCK(data);
data->channels[channel].callback = callback;
data->channels[channel].user_data = user_data;
DEVICE_UNLOCK(data);
return 0;
}
/* Dual Timer API 实现 */
static const lisa_hwtimer_api_t dual_timer_api = {
.get_capabilities = dual_timer_get_capabilities,
.set_frequency = dual_timer_set_frequency,
.start = dual_timer_start,
.stop = dual_timer_stop,
.reset = dual_timer_reset,
.get_value = dual_timer_get_value,
.set_callback = dual_timer_set_callback,
};
/* Dual Timer 初始化函数 */
static int arcs_dual_timer_init(void)
{
/* 创建互斥锁 */
dual_timer_priv.mutex = lisa_mutex_create();
if (!dual_timer_priv.mutex) {
LISA_LOGE(LOG_TAG, "Failed to create mutex");
return LISA_DEVICE_ERR_INIT_FAIL;
}
dual_timer_priv.dual_timer_handler = DUALTIMERS0();
DUALTIMERS_Initialize(dual_timer_priv.dual_timer_handler);
DUALTIMERS_PowerControl(dual_timer_priv.dual_timer_handler, CSK_POWER_FULL);
LISA_LOGI(LOG_TAG, "Dual Timer initialized base clock: %d Hz", dual_timer_priv.base_clock_hz);
return LISA_DEVICE_OK;
}
LISA_DEVICE_REGISTER(dual_timer, &dual_timer_api, &dual_timer_priv, NULL, arcs_dual_timer_init,
LISA_DEVICE_PRIORITY_NORMAL);