641 lines
16 KiB
C
641 lines
16 KiB
C
|
// Copyright 2020-2021 Beken
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
#include <common/bk_include.h>
|
||
|
#include <common/bk_compiler.h>
|
||
|
#include <os/mem.h>
|
||
|
#include "icu_driver.h"
|
||
|
#include "timer_driver.h"
|
||
|
#include "timer_hal.h"
|
||
|
#include <driver/timer.h>
|
||
|
#include "clock_driver.h"
|
||
|
#include "power_driver.h"
|
||
|
#include <driver/int.h>
|
||
|
#include "sys_driver.h"
|
||
|
#include "timer_driver.h"
|
||
|
|
||
|
#if (SOC_TIMER_INTERRUPT_NUM > 1)
|
||
|
static void timer1_isr(void) __BK_SECTION(".itcm");
|
||
|
#endif
|
||
|
static void timer_isr(void) __BK_SECTION(".itcm");
|
||
|
|
||
|
typedef struct {
|
||
|
timer_hal_t hal;
|
||
|
#if CONFIG_TIMER_PM_CB_SUPPORT
|
||
|
uint32_t pm_backup[SOC_TIMER_GROUP_NUM-1][TIMER_PM_BACKUP_REG_NUM];
|
||
|
uint8_t pm_bakeup_is_valid;
|
||
|
#endif
|
||
|
} timer_driver_t;
|
||
|
|
||
|
static timer_driver_t s_timer = {0};
|
||
|
static timer_isr_t s_timer_isr[SOC_TIMER_CHAN_NUM_PER_UNIT] = {NULL};
|
||
|
static bool s_timer_driver_is_init = false;
|
||
|
|
||
|
#define TIMER_RETURN_ON_NOT_INIT() do {\
|
||
|
if (!s_timer_driver_is_init) {\
|
||
|
return BK_ERR_TIMER_NOT_INIT;\
|
||
|
}\
|
||
|
} while(0)
|
||
|
|
||
|
#define TIMER_RETURN_ON_INVALID_ID(id) do {\
|
||
|
if ((id) >= SOC_TIMER_CHAN_NUM_PER_UNIT) {\
|
||
|
return BK_ERR_TIMER_ID;\
|
||
|
}\
|
||
|
} while(0)
|
||
|
|
||
|
#define TIMER_RETURN_ON_IS_RUNNING(id, status) do {\
|
||
|
if ((status) & BIT((id))) {\
|
||
|
return BK_ERR_TIMER_IS_RUNNING;\
|
||
|
}\
|
||
|
} while(0)
|
||
|
|
||
|
#define TIMER_RETURN_TIMER_ID_IS_ERR(id) do {\
|
||
|
if ((~CONFIG_TIMER_SUPPORT_ID_BITS) & BIT((id))) {\
|
||
|
return BK_ERR_TIMER_ID_ON_DEFCONFIG;\
|
||
|
}\
|
||
|
} while(0)
|
||
|
|
||
|
#if CONFIG_TIMER_PM_CB_SUPPORT
|
||
|
#define TIMER_PM_CHECK_RESTORE(id) do {\
|
||
|
uint32_t group_id;\
|
||
|
GLOBAL_INT_DECLARATION();\
|
||
|
GLOBAL_INT_DISABLE();\
|
||
|
group_id = id / SOC_TIMER_CHAN_NUM_PER_GROUP;\
|
||
|
switch (group_id){\
|
||
|
case 0:\
|
||
|
break;\
|
||
|
case 1:\
|
||
|
if (bk_pm_module_lv_sleep_state_get(PM_DEV_ID_TIMER_1)) {\
|
||
|
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_BAKP_TIMER1, PM_POWER_MODULE_STATE_ON);\
|
||
|
timer_pm_restore(0, (void *)id);\
|
||
|
bk_pm_module_lv_sleep_state_clear(PM_DEV_ID_TIMER_1);\
|
||
|
}\
|
||
|
break;\
|
||
|
default:\
|
||
|
break;\
|
||
|
}\
|
||
|
GLOBAL_INT_RESTORE();\
|
||
|
}while(0)
|
||
|
#else
|
||
|
#define TIMER_PM_CHECK_RESTORE(id)
|
||
|
#endif
|
||
|
|
||
|
#if (CONFIG_SYSTEM_CTRL)
|
||
|
static void timer_clock_select(timer_id_t id, timer_src_clk_t mode)
|
||
|
{
|
||
|
uint32_t group_index = 0;
|
||
|
|
||
|
group_index = id / SOC_TIMER_CHAN_NUM_PER_GROUP;
|
||
|
switch(group_index)
|
||
|
{
|
||
|
case 0:
|
||
|
sys_drv_timer_select_clock(SYS_SEL_TIMER0, mode);
|
||
|
break;
|
||
|
case 1:
|
||
|
sys_drv_timer_select_clock(SYS_SEL_TIMER1, mode);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void timer_clock_enable(timer_id_t id)
|
||
|
{
|
||
|
uint32_t group_index = 0;
|
||
|
|
||
|
group_index = id / SOC_TIMER_CHAN_NUM_PER_GROUP;
|
||
|
switch(group_index)
|
||
|
{
|
||
|
case 0:
|
||
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_1, CLK_PWR_CTRL_PWR_UP);
|
||
|
break;
|
||
|
case 1:
|
||
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_2, CLK_PWR_CTRL_PWR_UP);
|
||
|
break;
|
||
|
case 2:
|
||
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_3, CLK_PWR_CTRL_PWR_UP);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void timer_clock_disable(timer_id_t id)
|
||
|
{
|
||
|
uint32_t group_index = 0;
|
||
|
|
||
|
group_index = id / SOC_TIMER_CHAN_NUM_PER_GROUP;
|
||
|
switch(group_index)
|
||
|
{
|
||
|
case 0:
|
||
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_1, CLK_PWR_CTRL_PWR_DOWN);
|
||
|
break;
|
||
|
case 1:
|
||
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_2, CLK_PWR_CTRL_PWR_DOWN);
|
||
|
break;
|
||
|
case 2:
|
||
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_3, CLK_PWR_CTRL_PWR_DOWN);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void timer_interrupt_enable(timer_id_t id)
|
||
|
{
|
||
|
uint32_t group_index = 0;
|
||
|
|
||
|
group_index = id / SOC_TIMER_CHAN_NUM_PER_GROUP;
|
||
|
switch(group_index)
|
||
|
{
|
||
|
case 0:
|
||
|
sys_drv_int_enable(TIMER_INTERRUPT_CTRL_BIT);
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
sys_drv_int_enable(TIMER1_INTERRUPT_CTRL_BIT);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void timer_chan_init_common(timer_id_t timer_id)
|
||
|
{
|
||
|
#if (CONFIG_SYSTEM_CTRL)
|
||
|
timer_clock_select(timer_id, TIMER_SCLK_XTAL);
|
||
|
timer_clock_enable(timer_id);
|
||
|
#else
|
||
|
power_pwr_up_timer(timer_id);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static void timer_chan_deinit_common(timer_id_t timer_id)
|
||
|
{
|
||
|
timer_hal_stop_common(&s_timer.hal, timer_id);
|
||
|
timer_hal_reset_config_to_default(&s_timer.hal, timer_id);
|
||
|
#if (CONFIG_SYSTEM_CTRL)
|
||
|
timer_clock_disable(timer_id);
|
||
|
#else
|
||
|
power_pwr_down_timer(timer_id);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static void timer_chan_enable_interrupt_common(timer_id_t timer_id)
|
||
|
{
|
||
|
#if (CONFIG_SYSTEM_CTRL)
|
||
|
timer_interrupt_enable(timer_id);
|
||
|
#else
|
||
|
icu_enable_timer_interrupt();
|
||
|
#endif
|
||
|
timer_hal_enable_interrupt(&s_timer.hal, timer_id);
|
||
|
}
|
||
|
|
||
|
#if CONFIG_TIMER_PM_CB_SUPPORT
|
||
|
static bk_err_t timer_pm_backup(uint64_t sleep_time, void *args)
|
||
|
{
|
||
|
uint32_t group_id = (uint32_t)args;
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
|
||
|
if (group_id > SOC_TIMER_GROUP_NUM - 1)
|
||
|
return BK_FAIL;
|
||
|
|
||
|
if (group_id < 1)
|
||
|
return BK_OK;
|
||
|
|
||
|
for (group_id; group_id < SOC_TIMER_GROUP_NUM; group_id++ )
|
||
|
{
|
||
|
if (!s_timer.pm_bakeup_is_valid)
|
||
|
{
|
||
|
timer_hal_backup(&s_timer.hal, group_id, s_timer.pm_backup[group_id - 1]);
|
||
|
s_timer.pm_bakeup_is_valid = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
static bk_err_t timer_pm_restore(uint64_t sleep_time, void *args)
|
||
|
{
|
||
|
uint32_t group_id = (uint32_t)args;
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
|
||
|
if (group_id > SOC_TIMER_GROUP_NUM - 1)
|
||
|
return BK_FAIL;
|
||
|
|
||
|
if (group_id < 1)
|
||
|
return BK_OK;
|
||
|
|
||
|
for (group_id; group_id < SOC_TIMER_GROUP_NUM; group_id++ )
|
||
|
{
|
||
|
if (s_timer.pm_bakeup_is_valid)
|
||
|
{
|
||
|
timer_hal_restore(&s_timer.hal, group_id, s_timer.pm_backup[group_id - 1]);
|
||
|
s_timer.pm_bakeup_is_valid = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
static void timer_register_lvsleep_cb(uint32_t group_id)
|
||
|
{
|
||
|
pm_cb_conf_t timer_enter_config = {
|
||
|
.cb = (pm_cb)timer_pm_backup,
|
||
|
.args = (void *)group_id
|
||
|
};
|
||
|
|
||
|
switch(group_id)
|
||
|
{
|
||
|
case 0:
|
||
|
break; // timer0 of BK7236 is in AON domain
|
||
|
case 1:
|
||
|
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_BAKP_TIMER1, PM_POWER_MODULE_STATE_ON);
|
||
|
bk_pm_sleep_register_cb(PM_MODE_LOW_VOLTAGE, PM_DEV_ID_TIMER_1, &timer_enter_config, NULL);
|
||
|
bk_pm_module_lv_sleep_state_clear(PM_DEV_ID_TIMER_1);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void timer_unregister_lvsleep_cb(uint32_t group_id)
|
||
|
{
|
||
|
switch(group_id)
|
||
|
{
|
||
|
case 0:
|
||
|
break;
|
||
|
case 1:
|
||
|
bk_pm_sleep_unregister_cb(PM_MODE_LOW_VOLTAGE, PM_DEV_ID_TIMER_1, true, true);
|
||
|
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_BAKP_TIMER1, PM_POWER_MODULE_STATE_OFF);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void timer_isr(void) __BK_SECTION(".itcm");
|
||
|
|
||
|
bk_err_t bk_timer_driver_init(void)
|
||
|
{
|
||
|
if (s_timer_driver_is_init) {
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
os_memset(&s_timer, 0, sizeof(s_timer));
|
||
|
os_memset(&s_timer_isr, 0, sizeof(s_timer_isr));
|
||
|
|
||
|
#if CONFIG_TIMER_PM_CB_SUPPORT
|
||
|
for(uint32_t group_id = 1; group_id < SOC_TIMER_GROUP_NUM; group_id++)
|
||
|
{
|
||
|
timer_register_lvsleep_cb(group_id);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
bk_int_isr_register(INT_SRC_TIMER, timer_isr, NULL);
|
||
|
#if (SOC_TIMER_INTERRUPT_NUM > 1)
|
||
|
bk_int_isr_register(INT_SRC_TIMER1, timer1_isr, NULL);
|
||
|
#endif
|
||
|
timer_hal_init(&s_timer.hal);
|
||
|
|
||
|
s_timer_driver_is_init = true;
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
bk_err_t bk_timer_driver_deinit(void)
|
||
|
{
|
||
|
if (!s_timer_driver_is_init) {
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
#if CONFIG_TIMER_PM_CB_SUPPORT
|
||
|
for (uint32_t group_id = 1; group_id < SOC_TIMER_GROUP_NUM; group_id++)
|
||
|
{
|
||
|
timer_unregister_lvsleep_cb(group_id);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
for (int chan = 0; chan < SOC_TIMER_CHAN_NUM_PER_UNIT; chan++) {
|
||
|
timer_chan_deinit_common(chan);
|
||
|
}
|
||
|
|
||
|
s_timer_driver_is_init = false;
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
extern void delay(int num);//TODO fix me
|
||
|
|
||
|
bk_err_t bk_timer_start_without_callback(timer_id_t timer_id, uint32_t time_ms)
|
||
|
{
|
||
|
uint32_t en_status = 0;
|
||
|
|
||
|
#if CONFIG_TIMER_US
|
||
|
if (timer_id == TIMER_ID0) {
|
||
|
TIMER_LOGE("timer0 is reserved for us timer!\r\n");
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
TIMER_RETURN_ON_INVALID_ID(timer_id);
|
||
|
|
||
|
TIMER_PM_CHECK_RESTORE(timer_id);
|
||
|
|
||
|
timer_chan_init_common(timer_id);
|
||
|
|
||
|
#if !CONFIG_RTC_TIMER_PRECISION_TEST
|
||
|
timer_chan_enable_interrupt_common(timer_id);
|
||
|
#endif
|
||
|
|
||
|
en_status = timer_hal_get_enable_status(&s_timer.hal);
|
||
|
if (en_status & BIT(timer_id)) {
|
||
|
TIMER_LOGD("timer(%d) is running, stop it\r\n", timer_id);
|
||
|
timer_hal_disable(&s_timer.hal, timer_id);
|
||
|
/* Delay to fix the bug that timer counter becomes bigger than
|
||
|
* timer period. Once timer counter becomes bigger than timer period,
|
||
|
* the timer will never timeout, or takes very very long time to
|
||
|
* timeout.
|
||
|
*
|
||
|
* This issue is firstly observed in HOS tick timer. HOS restarts
|
||
|
* the tick timer with different time_ms(timer period) again and again,
|
||
|
* without the delay, the tick timer counter becomes bigger than timer
|
||
|
* period very soon, then the tick interrupt will never be triggered.
|
||
|
* */
|
||
|
delay(4);
|
||
|
}
|
||
|
|
||
|
timer_hal_init_timer(&s_timer.hal, timer_id, time_ms, TIMER_UNIT_MS);
|
||
|
timer_hal_start_common(&s_timer.hal, timer_id);
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
bk_err_t bk_timer_start(timer_id_t timer_id, uint32_t time_ms, timer_isr_t callback)
|
||
|
{
|
||
|
#if CONFIG_TIMER_US
|
||
|
if (timer_id == TIMER_ID0) {
|
||
|
TIMER_LOGE("timer0 is reserved for us timer!\r\n");
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if CONFIG_TIMER_SUPPORT_ID_BITS
|
||
|
TIMER_RETURN_TIMER_ID_IS_ERR(timer_id);
|
||
|
#endif
|
||
|
BK_LOG_ON_ERR(bk_timer_start_without_callback(timer_id, time_ms));
|
||
|
|
||
|
if (timer_id < SOC_TIMER_CHAN_NUM_PER_UNIT){
|
||
|
s_timer_isr[timer_id] = callback;
|
||
|
}
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
bk_err_t bk_timer_stop(timer_id_t timer_id)
|
||
|
{
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
#if CONFIG_TIMER_SUPPORT_ID_BITS
|
||
|
TIMER_RETURN_TIMER_ID_IS_ERR(timer_id);
|
||
|
#endif
|
||
|
TIMER_RETURN_ON_INVALID_ID(timer_id);
|
||
|
|
||
|
TIMER_PM_CHECK_RESTORE(timer_id);
|
||
|
|
||
|
timer_hal_stop_common(&s_timer.hal, timer_id);
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
bk_err_t bk_timer_cancel(timer_id_t timer_id)
|
||
|
{
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
#if CONFIG_TIMER_SUPPORT_ID_BITS
|
||
|
TIMER_RETURN_TIMER_ID_IS_ERR(timer_id);
|
||
|
#endif
|
||
|
TIMER_RETURN_ON_INVALID_ID(timer_id);
|
||
|
|
||
|
TIMER_PM_CHECK_RESTORE(timer_id);
|
||
|
|
||
|
timer_ll_reset_config_to_default(s_timer.hal.hw, timer_id);
|
||
|
|
||
|
s_timer_isr[timer_id] = NULL;
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
uint32_t bk_timer_get_cnt(timer_id_t timer_id)
|
||
|
{
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
TIMER_RETURN_ON_INVALID_ID(timer_id);
|
||
|
|
||
|
TIMER_PM_CHECK_RESTORE(timer_id);
|
||
|
|
||
|
return timer_hal_get_count(&s_timer.hal, timer_id);
|
||
|
}
|
||
|
|
||
|
bk_err_t bk_timer_enable(timer_id_t timer_id)
|
||
|
{
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
TIMER_RETURN_ON_INVALID_ID(timer_id);
|
||
|
|
||
|
TIMER_PM_CHECK_RESTORE(timer_id);
|
||
|
|
||
|
timer_hal_enable(&s_timer.hal, timer_id);
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
bk_err_t bk_timer_disable(timer_id_t timer_id)
|
||
|
{
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
TIMER_RETURN_ON_INVALID_ID(timer_id);
|
||
|
|
||
|
TIMER_PM_CHECK_RESTORE(timer_id);
|
||
|
|
||
|
timer_hal_disable(&s_timer.hal, timer_id);
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
uint32_t bk_timer_get_period(timer_id_t timer_id)
|
||
|
{
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
TIMER_RETURN_ON_INVALID_ID(timer_id);
|
||
|
|
||
|
TIMER_PM_CHECK_RESTORE(timer_id);
|
||
|
|
||
|
return timer_hal_get_end_count(&s_timer.hal, timer_id);
|
||
|
}
|
||
|
|
||
|
uint32_t bk_timer_get_enable_status(void)
|
||
|
{
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
return timer_hal_get_enable_status(&s_timer.hal);
|
||
|
}
|
||
|
|
||
|
bool bk_timer_is_interrupt_triggered(timer_id_t timer_id)
|
||
|
{
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
TIMER_RETURN_ON_INVALID_ID(timer_id);
|
||
|
|
||
|
TIMER_PM_CHECK_RESTORE(timer_id);
|
||
|
|
||
|
uint32_t int_status = timer_hal_get_interrupt_status(&s_timer.hal);
|
||
|
return timer_hal_is_interrupt_triggered(&s_timer.hal, timer_id, int_status);
|
||
|
}
|
||
|
|
||
|
uint32_t timer_clear_isr_status(void)
|
||
|
{
|
||
|
uint32_t int_status;
|
||
|
timer_hal_t *hal = &s_timer.hal;
|
||
|
|
||
|
int_status = timer_hal_get_interrupt_status(hal);
|
||
|
timer_hal_clear_interrupt_status(hal, int_status);
|
||
|
|
||
|
return int_status;
|
||
|
}
|
||
|
|
||
|
static void timer_isr(void)
|
||
|
{
|
||
|
uint32_t int_status;
|
||
|
timer_hal_t *hal = &s_timer.hal;
|
||
|
|
||
|
int_status = timer_clear_isr_status();
|
||
|
|
||
|
#if (SOC_TIMER_INTERRUPT_NUM > 1)
|
||
|
for(int chan = 0; chan < SOC_TIMER_CHAN_NUM_PER_GROUP; chan++) {
|
||
|
#else
|
||
|
for(int chan = 0; chan < SOC_TIMER_CHAN_NUM_PER_UNIT; chan++) {
|
||
|
#endif
|
||
|
if(timer_hal_is_interrupt_triggered(hal, chan, int_status)) {
|
||
|
if(s_timer_isr[chan]) {
|
||
|
s_timer_isr[chan](chan);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if (SOC_TIMER_INTERRUPT_NUM > 1)
|
||
|
static void timer1_isr(void)
|
||
|
{
|
||
|
uint32_t int_status;
|
||
|
timer_hal_t *hal = &s_timer.hal;
|
||
|
|
||
|
int_status = timer_clear_isr_status();
|
||
|
|
||
|
for(int chan = SOC_TIMER_CHAN_NUM_PER_GROUP; chan < SOC_TIMER_CHAN_NUM_PER_UNIT; chan++) {
|
||
|
if(timer_hal_is_interrupt_triggered(hal, chan, int_status)) {
|
||
|
if(s_timer_isr[chan]) {
|
||
|
s_timer_isr[chan](chan);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
uint64_t bk_timer_get_time(timer_id_t timer_id, uint32_t div, uint32_t last_count, timer_value_unit_t unit_type)
|
||
|
{
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
TIMER_RETURN_ON_INVALID_ID(timer_id);
|
||
|
|
||
|
TIMER_PM_CHECK_RESTORE(timer_id);
|
||
|
|
||
|
uint64_t current_time = 0;
|
||
|
uint64_t unit_factor = 1;
|
||
|
|
||
|
uint64_t current_count = timer_hal_get_count(&s_timer.hal, timer_id) + last_count;
|
||
|
|
||
|
if (div == 0) {
|
||
|
div = 1;
|
||
|
}
|
||
|
|
||
|
#if (CONFIG_SYSTEM_CTRL)
|
||
|
uint32_t group_index = 0;
|
||
|
uint32_t timer_clock = TIMER_SCLK_XTAL;
|
||
|
|
||
|
group_index = timer_id / SOC_TIMER_CHAN_NUM_PER_GROUP;
|
||
|
switch(group_index)
|
||
|
{
|
||
|
case 0:
|
||
|
timer_clock = sys_hal_timer_select_clock_get(SYS_SEL_TIMER0);
|
||
|
break;
|
||
|
case 1:
|
||
|
timer_clock = sys_hal_timer_select_clock_get(SYS_SEL_TIMER1);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
unit_factor = (unit_type == TIMER_UNIT_MS) ? 1 : 1000;
|
||
|
|
||
|
if(timer_clock == TIMER_SCLK_XTAL) {
|
||
|
current_time = unit_factor * current_count * (uint64_t)div / TIMER_CLOCK_FREQ_26M;
|
||
|
} else {
|
||
|
current_time = unit_factor * current_count * (uint64_t)div / TIMER_CLOCK_FREQ_32K;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
if (timer_id < SOC_TIMER_CHAN_NUM_PER_GROUP) {
|
||
|
current_time = unit_factor * current_count * div / TIMER_CLOCK_FREQ_26M;
|
||
|
} else {
|
||
|
current_time = unit_factor * current_count * div / TIMER_CLOCK_FREQ_32K;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return current_time;
|
||
|
}
|
||
|
|
||
|
bk_err_t bk_timer_delay_with_callback(timer_id_t timer_id, uint64_t time_us, timer_isr_t callback)
|
||
|
{
|
||
|
TIMER_RETURN_ON_NOT_INIT();
|
||
|
TIMER_RETURN_ON_INVALID_ID(timer_id);
|
||
|
|
||
|
#if CONFIG_TIMER_SUPPORT_ID_BITS
|
||
|
TIMER_RETURN_TIMER_ID_IS_ERR(timer_id);
|
||
|
#endif
|
||
|
uint64_t current_count = 0;
|
||
|
uint64_t delta_count = 0;
|
||
|
uint64_t end_count = 0;
|
||
|
|
||
|
TIMER_PM_CHECK_RESTORE(timer_id);
|
||
|
|
||
|
timer_chan_init_common(timer_id);
|
||
|
timer_chan_enable_interrupt_common(timer_id);
|
||
|
|
||
|
current_count = timer_hal_get_count(&s_timer.hal, timer_id);
|
||
|
delta_count = timer_hal_cal_end_count(timer_id, time_us, 1, TIMER_UNIT_US);
|
||
|
end_count = current_count + delta_count;
|
||
|
|
||
|
if(end_count > 0xFFFFFFFFFFFFFFFF){
|
||
|
end_count = 0xFFFFFFFFFFFFFFFF;
|
||
|
}
|
||
|
|
||
|
timer_ll_set_end_count(s_timer.hal.hw, timer_id, (uint32_t)end_count);
|
||
|
timer_ll_set_clk_div(s_timer.hal.hw, timer_id, 0);
|
||
|
timer_ll_clear_chan_interrupt_status(s_timer.hal.hw, timer_id);
|
||
|
|
||
|
timer_hal_start_common(&s_timer.hal, timer_id);
|
||
|
|
||
|
s_timer_isr[timer_id] = callback;
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
#if CONFIG_TIMER_US
|
||
|
__IRAM_SEC void bk_timer_delay_us(uint32_t us)
|
||
|
{
|
||
|
timer_hal_delay_us(us);
|
||
|
}
|
||
|
#endif
|