From dec667b49dd168f0bfb13f32610a7e6fd0a5c8a7 Mon Sep 17 00:00:00 2001 From: Przemyslaw Stekiel Date: Mon, 21 May 2018 08:59:41 +0200 Subject: [PATCH 1/9] NRF52_DK: use new ticker driver designed for NRF51_DK --- .../TARGET_NRF5x/TARGET_NRF52/common_rtc.c | 239 +++++++++++++++ .../TARGET_NRF5x/TARGET_NRF52/common_rtc.h | 18 +- .../TARGET_NRF5x/TARGET_NRF52/lp_ticker.c | 32 +- .../TARGET_NRF5x/TARGET_NRF52/us_ticker.c | 285 +++--------------- .../TARGET_NRF5x/TARGET_NRF52/us_ticker.h | 26 ++ 5 files changed, 343 insertions(+), 257 deletions(-) create mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.c create mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.h diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.c new file mode 100644 index 00000000000..efeea8b608b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2013 Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA + * integrated circuit in a product or a software update for such product, must reproduce + * the above copyright notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary or object form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "us_ticker_api.h" +#include "common_rtc.h" +#include "app_util.h" +#include "nrf_drv_common.h" +#include "lp_ticker_api.h" +#include "mbed_critical.h" + +#if defined(NRF52_ERRATA_20) + #include "softdevice_handler.h" +#endif + + +//------------------------------------------------------------------------------ +// Common stuff used also by lp_ticker and rtc_api (see "common_rtc.h"). +// +#include "app_util_platform.h" + +bool m_common_rtc_enabled = false; +uint32_t volatile m_common_rtc_overflows = 0; +bool volatile lp_ticker_interrupt_fire = false; + +__STATIC_INLINE void rtc_ovf_event_check(void) +{ + if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) { + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + /* Don't disable this event. It shall occur periodically. + * It is needed for RTC. */ + + ++m_common_rtc_overflows; + } +} + +#if defined(TARGET_MCU_NRF51822) +void common_rtc_irq_handler(void) +#else +void COMMON_RTC_IRQ_HANDLER(void) +#endif +{ + rtc_ovf_event_check(); + +#if DEVICE_LPTICKER + if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, LP_TICKER_EVENT) || + lp_ticker_interrupt_fire) { + + if (lp_ticker_interrupt_fire) { + lp_ticker_interrupt_fire = false; + } + + lp_ticker_irq_handler(); + } +#endif +} + +/* Function for fix errata 20: RTC Register values are invalid. */ +__STATIC_INLINE void errata_20(void) +{ +#if defined(NRF52_ERRATA_20) + if (!softdevice_handler_is_enabled()) + { + NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; + NRF_CLOCK->TASKS_LFCLKSTART = 1; + + while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) + { + } + } + NRF_RTC1->TASKS_STOP = 0; +#endif +} + +void RTC1_IRQHandler(void); + +void common_rtc_init(void) +{ + if (m_common_rtc_enabled) { +#if DEVICE_LPTICKER + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); + nrf_rtc_int_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); +#endif + return; + } + + errata_20(); + + nrf_rtc_task_trigger(COMMON_RTC_INSTANCE, NRF_RTC_TASK_STOP); + + NVIC_SetVector(RTC1_IRQn, (uint32_t)RTC1_IRQHandler); + + /* RTC is driven by the low frequency (32.768 kHz) clock, a proper request + * must be made to have it running. + * Currently this clock is started in 'SystemInit' (see "system_nrf51.c" + * or "system_nrf52.c", respectively). + */ + + nrf_rtc_prescaler_set(COMMON_RTC_INSTANCE, 0); + + /* Clear all RTC events. */ +#if defined(TARGET_MCU_NRF51822) + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, OS_TICK_EVENT); +#endif +#if DEVICE_LPTICKER + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); +#endif + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + + /* Disable all RTC events (According to NRF_51 Reference Manual + * RTC events can not be used to control RTC interrupts). + * IRQ signal to NVIC is provided if interrupt is enabled. + */ + + nrf_rtc_event_disable(COMMON_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK +#if defined(TARGET_MCU_NRF51822) + | OS_TICK_INT_MASK +#endif +#if DEVICE_LPTICKER + | LP_TICKER_INT_MASK +#endif + ); + + /* This interrupt is enabled permanently, since overflow indications are needed + * continuously. + */ + nrf_rtc_int_enable(COMMON_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); + + /* Disable LP ticker interrupt for now. */ +#if DEVICE_LPTICKER + nrf_rtc_int_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); +#endif + + nrf_drv_common_irq_enable(nrf_drv_get_IRQn(COMMON_RTC_INSTANCE), +#ifdef NRF51 + APP_IRQ_PRIORITY_LOW +#elif defined(NRF52) || defined(NRF52840_XXAA) + APP_IRQ_PRIORITY_LOWEST +#endif + ); + + nrf_rtc_task_trigger(COMMON_RTC_INSTANCE, NRF_RTC_TASK_START); + + m_common_rtc_enabled = true; +} + +void common_rtc_set_interrupt(uint32_t ticks_count, uint32_t cc_channel, + uint32_t int_mask) +{ + /* Set ticks value when interrupt should be fired. + * Interrupt scheduling is performed in upper layers. */ + + core_util_critical_section_enter(); + + /* COMPARE occurs when a CC register is N and the COUNTER value transitions from N-1 to N. + * If the COUNTER is N, writing N+2 to a CC register is guaranteed to trigger a + * COMPARE event at N+2. + */ + const uint32_t now = nrf_rtc_counter_get(COMMON_RTC_INSTANCE); + + if (now == ticks_count || + RTC_WRAP(now + 1) == ticks_count) { + ticks_count += 2; + } + + nrf_rtc_cc_set(COMMON_RTC_INSTANCE, cc_channel, RTC_WRAP(ticks_count)); + + if (!nrf_rtc_int_is_enabled(COMMON_RTC_INSTANCE, int_mask)) { + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); + nrf_rtc_int_enable(COMMON_RTC_INSTANCE, int_mask); + } + + core_util_critical_section_exit(); +} + +/* Since there is no SysTick on NRF51, the RTC1 channel 0 is used as an + * alternative source of RTOS ticks. + */ +#if defined(TARGET_MCU_NRF51822) + +#include "mbed_toolchain.h" + + +#define MAX_RTC_COUNTER_VAL ((1uL << RTC_COUNTER_BITS) - 1) + +#ifndef RTC1_CONFIG_FREQUENCY + #define RTC1_CONFIG_FREQUENCY 32678 // [Hz] +#endif + + + +void COMMON_RTC_IRQ_HANDLER(void) +{ + if(!nrf_rtc_event_pending(COMMON_RTC_INSTANCE, OS_TICK_EVENT)) { + common_rtc_irq_handler(); + } +} + +IRQn_Type mbed_get_m0_tick_irqn() +{ + return SWI3_IRQn; +} + + +#endif // defined(TARGET_MCU_NRF51822) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h index 2ebe70ecf72..dae27b263c4 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h @@ -20,29 +20,21 @@ #include "nrf_rtc.h" #define RTC_COUNTER_BITS 24u +#define RTC_FREQ 32768u // Instance 0 is reserved for SoftDevice. -// Instance 1 is used as a common one for us_ticker, lp_ticker and (in case +// Instance 1 is used as a common one for lp_ticker and (in case // of NRF51) as an alternative tick source for RTOS. -// ["us_ticker.c" uses hard coded addresses of the 'NRF_RTC1->EVENT_COMPARE[1]' -// register in inline assembly implementations of COMMON_RTC_IRQ_HANDLER, -// please remember to update those in case of doing changes here] #define COMMON_RTC_INSTANCE NRF_RTC1 #define COMMON_RTC_IRQ_HANDLER RTC1_IRQHandler -#define US_TICKER_CC_CHANNEL 0 -#define OS_TICK_CC_CHANNEL 1 -#define LP_TICKER_CC_CHANNEL 2 - -#define US_TICKER_SW_IRQ_MASK 0x1 -#define LP_TICKER_SW_IRQ_MASK 0x2 +#define OS_TICK_CC_CHANNEL 0 +#define LP_TICKER_CC_CHANNEL 1 #define COMMON_RTC_EVENT_COMPARE(channel) \ CONCAT_2(NRF_RTC_EVENT_COMPARE_, channel) #define COMMON_RTC_INT_COMPARE_MASK(channel) \ CONCAT_3(NRF_RTC_INT_COMPARE, channel, _MASK) -#define US_TICKER_EVENT COMMON_RTC_EVENT_COMPARE(US_TICKER_CC_CHANNEL) -#define US_TICKER_INT_MASK COMMON_RTC_INT_COMPARE_MASK(US_TICKER_CC_CHANNEL) #define OS_TICK_EVENT COMMON_RTC_EVENT_COMPARE(OS_TICK_CC_CHANNEL) #define OS_TICK_INT_MASK COMMON_RTC_INT_COMPARE_MASK(OS_TICK_CC_CHANNEL) #define LP_TICKER_EVENT COMMON_RTC_EVENT_COMPARE(LP_TICKER_CC_CHANNEL) @@ -50,7 +42,7 @@ extern bool m_common_rtc_enabled; extern uint32_t volatile m_common_rtc_overflows; -extern uint8_t volatile m_common_sw_irq_flag; +extern bool volatile lp_ticker_interrupt_fire; void common_rtc_init(void); uint32_t common_rtc_32bit_ticks_get(void); diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/lp_ticker.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/lp_ticker.c index def44835e29..9e197d8555e 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/lp_ticker.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/lp_ticker.c @@ -14,20 +14,35 @@ * limitations under the License. */ #include "lp_ticker_api.h" +#include "common_rtc.h" +#include "platform/mbed_critical.h" -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER -#include "common_rtc.h" -#include "mbed_critical.h" +/* LP ticker is driven by 32kHz clock and counter length is 24 bits. */ +const ticker_info_t* lp_ticker_get_info() +{ + static const ticker_info_t info = { + RTC_FREQ, + RTC_COUNTER_BITS + }; + return &info; +} void lp_ticker_init(void) { common_rtc_init(); } +void lp_ticker_free(void) +{ + // A common counter is used for RTC, lp_ticker and us_ticker, so it can't be + // disabled here, but this does not cause any extra cost. +} + uint32_t lp_ticker_read() { - return (uint32_t)common_rtc_64bit_us_get(); + return nrf_rtc_counter_get(COMMON_RTC_INSTANCE); } void lp_ticker_set_interrupt(timestamp_t timestamp) @@ -39,14 +54,17 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) void lp_ticker_fire_interrupt(void) { core_util_critical_section_enter(); - m_common_sw_irq_flag |= LP_TICKER_SW_IRQ_MASK; + + lp_ticker_interrupt_fire = true; + NVIC_SetPendingIRQ(RTC1_IRQn); + core_util_critical_section_exit(); } void lp_ticker_disable_interrupt(void) { - nrf_rtc_event_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); + nrf_rtc_int_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); } void lp_ticker_clear_interrupt(void) @@ -54,4 +72,4 @@ void lp_ticker_clear_interrupt(void) nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); } -#endif // DEVICE_LOWPOWERTIMER +#endif // DEVICE_LPTICKER diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.c index 64b5a267bf6..0ab3738bb1f 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.c @@ -36,137 +36,57 @@ * */ +#include "us_ticker.h" + #include "us_ticker_api.h" -#include "common_rtc.h" -#include "app_util.h" +#include "nrf_timer.h" +#include "app_util_platform.h" #include "nrf_drv_common.h" -#include "lp_ticker_api.h" #include "mbed_critical.h" -#if defined(NRF52_ERRATA_20) -#if defined(SOFTDEVICE_PRESENT) -#include "nrf_sdh.h" -#define NRF_HAL_US_TICKER_SD_IS_ENABLED() nrf_sdh_is_enabled() -#else -#define NRF_HAL_US_TICKER_SD_IS_ENABLED() 0 -#endif -#endif - -//------------------------------------------------------------------------------ -// Common stuff used also by lp_ticker and rtc_api (see "common_rtc.h"). -// -#include "app_util_platform.h" - -bool m_common_rtc_enabled = false; -uint32_t volatile m_common_rtc_overflows = 0; - -// lp/us ticker fire interrupt flag for IRQ handler -volatile uint8_t m_common_sw_irq_flag = 0; - -__STATIC_INLINE void rtc_ovf_event_check(void) -{ - if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) { - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); - // Don't disable this event. It shall occur periodically. - - ++m_common_rtc_overflows; - } -} +bool us_ticker_initialized = false; -#if defined(TARGET_MCU_NRF51822) -void common_rtc_irq_handler(void) -#else -void COMMON_RTC_IRQ_HANDLER(void) -#endif +/* us ticker is driven by 1MHz clock and counter length is 16 bits. */ +const ticker_info_t* us_ticker_get_info() { - - rtc_ovf_event_check(); - - if ((m_common_sw_irq_flag & US_TICKER_SW_IRQ_MASK) || nrf_rtc_event_pending(COMMON_RTC_INSTANCE, US_TICKER_EVENT)) { - us_ticker_irq_handler(); - } - -#if DEVICE_LOWPOWERTIMER - if (m_common_sw_irq_flag & LP_TICKER_SW_IRQ_MASK) { - m_common_sw_irq_flag &= ~LP_TICKER_SW_IRQ_MASK; - lp_ticker_irq_handler(); - } - if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, LP_TICKER_EVENT)) { - - lp_ticker_irq_handler(); - } -#endif + static const ticker_info_t info = { + US_TICKER_FREQ, + US_TICKER_COUNTER_BITS + }; + return &info; } -// Function for fix errata 20: RTC Register values are invalid -__STATIC_INLINE void errata_20(void) +void us_ticker_init(void) { -#if defined(NRF52_ERRATA_20) - if (!NRF_HAL_US_TICKER_SD_IS_ENABLED()) - { - NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; - NRF_CLOCK->TASKS_LFCLKSTART = 1; - - while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) - { - } + if (us_ticker_initialized) { + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); + nrf_timer_int_disable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); + return; } - NRF_RTC1->TASKS_STOP = 0; -#endif -} -void RTC1_IRQHandler(void); + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_STOP); -void common_rtc_init(void) -{ - if (m_common_rtc_enabled) { - return; - } + nrf_timer_int_disable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); - errata_20(); + /* Configure timer as follows: + * - timer mode, + * - timer width 16 bits, + * - timer freq 1 MHz. + */ + nrf_timer_mode_set(NRF_TIMER1, NRF_TIMER_MODE_TIMER); - NVIC_SetVector(RTC1_IRQn, (uint32_t)RTC1_IRQHandler); + nrf_timer_frequency_set(NRF_TIMER1, NRF_TIMER_FREQ_1MHz); - // RTC is driven by the low frequency (32.768 kHz) clock, a proper request - // must be made to have it running. - // Currently this clock is started in 'SystemInit' (see "system_nrf51.c" - // or "system_nrf52.c", respectively). + nrf_timer_bit_width_set(NRF_TIMER1, NRF_TIMER_BIT_WIDTH_16); - nrf_rtc_prescaler_set(COMMON_RTC_INSTANCE, 0); + nrf_timer_cc_write(NRF_TIMER1, NRF_TIMER_CC_CHANNEL0, 0); - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, US_TICKER_EVENT); -#if defined(TARGET_MCU_NRF51822) - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, OS_TICK_EVENT); -#endif -#if DEVICE_LOWPOWERTIMER - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); -#endif - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); - // Interrupts on all related events are enabled permanently. Particular - // events will be enabled or disabled as needed (such approach is more - // energy efficient). - nrf_rtc_int_enable(COMMON_RTC_INSTANCE, -#if DEVICE_LOWPOWERTIMER - LP_TICKER_INT_MASK | -#endif - US_TICKER_INT_MASK | - NRF_RTC_INT_OVERFLOW_MASK); + NVIC_SetVector(TIMER1_IRQn, (uint32_t)us_ticker_irq_handler); - // This event is enabled permanently, since overflow indications are needed - // continuously. - nrf_rtc_event_enable(COMMON_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); - // All other relevant events are initially disabled. - nrf_rtc_event_disable(COMMON_RTC_INSTANCE, -#if defined(TARGET_MCU_NRF51822) - OS_TICK_INT_MASK | -#endif -#if DEVICE_LOWPOWERTIMER - LP_TICKER_INT_MASK | -#endif - US_TICKER_INT_MASK); + nrf_drv_common_irq_enable(TIMER1_IRQn, - nrf_drv_common_irq_enable(nrf_drv_get_IRQn(COMMON_RTC_INSTANCE), #ifdef NRF51 APP_IRQ_PRIORITY_LOW #elif defined(NRF52) || defined(NRF52840_XXAA) @@ -174,158 +94,49 @@ void common_rtc_init(void) #endif ); - nrf_rtc_task_trigger(COMMON_RTC_INSTANCE, NRF_RTC_TASK_START); - - m_common_rtc_enabled = true; -} - -__STATIC_INLINE void rtc_ovf_event_safe_check(void) -{ - core_util_critical_section_enter(); - - rtc_ovf_event_check(); + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_START); - core_util_critical_section_exit(); + us_ticker_initialized = true; } - -uint32_t common_rtc_32bit_ticks_get(void) +uint32_t us_ticker_read() { - uint32_t ticks; - uint32_t prev_overflows; - - do { - prev_overflows = m_common_rtc_overflows; - - ticks = nrf_rtc_counter_get(COMMON_RTC_INSTANCE); - // The counter used for time measurements is less than 32 bit wide, - // so its value is complemented with the number of registered overflows - // of the counter. - ticks += (m_common_rtc_overflows << RTC_COUNTER_BITS); + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_CAPTURE1); - // Check in case that OVF occurred during execution of a RTC handler (apply if call was from RTC handler) - // m_common_rtc_overflows might been updated in this call. - rtc_ovf_event_safe_check(); - - // If call was made from a low priority level m_common_rtc_overflows might have been updated in RTC handler. - } while (m_common_rtc_overflows != prev_overflows); - - return ticks; + return nrf_timer_cc_read(NRF_TIMER1, NRF_TIMER_CC_CHANNEL1); } -uint64_t common_rtc_64bit_us_get(void) +void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t ticks = common_rtc_32bit_ticks_get(); - // [ticks -> microseconds] - return ROUNDED_DIV(((uint64_t)ticks) * 1000000, RTC_INPUT_FREQ); -} + core_util_critical_section_enter(); -void common_rtc_set_interrupt(uint32_t us_timestamp, uint32_t cc_channel, - uint32_t int_mask) -{ - // The internal counter is clocked with a frequency that cannot be easily - // multiplied to 1 MHz, therefore besides the translation of values - // (microsecond <-> ticks) a special care of overflows handling must be - // taken. Here the 32-bit timestamp value is complemented with information - // about current the system up time of (ticks + number of overflows of tick - // counter on upper bits, converted to microseconds), and such 64-bit value - // is then translated to counter ticks. Finally, the lower 24 bits of thus - // calculated value is written to the counter compare register to prepare - // the interrupt generation. - uint64_t current_time64 = common_rtc_64bit_us_get(); - // [add upper 32 bits from the current time to the timestamp value] - uint64_t timestamp64 = (current_time64 & ~(uint64_t)0xFFFFFFFF) | us_timestamp; - // [if the original timestamp value happens to be after the 32 bit counter - // of microsends overflows, correct the upper 32 bits accordingly] - if (timestamp64 < current_time64) { - timestamp64 += ((uint64_t)1 << 32); - } - // [microseconds -> ticks, always round the result up to avoid too early - // interrupt generation] - uint32_t compare_value = RTC_WRAP((uint32_t)CEIL_DIV((timestamp64) * RTC_INPUT_FREQ, 1000000)); + nrf_timer_cc_write(NRF_TIMER1, NRF_TIMER_CC_CHANNEL0, timestamp & 0xFFFF); - core_util_critical_section_enter(); - // The COMPARE event occurs when the value in compare register is N and - // the counter value changes from N-1 to N. Therefore, the minimal safe - // difference between the compare value to be set and the current counter - // value is 2 ticks. This guarantees that the compare trigger is properly - // setup before the compare condition occurs. - uint32_t closest_safe_compare = RTC_WRAP(common_rtc_32bit_ticks_get() + 2); - if (closest_safe_compare - compare_value < 2) { - compare_value = closest_safe_compare; + if (!nrf_timer_int_enable_check(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0))) { + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); + nrf_timer_int_enable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); } - nrf_rtc_cc_set(COMMON_RTC_INSTANCE, cc_channel, compare_value); - nrf_rtc_event_enable(COMMON_RTC_INSTANCE, int_mask); - core_util_critical_section_exit(); } -//------------------------------------------------------------------------------ - - -void us_ticker_init(void) -{ - common_rtc_init(); -} - -uint32_t us_ticker_read() -{ - us_ticker_init(); - return (uint32_t)common_rtc_64bit_us_get(); -} - -void us_ticker_set_interrupt(timestamp_t timestamp) -{ - common_rtc_set_interrupt(timestamp, - US_TICKER_CC_CHANNEL, US_TICKER_INT_MASK); -} void us_ticker_fire_interrupt(void) { - core_util_critical_section_enter(); - m_common_sw_irq_flag |= US_TICKER_SW_IRQ_MASK; - NVIC_SetPendingIRQ(RTC1_IRQn); - core_util_critical_section_exit(); + NVIC_SetPendingIRQ(TIMER1_IRQn); } void us_ticker_disable_interrupt(void) { - nrf_rtc_event_disable(COMMON_RTC_INSTANCE, US_TICKER_INT_MASK); + nrf_timer_int_disable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); } void us_ticker_clear_interrupt(void) { - m_common_sw_irq_flag &= ~US_TICKER_SW_IRQ_MASK; - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, US_TICKER_EVENT); + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); } - -// Since there is no SysTick on NRF51, the RTC1 channel 1 is used as an -// alternative source of RTOS ticks. -#if defined(TARGET_MCU_NRF51822) - -#include "mbed_toolchain.h" - - -#define MAX_RTC_COUNTER_VAL ((1uL << RTC_COUNTER_BITS) - 1) - -#ifndef RTC1_CONFIG_FREQUENCY - #define RTC1_CONFIG_FREQUENCY 32678 // [Hz] -#endif - - - -void COMMON_RTC_IRQ_HANDLER(void) -{ - if(!nrf_rtc_event_pending(COMMON_RTC_INSTANCE, OS_TICK_EVENT)) { - common_rtc_irq_handler(); - } -} - -IRQn_Type mbed_get_m0_tick_irqn() +void us_ticker_free(void) { - return SWI3_IRQn; + // A common counter is used for RTC, lp_ticker and us_ticker, so it can't be + // disabled here, but this does not cause any extra cost. } - - -#endif // defined(TARGET_MCU_NRF51822) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.h new file mode 100644 index 00000000000..f9bf80424c6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.h @@ -0,0 +1,26 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef US_TICKER_H +#define US_TICKER_H + +/* TIMER0 is reserved for SoftDevice. We will use TIMER1 for us ticker + * which counter size is 16 bits. */ + +#define US_TICKER_COUNTER_BITS 16u +#define US_TICKER_FREQ 1000000 + +#endif // US_TICKER_H From 9d6d7c07aca3335c5b761caad88bf458c964312b Mon Sep 17 00:00:00 2001 From: Przemyslaw Stekiel Date: Mon, 21 May 2018 09:02:46 +0200 Subject: [PATCH 2/9] NRF52_DK: Enable lp ticker and us ticker support --- targets/targets.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/targets/targets.json b/targets/targets.json index 4d1dc0aeadd..cacd581c98e 100755 --- a/targets/targets.json +++ b/targets/targets.json @@ -3545,6 +3545,7 @@ "I2C_ASYNCH", "INTERRUPTIN", "ITM", + "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", @@ -3557,7 +3558,8 @@ "SPI", "SPI_ASYNCH", "STCLK_OFF_DURING_SLEEP", - "TRNG" + "TRNG", + "USTICKER" ], "extra_labels": [ "NORDIC", @@ -3593,7 +3595,7 @@ "NRF52_DK": { "supported_form_factors": ["ARDUINO"], "inherits": ["MCU_NRF52832"], - "release_versions": [], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "UBLOX_EVA_NINA": { From eaf62ba276e454414eedfb2a039f84d573d2ca48 Mon Sep 17 00:00:00 2001 From: Przemyslaw Stekiel Date: Mon, 21 May 2018 09:07:35 +0200 Subject: [PATCH 3/9] tests-mbed_hal-common_tickers: fix bug in ticker increment test case It is possible that the difference between base and next tick count on some platforms is greater than 1, in this case we need to repeat counting with the reduced number of cycles (for slower boards). If number of cycles has been reduced than base tick count needs to be redefined. This operation is missing and is added by this patch. --- TESTS/mbed_hal/common_tickers/main.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/TESTS/mbed_hal/common_tickers/main.cpp b/TESTS/mbed_hal/common_tickers/main.cpp index ad8b758d214..2e8de400635 100644 --- a/TESTS/mbed_hal/common_tickers/main.cpp +++ b/TESTS/mbed_hal/common_tickers/main.cpp @@ -345,23 +345,28 @@ void ticker_increment_test(void) uint32_t num_of_cycles = NUM_OF_CYCLES; - const uint32_t base_tick_count = count_ticks(num_of_cycles, 1); + uint32_t base_tick_count = count_ticks(num_of_cycles, 1); uint32_t next_tick_count = base_tick_count; uint32_t inc_val = 0; while (inc_val < 100) { + next_tick_count = count_ticks(num_of_cycles + inc_val, 1); if (next_tick_count == base_tick_count) { + /* Same tick count, so increase num of cycles. */ inc_val++; } else { + /* It is possible that the difference between base and next * tick count on some platforms is greater that 1, in this case we need * to repeat counting with the reduced number of cycles (for slower boards). * In cases if difference is exactly 1 we can exit the loop. */ num_of_cycles /= 2; + inc_val = 0; + base_tick_count = count_ticks(num_of_cycles, 1); if (next_tick_count - base_tick_count == 1 || base_tick_count - next_tick_count == 1) { From e77ae328bef1da3cb6ca00161e725e7c49e7f4b1 Mon Sep 17 00:00:00 2001 From: Przemyslaw Stekiel Date: Mon, 21 May 2018 09:15:35 +0200 Subject: [PATCH 4/9] tests-mbed_drivers-timerevent: increase tolerance for NRF52_DK Test inserts event into the TimerEvent object which is scheduled 50 ms in the future. Then test thread hangs on the semaphore for 51 ms and after that time we expect that event handler has been executed. This test fails sometimes on NRF51_DK, NRF52_DK since different clocks are used for event handling and delay. TimerEvent class uses fast us ticker and semaphores are based on lp ticker (NRF51_DK) or System Tick Timer (NRF52_DK). We assume that ticker measurement error is 10% and our 1 [ms] extra corresponds to 2% error. I suggest to increase delay to 2 [ms] (4%). This should be enough for all boards at this moment. --- TESTS/mbed_drivers/timerevent/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/TESTS/mbed_drivers/timerevent/main.cpp b/TESTS/mbed_drivers/timerevent/main.cpp index 95f6f1b5803..5ac15e46b99 100644 --- a/TESTS/mbed_drivers/timerevent/main.cpp +++ b/TESTS/mbed_drivers/timerevent/main.cpp @@ -28,6 +28,7 @@ using namespace utest::v1; #endif #define TEST_DELAY_US 50000ULL +#define DELTA 2 class TestTimerEvent: public TimerEvent { private: @@ -125,7 +126,7 @@ void test_insert(void) { int32_t sem_slots = tte.sem_wait(0); TEST_ASSERT_EQUAL(0, sem_slots); - sem_slots = tte.sem_wait(TEST_DELAY_US / 1000 + 1); + sem_slots = tte.sem_wait(TEST_DELAY_US / 1000 + DELTA); TEST_ASSERT_EQUAL(1, sem_slots); tte.remove(); @@ -154,7 +155,7 @@ void test_remove(void) { TEST_ASSERT_EQUAL(0, sem_slots); tte.remove(); - sem_slots = tte.sem_wait(TEST_DELAY_US * 2 / 1000 + 1); + sem_slots = tte.sem_wait(TEST_DELAY_US * 2 / 1000 + DELTA); TEST_ASSERT_EQUAL(0, sem_slots); } From d78b6f9852f5ce2dd36bad7222ec5fd032401532 Mon Sep 17 00:00:00 2001 From: Przemyslaw Stekiel Date: Mon, 21 May 2018 09:52:55 +0200 Subject: [PATCH 5/9] tests-mbed_drivers-lp_timer: modify tolerance to percentage form Represent tolerance value as it is done in `tests-mbed_drivers_timer`. Use 5% tolerance for lp ticker. --- TESTS/mbed_drivers/lp_timer/main.cpp | 99 ++++++++++++++-------------- 1 file changed, 48 insertions(+), 51 deletions(-) diff --git a/TESTS/mbed_drivers/lp_timer/main.cpp b/TESTS/mbed_drivers/lp_timer/main.cpp index aded38268ea..60cffd307bc 100644 --- a/TESTS/mbed_drivers/lp_timer/main.cpp +++ b/TESTS/mbed_drivers/lp_timer/main.cpp @@ -35,26 +35,21 @@ extern uint32_t SystemCoreClock; * timer we need to adjust delta. */ -/* Macro to define delta based on CPU clock frequency. + /* + * Define tolerance as follows: + * tolerance = 500 us + 5% of measured time * - * Note that some extra time is counted by the timer. - * Additional time is caused by the function calls and - * additional operations performed by wait and - * stop functions before in fact timer is stopped. This may - * add additional time to the counted result. + * e.g. + * 1 ms delay: tolerance = 550 us + * 10 ms delay: tolerance = 1000 us + * 100 ms delay: tolerance = 5500 us + * 1000 ms delay: tolerance = 50500 us * - * To take in to account this extra time we introduce DELTA - * value based on CPU clock (speed): - * DELTA = TOLERANCE_FACTOR / SystemCoreClock * US_FACTOR - * - * e.g. - * For K64F DELTA = (80000 / 120000000) * 1000000 = 666[us] - * For NUCLEO_F070RB DELTA = (80000 / 48000000) * 1000000 = 1666[us] - * For NRF51_DK DELTA = (80000 / 16000000) * 1000000 = 5000[us] - * - * As low power timer cannot be too much accurate, this DELTA should not be more precise than 500us, - * which corresponds to a maximum CPU clock around 130MHz - */ + * */ +#define DELTA_US(delay_ms) (500 + delay_ms * US_PER_MSEC / 20) +#define DELTA_MS(delay_ms) (1 + (delay_ms * US_PER_MSEC / 20 / US_PER_MSEC)) +#define DELTA_S(delay_ms) (0.000500f + (((float)delay_ms) / MSEC_PER_SEC / 20)) + #define US_PER_SEC 1000000 #define US_PER_MSEC 1000 #define TOLERANCE_FACTOR 80000.0f @@ -122,10 +117,10 @@ void test_lptimer_time_accumulation() lp_timer.stop(); /* Check results - totally 10 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 10, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 10000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 10000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(10), 10, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(10), 10000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(10), 10000, lp_timer.read_high_resolution_us()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the @@ -144,10 +139,10 @@ void test_lptimer_time_accumulation() lp_timer.stop(); /* Check results - totally 30 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, lp_timer.read_high_resolution_us()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the @@ -165,10 +160,10 @@ void test_lptimer_time_accumulation() lp_timer.stop(); /* Check results - totally 60 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(3), 0.060f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(3), 60, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(3), 60000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(3), 60000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(60), 0.060f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(60), 60, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(60), 60000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(60), 60000, lp_timer.read_high_resolution_us()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the @@ -187,10 +182,10 @@ void test_lptimer_time_accumulation() lp_timer.stop(); /* Check results - totally 1060 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(4), 1.060f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(4), 1060, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(4), 1060000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(4), 1060000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1060), 1.060f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(1060), 1060, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(1060), 1060000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(1060), 1060000, lp_timer.read_high_resolution_us()); } /* This test verifies if reset() function resets the @@ -216,10 +211,10 @@ void test_lptimer_reset() lp_timer.stop(); /* Check results - totally 10 ms elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 10, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 10000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 10000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(10), 10, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(10), 10000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(10), 10000, lp_timer.read_high_resolution_us()); /* Reset the timer - previous measured time should be lost now. */ lp_timer.reset(); @@ -234,10 +229,10 @@ void test_lptimer_reset() lp_timer.stop(); /* Check results - 20 ms elapsed since the reset. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.020f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 20, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 20000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 20000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(20), 0.020f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(20), 20, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(20), 20000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(20), 20000, lp_timer.read_high_resolution_us()); } /* This test verifies if calling start() for already @@ -267,10 +262,10 @@ void test_lptimer_start_started_timer() lp_timer.stop(); /* Check results - 30 ms have elapsed since the first start. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, lp_timer.read_high_resolution_us()); } /* This test verifies low power timer float operator. @@ -294,7 +289,7 @@ void test_lptimer_float_operator() lp_timer.stop(); /* Check result - 10 ms elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, (float )(lp_timer)); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, (float )(lp_timer)); } /* This test verifies if time counted by the low power timer is @@ -310,6 +305,8 @@ void test_lptimer_time_measurement() { LowPowerTimer lp_timer; + const int delta_ms = (wait_val_us / US_PER_MSEC); + /* Start the timer. */ lp_timer.start(); @@ -320,10 +317,10 @@ void test_lptimer_time_measurement() lp_timer.stop(); /* Check results - wait_val_us us have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), (float )wait_val_us / 1000000, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), wait_val_us / 1000, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), wait_val_us, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), wait_val_us, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(delta_ms), (float )wait_val_us / 1000000, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(delta_ms), wait_val_us / 1000, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(delta_ms), wait_val_us, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(delta_ms), wait_val_us, lp_timer.read_high_resolution_us()); } utest::v1::status_t test_setup(const size_t number_of_cases) From 218d9b4276f49856585f7a60ece1103d343a497f Mon Sep 17 00:00:00 2001 From: Przemyslaw Stekiel Date: Mon, 21 May 2018 10:05:11 +0200 Subject: [PATCH 6/9] tests-mbed_hal-flash: Remove 5% extra tolerance for NRF52_DK NRF52_DK is now based on fast and accurate 1MHz counter. --- TESTS/mbed_hal/flash/functional_tests/main.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/TESTS/mbed_hal/flash/functional_tests/main.cpp b/TESTS/mbed_hal/flash/functional_tests/main.cpp index 8ca81ecb8b8..bbcf85c779e 100644 --- a/TESTS/mbed_hal/flash/functional_tests/main.cpp +++ b/TESTS/mbed_hal/flash/functional_tests/main.cpp @@ -29,12 +29,7 @@ using namespace utest::v1; #define TEST_CYCLES 10000000 -#ifdef TARGET_NRF52 -/* The increased tolerance is to account for the imprecise timers on the NRF52. */ -#define ALLOWED_DRIFT_PPM (1000000/50000) //5.0% -#else #define ALLOWED_DRIFT_PPM (1000000/5000) //0.5% -#endif /* return values to be checked are documented at: From 48bfc043740f8d782d6b7a6d937086f1b47a563f Mon Sep 17 00:00:00 2001 From: Przemyslaw Stekiel Date: Mon, 21 May 2018 10:08:40 +0200 Subject: [PATCH 7/9] tests-mbed_hal-flash: optimieze time_cpu_cycles() function This function should perform instruction cycles count in critical section. Additionally remove redundant code. --- TESTS/mbed_hal/flash/functional_tests/main.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/TESTS/mbed_hal/flash/functional_tests/main.cpp b/TESTS/mbed_hal/flash/functional_tests/main.cpp index bbcf85c779e..b5bdc51aff8 100644 --- a/TESTS/mbed_hal/flash/functional_tests/main.cpp +++ b/TESTS/mbed_hal/flash/functional_tests/main.cpp @@ -98,16 +98,18 @@ MBED_NOINLINE static int time_cpu_cycles(uint32_t cycles) { Timer timer; - timer.start(); - int timer_start = timer.read_us(); + core_util_critical_section_enter(); + + timer.start(); - uint32_t delay = cycles; - delay_loop(delay); - int timer_end = timer.read_us(); + delay_loop(cycles); timer.stop(); - return timer_end - timer_start; + + core_util_critical_section_exit(); + + return timer.read_us(); } void flash_init_test() From 318063e28428864595bb8804ba0115d95188353b Mon Sep 17 00:00:00 2001 From: Przemyslaw Stekiel Date: Mon, 21 May 2018 11:10:36 +0200 Subject: [PATCH 8/9] NRF52_DK: disable us ticker in deep-sleep mode This functionality is required by new sleep standards. --- .../TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/sleep.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/sleep.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/sleep.c index f7ec7911a64..a58591dd65a 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/sleep.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/sleep.c @@ -17,6 +17,8 @@ #include "cmsis.h" #include "mbed_interface.h" #include "nrf_soc.h" +#include "nrf_timer.h" +#include "us_ticker.h" #if defined(SOFTDEVICE_PRESENT) #include "nrf_sdh.h" @@ -31,6 +33,8 @@ #define FPU_EXCEPTION_MASK 0x0000009F +extern bool us_ticker_initialized; + void hal_sleep(void) { // ensure debug is disconnected if semihost is enabled.... @@ -83,6 +87,14 @@ void hal_sleep(void) void hal_deepsleep(void) { + if (us_ticker_initialized) { + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_STOP); + } + hal_sleep(); + + if (us_ticker_initialized) { + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_START); + } // NRF_POWER->SYSTEMOFF=1; } From 727d50bf9978da94231b88dc7cb45422b59821fc Mon Sep 17 00:00:00 2001 From: Przemyslaw Stekiel Date: Wed, 23 May 2018 13:58:46 +0200 Subject: [PATCH 9/9] Enable us lp ticker support for entire MCU_NRF52832 family --- targets/targets.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/targets/targets.json b/targets/targets.json index cacd581c98e..3f1d0136544 100755 --- a/targets/targets.json +++ b/targets/targets.json @@ -2454,7 +2454,7 @@ "RBLAB_BLENANO2": { "supported_form_factors": ["ARDUINO"], "inherits": ["MCU_NRF52832"], - "release_versions": [], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "NRF51822_Y5_MBUG": { @@ -3600,29 +3600,29 @@ }, "UBLOX_EVA_NINA": { "inherits": ["MCU_NRF52832"], - "release_versions": [], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "UBLOX_EVK_NINA_B1": { "supported_form_factors": ["ARDUINO"], "inherits": ["MCU_NRF52832"], - "release_versions": [], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "MTB_UBLOX_NINA_B1": { "inherits": ["MCU_NRF52832"], - "release_versions": [], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "MTB_LAIRD_BL652": { "inherits": ["MCU_NRF52832"], - "release_versions": [], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "DELTA_DFBM_NQ620": { "supported_form_factors": ["ARDUINO"], "inherits": ["MCU_NRF52832"], - "release_versions": [], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "MCU_NRF52840": { @@ -3957,7 +3957,7 @@ "VBLUNO52": { "supported_form_factors": ["ARDUINO"], "inherits": ["MCU_NRF52832"], - "release_versions": [], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "NUMAKER_PFM_M487": {