对比新文件 |
| | |
| | | /* |
| | | * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and |
| | | * its subsidiaries and affiliates (collectly called MKSEMI). |
| | | * |
| | | * All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * 1. Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * |
| | | * 2. Redistributions in binary form, except as embedded into an MKSEMI |
| | | * integrated circuit in a product or a software update for such product, |
| | | * must reproduce the above copyright notice, this list of conditions and |
| | | * the following disclaimer in the documentation and/or other materials |
| | | * provided with the distribution. |
| | | * |
| | | * 3. Neither the name of MKSEMI nor the names of its contributors may be used |
| | | * to endorse or promote products derived from this software without |
| | | * specific prior written permission. |
| | | * |
| | | * 4. This software, with or without modification, must only be used with a |
| | | * MKSEMI integrated circuit. |
| | | * |
| | | * 5. Any software provided in binary form under this license must not be |
| | | * reverse engineered, decompiled, modified and/or disassembled. |
| | | * |
| | | * THIS SOFTWARE IS PROVIDED BY MKSEMI "AS IS" AND ANY EXPRESS OR IMPLIED |
| | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| | | * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| | | * DISCLAIMED. IN NO EVENT SHALL MKSEMI OR CONTRIBUTORS BE LIABLE FOR ANY |
| | | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| | | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| | | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| | | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| | | */ |
| | | |
| | | #include "mk_sleep_timer.h" |
| | | #include "mk_trace.h" |
| | | #include "mk_clock.h" |
| | | #include "mk_power.h" |
| | | |
| | | #define SLEEP_TIMER_REG_STDR (RTC_BASE + 0x20) |
| | | #define SLEEP_TIMER_REG_STCR (RTC_BASE + 0x2C) |
| | | |
| | | #define SLEEP_TIMER_INT_STATUS (0x80000000) |
| | | #define SLEEP_TIMER_INT_CLR (0x00000004) |
| | | |
| | | static struct SLEEP_TIMER_HANDLE_T sleep_timer_handle = { |
| | | .mode = SLEEP_TIMER_MODE_ONESHOT, |
| | | .time = 32768, |
| | | .int_en = true, |
| | | .ppm = 0, |
| | | .callback = NULL, |
| | | }; |
| | | |
| | | void sleep_timer_open(bool int_en, enum SLEEP_TIMER_MODE_T mode, drv_callback_t callback) |
| | | { |
| | | // need open RTC clock |
| | | clock_enable(CLOCK_RTC); |
| | | |
| | | // disable sleep timer and clear int status |
| | | REG_WRITE(SLEEP_TIMER_REG_STCR, SLEEP_TIMER_MODE_STOP | SLEEP_TIMER_INT_CLR); |
| | | |
| | | sleep_timer_handle.callback = callback; |
| | | sleep_timer_handle.int_en = int_en; |
| | | sleep_timer_handle.mode = mode; |
| | | |
| | | if (sleep_timer_handle.int_en) |
| | | { |
| | | NVIC_SetPriority(SLEEP_TIMER_IRQn, IRQ_PRIORITY_NORMAL); |
| | | NVIC_ClearPendingIRQ(SLEEP_TIMER_IRQn); |
| | | NVIC_EnableIRQ(SLEEP_TIMER_IRQn); |
| | | } |
| | | |
| | | // enable sleep timer as wakeup source |
| | | power_wakeup_enable(POWER_WAKEUP_BY_SLEEP_TIMER, POWER_WAKEUP_LEVEL_NONE); |
| | | } |
| | | |
| | | void sleep_timer_close(void) |
| | | { |
| | | // disable sleep timer and clear int status |
| | | REG_WRITE(SLEEP_TIMER_REG_STCR, SLEEP_TIMER_MODE_STOP | SLEEP_TIMER_INT_CLR); |
| | | |
| | | if (sleep_timer_handle.int_en) |
| | | { |
| | | NVIC_DisableIRQ(SLEEP_TIMER_IRQn); |
| | | NVIC_ClearPendingIRQ(SLEEP_TIMER_IRQn); |
| | | } |
| | | } |
| | | |
| | | void sleep_timer_start(uint32_t time) |
| | | { |
| | | sleep_timer_handle.time = (uint32_t)((int32_t)time + (int32_t)((int32_t)time * sleep_timer_handle.ppm / 1000000)); |
| | | |
| | | // disable sleep timer |
| | | REG_WRITE(SLEEP_TIMER_REG_STCR, SLEEP_TIMER_MODE_STOP); |
| | | |
| | | // set sleep timer |
| | | REG_WRITE(SLEEP_TIMER_REG_STDR, sleep_timer_handle.time); |
| | | |
| | | // enable sleep timer |
| | | REG_WRITE(SLEEP_TIMER_REG_STCR, sleep_timer_handle.mode); |
| | | } |
| | | |
| | | void sleep_timer_stop(void) |
| | | { |
| | | // disable sleep timer |
| | | REG_WRITE(SLEEP_TIMER_REG_STCR, SLEEP_TIMER_MODE_STOP); |
| | | } |
| | | |
| | | uint32_t high_xtal_off_time(void) |
| | | { |
| | | #ifdef UWB_EN |
| | | uint32_t slp_cnt = REG_READ(0x40000074); |
| | | return (uint32_t)((int32_t)slp_cnt - (int32_t)((int32_t)slp_cnt * sleep_timer_handle.ppm / 1000000)); |
| | | #else |
| | | return REG_READ(SLEEP_TIMER_REG_STDR); |
| | | #endif |
| | | } |
| | | |
| | | void sleep_timer_ppm_set(int32_t ppm) |
| | | { |
| | | sleep_timer_handle.ppm = ppm; |
| | | } |
| | | |
| | | int32_t sleep_timer_ppm_get(void) |
| | | { |
| | | return sleep_timer_handle.ppm; |
| | | } |
| | | |
| | | void SLEEP_TIMER_IRQHandler(void) |
| | | { |
| | | uint32_t int_stat = REG_READ(SLEEP_TIMER_REG_STCR); |
| | | |
| | | if (int_stat & SLEEP_TIMER_INT_STATUS) |
| | | { |
| | | // clear interrupt status |
| | | if (sleep_timer_handle.mode == SLEEP_TIMER_MODE_ONESHOT) |
| | | { |
| | | REG_WRITE(SLEEP_TIMER_REG_STCR, SLEEP_TIMER_MODE_STOP | SLEEP_TIMER_INT_CLR); |
| | | } |
| | | else |
| | | { |
| | | REG_WRITE(SLEEP_TIMER_REG_STCR, sleep_timer_handle.mode | SLEEP_TIMER_INT_CLR); |
| | | } |
| | | |
| | | if (sleep_timer_handle.callback != NULL) |
| | | { |
| | | sleep_timer_handle.callback(NULL, sleep_timer_handle.time); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | ASSERT(0, "Unexpected sleep interrupt"); |
| | | } |
| | | } |