SiLabs Pearl: lp_ticker HAL adaptation

Use RTCC API for lp_ticker on Pearl. Basic adaptation, but more
work is required.

Now frees RTC when ticker is not used (detected through interrupt
disable), so that sleep modes below EM2 do not remain
permanently blocked.
pull/1501/head
Mikko Polojarvi 2015-10-12 16:25:13 +03:00 committed by Steven Cooreman
parent bf4cf1a5ec
commit dcc6b61ed5
1 changed files with 96 additions and 0 deletions

View File

@ -35,18 +35,34 @@
#include "rtc_api_HAL.h"
#include "lp_ticker_api.h"
static int rtc_reserved = 0;
void lp_ticker_init()
{
rtc_init_real(RTC_INIT_LPTIMER);
rtc_set_comp0_handler((uint32_t)lp_ticker_irq_handler);
rtc_reserved = 1;
}
#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 */
rtc_set_comp0_handler((uint32_t)lp_ticker_irq_handler);
INT_Disable();
if(!rtc_reserved) {
rtc_init_real(RTC_INIT_LPTIMER);
rtc_reserved = 1;
}
INT_Enable();
/* calculate offset value */
timestamp_t offset = timestamp - current_time;
@ -73,6 +89,13 @@ void lp_ticker_set_interrupt(timestamp_t timestamp)
inline void lp_ticker_disable_interrupt()
{
RTC_IntDisable(RTC_IF_COMP0);
INT_Disable();
if(rtc_reserved) {
rtc_free_real(RTC_INIT_LPTIMER);
rtc_reserved = 0;
}
INT_Enable();
}
inline void lp_ticker_clear_interrupt()
@ -94,4 +117,77 @@ timestamp_t lp_ticker_read()
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 */
rtc_set_comp0_handler((uint32_t)lp_ticker_irq_handler);
INT_Disable();
if(!rtc_reserved) {
rtc_init_real(RTC_INIT_LPTIMER);
rtc_reserved = 1;
}
INT_Enable();
/* 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;
timestamp_ticks += 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;
/* Set callback */
RTCC_ChannelCCVSet(0, (uint32_t)timestamp_ticks);
RTCC_IntEnable(RTCC_IF_COMP0);
}
inline void lp_ticker_disable_interrupt()
{
RTCC_IntDisable(RTCC_IF_COMP0);
INT_Disable();
if(rtc_reserved) {
rtc_free_real(RTC_INIT_LPTIMER);
rtc_reserved = 0;
}
INT_Enable();
}
inline void lp_ticker_clear_interrupt()
{
RTCC_IntClear(RTCC_IF_COMP0);
}
timestamp_t lp_ticker_read()
{
uint64_t ticks_temp;
uint64_t ticks = RTCC_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);
}
#endif /* RTCC */
#endif