mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
Diff: targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c
- Revision:
- 186:707f6e361f3e
- Parent:
- 182:a56a73fd2a6f
--- a/targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c Thu Apr 19 17:12:19 2018 +0100 +++ b/targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c Fri Jun 22 16:45:37 2018 +0100 @@ -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,81 @@ */ #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 - -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(); - } - } - } -} +#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 //****************************************************************************** void us_ticker_init(void) { - 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 + // Disable and deconfigure + US_TIMER->ctrl = 0; + US_TIMER->term_cnt32 = 0; + US_TIMER->inten = 0; + US_TIMER->intfl = MXC_F_TMR_INTFL_TIMER0; - int retval = TMR_Init(US_TIMER, TMR_PRESCALE_DIV_2_0, NULL); - MBED_ASSERT(retval == E_NO_ERROR); + // Configure and enable + 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); - tmr32_cfg_t cfg; - cfg.mode = TMR32_MODE_CONTINUOUS; - cfg.polarity = TMR_POLARITY_UNUSED; - cfg.compareCount = 0xFFFFFFFF; - 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) +void us_ticker_free(void) { - TMR32_Stop(US_TIMER); - TMR32_DisableINT(US_TIMER); - TMR32_ClearFlag(US_TIMER); - us_ticker_inited = 0; + US_TIMER->ctrl = 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) ? timestamp : 1; + 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; }