WXK
2025-02-11 e328ebef585cea2351b37117b2d5ac4978ecd3c0
keil/include/components/wsf/sources/port/baremetal/wsf_timer.c
@@ -1,67 +1,14 @@
/*************************************************************************************************/
/*!
 *  \file   wsf_timer.c
 *
 *  \brief  Timer service.
 *
 *  Copyright (c) 2009-2019 Arm Ltd. All Rights Reserved.
 *
 *  Copyright (c) 2019-2020 Packetcraft, Inc.
 *
 *  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 "wsf_types.h"
#include "wsf_queue.h"
#include "wsf_timer.h"
#include "wsf_assert.h"
#include "wsf_cs.h"
#include "wsf_trace.h"
#include "pal_sys.h"
/**************************************************************************************************
  Macros
**************************************************************************************************/
#if (WSF_MS_PER_TICK == 10)
/*! \brief  WSF timer ticks per second. */
#define WSF_TIMER_TICKS_PER_SEC (1000 / WSF_MS_PER_TICK)
/* convert seconds to timer ticks */
#define WSF_TIMER_SEC_TO_TICKS(sec) (WSF_TIMER_TICKS_PER_SEC * (sec))
/* convert milliseconds to timer ticks */
#define WSF_TIMER_MS_TO_TICKS(ms) ((ms) / WSF_MS_PER_TICK)
#else
#error "WSF_TIMER_MS_TO_TICKS and WSF_TIMER_SEC_TO_TICKS not defined for WSF_MS_PER_TICK"
#endif
/*! \brief  Minimum RTC ticks required to go into sleep. */
#define WSF_TIMER_MIN_MS_FOR_POWERDOWN (2)
#define WSF_TIMER_MAX_MS_FOR_POWERDOWN (10000)
#include "mk_common.h"
#include "mk_misc.h"
// #include "mk_trace.h"
/**************************************************************************************************
  Global Variables
**************************************************************************************************/
static wsfQueue_t wsfTimerTimerQueue; /*!< Timer queue */
/*! \brief  Last SysTick value read. */
static uint32_t wsfTimerSysTickcLastTick = 0;
/*************************************************************************************************/
/*!
@@ -88,7 +35,7 @@
        pElem = pElem->pNext;
    }
    /* if timer found remove from queue */
    /* if timer found, remove from queue */
    if (pElem != NULL)
    {
        WsfQueueRemove(&wsfTimerTimerQueue, pTimer, pPrev);
@@ -106,13 +53,12 @@
 *  \param  mode    Timer work mode.
 */
/*************************************************************************************************/
static void wsfTimerInsert(wsfTimer_t *pTimer, wsfTimerTicks_t ticks, uint8_t mode)
static void wsfTimerInsert(wsfTimer_t *pTimer, uint32_t ticks, uint8_t mode)
{
    wsfTimer_t *pElem;
    wsfTimer_t *pPrev = NULL;
    /* task schedule lock */
    uint32_t lock = WsfTaskLock();
    uint32_t lock = int_lock();
    /* if timer is already running stop it first */
    if (pTimer->isStarted)
@@ -138,11 +84,8 @@
        pElem = pElem->pNext;
    }
    /* insert timer into queue */
    WsfQueueInsert(&wsfTimerTimerQueue, pTimer, pPrev);
    /* task schedule unlock */
    WsfTaskUnlock(lock);
    int_unlock(lock);
}
/*************************************************************************************************/
@@ -151,32 +94,24 @@
 *          function can return zero even if a timer is running, indicating a timer
 *          has expired but has not yet been serviced.
 *
 *  \param  pTimerRunning   Returns TRUE if a timer is running, FALSE if no timers running.
 *
 *  \return The number of ticks until the next timer expiration.
 */
/*************************************************************************************************/
static wsfTimerTicks_t WsfTimerNextExpiration(bool_t *pTimerRunning)
uint32_t WsfTimerNextExpiration(void)
{
    wsfTimerTicks_t ticks;
    /* task schedule lock */
    uint32_t lock = WsfTaskLock();
    uint32_t ticks;
    uint32_t lock = int_lock();
    if (wsfTimerTimerQueue.pHead == NULL)
    {
        *pTimerRunning = FALSE;
        ticks = 0;
        ticks = UINT32_MAX;
    }
    else
    {
        *pTimerRunning = TRUE;
        ticks = ((wsfTimer_t *)wsfTimerTimerQueue.pHead)->ticks;
    }
    /* task schedule unlock */
    WsfTaskUnlock(lock);
    int_unlock(lock);
    return ticks;
}
@@ -193,19 +128,16 @@
/*************************************************************************************************/
/*!
 *  \brief  Start a timer in units of seconds.
 *  \brief  Start a timer in units of 32768Hz ticks.
 *
 *  \param  pTimer  Pointer to timer.
 *  \param  sec     Seconds until expiration.
 *  \param  ticks   32768Hz ticks until expiration.
 *  \param  mode    Timer work mode.
 */
/*************************************************************************************************/
void WsfTimerStartSec(wsfTimer_t *pTimer, wsfTimerTicks_t sec, uint8_t mode)
void WsfTimerStartTick(wsfTimer_t *pTimer, uint32_t ticks, uint8_t mode)
{
    WSF_TRACE_INFO2("WsfTimerStartSec pTimer:0x%x ticks:%u", (uint32_t)pTimer, WSF_TIMER_SEC_TO_TICKS(sec));
    /* insert timer into queue */
    wsfTimerInsert(pTimer, WSF_TIMER_SEC_TO_TICKS(sec), mode);
    wsfTimerInsert(pTimer, ticks, mode);
}
/*************************************************************************************************/
@@ -217,12 +149,9 @@
 *  \param  mode    Timer work mode.
 */
/*************************************************************************************************/
void WsfTimerStartMs(wsfTimer_t *pTimer, wsfTimerTicks_t ms, uint8_t mode)
void WsfTimerStartMs(wsfTimer_t *pTimer, uint32_t ms, uint8_t mode)
{
    WSF_TRACE_INFO2("WsfTimerStartMs pTimer:0x%x ticks:%u", (uint32_t)pTimer, WSF_TIMER_MS_TO_TICKS(ms));
    /* insert timer into queue */
    wsfTimerInsert(pTimer, WSF_TIMER_MS_TO_TICKS(ms), mode);
    wsfTimerInsert(pTimer, __MS_TO_32K_CNT(ms), mode);
}
/*************************************************************************************************/
@@ -234,15 +163,11 @@
/*************************************************************************************************/
void WsfTimerStop(wsfTimer_t *pTimer)
{
    WSF_TRACE_INFO1("WsfTimerStop pTimer:0x%x", pTimer);
    /* task schedule lock */
    uint32_t lock = WsfTaskLock();
    uint32_t lock = int_lock();
    wsfTimerRemove(pTimer);
    /* task schedule unlock */
    WsfTaskUnlock(lock);
    int_unlock(lock);
}
/*************************************************************************************************/
@@ -252,12 +177,11 @@
 *  \param  ticks  Number of ticks since last update.
 */
/*************************************************************************************************/
void WsfTimerUpdate(wsfTimerTicks_t ticks)
void WsfTimerUpdate(uint32_t ticks)
{
    wsfTimer_t *pElem;
    /* task schedule lock */
    uint32_t lock = WsfTaskLock();
    uint32_t lock = int_lock();
    pElem = (wsfTimer_t *)wsfTimerTimerQueue.pHead;
@@ -272,37 +196,36 @@
        else
        {
            pElem->ticks = 0;
        }
        if (pElem->ticks < POWER_DOWN_TIME_TICK_MIN)
        {
            pElem->ticks = 0;
            /* timer expired; set task for this timer as ready */
            WsfTaskSetReady(pElem->handlerId, WSF_TIMER_EVENT);
        }
        // LOG_INFO(TRACE_MODULE_OS, "WsfTimerUpdate  %u %u %u %u\r\n", pElem->handlerId, pElem->msg.event, pElem->ticks, ticks);
        pElem = pElem->pNext;
    }
    /* task schedule unlock */
    WsfTaskUnlock(lock);
    int_unlock(lock);
}
/*************************************************************************************************/
/*!
 *  \brief  Service expired timers for the given task.
 *
 *  \param  taskId      Task ID.
 *
 *  \return Pointer to timer or NULL.
 */
