mirror of https://github.com/ARMmbed/mbed-os.git
Re-implement us_ticker and lp_ticker for Silicon Labs targets
Re-implemented both us_ticker and lp_ticker to match the new API and specifications. Details: * On EFM32GG, EFM32WG, EFM32LG, EFM32HG, EFM32ZG: Use the RTC peripheral to back lp_ticker, and a TIMER to back us_ticker. * On EFM32PG, EFR32MG, EFM32PG12, EFR32MG12: Use the RTCC peripheral to back lp_ticker (dual-purpose, also used to back RTC), and a TIMER to back us_ticker.pull/7009/head
parent
5590f2b495
commit
1448f81620
|
|
@ -106,12 +106,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Adjust this to change speed of RTC and LP ticker ticks */
|
/* Adjust this to change speed of RTC and LP ticker ticks */
|
||||||
#define RTC_CLOCKDIV cmuClkDiv_8
|
#define RTC_CLOCKDIV cmuClkDiv_1
|
||||||
/* Adjust this to match RTC_CLOCKDIV as integer value */
|
/* Adjust this to match RTC_CLOCKDIV as integer value */
|
||||||
#define RTC_CLOCKDIV_INT 8U
|
#define RTC_CLOCKDIV_INT 1U
|
||||||
/* Adjust this to match RTC_CLOCKDIV as shift for 1 second worth of ticks.
|
/* 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.
|
* 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. */
|
* 4096 equals 1 << 12, so RTC_FREQ_SHIFT needs to be 12. */
|
||||||
#define RTC_FREQ_SHIFT 12U
|
#define RTC_FREQ_SHIFT 15U
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -65,71 +65,53 @@
|
||||||
#define RTC_MAX_VALUE (0xFFFFFFUL)
|
#define RTC_MAX_VALUE (0xFFFFFFUL)
|
||||||
|
|
||||||
static bool rtc_inited = false;
|
static bool rtc_inited = false;
|
||||||
static time_t time_base = 0;
|
|
||||||
static uint32_t time_extend = 0;
|
const ticker_info_t* lp_ticker_get_info(void)
|
||||||
static uint32_t extended_comp0 = 0;
|
{
|
||||||
|
static const ticker_info_t rtc_info = {
|
||||||
|
LOW_ENERGY_CLOCK_FREQUENCY,
|
||||||
|
RTC_BITS
|
||||||
|
};
|
||||||
|
return &rtc_info;
|
||||||
|
}
|
||||||
|
|
||||||
void RTC_IRQHandler(void)
|
void RTC_IRQHandler(void)
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
flags = RTC_IntGet();
|
flags = RTC_IntGet();
|
||||||
if (flags & RTC_IF_OF) {
|
if ((flags & RTC_IF_COMP0) && rtc_inited) {
|
||||||
RTC_IntClear(RTC_IF_OF);
|
|
||||||
/* RTC has overflowed (24 bits). Use time_extend as software counter for 32 more bits. */
|
|
||||||
time_extend += 1;
|
|
||||||
}
|
|
||||||
if (flags & RTC_IF_COMP0) {
|
|
||||||
RTC_IntClear(RTC_IF_COMP0);
|
RTC_IntClear(RTC_IF_COMP0);
|
||||||
if (lp_ticker_irq_handler != NULL && time_extend == extended_comp0) {
|
lp_ticker_irq_handler();
|
||||||
lp_ticker_irq_handler();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t rtc_get_full(void)
|
|
||||||
{
|
|
||||||
uint64_t ticks = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
/* In case someone's trying to read time in a critical section */
|
|
||||||
if (RTC_IntGet() & RTC_IF_OF) {
|
|
||||||
RTC_IntClear(RTC_IF_OF);
|
|
||||||
time_extend += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ticks = (uint64_t)time_extend << RTC_BITS;
|
|
||||||
ticks += RTC_CounterGet();
|
|
||||||
}
|
|
||||||
while ( (ticks & RTC_MAX_VALUE) != RTC_CounterGet() );
|
|
||||||
|
|
||||||
return ticks;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lp_ticker_init()
|
void lp_ticker_init()
|
||||||
{
|
{
|
||||||
core_util_critical_section_enter();
|
core_util_critical_section_enter();
|
||||||
if (!rtc_inited) {
|
if (!rtc_inited) {
|
||||||
CMU_ClockEnable(cmuClock_RTC, true);
|
CMU_ClockEnable(cmuClock_RTC, true);
|
||||||
|
|
||||||
/* Scale clock to save power */
|
|
||||||
CMU_ClockDivSet(cmuClock_RTC, RTC_CLOCKDIV);
|
|
||||||
|
|
||||||
/* Initialize RTC */
|
/* Initialize RTC */
|
||||||
RTC_Init_TypeDef init = RTC_INIT_DEFAULT;
|
RTC_Init_TypeDef init = RTC_INIT_DEFAULT;
|
||||||
init.enable = 1;
|
init.enable = 1;
|
||||||
/* Don't use compare register 0 as top value */
|
/* Don't use compare register 0 as top value */
|
||||||
init.comp0Top = 0;
|
init.comp0Top = 0;
|
||||||
|
|
||||||
|
/* Initialize */
|
||||||
|
RTC_Init(&init);
|
||||||
|
RTC_CounterSet(20);
|
||||||
|
|
||||||
/* Enable Interrupt from RTC */
|
/* Enable Interrupt from RTC */
|
||||||
RTC_IntEnable(RTC_IEN_OF);
|
RTC_IntDisable(RTC_IF_COMP0);
|
||||||
|
RTC_IntClear(RTC_IF_COMP0);
|
||||||
NVIC_SetVector(RTC_IRQn, (uint32_t)RTC_IRQHandler);
|
NVIC_SetVector(RTC_IRQn, (uint32_t)RTC_IRQHandler);
|
||||||
NVIC_EnableIRQ(RTC_IRQn);
|
NVIC_EnableIRQ(RTC_IRQn);
|
||||||
|
|
||||||
/* Initialize */
|
|
||||||
RTC_Init(&init);
|
|
||||||
|
|
||||||
rtc_inited = true;
|
rtc_inited = true;
|
||||||
|
} else {
|
||||||
|
/* Cancel current interrupt by virtue of calling init again */
|
||||||
|
RTC_IntDisable(RTC_IF_COMP0);
|
||||||
|
RTC_IntClear(RTC_IF_COMP0);
|
||||||
}
|
}
|
||||||
core_util_critical_section_exit();
|
core_util_critical_section_exit();
|
||||||
}
|
}
|
||||||
|
|
@ -145,90 +127,38 @@ void lp_ticker_free()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 lp_ticker_set_interrupt(timestamp_t timestamp)
|
void lp_ticker_set_interrupt(timestamp_t timestamp)
|
||||||
{
|
{
|
||||||
uint64_t rtc_compare_value;
|
RTC_IntDisable(RTC_IF_COMP0);
|
||||||
uint64_t current_ticks = rtc_get_full();
|
RTC_IntClear(RTC_IF_COMP0);
|
||||||
timestamp_t current_time = lp_ticker_read();
|
RTC_FreezeEnable(true);
|
||||||
|
RTC_CompareSet(0, (uint32_t) (timestamp & RTC_MAX_VALUE));
|
||||||
/* calculate offset value */
|
RTC_FreezeEnable(false);
|
||||||
timestamp_t offset = timestamp - current_time;
|
RTC_IntEnable(RTC_IF_COMP0);
|
||||||
|
|
||||||
/* 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
|
|
||||||
rtc_compare_value = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000;
|
|
||||||
|
|
||||||
/* If RTC offset is less then 2 RTC ticks, the interrupt won't fire */
|
|
||||||
if(rtc_compare_value < 2) {
|
|
||||||
rtc_compare_value = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc_compare_value += current_ticks;
|
|
||||||
|
|
||||||
rtc_set_comp0_value(rtc_compare_value, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lp_ticker_fire_interrupt(void)
|
void lp_ticker_fire_interrupt(void)
|
||||||
{
|
{
|
||||||
RTC_IntSet(RTC_IFS_COMP0);
|
RTC_IntEnable(RTC_IF_COMP0);
|
||||||
|
RTC_IntSet(RTC_IF_COMP0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lp_ticker_disable_interrupt()
|
void lp_ticker_disable_interrupt()
|
||||||
{
|
{
|
||||||
rtc_enable_comp0(false);
|
RTC_IntDisable(RTC_IF_COMP0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lp_ticker_clear_interrupt()
|
void lp_ticker_clear_interrupt()
|
||||||
{
|
{
|
||||||
/* No need to clear interrupt flag, since that already happens at RTC level */
|
RTC_IntClear(RTC_IF_COMP0);
|
||||||
}
|
}
|
||||||
|
|
||||||
timestamp_t lp_ticker_read()
|
timestamp_t lp_ticker_read()
|
||||||
{
|
{
|
||||||
lp_ticker_init();
|
return (timestamp_t) RTC_CounterGet();
|
||||||
|
|
||||||
uint64_t ticks_temp;
|
|
||||||
uint64_t ticks = rtc_get_full();
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(RTCC_PRESENT)
|
#elif defined(RTCC_PRESENT)
|
||||||
/* lp_ticker api is implemented in rtc_rtcc.c */
|
/* lp_ticker api is implemented in rtc_rtcc.c */
|
||||||
#endif /* RTC_PRESENT */
|
#endif /* RTC_PRESENT */
|
||||||
#endif /* DEVICE_LOWPOWERTIMER */
|
#endif /* DEVICE_LPTICKER */
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@
|
||||||
|
|
||||||
static bool lptick_inited = false;
|
static bool lptick_inited = false;
|
||||||
static uint32_t lptick_offset = 0;
|
static uint32_t lptick_offset = 0;
|
||||||
static uint32_t extended_comp0 = 0;
|
|
||||||
|
|
||||||
void rtc_init(void)
|
void rtc_init(void)
|
||||||
{
|
{
|
||||||
|
|
@ -79,30 +78,32 @@ void rtc_write(time_t t)
|
||||||
{
|
{
|
||||||
core_util_critical_section_enter();
|
core_util_critical_section_enter();
|
||||||
uint32_t diff = t - RTCC_CounterGet();
|
uint32_t diff = t - RTCC_CounterGet();
|
||||||
if (extended_comp0 != 0xFFFFFFFFUL) {
|
|
||||||
extended_comp0 += diff;
|
|
||||||
}
|
|
||||||
lptick_offset += diff;
|
lptick_offset += diff;
|
||||||
|
|
||||||
|
if(RTCC_IntGetEnabled() & RTCC_IF_CC0) {
|
||||||
|
RTCC->CC[0].CCV += diff << 15;
|
||||||
|
}
|
||||||
|
|
||||||
RTCC_CounterSet(t);
|
RTCC_CounterSet(t);
|
||||||
core_util_critical_section_exit();
|
core_util_critical_section_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************* LP_TICKER **************************/
|
/************************* LP_TICKER **************************/
|
||||||
|
const ticker_info_t* lp_ticker_get_info(void)
|
||||||
|
{
|
||||||
|
static const ticker_info_t rtc_info = {
|
||||||
|
LOW_ENERGY_CLOCK_FREQUENCY,
|
||||||
|
32
|
||||||
|
};
|
||||||
|
return &rtc_info;
|
||||||
|
}
|
||||||
|
|
||||||
void RTCC_IRQHandler(void)
|
void RTCC_IRQHandler(void)
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
flags = RTCC_IntGet();
|
flags = RTCC_IntGet();
|
||||||
if (flags & RTCC_IF_CC0) {
|
if (flags & RTCC_IF_CC0) {
|
||||||
RTCC_IntClear(RTCC_IF_CC0);
|
lp_ticker_irq_handler();
|
||||||
if ((RTCC_CounterGet() - lptick_offset) == extended_comp0) {
|
|
||||||
RTCC_IntDisable(RTCC_IF_CC0);
|
|
||||||
lp_ticker_irq_handler();
|
|
||||||
}
|
|
||||||
if (0xFFFFFFFFUL == extended_comp0) {
|
|
||||||
RTCC_IntDisable(RTCC_IF_CC0);
|
|
||||||
lp_ticker_irq_handler();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,12 +114,17 @@ void lp_ticker_init()
|
||||||
lptick_offset = RTCC_CounterGet();
|
lptick_offset = RTCC_CounterGet();
|
||||||
RTCC_CCChConf_TypeDef lp_chan_init = RTCC_CH_INIT_COMPARE_DEFAULT;
|
RTCC_CCChConf_TypeDef lp_chan_init = RTCC_CH_INIT_COMPARE_DEFAULT;
|
||||||
lp_chan_init.compBase = rtccCompBasePreCnt;
|
lp_chan_init.compBase = rtccCompBasePreCnt;
|
||||||
lp_chan_init.compMask = 17;
|
lp_chan_init.compMask = 0;
|
||||||
RTCC_ChannelInit(0, &lp_chan_init);
|
RTCC_ChannelInit(0, &lp_chan_init);
|
||||||
lptick_inited = true;
|
lptick_inited = true;
|
||||||
|
|
||||||
/* Enable Interrupt from RTCC */
|
/* Enable Interrupt from RTCC in NVIC, but don't start generating them */
|
||||||
|
RTCC_IntDisable(RTCC_IF_CC0);
|
||||||
|
RTCC_IntClear(RTCC_IF_CC0);
|
||||||
NVIC_EnableIRQ(RTCC_IRQn);
|
NVIC_EnableIRQ(RTCC_IRQn);
|
||||||
|
} else {
|
||||||
|
RTCC_IntDisable(RTCC_IF_CC0);
|
||||||
|
RTCC_IntClear(RTCC_IF_CC0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,45 +139,13 @@ void lp_ticker_free()
|
||||||
|
|
||||||
void lp_ticker_set_interrupt(timestamp_t timestamp)
|
void lp_ticker_set_interrupt(timestamp_t timestamp)
|
||||||
{
|
{
|
||||||
uint64_t rtc_compare_value;
|
RTCC_ChannelCCVSet(0, timestamp + (lptick_offset << 15));
|
||||||
uint64_t current_ticks = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
current_ticks = (uint64_t)((uint64_t)RTCC_CounterGet() - lptick_offset) << 15;
|
|
||||||
current_ticks += RTCC_PreCounterGet();
|
|
||||||
}
|
|
||||||
while ( (current_ticks & 0x7FFF) != RTCC_PreCounterGet() );
|
|
||||||
|
|
||||||
uint64_t ticks_temp = (current_ticks * 1000000) / LOW_ENERGY_CLOCK_FREQUENCY;
|
|
||||||
timestamp_t current_time = ticks_temp & 0xFFFFFFFF;
|
|
||||||
|
|
||||||
/* calculate offset value */
|
|
||||||
timestamp_t offset = timestamp - current_time;
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
rtc_compare_value = ((uint64_t)offset * LOW_ENERGY_CLOCK_FREQUENCY) / 1000000;
|
|
||||||
|
|
||||||
/* If RTC offset is less then 2 RTC ticks, the interrupt won't fire */
|
|
||||||
if(rtc_compare_value < 2) {
|
|
||||||
rtc_compare_value = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc_compare_value += current_ticks;
|
|
||||||
|
|
||||||
extended_comp0 = rtc_compare_value >> 15;
|
|
||||||
RTCC_ChannelCCVSet(0, rtc_compare_value & 0xFFFFFFFFUL);
|
|
||||||
RTCC_IntEnable(RTCC_IF_CC0);
|
RTCC_IntEnable(RTCC_IF_CC0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lp_ticker_fire_interrupt(void)
|
void lp_ticker_fire_interrupt(void)
|
||||||
{
|
{
|
||||||
extended_comp0 = 0xFFFFFFFFUL;
|
RTCC_IntEnable(RTCC_IF_CC0);
|
||||||
RTCC_IntSet(RTCC_IF_CC0);
|
RTCC_IntSet(RTCC_IF_CC0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,25 +161,11 @@ void lp_ticker_clear_interrupt()
|
||||||
|
|
||||||
timestamp_t lp_ticker_read()
|
timestamp_t lp_ticker_read()
|
||||||
{
|
{
|
||||||
lp_ticker_init();
|
core_util_critical_section_enter();
|
||||||
|
uint32_t ticks = RTCC_CombinedCounterGet() - (lptick_offset << 15);
|
||||||
|
core_util_critical_section_exit();
|
||||||
|
|
||||||
uint64_t ticks_temp;
|
return (timestamp_t) (ticks);
|
||||||
uint64_t ticks = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ticks = (uint64_t)((uint64_t)RTCC_CounterGet() - lptick_offset) << 15;
|
|
||||||
ticks += RTCC_PreCounterGet();
|
|
||||||
}
|
|
||||||
while ( (ticks & 0x7FFF) != RTCC_PreCounterGet() );
|
|
||||||
|
|
||||||
/* ticks = counter tick value
|
|
||||||
* timestamp = value in microseconds
|
|
||||||
* timestamp = ticks * 1.000.000 / RTC frequency
|
|
||||||
*/
|
|
||||||
|
|
||||||
ticks_temp = (ticks * 1000000) / LOW_ENERGY_CLOCK_FREQUENCY;
|
|
||||||
return (timestamp_t) (ticks_temp & 0xFFFFFFFF);
|
|
||||||
}
|
}
|
||||||
#endif /* RTCC_PRESENT */
|
#endif /* RTCC_PRESENT */
|
||||||
#endif /* DEVICE_RTC */
|
#endif /* DEVICE_RTC */
|
||||||
|
|
@ -29,80 +29,42 @@
|
||||||
#include "em_timer.h"
|
#include "em_timer.h"
|
||||||
#include "clocking.h"
|
#include "clocking.h"
|
||||||
|
|
||||||
/**
|
#define TICKER_FREQUENCY ((REFERENCE_FREQUENCY > 24000000) ? REFERENCE_FREQUENCY / 16 : REFERENCE_FREQUENCY / 8)
|
||||||
* Timer functions for microsecond ticker.
|
|
||||||
* mbed expects a 32-bit timer. Since the EFM32 only has 16-bit timers,
|
|
||||||
* the upper 16 bits are implemented in software.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static uint8_t us_ticker_inited = 0; // Is ticker initialized yet
|
const ticker_info_t* us_ticker_get_info(void)
|
||||||
|
|
||||||
static volatile uint32_t ticker_cnt = 0; // Internal overflow count, used to extend internal 16-bit counter to (MHz * 32-bit)
|
|
||||||
static volatile uint32_t ticker_int_cnt = 0; // Amount of overflows until user interrupt
|
|
||||||
static volatile uint32_t ticker_freq_khz = 0; // Frequency of timer in MHz
|
|
||||||
static volatile uint32_t ticker_top_ms = 0; // Amount of ms corresponding to the top value of the timer
|
|
||||||
static volatile uint32_t soft_timer_top = 0; // When to wrap the software counter
|
|
||||||
|
|
||||||
void us_ticker_irq_handler_internal(void)
|
|
||||||
{
|
{
|
||||||
/* Handle timer overflow */
|
static const ticker_info_t info = {
|
||||||
if (TIMER_IntGet(US_TICKER_TIMER) & TIMER_IF_OF) {
|
TICKER_FREQUENCY,
|
||||||
ticker_cnt++;
|
16
|
||||||
|
};
|
||||||
/* Wrap ticker_cnt when we've gone over 32-bit us value */
|
return &info;
|
||||||
if (ticker_cnt >= soft_timer_top) {
|
|
||||||
ticker_cnt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TIMER_IntClear(US_TICKER_TIMER, TIMER_IF_OF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for user interrupt expiration */
|
|
||||||
if (TIMER_IntGet(US_TICKER_TIMER) & TIMER_IF_CC0) {
|
|
||||||
if (ticker_int_cnt > 0) {
|
|
||||||
ticker_int_cnt--;
|
|
||||||
TIMER_IntClear(US_TICKER_TIMER, TIMER_IF_CC0);
|
|
||||||
} else {
|
|
||||||
us_ticker_irq_handler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool us_ticker_inited = false; // Is ticker initialized yet
|
||||||
|
|
||||||
void us_ticker_init(void)
|
void us_ticker_init(void)
|
||||||
{
|
{
|
||||||
if (us_ticker_inited) {
|
if (us_ticker_inited) {
|
||||||
|
/* calling init again should cancel current interrupt */
|
||||||
|
us_ticker_disable_interrupt();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
us_ticker_inited = 1;
|
us_ticker_inited = true;
|
||||||
|
|
||||||
/* Enable clock for TIMERs */
|
/* Enable clock for TIMERs */
|
||||||
CMU_ClockEnable(US_TICKER_TIMER_CLOCK, true);
|
CMU_ClockEnable(US_TICKER_TIMER_CLOCK, true);
|
||||||
|
|
||||||
|
if (REFERENCE_FREQUENCY > 24000000) {
|
||||||
|
US_TICKER_TIMER->CTRL = (US_TICKER_TIMER->CTRL & ~_TIMER_CTRL_PRESC_MASK) | (4 << _TIMER_CTRL_PRESC_SHIFT);
|
||||||
|
} else {
|
||||||
|
US_TICKER_TIMER->CTRL = (US_TICKER_TIMER->CTRL & ~_TIMER_CTRL_PRESC_MASK) | (3 << _TIMER_CTRL_PRESC_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Clear TIMER counter value */
|
/* Clear TIMER counter value */
|
||||||
TIMER_CounterSet(US_TICKER_TIMER, 0);
|
TIMER_CounterSet(US_TICKER_TIMER, 0);
|
||||||
|
|
||||||
/* Get frequency of clock in kHz for scaling ticks to microseconds */
|
/* Start TIMER */
|
||||||
ticker_freq_khz = (REFERENCE_FREQUENCY / 1000);
|
TIMER_Enable(US_TICKER_TIMER, true);
|
||||||
MBED_ASSERT(ticker_freq_khz > 0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate maximum prescaler that gives at least 1 MHz frequency, giving us 1us resolution.
|
|
||||||
* Limit prescaling to maximum prescaler value, which is 10 (DIV1024).
|
|
||||||
*/
|
|
||||||
uint32_t prescaler = 0;
|
|
||||||
while((ticker_freq_khz >= 2000) && prescaler <= 10) {
|
|
||||||
ticker_freq_khz = ticker_freq_khz >> 1;
|
|
||||||
prescaler++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set prescaler */
|
|
||||||
US_TICKER_TIMER->CTRL = (US_TICKER_TIMER->CTRL & ~_TIMER_CTRL_PRESC_MASK) | (prescaler << _TIMER_CTRL_PRESC_SHIFT);
|
|
||||||
|
|
||||||
/* calculate top value.*/
|
|
||||||
ticker_top_ms = (uint32_t) 0x10000 / ticker_freq_khz;
|
|
||||||
|
|
||||||
/* calculate software timer overflow */
|
|
||||||
soft_timer_top = ((0xFFFFFFFFUL / 1000UL) / ticker_top_ms) + 1;
|
|
||||||
|
|
||||||
/* Select Compare Channel parameters */
|
/* Select Compare Channel parameters */
|
||||||
TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
|
TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
|
||||||
|
|
@ -112,98 +74,47 @@ void us_ticker_init(void)
|
||||||
TIMER_InitCC(US_TICKER_TIMER, 0, &timerCCInit);
|
TIMER_InitCC(US_TICKER_TIMER, 0, &timerCCInit);
|
||||||
|
|
||||||
/* Enable interrupt vector in NVIC */
|
/* Enable interrupt vector in NVIC */
|
||||||
TIMER_IntEnable(US_TICKER_TIMER, TIMER_IEN_OF);
|
TIMER_IntClear(US_TICKER_TIMER, TIMER_IEN_CC0);
|
||||||
NVIC_SetVector(US_TICKER_TIMER_IRQ, (uint32_t) us_ticker_irq_handler_internal);
|
NVIC_SetVector(US_TICKER_TIMER_IRQ, (uint32_t) us_ticker_irq_handler);
|
||||||
NVIC_EnableIRQ(US_TICKER_TIMER_IRQ);
|
NVIC_EnableIRQ(US_TICKER_TIMER_IRQ);
|
||||||
|
}
|
||||||
|
|
||||||
/* Set top value */
|
void us_ticker_free(void)
|
||||||
TIMER_TopSet(US_TICKER_TIMER, (ticker_top_ms * ticker_freq_khz) - 1);
|
{
|
||||||
|
if (us_ticker_inited) {
|
||||||
|
us_ticker_disable_interrupt();
|
||||||
|
NVIC_DisableIRQ(US_TICKER_TIMER_IRQ);
|
||||||
|
|
||||||
/* Start TIMER */
|
TIMER_Enable(US_TICKER_TIMER, false);
|
||||||
TIMER_Enable(US_TICKER_TIMER, true);
|
|
||||||
|
CMU_ClockEnable(US_TICKER_TIMER_CLOCK, false);
|
||||||
|
|
||||||
|
us_ticker_inited = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t us_ticker_read()
|
uint32_t us_ticker_read()
|
||||||
{
|
{
|
||||||
uint32_t countH_old, countH;
|
|
||||||
uint32_t countL;
|
|
||||||
|
|
||||||
if (!us_ticker_inited) {
|
if (!us_ticker_inited) {
|
||||||
us_ticker_init();
|
us_ticker_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Avoid jumping in time by reading high bits twice */
|
return US_TICKER_TIMER->CNT;
|
||||||
do {
|
|
||||||
countH_old = ticker_cnt;
|
|
||||||
if (TIMER_IntGet(US_TICKER_TIMER) & TIMER_IF_OF) {
|
|
||||||
countH_old++;
|
|
||||||
}
|
|
||||||
countL = US_TICKER_TIMER->CNT;
|
|
||||||
countH = ticker_cnt;
|
|
||||||
if (TIMER_IntGet(US_TICKER_TIMER) & TIMER_IF_OF) {
|
|
||||||
countH++;
|
|
||||||
}
|
|
||||||
} while (countH_old != countH);
|
|
||||||
|
|
||||||
/* Timer count value needs to be div'ed by the frequency to get to 1MHz ticks.
|
|
||||||
* For the software-extended part, the amount of us in one overflow is constant.
|
|
||||||
*/
|
|
||||||
return ((countL * 1000UL) / ticker_freq_khz) + (countH * ticker_top_ms * 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void us_ticker_set_interrupt(timestamp_t timestamp)
|
void us_ticker_set_interrupt(timestamp_t timestamp)
|
||||||
{
|
{
|
||||||
uint32_t goal = timestamp;
|
|
||||||
uint32_t trigger;
|
|
||||||
|
|
||||||
TIMER_IntDisable(US_TICKER_TIMER, TIMER_IEN_CC0);
|
TIMER_IntDisable(US_TICKER_TIMER, TIMER_IEN_CC0);
|
||||||
|
|
||||||
/* convert us delta value back to timer ticks */
|
|
||||||
trigger = us_ticker_read();
|
|
||||||
if (trigger < goal) {
|
|
||||||
goal -= trigger;
|
|
||||||
} else {
|
|
||||||
goal = (0xFFFFFFFFUL - (trigger - goal));
|
|
||||||
}
|
|
||||||
trigger = US_TICKER_TIMER->CNT;
|
|
||||||
|
|
||||||
/* Catch "Going back in time" */
|
|
||||||
if(goal < 10 ||
|
|
||||||
goal >= 0xFFFFFF00UL) {
|
|
||||||
TIMER_IntClear(US_TICKER_TIMER, TIMER_IFC_CC0);
|
|
||||||
TIMER_CompareSet(US_TICKER_TIMER, 0, (US_TICKER_TIMER->CNT + 3 >= US_TICKER_TIMER->TOP ? 3 : US_TICKER_TIMER->CNT + 3));
|
|
||||||
TIMER_IntEnable(US_TICKER_TIMER, TIMER_IEN_CC0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t timer_top = TIMER_TopGet(US_TICKER_TIMER);
|
|
||||||
uint32_t top_us = 1000 * ticker_top_ms;
|
|
||||||
|
|
||||||
/* Amount of times we expect to overflow: us offset / us period of timer */
|
|
||||||
ticker_int_cnt = goal / top_us;
|
|
||||||
|
|
||||||
/* Leftover microseconds need to be converted to timer timebase */
|
|
||||||
trigger += (((goal % top_us) * ticker_freq_khz) / 1000);
|
|
||||||
|
|
||||||
/* Cap compare value to timer top */
|
|
||||||
if (trigger >= timer_top) {
|
|
||||||
trigger -= timer_top;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set compare channel 0 to (current position + lower 16 bits of target).
|
|
||||||
* When lower 16 bits match, run complete cycles with ticker_int_rem as trigger value
|
|
||||||
* for ticker_int_cnt times. */
|
|
||||||
TIMER_IntClear(US_TICKER_TIMER, TIMER_IEN_CC0);
|
TIMER_IntClear(US_TICKER_TIMER, TIMER_IEN_CC0);
|
||||||
|
|
||||||
TIMER_CompareSet(US_TICKER_TIMER, 0, trigger);
|
TIMER_CompareSet(US_TICKER_TIMER, 0, timestamp);
|
||||||
|
|
||||||
TIMER_IntEnable(US_TICKER_TIMER, TIMER_IEN_CC0);
|
TIMER_IntEnable(US_TICKER_TIMER, TIMER_IEN_CC0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void us_ticker_fire_interrupt(void)
|
void us_ticker_fire_interrupt(void)
|
||||||
{
|
{
|
||||||
ticker_int_cnt = 0;
|
|
||||||
TIMER_IntSet(US_TICKER_TIMER, TIMER_IF_CC0);
|
|
||||||
NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQ);
|
NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2907,7 +2907,7 @@
|
||||||
"EFM32GG_STK3700": {
|
"EFM32GG_STK3700": {
|
||||||
"inherits": ["EFM32GG990F1024"],
|
"inherits": ["EFM32GG990F1024"],
|
||||||
"progen": {"target": "efm32gg-stk"},
|
"progen": {"target": "efm32gg-stk"},
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH", "ITM"],
|
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH", "ITM"],
|
||||||
"forced_reset_timeout": 2,
|
"forced_reset_timeout": 2,
|
||||||
"config": {
|
"config": {
|
||||||
"hf_clock_src": {
|
"hf_clock_src": {
|
||||||
|
|
@ -2960,7 +2960,7 @@
|
||||||
},
|
},
|
||||||
"EFM32LG_STK3600": {
|
"EFM32LG_STK3600": {
|
||||||
"inherits": ["EFM32LG990F256"],
|
"inherits": ["EFM32LG990F256"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH"],
|
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"],
|
||||||
"forced_reset_timeout": 2,
|
"forced_reset_timeout": 2,
|
||||||
"device_name": "EFM32LG990F256",
|
"device_name": "EFM32LG990F256",
|
||||||
"config": {
|
"config": {
|
||||||
|
|
@ -3015,7 +3015,7 @@
|
||||||
"EFM32WG_STK3800": {
|
"EFM32WG_STK3800": {
|
||||||
"inherits": ["EFM32WG990F256"],
|
"inherits": ["EFM32WG990F256"],
|
||||||
"progen": {"target": "efm32wg-stk"},
|
"progen": {"target": "efm32wg-stk"},
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH"],
|
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"],
|
||||||
"forced_reset_timeout": 2,
|
"forced_reset_timeout": 2,
|
||||||
"config": {
|
"config": {
|
||||||
"hf_clock_src": {
|
"hf_clock_src": {
|
||||||
|
|
@ -3069,7 +3069,7 @@
|
||||||
},
|
},
|
||||||
"EFM32ZG_STK3200": {
|
"EFM32ZG_STK3200": {
|
||||||
"inherits": ["EFM32ZG222F32"],
|
"inherits": ["EFM32ZG222F32"],
|
||||||
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER"],
|
||||||
"forced_reset_timeout": 2,
|
"forced_reset_timeout": 2,
|
||||||
"config": {
|
"config": {
|
||||||
"hf_clock_src": {
|
"hf_clock_src": {
|
||||||
|
|
@ -3123,7 +3123,7 @@
|
||||||
},
|
},
|
||||||
"EFM32HG_STK3400": {
|
"EFM32HG_STK3400": {
|
||||||
"inherits": ["EFM32HG322F64"],
|
"inherits": ["EFM32HG322F64"],
|
||||||
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER"],
|
||||||
"forced_reset_timeout": 2,
|
"forced_reset_timeout": 2,
|
||||||
"config": {
|
"config": {
|
||||||
"hf_clock_src": {
|
"hf_clock_src": {
|
||||||
|
|
@ -3176,7 +3176,7 @@
|
||||||
},
|
},
|
||||||
"EFM32PG_STK3401": {
|
"EFM32PG_STK3401": {
|
||||||
"inherits": ["EFM32PG1B100F256GM32"],
|
"inherits": ["EFM32PG1B100F256GM32"],
|
||||||
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH"],
|
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"],
|
||||||
"forced_reset_timeout": 2,
|
"forced_reset_timeout": 2,
|
||||||
"config": {
|
"config": {
|
||||||
"hf_clock_src": {
|
"hf_clock_src": {
|
||||||
|
|
@ -3239,7 +3239,7 @@
|
||||||
},
|
},
|
||||||
"EFR32MG1_BRD4150": {
|
"EFR32MG1_BRD4150": {
|
||||||
"inherits": ["EFR32MG1P132F256GM48"],
|
"inherits": ["EFR32MG1P132F256GM48"],
|
||||||
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH"],
|
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"],
|
||||||
"forced_reset_timeout": 2,
|
"forced_reset_timeout": 2,
|
||||||
"config": {
|
"config": {
|
||||||
"hf_clock_src": {
|
"hf_clock_src": {
|
||||||
|
|
@ -3282,7 +3282,7 @@
|
||||||
},
|
},
|
||||||
"TB_SENSE_1": {
|
"TB_SENSE_1": {
|
||||||
"inherits": ["EFR32MG1P233F256GM48"],
|
"inherits": ["EFR32MG1P233F256GM48"],
|
||||||
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH"],
|
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"],
|
||||||
"forced_reset_timeout": 5,
|
"forced_reset_timeout": 5,
|
||||||
"config": {
|
"config": {
|
||||||
"hf_clock_src": {
|
"hf_clock_src": {
|
||||||
|
|
@ -3330,7 +3330,7 @@
|
||||||
},
|
},
|
||||||
"EFM32PG12_STK3402": {
|
"EFM32PG12_STK3402": {
|
||||||
"inherits": ["EFM32PG12B500F1024GL125"],
|
"inherits": ["EFM32PG12B500F1024GL125"],
|
||||||
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG", "FLASH"],
|
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", "FLASH"],
|
||||||
"forced_reset_timeout": 2,
|
"forced_reset_timeout": 2,
|
||||||
"config": {
|
"config": {
|
||||||
"hf_clock_src": {
|
"hf_clock_src": {
|
||||||
|
|
@ -3384,7 +3384,7 @@
|
||||||
"TB_SENSE_12": {
|
"TB_SENSE_12": {
|
||||||
"inherits": ["EFR32MG12P332F1024GL125"],
|
"inherits": ["EFR32MG12P332F1024GL125"],
|
||||||
"device_name": "EFR32MG12P332F1024GL125",
|
"device_name": "EFR32MG12P332F1024GL125",
|
||||||
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG", "FLASH"],
|
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", "FLASH"],
|
||||||
"forced_reset_timeout": 5,
|
"forced_reset_timeout": 5,
|
||||||
"config": {
|
"config": {
|
||||||
"hf_clock_src": {
|
"hf_clock_src": {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue