mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #5854 from SiliconLabs/bugfix/rtc_overflow
Fix for Silicon Labs RTCpull/5865/head
						commit
						3cb9728ae7
					
				| 
						 | 
				
			
			@ -24,6 +24,8 @@
 | 
			
		|||
#ifndef MBED_CLOCKING_H
 | 
			
		||||
#define MBED_CLOCKING_H
 | 
			
		||||
 | 
			
		||||
#include "em_cmu.h"
 | 
			
		||||
 | 
			
		||||
/* Clock definitions */
 | 
			
		||||
#define LFXO    0
 | 
			
		||||
#define HFXO    1
 | 
			
		||||
| 
						 | 
				
			
			@ -51,8 +53,8 @@
 | 
			
		|||
#ifndef CORE_CLOCK_SOURCE
 | 
			
		||||
#define CORE_CLOCK_SOURCE   HFRCO
 | 
			
		||||
#if defined(_CMU_HFRCOCTRL_BAND_MASK)
 | 
			
		||||
#define HFRCO_FREQUENCY_ENUM   _CMU_HFRCOCTRL_BAND_21MHZ 
 | 
			
		||||
#define HFRCO_FREQUENCY        21000000 
 | 
			
		||||
#define HFRCO_FREQUENCY_ENUM   _CMU_HFRCOCTRL_BAND_21MHZ
 | 
			
		||||
#define HFRCO_FREQUENCY        21000000
 | 
			
		||||
#elif defined(_CMU_HFRCOCTRL_FREQRANGE_MASK)
 | 
			
		||||
#define HFRCO_FREQUENCY_ENUM   cmuHFRCOFreq_32M0Hz
 | 
			
		||||
#define HFRCO_FREQUENCY        32000000
 | 
			
		||||
| 
						 | 
				
			
			@ -103,4 +105,13 @@
 | 
			
		|||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Adjust this to change speed of RTC and LP ticker ticks */
 | 
			
		||||
#define RTC_CLOCKDIV        cmuClkDiv_8
 | 
			
		||||
/* Adjust this to match RTC_CLOCKDIV as integer value */
 | 
			
		||||
#define RTC_CLOCKDIV_INT    8U
 | 
			
		||||
/* Adjust this to match RTC_CLOCKDIV as shift for 1 second worth of ticks.
 | 
			
		||||
 * E.g. with 32768 Hz crystal and CLOCKDIV of 8, 1 second is 4096 ticks.
 | 
			
		||||
 * 4096 equals 1 << 12, so RTC_FREQ_SHIFT needs to be 12. */
 | 
			
		||||
#define RTC_FREQ_SHIFT      12U
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,14 +25,25 @@
 | 
			
		|||
#include "clocking.h"
 | 
			
		||||
#if DEVICE_LOWPOWERTIMER
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * The Silicon Labs lp_ticker implementation is mapped on top of an extended RTC
 | 
			
		||||
 * API, since the RTC is available in the lowest energy modes. By default, the
 | 
			
		||||
 * RTC counter is configured to run at 4kHz, giving us a quarter-ms resolution
 | 
			
		||||
 * for the low power timer, which should be good enough for a low power use
 | 
			
		||||
 * case.
 | 
			
		||||
 *
 | 
			
		||||
 * On Silicon Labs devices, the lowest width RTC implementation has a 24-bit
 | 
			
		||||
 * counter, which gets extended with a further 32-bit software counter. This
 | 
			
		||||
 * gives 56 bits of actual width, which with the default speed maps to
 | 
			
		||||
 * 557462 years before the extended RTC counter wraps around. We are pretty
 | 
			
		||||
 * certain no device is going to have that amount of uptime.
 | 
			
		||||
 * (At max speed the wraparound is at 69730 years, which is unlikely as well)
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "rtc_api.h"
 | 
			
		||||
#include "rtc_api_HAL.h"
 | 
			
		||||
#include "lp_ticker_api.h"
 | 
			
		||||
 | 
			
		||||
#include "mbed_critical.h"
 | 
			
		||||
#if (defined RTCC_COUNT) && (RTCC_COUNT > 0)
 | 
			
		||||
#include "em_rtcc.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int rtc_reserved = 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -57,135 +68,55 @@ void lp_ticker_free()
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef RTCC_COUNT
 | 
			
		||||
 | 
			
		||||
/* RTC API */
 | 
			
		||||
 | 
			
		||||
void lp_ticker_set_interrupt(timestamp_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t timestamp_ticks;
 | 
			
		||||
    uint64_t current_ticks = RTC_CounterGet();
 | 
			
		||||
    timestamp_t current_time = ((uint64_t)(current_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT));
 | 
			
		||||
 | 
			
		||||
    /* Initialize RTC */
 | 
			
		||||
    lp_ticker_init();
 | 
			
		||||
    uint64_t rtc_compare_value;
 | 
			
		||||
    uint64_t current_ticks = rtc_get_full();
 | 
			
		||||
    timestamp_t current_time = lp_ticker_read();
 | 
			
		||||
 | 
			
		||||
    /* calculate offset value */
 | 
			
		||||
    timestamp_t offset = timestamp - current_time;
 | 
			
		||||
    if(offset > 0xEFFFFFFF) offset = 100;
 | 
			
		||||
 | 
			
		||||
    /* If the requested timestamp is too far in the future, we might not be able
 | 
			
		||||
     * to set the interrupt accurately due to potentially having ticked between
 | 
			
		||||
     * calculating the timestamp to set and us calculating the offset. */
 | 
			
		||||
    if(offset > 0xFFFF0000) offset = 100;
 | 
			
		||||
 | 
			
		||||
    /* map offset to RTC value */
 | 
			
		||||
    // ticks = offset * RTC frequency div 1000000
 | 
			
		||||
    timestamp_ticks = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000;
 | 
			
		||||
    timestamp_ticks += current_ticks;
 | 
			
		||||
    rtc_compare_value = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000;
 | 
			
		||||
 | 
			
		||||
    /* RTC has 24 bit resolution */
 | 
			
		||||
    timestamp_ticks &= 0xFFFFFF;
 | 
			
		||||
 | 
			
		||||
    /* check for RTC limitation */
 | 
			
		||||
    if((timestamp_ticks - RTC_CounterGet()) >= 0x800000) timestamp_ticks = RTC_CounterGet() + 2;
 | 
			
		||||
 | 
			
		||||
    /* Set callback */
 | 
			
		||||
    RTC_FreezeEnable(true);
 | 
			
		||||
    RTC_CompareSet(0, (uint32_t)timestamp_ticks);
 | 
			
		||||
    RTC_IntEnable(RTC_IF_COMP0);
 | 
			
		||||
    RTC_FreezeEnable(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lp_ticker_fire_interrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    RTC_IntSet(RTC_IFS_COMP0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void lp_ticker_disable_interrupt()
 | 
			
		||||
{
 | 
			
		||||
    RTC_IntDisable(RTC_IF_COMP0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void lp_ticker_clear_interrupt()
 | 
			
		||||
{
 | 
			
		||||
    RTC_IntClear(RTC_IF_COMP0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
timestamp_t lp_ticker_read()
 | 
			
		||||
{
 | 
			
		||||
    lp_ticker_init();
 | 
			
		||||
    
 | 
			
		||||
    uint64_t ticks_temp;
 | 
			
		||||
    uint64_t ticks = RTC_CounterGet();
 | 
			
		||||
 | 
			
		||||
    /* ticks = counter tick value
 | 
			
		||||
     * timestamp = value in microseconds
 | 
			
		||||
     * timestamp = ticks * 1.000.000 / RTC frequency
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    ticks_temp = (ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT);
 | 
			
		||||
    return (timestamp_t) (ticks_temp & 0xFFFFFFFF);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
/* RTCC API */
 | 
			
		||||
 | 
			
		||||
void lp_ticker_set_interrupt(timestamp_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t timestamp_ticks;
 | 
			
		||||
    uint64_t current_ticks = RTCC_CounterGet();
 | 
			
		||||
    timestamp_t current_time = ((uint64_t)(current_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT));
 | 
			
		||||
 | 
			
		||||
    /* Initialize RTC */
 | 
			
		||||
    lp_ticker_init();
 | 
			
		||||
 | 
			
		||||
    /* calculate offset value */
 | 
			
		||||
    timestamp_t offset = timestamp - current_time;
 | 
			
		||||
    if(offset > 0xEFFFFFFF) offset = 100;
 | 
			
		||||
 | 
			
		||||
    /* map offset to RTC value */
 | 
			
		||||
    // ticks = offset * RTC frequency div 1000000
 | 
			
		||||
    timestamp_ticks = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000;
 | 
			
		||||
    // checking the rounding. If timeout is wanted between RTCC ticks, irq should be configured to
 | 
			
		||||
    // trigger in the latter RTCC-tick. Otherwise ticker-api fails to send timer event to its client
 | 
			
		||||
    if(((timestamp_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) < offset){
 | 
			
		||||
        timestamp_ticks++;
 | 
			
		||||
    /* If RTC offset is less then 2 RTC ticks, the interrupt won't fire */
 | 
			
		||||
    if(rtc_compare_value < 2) {
 | 
			
		||||
        rtc_compare_value = 2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    timestamp_ticks += current_ticks;
 | 
			
		||||
    rtc_compare_value += current_ticks;
 | 
			
		||||
 | 
			
		||||
    /* RTCC has 32 bit resolution */
 | 
			
		||||
    timestamp_ticks &= 0xFFFFFFFF;
 | 
			
		||||
 | 
			
		||||
    /* check for RTCC limitation */
 | 
			
		||||
    if((timestamp_ticks - RTCC_CounterGet()) >= 0x80000000) timestamp_ticks = RTCC_CounterGet() + 2;
 | 
			
		||||
 | 
			
		||||
    /* init channel */
 | 
			
		||||
    RTCC_CCChConf_TypeDef ccchConf = RTCC_CH_INIT_COMPARE_DEFAULT;
 | 
			
		||||
    RTCC_ChannelInit(0,&ccchConf);
 | 
			
		||||
    /* Set callback */
 | 
			
		||||
    RTCC_ChannelCCVSet(0, (uint32_t)timestamp_ticks);
 | 
			
		||||
    RTCC_IntEnable(RTCC_IF_CC0);
 | 
			
		||||
    rtc_set_comp0_value(rtc_compare_value, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lp_ticker_fire_interrupt(void)
 | 
			
		||||
inline void lp_ticker_fire_interrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    RTCC_IntSet(RTCC_IFS_CC0);
 | 
			
		||||
    rtc_force_comp0();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void lp_ticker_disable_interrupt()
 | 
			
		||||
{
 | 
			
		||||
    RTCC_IntDisable(RTCC_IF_CC0);
 | 
			
		||||
    rtc_enable_comp0(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void lp_ticker_clear_interrupt()
 | 
			
		||||
{
 | 
			
		||||
    RTCC_IntClear(RTCC_IF_CC0);
 | 
			
		||||
    /* No need to clear interrupt flag, since that already happens at RTC level */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
timestamp_t lp_ticker_read()
 | 
			
		||||
{
 | 
			
		||||
    lp_ticker_init();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    uint64_t ticks_temp;
 | 
			
		||||
    uint64_t ticks = RTCC_CounterGet();
 | 
			
		||||
    uint64_t ticks = rtc_get_full();
 | 
			
		||||
 | 
			
		||||
    /* ticks = counter tick value
 | 
			
		||||
     * timestamp = value in microseconds
 | 
			
		||||
| 
						 | 
				
			
			@ -196,6 +127,4 @@ timestamp_t lp_ticker_read()
 | 
			
		|||
    return (timestamp_t) (ticks_temp & 0xFFFFFFFF);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* RTCC */
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,17 +37,21 @@
 | 
			
		|||
#include "em_rtcc.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static bool         rtc_inited  = false;
 | 
			
		||||
static time_t       time_base   = 0;
 | 
			
		||||
static uint32_t     useflags    = 0;
 | 
			
		||||
static uint32_t     time_extend = 0;
 | 
			
		||||
static bool         rtc_inited      = false;
 | 
			
		||||
static bool         rtc_cancelled   = false;
 | 
			
		||||
static time_t       time_base       = 0;
 | 
			
		||||
static uint32_t     useflags        = 0;
 | 
			
		||||
static uint32_t     time_extend     = 0;
 | 
			
		||||
static uint32_t     extended_comp0  = 0;
 | 
			
		||||
 | 
			
		||||
static void (*comp0_handler)(void) = NULL;
 | 
			
		||||
 | 
			
		||||
#ifndef RTCC_COUNT
 | 
			
		||||
static void (*comp0_handler)(void)  = NULL;
 | 
			
		||||
 | 
			
		||||
#ifndef RTCC_PRESENT
 | 
			
		||||
/* Using RTC API */
 | 
			
		||||
#define RTC_NUM_BITS                (24)
 | 
			
		||||
 | 
			
		||||
#if RTC_CLOCKDIV_INT > 16
 | 
			
		||||
#error invalid prescaler value RTC_CLOCKDIV_INT, since LP ticker resolution will exceed 1ms.
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void RTC_IRQHandler(void)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -60,24 +64,31 @@ void RTC_IRQHandler(void)
 | 
			
		|||
    }
 | 
			
		||||
    if (flags & RTC_IF_COMP0) {
 | 
			
		||||
        RTC_IntClear(RTC_IF_COMP0);
 | 
			
		||||
        if (comp0_handler != NULL) {
 | 
			
		||||
        if (comp0_handler != NULL && ((time_extend == extended_comp0) || (rtc_cancelled))) {
 | 
			
		||||
            rtc_cancelled = false;
 | 
			
		||||
            comp0_handler();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t rtc_get_32bit(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t pending = (RTC_IntGet() & RTC_IF_OF) ? 1 : 0;
 | 
			
		||||
    return (RTC_CounterGet() + ((time_extend + pending) << RTC_NUM_BITS));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint64_t rtc_get_full(void)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t ticks = 0;
 | 
			
		||||
    ticks += time_extend;
 | 
			
		||||
    ticks = ticks << RTC_NUM_BITS;
 | 
			
		||||
    ticks += RTC_CounterGet();
 | 
			
		||||
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        ticks = RTC_CounterGet();
 | 
			
		||||
 | 
			
		||||
        if (RTC_IntGet() & RTC_IF_OF) {
 | 
			
		||||
            RTC_IntClear(RTC_IF_OF);
 | 
			
		||||
            /* RTC has overflowed in a critical section, so handle the overflow here */
 | 
			
		||||
            time_extend += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ticks += (uint64_t)time_extend << RTC_BITS;
 | 
			
		||||
    }
 | 
			
		||||
    while ( (ticks & RTC_MAX_VALUE) != RTC_CounterGet() );
 | 
			
		||||
 | 
			
		||||
    return ticks;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -131,10 +142,38 @@ void rtc_free_real(uint32_t flags)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
void rtc_enable_comp0(bool enable)
 | 
			
		||||
{
 | 
			
		||||
    RTC_FreezeEnable(true);
 | 
			
		||||
    if (!enable) {
 | 
			
		||||
        RTC_IntDisable(RTC_IF_COMP0);
 | 
			
		||||
    } else {
 | 
			
		||||
        RTC_IntEnable(RTC_IF_COMP0);
 | 
			
		||||
    }
 | 
			
		||||
    RTC_FreezeEnable(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_set_comp0_value(uint64_t value, bool enable)
 | 
			
		||||
{
 | 
			
		||||
    rtc_enable_comp0(false);
 | 
			
		||||
 | 
			
		||||
    /* Set callback */
 | 
			
		||||
    RTC_FreezeEnable(true);
 | 
			
		||||
    extended_comp0 = (uint32_t) (value >> RTC_BITS);
 | 
			
		||||
    RTC_CompareSet(0, (uint32_t) (value & RTC_MAX_VALUE));
 | 
			
		||||
    RTC_FreezeEnable(false);
 | 
			
		||||
 | 
			
		||||
    rtc_enable_comp0(enable);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_force_comp0(void)
 | 
			
		||||
{
 | 
			
		||||
    rtc_cancelled = true;
 | 
			
		||||
    RTC_IntSet(RTC_IFS_COMP0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
/* Using RTCC API */
 | 
			
		||||
#define RTCC_NUM_BITS                (32)
 | 
			
		||||
 | 
			
		||||
void RTCC_IRQHandler(void)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -149,23 +188,30 @@ void RTCC_IRQHandler(void)
 | 
			
		|||
 | 
			
		||||
    if (flags & RTCC_IF_CC0) {
 | 
			
		||||
        RTCC_IntClear(RTCC_IF_CC0);
 | 
			
		||||
        if (comp0_handler != NULL) {
 | 
			
		||||
        if (comp0_handler != NULL && ((time_extend == extended_comp0) || (rtc_cancelled))) {
 | 
			
		||||
            comp0_handler();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t rtc_get_32bit(void)
 | 
			
		||||
{
 | 
			
		||||
    return RTCC_CounterGet();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint64_t rtc_get_full(void)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t ticks = 0;
 | 
			
		||||
    ticks += time_extend;
 | 
			
		||||
    ticks = ticks << RTCC_NUM_BITS;
 | 
			
		||||
    ticks += RTCC_CounterGet();
 | 
			
		||||
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        ticks = RTCC_CounterGet();
 | 
			
		||||
 | 
			
		||||
        if (RTCC_IntGet() & RTCC_IF_OF) {
 | 
			
		||||
            RTCC_IntClear(RTCC_IF_OF);
 | 
			
		||||
            /* RTCC has overflowed in critical section, so handle the rollover here */
 | 
			
		||||
            time_extend += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ticks += (uint64_t)time_extend << RTC_BITS;
 | 
			
		||||
    }
 | 
			
		||||
    while ( (ticks & RTC_MAX_VALUE) != RTCC_CounterGet() );
 | 
			
		||||
 | 
			
		||||
    return ticks;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -184,10 +230,18 @@ void rtc_init_real(uint32_t flags)
 | 
			
		|||
        init.enable = 1;
 | 
			
		||||
        init.precntWrapOnCCV0 = false;
 | 
			
		||||
        init.cntWrapOnCCV1 = false;
 | 
			
		||||
#if RTC_CLOCKDIV_INT == 8
 | 
			
		||||
#if RTC_CLOCKDIV_INT == 1
 | 
			
		||||
        init.presc = rtccCntPresc_1;
 | 
			
		||||
#elif RTC_CLOCKDIV_INT == 2
 | 
			
		||||
        init.presc = rtccCntPresc_2;
 | 
			
		||||
#elif RTC_CLOCKDIV_INT == 4
 | 
			
		||||
        init.presc = rtccCntPresc_4;
 | 
			
		||||
#elif RTC_CLOCKDIV_INT == 8
 | 
			
		||||
        init.presc = rtccCntPresc_8;
 | 
			
		||||
#elif RTC_CLOCKDIV_INT == 16
 | 
			
		||||
        init.presc = rtccCntPresc_16;
 | 
			
		||||
#else
 | 
			
		||||
#error invalid prescaler value RTC_CLOCKDIV_INT
 | 
			
		||||
#error invalid prescaler value RTC_CLOCKDIV_INT, since LP ticker resolution will exceed 1ms.
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        /* Enable Interrupt from RTC */
 | 
			
		||||
| 
						 | 
				
			
			@ -220,6 +274,35 @@ void rtc_free_real(uint32_t flags)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_enable_comp0(bool enable)
 | 
			
		||||
{
 | 
			
		||||
    if(!enable) {
 | 
			
		||||
        RTCC_IntDisable(RTCC_IF_CC0);
 | 
			
		||||
    } else {
 | 
			
		||||
        RTCC_IntEnable(RTCC_IF_CC0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_set_comp0_value(uint64_t value, bool enable)
 | 
			
		||||
{
 | 
			
		||||
    rtc_enable_comp0(false);
 | 
			
		||||
 | 
			
		||||
    /* init channel */
 | 
			
		||||
    RTCC_CCChConf_TypeDef ccchConf = RTCC_CH_INIT_COMPARE_DEFAULT;
 | 
			
		||||
    RTCC_ChannelInit(0,&ccchConf);
 | 
			
		||||
    /* Set callback */
 | 
			
		||||
    extended_comp0 = (uint32_t) (value >> RTC_BITS);
 | 
			
		||||
    RTCC_ChannelCCVSet(0, (uint32_t) (value & RTC_MAX_VALUE));
 | 
			
		||||
 | 
			
		||||
    rtc_enable_comp0(enable);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_force_comp0(void)
 | 
			
		||||
{
 | 
			
		||||
    rtc_cancelled = true;
 | 
			
		||||
    RTCC_IntSet(RTCC_IFS_CC0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* RTCC_COUNT */
 | 
			
		||||
 | 
			
		||||
void rtc_set_comp0_handler(uint32_t handler)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,15 +26,18 @@
 | 
			
		|||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "rtc_api.h"
 | 
			
		||||
#include "em_rtc.h"
 | 
			
		||||
#include "clocking.h"
 | 
			
		||||
 | 
			
		||||
#define RTC_CLOCKDIV 		cmuClkDiv_8
 | 
			
		||||
#define RTC_CLOCKDIV_INT	8
 | 
			
		||||
#define RTC_FREQ_SHIFT 		12
 | 
			
		||||
#define RTC_INIT_LPTIMER (1U << 1)
 | 
			
		||||
#define RTC_INIT_RTC     (1U << 0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define RTC_INIT_LPTIMER (1 << 1)
 | 
			
		||||
#define RTC_INIT_RTC     (1 << 0)
 | 
			
		||||
#if defined(RTCC_PRESENT)
 | 
			
		||||
#define RTC_BITS (32U)
 | 
			
		||||
#define RTC_MAX_VALUE (0xFFFFFFFFUL)
 | 
			
		||||
#elif defined(RTC_PRESENT)
 | 
			
		||||
#define RTC_BITS (24U)
 | 
			
		||||
#define RTC_MAX_VALUE (0xFFFFFFUL)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +45,11 @@ extern "C" {
 | 
			
		|||
 | 
			
		||||
/* Purpose of this file: extend rtc_api.h to include EFM-specific stuff*/
 | 
			
		||||
void rtc_set_comp0_handler(uint32_t handler);
 | 
			
		||||
void rtc_enable_comp0(bool enable);
 | 
			
		||||
void rtc_set_comp0_value(uint64_t value, bool enable);
 | 
			
		||||
void rtc_force_comp0(void);
 | 
			
		||||
 | 
			
		||||
uint64_t rtc_get_full(void);
 | 
			
		||||
 | 
			
		||||
void rtc_init_real(uint32_t flags);
 | 
			
		||||
void rtc_free_real(uint32_t flags);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,11 +25,9 @@
 | 
			
		|||
#include "us_ticker_api.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
#include "mbed_sleep.h"
 | 
			
		||||
#include "em_cmu.h"
 | 
			
		||||
#include "em_timer.h"
 | 
			
		||||
#include "clocking.h"
 | 
			
		||||
#include "sleep_api.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Timer functions for microsecond ticker.
 | 
			
		||||
| 
						 | 
				
			
			@ -158,10 +156,6 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
 | 
			
		|||
    uint32_t goal = timestamp;
 | 
			
		||||
    uint32_t trigger;
 | 
			
		||||
 | 
			
		||||
    if((US_TICKER_TIMER->IEN & TIMER_IEN_CC0) == 0) {
 | 
			
		||||
        //Timer was disabled, but is going to be enabled. Set sleep mode.
 | 
			
		||||
        sleep_manager_lock_deep_sleep();
 | 
			
		||||
    }
 | 
			
		||||
    TIMER_IntDisable(US_TICKER_TIMER, TIMER_IEN_CC0);
 | 
			
		||||
 | 
			
		||||
    /* convert us delta value back to timer ticks */
 | 
			
		||||
| 
						 | 
				
			
			@ -215,10 +209,6 @@ void us_ticker_fire_interrupt(void)
 | 
			
		|||
 | 
			
		||||
void us_ticker_disable_interrupt(void)
 | 
			
		||||
{
 | 
			
		||||
    if((US_TICKER_TIMER->IEN & TIMER_IEN_CC0) != 0) {
 | 
			
		||||
        //Timer was enabled, but is going to get disabled. Clear sleepmode.
 | 
			
		||||
        sleep_manager_unlock_deep_sleep();
 | 
			
		||||
    }
 | 
			
		||||
    /* Disable compare channel interrupts */
 | 
			
		||||
    TIMER_IntDisable(US_TICKER_TIMER, TIMER_IEN_CC0);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue