Files
TencentOS-tiny/kernel/pm/tos_tickless.c
supowang edb2879617 first commit for opensource
first commit for opensource
2019-09-16 13:19:50 +08:00

145 lines
3.5 KiB
C

#include "tos.h"
#if TOS_CFG_TICKLESS_EN > 0u
__API__ void tos_tickless_wkup_alarm_install(k_cpu_lpwr_mode_t mode, k_tickless_wkup_alarm_t *wkup_alarm)
{
k_tickless_wkup_alarm[mode] = wkup_alarm;
}
__API__ k_err_t tos_tickless_wkup_alarm_init(k_cpu_lpwr_mode_t mode)
{
if (!k_tickless_wkup_alarm[mode]) {
return K_ERR_TICKLESS_WKUP_ALARM_NOT_INSTALLED;
}
if (!k_tickless_wkup_alarm[mode]->init) {
return K_ERR_TICKLESS_WKUP_ALARM_NO_INIT;
}
if (k_tickless_wkup_alarm[mode]->init() != 0) {
return K_ERR_TICKLESS_WKUP_ALARM_INIT_FAILED;
}
return K_ERR_NONE;
}
__KERNEL__ int tickless_wkup_alarm_is_installed(k_cpu_lpwr_mode_t mode)
{
return k_tickless_wkup_alarm[mode] != K_NULL;
}
__STATIC__ int tickless_wkup_alarm_setup(k_cpu_lpwr_mode_t mode, k_time_t expires)
{
if (k_tickless_wkup_alarm[mode] && k_tickless_wkup_alarm[mode]->setup) {
return k_tickless_wkup_alarm[mode]->setup(expires);
}
return -1;
}
__STATIC__ int tickless_wkup_alarm_dismiss(k_cpu_lpwr_mode_t mode)
{
if (k_tickless_wkup_alarm[mode] && k_tickless_wkup_alarm[mode]->dismiss) {
return k_tickless_wkup_alarm[mode]->dismiss();
}
return -1;
}
__STATIC__ k_time_t tickless_wkup_alarm_max_delay(k_cpu_lpwr_mode_t mode)
{
if (k_tickless_wkup_alarm[mode] && k_tickless_wkup_alarm[mode]->max_delay) {
return k_tickless_wkup_alarm[mode]->max_delay();
}
return (k_time_t)0u;
}
__STATIC__ k_time_t tickless_cpu_sleep_time_get(k_cpu_lpwr_mode_t lpwr_mode)
{
k_tick_t next_expires;
k_time_t time_sleep_ms, max_delay_ms;
/* the max time(in millisecond) we can sleep */
max_delay_ms = tickless_wkup_alarm_max_delay(lpwr_mode);
next_expires = knl_next_expires_get();
if (next_expires == TOS_TIME_FOREVER) {
return max_delay_ms;
}
/* how much time should we sleep(in millisecond) */
time_sleep_ms = (k_time_t)(next_expires * K_TIME_MILLISEC_PER_SEC / k_cpu_tick_per_second);
return time_sleep_ms > max_delay_ms ? max_delay_ms : time_sleep_ms;
}
__STATIC__ void tickless_systick_suspend(void)
{
cpu_systick_suspend();
cpu_systick_pending_reset();
}
__STATIC__ void tickless_systick_resume(void)
{
cpu_systick_suspend();
cpu_systick_reset();
cpu_systick_resume();
}
__STATIC__ void tickless_systick_fix(k_tick_t tick_sleep)
{
TOS_CPU_CPSR_ALLOC();
TOS_CPU_INT_DISABLE();
/* we wakeup from SLEEP mode, fix the system's tick & timer */
tick_update(tick_sleep);
#if TOS_CFG_TIMER_EN > 0u && TOS_CFG_TIMER_AS_PROC > 0u
timer_update();
#endif
tickless_systick_resume();
TOS_CPU_INT_ENABLE();
}
__STATIC__ void tickless_enter(void)
{
tickless_systick_suspend();
}
__STATIC__ void tickless_leave(k_time_t time_sleep_ms)
{
k_tick_t tick_sleep;
/* how many "ticks" have we sleep */
tick_sleep = k_cpu_tick_per_second * time_sleep_ms / K_TIME_MILLISEC_PER_SEC;
tickless_systick_fix(tick_sleep);
}
__KERNEL__ void tickless_proc(void)
{
k_time_t time_sleep;
k_cpu_lpwr_mode_t lpwr_mode;
lpwr_mode = pm_cpu_lpwr_mode_get();
time_sleep = tickless_cpu_sleep_time_get(lpwr_mode); /* in millisecond */
tickless_enter();
tickless_wkup_alarm_setup(lpwr_mode, time_sleep);
pm_cpu_lpwr_mode_enter(lpwr_mode);
tickless_wkup_alarm_dismiss(lpwr_mode);
tickless_leave(time_sleep);
}
__KERNEL__ void tickless_init(void)
{
pm_idle_pwr_mgr_mode_set(IDLE_POWER_MANAGER_MODE_TICKLESS);
tos_bsp_tickless_setup();
}
#endif