/*************************************************************************************************/
wsfTimer_t *WsfTimerServiceExpired(wsfTaskId_t taskId)
wsfTimer_t *WsfTimerServiceExpired(void)
{
    wsfTimer_t *pElem;
    wsfTimer_t *pPrev = NULL;
    /* Unused parameters */
    (void)taskId;
    /* task schedule lock */
    uint32_t lock = WsfTaskLock();
    uint32_t lock = int_lock();
    /* find expired timers in queue */
    pElem = (wsfTimer_t *)wsfTimerTimerQueue.pHead;
@@ -314,101 +237,14 @@
        }
        else
        {
            /* remove timer from queue */
            WsfQueueRemove(&wsfTimerTimerQueue, pElem, pPrev);
            pElem->isStarted = FALSE;
        }
        /* task schedule unlock */
        WsfTaskUnlock(lock);
        WSF_TRACE_INFO1("Timer expired pTimer:0x%x", pElem);
        /* return timer */
        int_unlock(lock);
        return pElem;
    }
    /* task schedule unlock */
    WsfTaskUnlock(lock);
    int_unlock(lock);
    return NULL;
}
/*************************************************************************************************/
/*!
 *  \brief  Function for checking if there is an active timer and if there is enough time to
 *          go to sleep and going to sleep.
 */
/*************************************************************************************************/
uint8_t WsfTimerSleepCheck(uint32_t *sleep_ms)
{
    wsfTimerTicks_t nextExpiration;
    /* If PAL system is busy, no need to sleep. */
    if (PalSysIsBusy())
    {
        // active
        return 0;
    }
    bool_t running;
    nextExpiration = WsfTimerNextExpiration(&running);
    if (running)
    {
        uint32_t awake = WSF_MS_PER_TICK * nextExpiration;
        uint32_t elapsed = PalSysTickElapse();
        /* if we have time to sleep before timer expiration */
        if ((awake - elapsed) > WSF_TIMER_MIN_MS_FOR_POWERDOWN)
        {
            *sleep_ms = awake - elapsed;
            // Power down
            return 2;
        }
        else
        {
            /* Not enough time to go to powerdown. Let the system sleep. */
            // Sleep
            return 1;
        }
    }
    else
    {
        *sleep_ms = WSF_TIMER_MAX_MS_FOR_POWERDOWN;
        // Power down
        return 2;
    }
}
//*****************************************************************************
//
// Calculate the elapsed time, and update the WSF software timers.
//
//*****************************************************************************
void WsfTimerUpdateTicks(void)
{
    uint32_t ui32CurrentTick, ui32ElapsedTicks;
    //
    // Read the continuous systick.
    //
    ui32CurrentTick = PalSysTickGet();
    //
    // Figure out how long it has been since the last time we've read the
    // continuous systick.
    //
    if (ui32CurrentTick > wsfTimerSysTickcLastTick)
    {
        ui32ElapsedTicks = ui32CurrentTick - wsfTimerSysTickcLastTick;
    }
    else
    {
        ui32ElapsedTicks = 0xffffffff - wsfTimerSysTickcLastTick + ui32CurrentTick;
    }
    WsfTimerUpdate(ui32ElapsedTicks);
    wsfTimerSysTickcLastTick = ui32CurrentTick;
}