From 1448f816206c70cb4a58c5d257dc90def3b4d382 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Tue, 27 Mar 2018 10:55:46 +0200 Subject: [PATCH] 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. --- .../TARGET_EFM32/common/clocking.h | 6 +- .../TARGET_EFM32/lp_ticker.c | 136 ++++----------- .../TARGET_Silicon_Labs/TARGET_EFM32/rtcc.c | 94 +++------- .../TARGET_EFM32/us_ticker.c | 161 ++++-------------- targets/targets.json | 20 +-- 5 files changed, 109 insertions(+), 308 deletions(-) diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/clocking.h b/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/clocking.h index b9ad628edc..4eac51774a 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/clocking.h +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/clocking.h @@ -106,12 +106,12 @@ #endif /* 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 */ -#define RTC_CLOCKDIV_INT 8U +#define RTC_CLOCKDIV_INT 1U /* 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 +#define RTC_FREQ_SHIFT 15U #endif diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c index 42f589b5af..d77019ecb2 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c @@ -65,71 +65,53 @@ #define RTC_MAX_VALUE (0xFFFFFFUL) static bool rtc_inited = false; -static time_t time_base = 0; -static uint32_t time_extend = 0; -static uint32_t extended_comp0 = 0; + +const ticker_info_t* lp_ticker_get_info(void) +{ + static const ticker_info_t rtc_info = { + LOW_ENERGY_CLOCK_FREQUENCY, + RTC_BITS + }; + return &rtc_info; +} void RTC_IRQHandler(void) { uint32_t flags; flags = RTC_IntGet(); - if (flags & RTC_IF_OF) { - 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) { + if ((flags & RTC_IF_COMP0) && rtc_inited) { 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() { core_util_critical_section_enter(); if (!rtc_inited) { CMU_ClockEnable(cmuClock_RTC, true); - /* Scale clock to save power */ - CMU_ClockDivSet(cmuClock_RTC, RTC_CLOCKDIV); - /* Initialize RTC */ RTC_Init_TypeDef init = RTC_INIT_DEFAULT; init.enable = 1; /* Don't use compare register 0 as top value */ init.comp0Top = 0; + /* Initialize */ + RTC_Init(&init); + RTC_CounterSet(20); + /* 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_EnableIRQ(RTC_IRQn); - /* Initialize */ - RTC_Init(&init); - 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(); } @@ -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) { - 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 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); + RTC_IntDisable(RTC_IF_COMP0); + RTC_IntClear(RTC_IF_COMP0); + RTC_FreezeEnable(true); + RTC_CompareSet(0, (uint32_t) (timestamp & RTC_MAX_VALUE)); + RTC_FreezeEnable(false); + RTC_IntEnable(RTC_IF_COMP0); } 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() { - rtc_enable_comp0(false); + RTC_IntDisable(RTC_IF_COMP0); } 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() { - lp_ticker_init(); - - 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); + return (timestamp_t) RTC_CounterGet(); } #elif defined(RTCC_PRESENT) /* lp_ticker api is implemented in rtc_rtcc.c */ #endif /* RTC_PRESENT */ -#endif /* DEVICE_LOWPOWERTIMER */ +#endif /* DEVICE_LPTICKER */ diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtcc.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtcc.c index 5efe497aa1..4b14f42ec4 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtcc.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtcc.c @@ -36,7 +36,6 @@ static bool lptick_inited = false; static uint32_t lptick_offset = 0; -static uint32_t extended_comp0 = 0; void rtc_init(void) { @@ -79,30 +78,32 @@ void rtc_write(time_t t) { core_util_critical_section_enter(); uint32_t diff = t - RTCC_CounterGet(); - if (extended_comp0 != 0xFFFFFFFFUL) { - extended_comp0 += diff; - } lptick_offset += diff; + if(RTCC_IntGetEnabled() & RTCC_IF_CC0) { + RTCC->CC[0].CCV += diff << 15; + } + RTCC_CounterSet(t); core_util_critical_section_exit(); } /************************* 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) { uint32_t flags; flags = RTCC_IntGet(); if (flags & RTCC_IF_CC0) { - RTCC_IntClear(RTCC_IF_CC0); - 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(); - } + lp_ticker_irq_handler(); } } @@ -113,12 +114,17 @@ void lp_ticker_init() lptick_offset = RTCC_CounterGet(); RTCC_CCChConf_TypeDef lp_chan_init = RTCC_CH_INIT_COMPARE_DEFAULT; lp_chan_init.compBase = rtccCompBasePreCnt; - lp_chan_init.compMask = 17; + lp_chan_init.compMask = 0; RTCC_ChannelInit(0, &lp_chan_init); 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); + } 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) { - uint64_t rtc_compare_value; - 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_ChannelCCVSet(0, timestamp + (lptick_offset << 15)); RTCC_IntEnable(RTCC_IF_CC0); } void lp_ticker_fire_interrupt(void) { - extended_comp0 = 0xFFFFFFFFUL; + RTCC_IntEnable(RTCC_IF_CC0); RTCC_IntSet(RTCC_IF_CC0); } @@ -187,25 +161,11 @@ void lp_ticker_clear_interrupt() 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; - 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); + return (timestamp_t) (ticks); } #endif /* RTCC_PRESENT */ #endif /* DEVICE_RTC */ \ No newline at end of file diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c index 74ac081768..ab38dd2fac 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c @@ -29,80 +29,42 @@ #include "em_timer.h" #include "clocking.h" -/** - * 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. - */ +#define TICKER_FREQUENCY ((REFERENCE_FREQUENCY > 24000000) ? REFERENCE_FREQUENCY / 16 : REFERENCE_FREQUENCY / 8) -static uint8_t us_ticker_inited = 0; // Is ticker initialized yet - -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) +const ticker_info_t* us_ticker_get_info(void) { - /* Handle timer overflow */ - if (TIMER_IntGet(US_TICKER_TIMER) & TIMER_IF_OF) { - ticker_cnt++; - - /* Wrap ticker_cnt when we've gone over 32-bit us value */ - 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 const ticker_info_t info = { + TICKER_FREQUENCY, + 16 + }; + return &info; } +static bool us_ticker_inited = false; // Is ticker initialized yet + void us_ticker_init(void) { if (us_ticker_inited) { + /* calling init again should cancel current interrupt */ + us_ticker_disable_interrupt(); return; } - us_ticker_inited = 1; + us_ticker_inited = true; /* Enable clock for TIMERs */ 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 */ TIMER_CounterSet(US_TICKER_TIMER, 0); - /* Get frequency of clock in kHz for scaling ticks to microseconds */ - ticker_freq_khz = (REFERENCE_FREQUENCY / 1000); - 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; + /* Start TIMER */ + TIMER_Enable(US_TICKER_TIMER, true); /* Select Compare Channel parameters */ TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT; @@ -112,98 +74,47 @@ void us_ticker_init(void) TIMER_InitCC(US_TICKER_TIMER, 0, &timerCCInit); /* Enable interrupt vector in NVIC */ - TIMER_IntEnable(US_TICKER_TIMER, TIMER_IEN_OF); - NVIC_SetVector(US_TICKER_TIMER_IRQ, (uint32_t) us_ticker_irq_handler_internal); + TIMER_IntClear(US_TICKER_TIMER, TIMER_IEN_CC0); + NVIC_SetVector(US_TICKER_TIMER_IRQ, (uint32_t) us_ticker_irq_handler); NVIC_EnableIRQ(US_TICKER_TIMER_IRQ); +} - /* Set top value */ - TIMER_TopSet(US_TICKER_TIMER, (ticker_top_ms * ticker_freq_khz) - 1); +void us_ticker_free(void) +{ + if (us_ticker_inited) { + us_ticker_disable_interrupt(); + NVIC_DisableIRQ(US_TICKER_TIMER_IRQ); - /* Start TIMER */ - TIMER_Enable(US_TICKER_TIMER, true); + TIMER_Enable(US_TICKER_TIMER, false); + + CMU_ClockEnable(US_TICKER_TIMER_CLOCK, false); + + us_ticker_inited = false; + } } uint32_t us_ticker_read() { - uint32_t countH_old, countH; - uint32_t countL; - if (!us_ticker_inited) { us_ticker_init(); } - /* Avoid jumping in time by reading high bits twice */ - 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); + return US_TICKER_TIMER->CNT; } void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t goal = timestamp; - uint32_t trigger; - 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_CompareSet(US_TICKER_TIMER, 0, trigger); + TIMER_CompareSet(US_TICKER_TIMER, 0, timestamp); TIMER_IntEnable(US_TICKER_TIMER, TIMER_IEN_CC0); } void us_ticker_fire_interrupt(void) { - ticker_int_cnt = 0; - TIMER_IntSet(US_TICKER_TIMER, TIMER_IF_CC0); NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQ); } diff --git a/targets/targets.json b/targets/targets.json index f2103ccffa..329b3b9671 100755 --- a/targets/targets.json +++ b/targets/targets.json @@ -2907,7 +2907,7 @@ "EFM32GG_STK3700": { "inherits": ["EFM32GG990F1024"], "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, "config": { "hf_clock_src": { @@ -2960,7 +2960,7 @@ }, "EFM32LG_STK3600": { "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, "device_name": "EFM32LG990F256", "config": { @@ -3015,7 +3015,7 @@ "EFM32WG_STK3800": { "inherits": ["EFM32WG990F256"], "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, "config": { "hf_clock_src": { @@ -3069,7 +3069,7 @@ }, "EFM32ZG_STK3200": { "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, "config": { "hf_clock_src": { @@ -3123,7 +3123,7 @@ }, "EFM32HG_STK3400": { "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, "config": { "hf_clock_src": { @@ -3176,7 +3176,7 @@ }, "EFM32PG_STK3401": { "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, "config": { "hf_clock_src": { @@ -3239,7 +3239,7 @@ }, "EFR32MG1_BRD4150": { "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, "config": { "hf_clock_src": { @@ -3282,7 +3282,7 @@ }, "TB_SENSE_1": { "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, "config": { "hf_clock_src": { @@ -3330,7 +3330,7 @@ }, "EFM32PG12_STK3402": { "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, "config": { "hf_clock_src": { @@ -3384,7 +3384,7 @@ "TB_SENSE_12": { "inherits": ["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, "config": { "hf_clock_src": {