127 lines
3.4 KiB
C
Raw Normal View History

2025-10-10 16:07:00 +08:00
// 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 "timer_hal.h"
#include "timer_ll.h"
#if (CONFIG_SYSTEM_CTRL)
#include "sys_hal.h"
#endif
/*
* timer_s = counter_value * (1 / (freq /div))
*/
uint32_t timer_hal_cal_end_count(timer_id_t chan, uint64_t time, uint32_t div, timer_value_unit_t unit_type)
{
if (div == 0) {
div = 1;
}
uint64_t value = 0;
uint16_t unit_factor = 1;
unit_factor = (unit_type == TIMER_UNIT_MS) ? 1 : 1000;
#if (CONFIG_SYSTEM_CTRL)
uint32_t group_index = 0;
uint32_t timer_clock = TIMER_SCLK_XTAL;
group_index = chan / 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;
}
if(timer_clock == TIMER_SCLK_XTAL) {
value = time * TIMER_CLOCK_FREQ_26M / unit_factor / div;
} else {
value = time * TIMER_CLOCK_FREQ_32K / unit_factor / div;
}
#else
if (chan < SOC_TIMER_CHAN_NUM_PER_GROUP) {
value = time * TIMER_CLOCK_FREQ_26M / unit_factor / div;
} else {
value = time * TIMER_CLOCK_FREQ_32K / unit_factor / div;
}
#endif
if (value > 0xffffffff)
value = 0xffffffff;
return (uint32_t)value;
}
bk_err_t timer_hal_init(timer_hal_t *hal)
{
hal->hw = (timer_hw_t *)TIMER_LL_REG_BASE(hal->id);
for (int chan = 0; chan < SOC_TIMER_CHAN_NUM_PER_UNIT; chan++) {
timer_ll_init(hal->hw, chan);
}
return BK_OK;
}
bk_err_t timer_hal_init_timer(timer_hal_t *hal, timer_id_t chan, uint64_t time, timer_value_unit_t unit_type)
{
uint32_t end_count = timer_hal_cal_end_count(chan, time, 1, unit_type);
timer_ll_set_end_count(hal->hw, chan, end_count);
timer_ll_set_clk_div(hal->hw, chan, 0);
timer_ll_clear_chan_interrupt_status(hal->hw, chan);
return BK_OK;
}
bk_err_t timer_hal_set_period(timer_hal_t *hal, timer_id_t chan, uint32_t time_ms)
{
uint32_t end_count = timer_hal_cal_end_count(chan, time_ms, 1, TIMER_UNIT_MS);
timer_ll_set_end_count(hal->hw, chan, end_count);
return BK_OK;
}
bk_err_t timer_hal_start_common(timer_hal_t *hal, timer_id_t chan)
{
timer_ll_enable(hal->hw, chan);
return BK_OK;
}
bk_err_t timer_hal_stop_common(timer_hal_t *hal, timer_id_t chan)
{
timer_ll_disable_interrupt(hal->hw, chan);
timer_ll_clear_chan_interrupt_status(hal->hw, chan);
timer_ll_disable(hal->hw, chan);
return BK_OK;
}
uint32_t timer_hal_get_count(timer_hal_t *hal, timer_id_t chan)
{
uint32_t en_status = timer_ll_get_enable_status(hal->hw);
if (!(en_status & BIT(chan))) {
return 0;
}
timer_ll_set_read_index(hal->hw, chan);
timer_ll_set_cnt_read(hal->hw, chan);
//Wait hardware to prepare the data
BK_WHILE (!timer_ll_is_cnt_read_valid(hal->hw, chan));
return timer_ll_get_timer_count(hal->hw, chan);
}