mirror of https://github.com/ARMmbed/mbed-os.git
Rework us_ticker and rtc_api/lp_ticker | Fix compiler warnings for spi_api
Simplify tickers to stop emulating 1us ticks by using native timer resolutions. Implement ticker get info functions. Separate rtc and lp ticker init status by implementing separate functions. Add mbed_critical include file to disable compiler warning messages.pull/6697/head
parent
fac4ed0a27
commit
a6cc79faf1
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
|
||||
* Copyright (C) 2016,2018 Maxim Integrated Products, Inc., All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -36,33 +36,24 @@
|
|||
#include "rtc.h"
|
||||
#include "lp.h"
|
||||
|
||||
#define PRESCALE_VAL RTC_PRESCALE_DIV_2_0 // Set the divider for the 4kHz clock
|
||||
#define SHIFT_AMT (RTC_PRESCALE_DIV_2_12 - PRESCALE_VAL)
|
||||
// LOG2 for 32-bit powers of 2
|
||||
#define LOG2_1(n) (((n) >= (1 << 1)) ? 1 : 0)
|
||||
#define LOG2_2(n) (((n) >= (1 << 2)) ? ( 2 + (LOG2_1((n) >> 2))) : LOG2_1(n))
|
||||
#define LOG2_4(n) (((n) >= (1 << 4)) ? ( 4 + (LOG2_2((n) >> 4))) : LOG2_2(n))
|
||||
#define LOG2_8(n) (((n) >= (1 << 8)) ? ( 8 + (LOG2_4((n) >> 8))) : LOG2_4(n))
|
||||
#define LOG2(n) (((n) >= (1 << 16)) ? (16 + (LOG2_8((n) >> 16))) : LOG2_8(n))
|
||||
|
||||
#define WINDOW 1000
|
||||
#define LP_TIMER_FREQ_HZ 4096
|
||||
#define LP_TIMER_PRESCALE RTC_PRESCALE_DIV_2_0
|
||||
#define LP_TIMER_RATE_HZ (LP_TIMER_FREQ_HZ >> LP_TIMER_PRESCALE)
|
||||
#define LP_TIMER_WIDTH 32
|
||||
|
||||
static int rtc_inited = 0;
|
||||
static volatile uint32_t overflow_cnt = 0;
|
||||
|
||||
static uint64_t rtc_read64(void);
|
||||
static volatile int rtc_inited = 0;
|
||||
static volatile int lp_ticker_inited = 0;
|
||||
|
||||
//******************************************************************************
|
||||
static void overflow_handler(void)
|
||||
static void init_rtc(void)
|
||||
{
|
||||
overflow_cnt++;
|
||||
RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void rtc_init(void)
|
||||
{
|
||||
if (rtc_inited) {
|
||||
return;
|
||||
}
|
||||
rtc_inited = 1;
|
||||
|
||||
overflow_cnt = 0;
|
||||
|
||||
/* Enable power for RTC for all LPx states */
|
||||
MXC_PWRSEQ->reg0 |= (MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN |
|
||||
MXC_F_PWRSEQ_REG0_PWR_RTCEN_SLP);
|
||||
|
@ -70,21 +61,12 @@ void rtc_init(void)
|
|||
/* Enable clock to synchronizers */
|
||||
CLKMAN_SetClkScale(CLKMAN_CLK_SYNC, CLKMAN_SCALE_DIV_1);
|
||||
|
||||
// Prepare interrupt handlers
|
||||
NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler);
|
||||
NVIC_EnableIRQ(RTC0_IRQn);
|
||||
NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler);
|
||||
NVIC_EnableIRQ(RTC3_IRQn);
|
||||
|
||||
// Enable wakeup on RTC rollover
|
||||
LP_ConfigRTCWakeUp(0, 0, 0, 1);
|
||||
|
||||
/* RTC registers are only reset on a power cycle. Do not reconfigure the RTC
|
||||
* if it is already running.
|
||||
*/
|
||||
if (!RTC_IsActive()) {
|
||||
rtc_cfg_t cfg = {0};
|
||||
cfg.prescaler = PRESCALE_VAL;
|
||||
rtc_cfg_t cfg = { 0 };
|
||||
cfg.prescaler = LP_TIMER_PRESCALE;
|
||||
cfg.snoozeMode = RTC_SNOOZE_DISABLE;
|
||||
|
||||
int retval = RTC_Init(&cfg);
|
||||
|
@ -96,163 +78,128 @@ void rtc_init(void)
|
|||
}
|
||||
|
||||
//******************************************************************************
|
||||
void lp_ticker_init(void)
|
||||
static void overflow_handler(void)
|
||||
{
|
||||
rtc_init();
|
||||
MXC_RTCTMR->comp[1] += ((UINT32_MAX >> LOG2(LP_TIMER_RATE_HZ)) + 1);
|
||||
RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void rtc_init(void)
|
||||
{
|
||||
if (rtc_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler);
|
||||
NVIC_EnableIRQ(RTC3_IRQn);
|
||||
// Enable wakeup on RTC overflow
|
||||
LP_ConfigRTCWakeUp(lp_ticker_inited, 0, 0, 1);
|
||||
init_rtc();
|
||||
rtc_inited = 1;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void rtc_free(void)
|
||||
{
|
||||
if (RTC_IsActive()) {
|
||||
// Clear and disable RTC
|
||||
MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_CLEAR;
|
||||
RTC_Stop();
|
||||
if (rtc_inited) {
|
||||
rtc_inited = 0;
|
||||
if (lp_ticker_inited) {
|
||||
RTC_DisableINT(MXC_F_RTC_FLAGS_OVERFLOW);
|
||||
} else {
|
||||
MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_CLEAR;
|
||||
RTC_Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
int rtc_isenabled(void)
|
||||
{
|
||||
return RTC_IsActive();
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
time_t rtc_read(void)
|
||||
{
|
||||
uint32_t ovf_cnt_1, ovf_cnt_2, timer_cnt;
|
||||
uint32_t ovf1, ovf2;
|
||||
|
||||
// Make sure RTC is setup before trying to read
|
||||
if (!rtc_inited) {
|
||||
rtc_init();
|
||||
}
|
||||
|
||||
// Ensure coherency between overflow_cnt and timer
|
||||
do {
|
||||
ovf_cnt_1 = overflow_cnt;
|
||||
ovf1 = RTC_GetFlags() & MXC_F_RTC_FLAGS_OVERFLOW;
|
||||
timer_cnt = RTC_GetCount();
|
||||
ovf2 = RTC_GetFlags() & MXC_F_RTC_FLAGS_OVERFLOW;
|
||||
ovf_cnt_2 = overflow_cnt;
|
||||
} while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
|
||||
|
||||
// Account for an unserviced interrupt
|
||||
if (ovf1) {
|
||||
ovf_cnt_1++;
|
||||
}
|
||||
|
||||
return (timer_cnt >> SHIFT_AMT) + (ovf_cnt_1 << (32 - SHIFT_AMT));
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
static uint64_t rtc_read64(void)
|
||||
{
|
||||
uint32_t ovf_cnt_1, ovf_cnt_2, timer_cnt;
|
||||
uint32_t ovf1, ovf2;
|
||||
uint64_t current_us;
|
||||
|
||||
// Make sure RTC is setup before trying to read
|
||||
if (!rtc_inited) {
|
||||
rtc_init();
|
||||
}
|
||||
|
||||
// Ensure coherency between overflow_cnt and timer
|
||||
do {
|
||||
ovf_cnt_1 = overflow_cnt;
|
||||
ovf1 = RTC_GetFlags() & MXC_F_RTC_FLAGS_OVERFLOW;
|
||||
timer_cnt = RTC_GetCount();
|
||||
ovf2 = RTC_GetFlags() & MXC_F_RTC_FLAGS_OVERFLOW;
|
||||
ovf_cnt_2 = overflow_cnt;
|
||||
} while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
|
||||
|
||||
// Account for an unserviced interrupt
|
||||
if (ovf1) {
|
||||
ovf_cnt_1++;
|
||||
}
|
||||
|
||||
current_us = (((uint64_t)timer_cnt * 1000000) >> SHIFT_AMT) + (((uint64_t)ovf_cnt_1 * 1000000) << (32 - SHIFT_AMT));
|
||||
|
||||
return current_us;
|
||||
return rtc_inited;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void rtc_write(time_t t)
|
||||
{
|
||||
// Make sure RTC is setup before accessing
|
||||
if (!rtc_inited) {
|
||||
rtc_init();
|
||||
}
|
||||
|
||||
RTC_Stop();
|
||||
RTC_SetCount(t << SHIFT_AMT);
|
||||
overflow_cnt = t >> (32 - SHIFT_AMT);
|
||||
RTC_Start();
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void lp_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
uint32_t comp_value;
|
||||
uint64_t curr_ts64;
|
||||
uint64_t ts64;
|
||||
|
||||
// Note: interrupts are disabled before this function is called.
|
||||
|
||||
// Disable the alarm while it is prepared
|
||||
RTC_DisableINT(MXC_F_RTC_INTEN_COMP0);
|
||||
|
||||
curr_ts64 = rtc_read64();
|
||||
ts64 = (uint64_t)timestamp | (curr_ts64 & 0xFFFFFFFF00000000ULL);
|
||||
|
||||
// If this event is older than a recent window, it must be in the future
|
||||
if ((ts64 < (curr_ts64 - WINDOW)) && ((curr_ts64 - WINDOW) < curr_ts64)) {
|
||||
ts64 += 0x100000000ULL;
|
||||
}
|
||||
|
||||
uint32_t timer = RTC_GetCount();
|
||||
if (ts64 <= curr_ts64) {
|
||||
// This event has already occurred. Set the alarm to expire immediately.
|
||||
comp_value = timer + 1;
|
||||
} else {
|
||||
comp_value = (ts64 << SHIFT_AMT) / 1000000;
|
||||
}
|
||||
|
||||
// Ensure that the compare value is far enough in the future to guarantee the interrupt occurs.
|
||||
if ((comp_value < (timer + 2)) && (comp_value > (timer - 10))) {
|
||||
comp_value = timer + 2;
|
||||
}
|
||||
|
||||
MXC_RTCTMR->comp[0] = comp_value;
|
||||
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
|
||||
RTC_EnableINT(MXC_F_RTC_INTEN_COMP0);
|
||||
|
||||
// Enable wakeup from RTC
|
||||
LP_ConfigRTCWakeUp(1, 0, 0, 1);
|
||||
MXC_RTCTMR->comp[1] = t - (MXC_RTCTMR->timer >> LOG2(LP_TIMER_RATE_HZ));
|
||||
|
||||
// Wait for pending transactions
|
||||
while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
time_t rtc_read(void)
|
||||
{
|
||||
if (!rtc_inited) {
|
||||
rtc_init();
|
||||
}
|
||||
|
||||
return (MXC_RTCTMR->timer >> LOG2(LP_TIMER_RATE_HZ)) + MXC_RTCTMR->comp[1];
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void lp_ticker_init(void)
|
||||
{
|
||||
if (lp_ticker_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler);
|
||||
NVIC_EnableIRQ(RTC0_IRQn);
|
||||
init_rtc();
|
||||
lp_ticker_inited = 1;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
uint32_t lp_ticker_read(void)
|
||||
{
|
||||
return MXC_RTCTMR->timer;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void lp_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
MXC_RTCTMR->comp[0] = timestamp;
|
||||
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
|
||||
MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
|
||||
|
||||
// Enable wakeup from RTC compare 0
|
||||
LP_ConfigRTCWakeUp(1, 0, 0, rtc_inited);
|
||||
|
||||
// Wait for pending transactions
|
||||
while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void lp_ticker_disable_interrupt(void)
|
||||
{
|
||||
RTC_DisableINT(MXC_F_RTC_INTEN_COMP0);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void lp_ticker_clear_interrupt(void)
|
||||
{
|
||||
RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void lp_ticker_fire_interrupt(void)
|
||||
{
|
||||
NVIC_SetPendingIRQ(RTC0_IRQn);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
inline void lp_ticker_disable_interrupt(void)
|
||||
const ticker_info_t *lp_ticker_get_info(void)
|
||||
{
|
||||
RTC_DisableINT(MXC_F_RTC_INTEN_COMP0);
|
||||
}
|
||||
static const ticker_info_t info = {
|
||||
LP_TIMER_RATE_HZ,
|
||||
LP_TIMER_WIDTH
|
||||
};
|
||||
|
||||
//******************************************************************************
|
||||
inline void lp_ticker_clear_interrupt(void)
|
||||
{
|
||||
RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
inline uint32_t lp_ticker_read(void)
|
||||
{
|
||||
return rtc_read64();
|
||||
return &info;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
*/
|
||||
|
||||
#include "mbed_assert.h"
|
||||
#include "mbed_critical.h"
|
||||
#include "spi_api.h" // mbed HAL
|
||||
#include "spim_regs.h" // bare metal
|
||||
#include "spim.h" // Maxim CMSIS driver
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
|
||||
* Copyright (c) 2016,2018 Maxim Integrated Products, Inc., All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -32,251 +32,84 @@
|
|||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "mbed_error.h"
|
||||
#include "mbed_critical.h"
|
||||
#include "us_ticker_api.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "tmr.h"
|
||||
#include "assert.h"
|
||||
|
||||
#define US_TIMER MXC_TMR0
|
||||
#define US_TIMER_IRQn TMR0_0_IRQn
|
||||
#define US_TIMER MXC_TMR0
|
||||
#define US_TIMER_IRQn TMR0_0_IRQn
|
||||
#define US_TIMER_PRESCALE TMR_PRESCALE_DIV_2_5
|
||||
#define US_TIMER_MODE TMR32_MODE_COMPARE
|
||||
#define US_TIMER_WIDTH 32
|
||||
|
||||
static int us_ticker_inited = 0;
|
||||
static uint32_t ticks_per_us;
|
||||
static uint32_t tick_win;
|
||||
static volatile uint64_t current_cnt; // Hold the current ticks
|
||||
static volatile uint64_t event_cnt; // Holds the value of the next event
|
||||
|
||||
#define MAX_TICK_VAL ((uint64_t)0xFFFFFFFF * ticks_per_us)
|
||||
|
||||
//******************************************************************************
|
||||
static inline void inc_current_cnt_no_crit(uint32_t inc)
|
||||
{
|
||||
// Overflow the ticker when the us ticker overflows
|
||||
current_cnt += inc;
|
||||
if (current_cnt > MAX_TICK_VAL) {
|
||||
current_cnt -= (MAX_TICK_VAL + 1);
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
static inline void inc_current_cnt(uint32_t inc)
|
||||
{
|
||||
core_util_critical_section_enter();
|
||||
inc_current_cnt_no_crit(inc);
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
static inline int event_passed(uint64_t current, uint64_t event)
|
||||
{
|
||||
// Determine if the event has already happened.
|
||||
// If the event is behind the current ticker, within a window,
|
||||
// then the event has already happened.
|
||||
if (((current < tick_win) && ((event < current) ||
|
||||
(event > (MAX_TICK_VAL - (tick_win - current))))) ||
|
||||
((event < current) && (event > (current - tick_win)))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
static inline uint64_t event_diff(uint64_t current, uint64_t event)
|
||||
{
|
||||
// Check to see if the ticker will overflow before the event
|
||||
if(current <= event) {
|
||||
return (event - current);
|
||||
}
|
||||
|
||||
return ((MAX_TICK_VAL - current) + event);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
static void tmr_handler(void)
|
||||
{
|
||||
uint32_t cmp = TMR32_GetCompare(US_TIMER);
|
||||
TMR32_SetCompare(US_TIMER, 0xFFFFFFFF); // reset to max value to prevent further interrupts
|
||||
if (TMR32_GetFlag(US_TIMER)) {
|
||||
inc_current_cnt_no_crit(cmp);
|
||||
}
|
||||
TMR32_ClearFlag(US_TIMER);
|
||||
NVIC_ClearPendingIRQ(US_TIMER_IRQn);
|
||||
|
||||
if (event_passed(current_cnt + TMR32_GetCount(US_TIMER), event_cnt)) {
|
||||
// the timestamp has expired
|
||||
event_cnt = 0xFFFFFFFFFFFFFFFFULL; // reset to max value
|
||||
us_ticker_irq_handler();
|
||||
} else {
|
||||
uint64_t diff = event_diff(current_cnt, event_cnt);
|
||||
if (diff < (uint64_t)0xFFFFFFFF) {
|
||||
// the event occurs before the next overflow
|
||||
TMR32_SetCompare(US_TIMER, diff);
|
||||
|
||||
// Since the timer keeps counting after the terminal value is reached, it is possible that the new
|
||||
// terminal value is in the past.
|
||||
if (TMR32_GetCompare(US_TIMER) < TMR32_GetCount(US_TIMER)) {
|
||||
// the timestamp has expired
|
||||
TMR32_SetCompare(US_TIMER, 0xFFFFFFFF); // reset to max value to prevent further interrupts
|
||||
TMR32_ClearFlag(US_TIMER);
|
||||
NVIC_ClearPendingIRQ(US_TIMER_IRQn);
|
||||
event_cnt = 0xFFFFFFFFFFFFFFFFULL; // reset to max value
|
||||
us_ticker_irq_handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static volatile int us_ticker_inited = 0;
|
||||
|
||||
//******************************************************************************
|
||||
void us_ticker_init(void)
|
||||
{
|
||||
tmr32_cfg_t cfg;
|
||||
|
||||
if (us_ticker_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
us_ticker_inited = 1;
|
||||
current_cnt = 0;
|
||||
event_cnt = 0xFFFFFFFFFFFFFFFFULL; // reset to max value
|
||||
ticks_per_us = SystemCoreClock / 1000000;
|
||||
tick_win = SystemCoreClock / 100; // Set the tick window to 10ms
|
||||
|
||||
int retval = TMR_Init(US_TIMER, TMR_PRESCALE_DIV_2_0, NULL);
|
||||
MBED_ASSERT(retval == E_NO_ERROR);
|
||||
|
||||
tmr32_cfg_t cfg;
|
||||
cfg.mode = TMR32_MODE_CONTINUOUS;
|
||||
cfg.mode = US_TIMER_MODE;
|
||||
cfg.polarity = TMR_POLARITY_UNUSED;
|
||||
cfg.compareCount = 0xFFFFFFFF;
|
||||
cfg.compareCount = UINT32_MAX;
|
||||
|
||||
TMR_Init(US_TIMER, US_TIMER_PRESCALE, NULL);
|
||||
TMR32_Config(US_TIMER, &cfg);
|
||||
|
||||
NVIC_SetVector(US_TIMER_IRQn, (uint32_t)tmr_handler);
|
||||
NVIC_SetVector(US_TIMER_IRQn, (uint32_t)us_ticker_irq_handler);
|
||||
NVIC_EnableIRQ(US_TIMER_IRQn);
|
||||
TMR32_EnableINT(US_TIMER);
|
||||
|
||||
TMR32_Start(US_TIMER);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void us_ticker_deinit(void)
|
||||
{
|
||||
TMR32_Stop(US_TIMER);
|
||||
TMR32_DisableINT(US_TIMER);
|
||||
TMR32_ClearFlag(US_TIMER);
|
||||
us_ticker_inited = 0;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
uint32_t us_ticker_read(void)
|
||||
{
|
||||
uint64_t current_cnt1, current_cnt2;
|
||||
uint32_t cmp, cnt;
|
||||
uint32_t flag1, flag2;
|
||||
static uint32_t last = 0;
|
||||
|
||||
if (!us_ticker_inited) {
|
||||
us_ticker_init();
|
||||
}
|
||||
|
||||
// Ensure coherency between current_cnt and TMR32_GetCount()
|
||||
do {
|
||||
current_cnt1 = current_cnt;
|
||||
flag1 = TMR32_GetFlag(US_TIMER);
|
||||
cmp = TMR32_GetCompare(US_TIMER);
|
||||
cnt = TMR32_GetCount(US_TIMER);
|
||||
flag2 = TMR32_GetFlag(US_TIMER);
|
||||
current_cnt2 = current_cnt;
|
||||
} while ((current_cnt1 != current_cnt2) || (flag1 != flag2));
|
||||
|
||||
// Account for an unserviced interrupt
|
||||
if (flag1) {
|
||||
// Clear peripheral interrupt flag; leaving NVIC pending set
|
||||
TMR32_ClearFlag(US_TIMER);
|
||||
// Advance global count
|
||||
inc_current_cnt(cmp + cnt);
|
||||
|
||||
current_cnt1 += cmp;
|
||||
}
|
||||
|
||||
current_cnt1 += cnt;
|
||||
|
||||
assert(last <= (current_cnt1 / ticks_per_us));
|
||||
last = (current_cnt1 / ticks_per_us);
|
||||
return last;
|
||||
return US_TIMER->count32;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void us_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
// Note: interrupts are disabled before this function is called.
|
||||
|
||||
TMR32_Stop(US_TIMER);
|
||||
|
||||
if (TMR32_GetFlag(US_TIMER)) {
|
||||
TMR32_ClearFlag(US_TIMER);
|
||||
NVIC_ClearPendingIRQ(US_TIMER_IRQn);
|
||||
inc_current_cnt(TMR32_GetCompare(US_TIMER));
|
||||
}
|
||||
|
||||
// add and reset the current count value
|
||||
inc_current_cnt(TMR32_GetCount(US_TIMER));
|
||||
TMR32_SetCount(US_TIMER, 0);
|
||||
|
||||
// add the number of cycles that the timer is disabled here for
|
||||
inc_current_cnt(200);
|
||||
|
||||
event_cnt = (uint64_t)timestamp * ticks_per_us;
|
||||
|
||||
// Check to see if the event has already passed
|
||||
if (!event_passed(current_cnt, event_cnt)) {
|
||||
uint64_t diff = event_diff(current_cnt, event_cnt);
|
||||
if (diff < (uint64_t)0xFFFFFFFF) {
|
||||
// the event occurs before the next overflow
|
||||
TMR32_SetCompare(US_TIMER, diff);
|
||||
} else {
|
||||
// the event occurs after the next overflow
|
||||
TMR32_SetCompare(US_TIMER, 0xFFFFFFFF); // set to max
|
||||
}
|
||||
} else {
|
||||
// the requested timestamp occurs in the past
|
||||
// set the timer up to immediately expire
|
||||
TMR32_SetCompare(US_TIMER, 1);
|
||||
}
|
||||
|
||||
TMR32_Start(US_TIMER);
|
||||
US_TIMER->ctrl = 0;
|
||||
US_TIMER->term_cnt32 = timestamp;
|
||||
US_TIMER->inten = MXC_F_TMR_INTEN_TIMER0;
|
||||
US_TIMER->ctrl = MXC_F_TMR_CTRL_ENABLE0 |
|
||||
(US_TIMER_MODE << MXC_F_TMR_CTRL_MODE_POS) |
|
||||
(US_TIMER_PRESCALE << MXC_F_TMR_CTRL_PRESCALE_POS);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
TMR32_SetCompare(US_TIMER, 1);
|
||||
NVIC_SetPendingIRQ(US_TIMER_IRQn);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void us_ticker_disable_interrupt(void)
|
||||
{
|
||||
// There are no more events, set timer overflow to the max
|
||||
TMR32_SetCompare(US_TIMER, 0xFFFFFFFF);
|
||||
US_TIMER->inten = 0;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void us_ticker_clear_interrupt(void)
|
||||
{
|
||||
// cleared in the local handler
|
||||
US_TIMER->intfl = MXC_F_TMR_INTFL_TIMER0;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
void us_ticker_set(timestamp_t timestamp)
|
||||
const ticker_info_t* us_ticker_get_info(void)
|
||||
{
|
||||
TMR32_Stop(US_TIMER);
|
||||
current_cnt = (uint64_t)timestamp * ticks_per_us;
|
||||
TMR32_SetCount(US_TIMER, 0);
|
||||
TMR32_SetCompare(US_TIMER, 0xFFFFFFFF);
|
||||
TMR32_Start(US_TIMER);
|
||||
static const ticker_info_t info = {
|
||||
RO_FREQ >> US_TIMER_PRESCALE,
|
||||
US_TIMER_WIDTH
|
||||
};
|
||||
|
||||
if (((uint64_t)timestamp * ticks_per_us) >= event_cnt) {
|
||||
// The next timestamp has elapsed. Trigger the interrupt to handle it.
|
||||
NVIC_SetPendingIRQ(US_TIMER_IRQn);
|
||||
}
|
||||
return &info;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue