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

330 lines
9.7 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file arcs_aon_timer.c
* @brief AON Timer 适配 LISA硬件定时器驱动框架
*/
#include "lisa_hwtimer.h"
#include "ClockManager.h"
#include "Driver_AON_TIMER.h"
#include <string.h>
#include <lisa_mutex.h>
#define LOG_TAG "arcs_aon_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)
/* XO32K 是外部32K晶振固定频率 */
#define AON_TIMER_CLK_XO32K 32768
/* AON Timer 私有数据结构 */
typedef struct {
void *aon_timer_handler;
lisa_hwtimer_callback_t callback;
void *user_data;
uint32_t frequency_hz; /* 当前设置的频率 */
bool is_running;
lisa_mutex_t *mutex; /* 互斥锁 */
} arcs_aon_timer_priv_data_t;
/* 静态实例数据 */
static arcs_aon_timer_priv_data_t arcs_aon_timer_priv = {
.is_running = false,
.frequency_hz = 0, /* 在初始化时设置 */
};
/* AON Timer 事件回调 */
static void arcs_aon_timer_event_callback(uint32_t event, void *workspace)
{
arcs_aon_timer_priv_data_t *data = (arcs_aon_timer_priv_data_t *)workspace;
if (data && data->callback) {
data->callback(data->user_data);
}
}
/* 获取硬件能力 */
static int arcs_aon_timer_get_capabilities(lisa_device_t *dev, lisa_hwtimer_capabilities_t *caps)
{
if (!lisa_device_is_initialized(dev) || !caps) {
return LISA_DEVICE_ERR_INVALID;
}
arcs_aon_timer_priv_data_t *data = (arcs_aon_timer_priv_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
caps->channel_count = 1; /* AON Timer 只有1个通道 */
caps->max_count = 0xFFFFFF; /* 24位计数器 */
caps->min_count = 1;
caps->max_freq_hz = data->frequency_hz; /* 使用实际的时钟频率 */
caps->min_freq_hz = data->frequency_hz;
caps->support_oneshot = true; /* 支持单次模式 */
caps->support_periodic = true; /* 支持周期模式 */
return LISA_DEVICE_OK;
}
/* 设置频率 */
static int arcs_aon_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;
}
arcs_aon_timer_priv_data_t *data = (arcs_aon_timer_priv_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel != 0) {
return LISA_DEVICE_ERR_RANGE;
}
/* AON Timer 只支持 Kconfig 配置的时钟源频率 */
if (freq_hz != data->frequency_hz) {
LISA_LOGE(LOG_TAG, "Invalid frequency: %d Hz, only %d Hz is supported", freq_hz, data->frequency_hz);
return LISA_DEVICE_ERR_RANGE;
}
data->frequency_hz = freq_hz;
return LISA_DEVICE_OK;
}
/* 启动定时器 */
static int arcs_aon_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;
}
arcs_aon_timer_priv_data_t *data = (arcs_aon_timer_priv_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel != 0) {
return LISA_DEVICE_ERR_RANGE;
}
DEVICE_LOCK(data);
/* 检查是否设置了回调函数,如果没有设置则不允许启动定时器
* 避免 HAL 库中断处理时的空指针访问 */
if (!data->callback) {
LISA_LOGE(LOG_TAG, "Callback not set for channel %d, cannot start timer", channel);
DEVICE_UNLOCK(data);
return LISA_DEVICE_ERR_INVALID;
}
/* 配置定时器模式和时钟源 */
uint32_t control = HAL_AON_TIMER_INTERRUPT_Enabled;
/* 根据模式选择定时器模式 */
if (mode == LISA_HWTIMER_MODE_ONESHOT) {
control |= HAL_AON_TIMER_MODE_Normal;
} else {
control |= HAL_AON_TIMER_MODE_Repeat;
}
/* 根据 Kconfig 配置选择时钟源 */
#ifdef CONFIG_LISA_HWTIMER_ARCS_AON_TIMER_CLK_XO32K
control |= HAL_AON_TIMER_CLK_SEL_Xo32k;
#else
control |= HAL_AON_TIMER_CLK_SEL_Rc32k;
#endif
AON_TIMER_Control(data->aon_timer_handler, control);
/* 设置计数周期 */
AON_TIMER_SetTimerPeriodByCount(data->aon_timer_handler, count);
/* 启动定时器 */
AON_TIMER_StartTimer(data->aon_timer_handler);
data->is_running = true;
DEVICE_UNLOCK(data);
return LISA_DEVICE_OK;
}
/* 停止定时器 */
static int arcs_aon_timer_stop(lisa_device_t *dev, uint8_t channel)
{
if (!lisa_device_is_initialized(dev)) {
return LISA_DEVICE_ERR_INVALID;
}
arcs_aon_timer_priv_data_t *data = (arcs_aon_timer_priv_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel != 0) {
return LISA_DEVICE_ERR_RANGE;
}
DEVICE_LOCK(data);
if (!data->is_running) {
DEVICE_UNLOCK(data);
return LISA_DEVICE_ERR_INVALID;
}
AON_TIMER_StopTimer(data->aon_timer_handler);
data->is_running = false;
DEVICE_UNLOCK(data);
return LISA_DEVICE_OK;
}
/* 重置定时器 */
static int arcs_aon_timer_reset(lisa_device_t *dev, uint8_t channel)
{
if (!lisa_device_is_initialized(dev)) {
return LISA_DEVICE_ERR_INVALID;
}
arcs_aon_timer_priv_data_t *data = (arcs_aon_timer_priv_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel != 0) {
return LISA_DEVICE_ERR_RANGE;
}
DEVICE_LOCK(data);
if (!data->is_running) {
DEVICE_UNLOCK(data);
return LISA_DEVICE_ERR_INVALID;
}
/* AON Timer 没有独立的reset功能通过停止再启动实现 */
AON_TIMER_StopTimer(data->aon_timer_handler);
AON_TIMER_StartTimer(data->aon_timer_handler);
DEVICE_UNLOCK(data);
return LISA_DEVICE_OK;
}
/* 获取当前计数值 */
static int arcs_aon_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;
}
arcs_aon_timer_priv_data_t *data = (arcs_aon_timer_priv_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel != 0) {
return LISA_DEVICE_ERR_RANGE;
}
AON_TIMER_ReadTimerCount(data->aon_timer_handler, count);
return LISA_DEVICE_OK;
}
/* 设置回调函数 */
static int arcs_aon_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;
}
arcs_aon_timer_priv_data_t *data = (arcs_aon_timer_priv_data_t *)dev->priv_data;
if (!data) {
return LISA_DEVICE_ERR_INVALID;
}
/* 检查通道号 */
if (channel != 0) {
return LISA_DEVICE_ERR_RANGE;
}
DEVICE_LOCK(data);
data->callback = callback;
data->user_data = user_data;
DEVICE_UNLOCK(data);
return LISA_DEVICE_OK;
}
/* AON Timer API 实现 */
static const lisa_hwtimer_api_t arcs_aon_timer_api = {
.get_capabilities = arcs_aon_timer_get_capabilities,
.set_frequency = arcs_aon_timer_set_frequency,
.start = arcs_aon_timer_start,
.stop = arcs_aon_timer_stop,
.reset = arcs_aon_timer_reset,
.get_value = arcs_aon_timer_get_value,
.set_callback = arcs_aon_timer_set_callback,
};
/* AON Timer 初始化函数 */
static int arcs_aon_timer_init(void)
{
/* 根据配置选择时钟源 */
#ifdef CONFIG_LISA_HWTIMER_ARCS_AON_TIMER_CLK_XO32K
/* 使用外部32K晶振固定频率 */
arcs_aon_timer_priv.frequency_hz = AON_TIMER_CLK_XO32K;
#else
/* 使用内部RC32K通过CRM动态获取频率 */
arcs_aon_timer_priv.frequency_hz = CRM_GetSrcFreq(CRM_IpSrcAon32kClk);
#endif
/* 创建互斥锁 */
arcs_aon_timer_priv.mutex = lisa_mutex_create();
if (!arcs_aon_timer_priv.mutex) {
LISA_LOGE(LOG_TAG, "Failed to create mutex");
return LISA_DEVICE_ERR_INIT_FAIL;
}
/* 初始化 AON Timer 硬件 */
arcs_aon_timer_priv.aon_timer_handler = AON_TIMER();
AON_TIMER_Initialize(arcs_aon_timer_priv.aon_timer_handler, arcs_aon_timer_event_callback,
&arcs_aon_timer_priv);
AON_TIMER_PowerControl(arcs_aon_timer_priv.aon_timer_handler, CSK_POWER_FULL);
return LISA_DEVICE_OK;
}
LISA_DEVICE_REGISTER(aon_timer, &arcs_aon_timer_api, &arcs_aon_timer_priv, NULL, arcs_aon_timer_init,
LISA_DEVICE_PRIORITY_NORMAL);