diff --git a/hw/bsp/nordic_pca10156/syscfg.yml b/hw/bsp/nordic_pca10156/syscfg.yml index 28c25c61f5..f83f88c361 100644 --- a/hw/bsp/nordic_pca10156/syscfg.yml +++ b/hw/bsp/nordic_pca10156/syscfg.yml @@ -38,3 +38,10 @@ syscfg.vals: MYNEWT_DOWNLOADER: nrfutil JLINK_TARGET: CORTEX-M33 MYNEWT_DOWNLOADER_MFG_IMAGE_FLASH_OFFSET: 0x0 + +syscfg.vals.BLE_CONTROLLER: + TIMER_0: 0 + TIMER_5: 1 + OS_CPUTIME_FREQ: 32768 + OS_CPUTIME_TIMER_NUM: 5 + BLE_LL_RFMGMT_ENABLE_TIME: 1500 diff --git a/hw/mcu/nordic/nrf54lxx/include/mcu/nrf54l15_rtc.h b/hw/mcu/nordic/nrf54lxx/include/mcu/nrf54l15_rtc.h new file mode 100644 index 0000000000..16523d5c5f --- /dev/null +++ b/hw/mcu/nordic/nrf54lxx/include/mcu/nrf54l15_rtc.h @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 _NRF54L_RTC_H_ +#define _NRF54L_RTC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(NRF_RTC10) +#include "core_cm33.h" +/** + * @brief Real-time counter + */ +typedef struct { /*!< RTC Structure */ + __OM uint32_t TASKS_START; /*!< (@ 0x00000000) Start RTC counter */ + __OM uint32_t TASKS_STOP; /*!< (@ 0x00000004) Stop RTC counter */ + __OM uint32_t TASKS_CLEAR; /*!< (@ 0x00000008) Clear RTC counter */ + __OM uint32_t TASKS_TRIGOVRFLW; /*!< (@ 0x0000000C) Set counter to 0xFFFFF0 */ + __IM uint32_t RESERVED[12]; + __OM uint32_t TASKS_CAPTURE[4]; /*!< (@ 0x00000040) Capture RTC counter to CC[n] register */ + __IM uint32_t RESERVED1[12]; + __IOM uint32_t SUBSCRIBE_START; /*!< (@ 0x00000080) Subscribe configuration for task START */ + __IOM uint32_t SUBSCRIBE_STOP; /*!< (@ 0x00000084) Subscribe configuration for task STOP */ + __IOM uint32_t SUBSCRIBE_CLEAR; /*!< (@ 0x00000088) Subscribe configuration for task CLEAR */ + __IOM uint32_t SUBSCRIBE_TRIGOVRFLW; /*!< (@ 0x0000008C) Subscribe configuration for task TRIGOVRFLW */ + __IM uint32_t RESERVED2[12]; + __IOM uint32_t SUBSCRIBE_CAPTURE[4]; /*!< (@ 0x000000C0) Subscribe configuration for task CAPTURE[n] */ + __IM uint32_t RESERVED3[12]; + __IOM uint32_t EVENTS_TICK; /*!< (@ 0x00000100) Event on counter increment */ + __IOM uint32_t EVENTS_OVRFLW; /*!< (@ 0x00000104) Event on counter overflow */ + __IM uint32_t RESERVED4[14]; + __IOM uint32_t EVENTS_COMPARE[4]; /*!< (@ 0x00000140) Compare event on CC[n] match */ + __IM uint32_t RESERVED5[12]; + __IOM uint32_t PUBLISH_TICK; /*!< (@ 0x00000180) Publish configuration for event TICK */ + __IOM uint32_t PUBLISH_OVRFLW; /*!< (@ 0x00000184) Publish configuration for event OVRFLW */ + __IM uint32_t RESERVED6[14]; + __IOM uint32_t PUBLISH_COMPARE[4]; /*!< (@ 0x000001C0) Publish configuration for event COMPARE[n] */ + __IM uint32_t RESERVED7[12]; + __IOM uint32_t SHORTS; /*!< (@ 0x00000200) Shortcuts between local events and tasks */ + __IM uint32_t RESERVED8[64]; + __IOM uint32_t INTENSET; /*!< (@ 0x00000304) Enable interrupt */ + __IOM uint32_t INTENCLR; /*!< (@ 0x00000308) Disable interrupt */ + __IM uint32_t RESERVED9[13]; + __IOM uint32_t EVTEN; /*!< (@ 0x00000340) Enable or disable event routing */ + __IOM uint32_t EVTENSET; /*!< (@ 0x00000344) Enable event routing */ + __IOM uint32_t EVTENCLR; /*!< (@ 0x00000348) Disable event routing */ + __IM uint32_t RESERVED10[110]; + __IM uint32_t COUNTER; /*!< (@ 0x00000504) Current counter value */ + __IOM uint32_t PRESCALER; /*!< (@ 0x00000508) 12-bit prescaler for counter frequency (32768 / + (PRESCALER + 1)). Must be written when RTC is stopped.*/ + __IM uint32_t RESERVED11[13]; + __IOM uint32_t CC[4]; /*!< (@ 0x00000540) Compare register n */ +} NRF_RTC_Type; /*!< Size = 1360 (0x550) */ + +#define NRF_RTC10_NS_BASE 0x40086000UL +#define NRF_RTC10_S_BASE 0x50086000UL +#define NRF_RTC10_NS ((NRF_RTC_Type*)NRF_RTC10_NS_BASE) +#define NRF_RTC10_S ((NRF_RTC_Type*)NRF_RTC10_S_BASE) +#define NRF_RTC10 NRF_RTC10_S + +#define RTC10_IRQn (134) +#define RTC_INTENCLR_TICK_Pos (0UL) /*!< Position of TICK field. */ +#define RTC_INTENCLR_TICK_Msk (0x1UL << RTC_INTENCLR_TICK_Pos) /*!< Bit mask of TICK field. */ +#define RTC_INTENSET_TICK_Pos (0UL) /*!< Position of TICK field. */ +#define RTC_INTENSET_TICK_Msk (0x1UL << RTC_INTENSET_TICK_Pos) /*!< Bit mask of TICK field. */ +#define RTC_INTENSET_OVRFLW_Pos (1UL) /*!< Position of OVRFLW field. */ +#define RTC_INTENSET_OVRFLW_Msk (0x1UL << RTC_INTENSET_OVRFLW_Pos) /*!< Bit mask of OVRFLW field. */ +#define RTC_EVTENSET_COMPARE0_Pos (16UL) /*!< Position of COMPARE0 field. */ +#define RTC_EVTENSET_COMPARE0_Msk (0x1UL << RTC_EVTENSET_COMPARE0_Pos) /*!< Bit mask of COMPARE0 field. */ + +static inline void nrf_rtc_event_enable(NRF_RTC_Type * p_reg, uint32_t mask) +{ + p_reg->EVTENSET = mask; +} + +static inline void nrf_rtc_event_disable(NRF_RTC_Type * p_reg, uint32_t mask) +{ + p_reg->EVTENCLR = mask; +} + +static inline void nrf_rtc_cc_set(NRF_RTC_Type * p_reg, uint32_t ch, uint32_t cc_val) +{ + p_reg->CC[ch] = cc_val; +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _NRF54L_RTC_H_ */ diff --git a/hw/mcu/nordic/nrf54lxx/src/hal_os_tick.c b/hw/mcu/nordic/nrf54lxx/src/hal_os_tick.c index c1ecc6dd53..0d245576ee 100644 --- a/hw/mcu/nordic/nrf54lxx/src/hal_os_tick.c +++ b/hw/mcu/nordic/nrf54lxx/src/hal_os_tick.c @@ -22,6 +22,7 @@ #include #include #include +#include /* The OS scheduler requires a low-frequency timer. */ #if MYNEWT_VAL(OS_SCHEDULING) && !MYNEWT_VAL(MCU_LFCLK_SOURCE) diff --git a/hw/mcu/nordic/nrf54lxx/src/hal_timer.c b/hw/mcu/nordic/nrf54lxx/src/hal_timer.c index 549238aced..da6d596ea9 100644 --- a/hw/mcu/nordic/nrf54lxx/src/hal_timer.c +++ b/hw/mcu/nordic/nrf54lxx/src/hal_timer.c @@ -26,6 +26,7 @@ #include #include #include +#include /* IRQ prototype */ typedef void (*hal_timer_irq_handler_t)(void); @@ -46,6 +47,7 @@ typedef void (*hal_timer_irq_handler_t)(void); struct nrf54l_hal_timer { uint8_t tmr_enabled; uint16_t tmr_irq_num; + uint8_t tmr_rtc; uint8_t tmr_pad; uint32_t tmr_cntr; uint32_t timer_isrs; @@ -69,6 +71,9 @@ struct nrf54l_hal_timer nrf54l_hal_timer3; #if MYNEWT_VAL(TIMER_4) struct nrf54l_hal_timer nrf54l_hal_timer4; #endif +#if MYNEWT_VAL(TIMER_5) +struct nrf54l_hal_timer nrf54l_hal_timer5; +#endif static const struct nrf54l_hal_timer *nrf54l_hal_timers[nrf54l_hal_timer_MAX] = { #if MYNEWT_VAL(TIMER_0) @@ -96,6 +101,11 @@ static const struct nrf54l_hal_timer *nrf54l_hal_timers[nrf54l_hal_timer_MAX] = #else NULL, #endif +#if MYNEWT_VAL(TIMER_5) + &nrf54l_hal_timer5, +#else + NULL, +#endif }; /* Resolve timer number into timer structure */ @@ -137,25 +147,74 @@ nrf_read_timer_cntr(NRF_TIMER_Type *hwtimer) static void nrf_timer_set_ocmp(struct nrf54l_hal_timer *bsptimer, uint32_t expiry) { + int32_t delta_t; + uint32_t temp; + uint32_t cntr; NRF_TIMER_Type *hwtimer; + NRF_RTC_Type *rtctimer; + + if (bsptimer->tmr_rtc) { + rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg; + rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT); + temp = bsptimer->tmr_cntr; + cntr = rtctimer->COUNTER; + if (rtctimer->EVENTS_OVRFLW) { + temp += (1UL << 24); + cntr = rtctimer->COUNTER; + } + temp |= cntr; + delta_t = (int32_t)(expiry - temp); + + /* + * XXX: There is no RTC peripheral description in documentation yet, + * but following information was true for every previous nRF5x MCU: + * The documentation states that COMPARE event is guaranteed + * only if value written to CC register is at least 2 greater than the + * current counter value. We also need to account for possible extra + * tick during calculations so effectively any delta less than 3 needs + * to be handled differently. TICK event is used to have interrupt on + * each subsequent tick so we won't miss any and in case we detected + * mentioned extra tick during calculations, interrupt is triggered + * immediately. Delta 0 or less means we should always fire immediately. + */ + if (delta_t < 1) { + rtctimer->INTENCLR = RTC_INTENCLR_TICK_Msk; + NVIC_SetPendingIRQ(bsptimer->tmr_irq_num); + } else if (delta_t < 3) { + rtctimer->INTENSET = RTC_INTENSET_TICK_Msk; + if (rtctimer->COUNTER != cntr) { + NVIC_SetPendingIRQ(bsptimer->tmr_irq_num); + } + } else { + rtctimer->INTENCLR = RTC_INTENCLR_TICK_Msk; - hwtimer = bsptimer->tmr_reg; + if (delta_t < (1UL << 24)) { + rtctimer->CC[NRF_RTC_TIMER_CC_INT] = expiry & 0x00ffffff; + } else { + /* CC too far ahead. Just make sure we set compare far ahead */ + rtctimer->CC[NRF_RTC_TIMER_CC_INT] = cntr + (1UL << 23); + } + rtctimer->INTENSET = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT); + } + } else { + hwtimer = bsptimer->tmr_reg; - /* Disable ocmp interrupt and set new value */ - hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT); + /* Disable ocmp interrupt and set new value */ + hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT); - /* Set output compare register to timer expiration */ - hwtimer->CC[NRF_TIMER_CC_INT] = expiry; + /* Set output compare register to timer expiration */ + hwtimer->CC[NRF_TIMER_CC_INT] = expiry; - /* Clear interrupt flag */ - hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT] = 0; + /* Clear interrupt flag */ + hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT] = 0; - /* Enable the output compare interrupt */ - hwtimer->INTENSET = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT); + /* Enable the output compare interrupt */ + hwtimer->INTENSET = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT); - /* Force interrupt to occur as we may have missed it */ - if ((int32_t)(nrf_read_timer_cntr(hwtimer) - expiry) >= 0) { - NVIC_SetPendingIRQ(bsptimer->tmr_irq_num); + /* Force interrupt to occur as we may have missed it */ + if ((int32_t)(nrf_read_timer_cntr(hwtimer) - expiry) >= 0) { + NVIC_SetPendingIRQ(bsptimer->tmr_irq_num); + } } } @@ -166,8 +225,41 @@ nrf_timer_disable_ocmp(NRF_TIMER_Type *hwtimer) hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT); } -#if (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(TIMER_2) || \ - MYNEWT_VAL(TIMER_3) || MYNEWT_VAL(TIMER_4)) +static void +nrf_rtc_disable_ocmp(NRF_RTC_Type *rtctimer) +{ + rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT); + rtctimer->INTENCLR = RTC_INTENCLR_TICK_Msk; +} + +static uint32_t +hal_timer_read_bsptimer(struct nrf54l_hal_timer *bsptimer) +{ + uint32_t low32; + uint32_t ctx; + uint32_t tcntr; + NRF_RTC_Type *rtctimer; + + rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg; + __HAL_DISABLE_INTERRUPTS(ctx); + tcntr = bsptimer->tmr_cntr; + low32 = rtctimer->COUNTER; + if (rtctimer->EVENTS_OVRFLW) { + tcntr += (1UL << 24); + bsptimer->tmr_cntr = tcntr; + low32 = rtctimer->COUNTER; + rtctimer->EVENTS_OVRFLW = 0; + NVIC_SetPendingIRQ(bsptimer->tmr_irq_num); + } + tcntr |= low32; + __HAL_ENABLE_INTERRUPTS(ctx); + + return tcntr; +} + +#if (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(TIMER_2) || \ + MYNEWT_VAL(TIMER_3) || MYNEWT_VAL(TIMER_4) || MYNEWT_VAL(TIMER_5)) + static void hal_timer_chk_queue(struct nrf54l_hal_timer *bsptimer) { @@ -178,7 +270,11 @@ hal_timer_chk_queue(struct nrf54l_hal_timer *bsptimer) /* disable interrupts */ __HAL_DISABLE_INTERRUPTS(ctx); while ((timer = TAILQ_FIRST(&bsptimer->hal_timer_q)) != NULL) { - tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg); + if (bsptimer->tmr_rtc) { + tcntr = hal_timer_read_bsptimer(bsptimer); + } else { + tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg); + } if ((int32_t)(tcntr - timer->expiry) >= 0) { TAILQ_REMOVE(&bsptimer->hal_timer_q, timer, link); timer->link.tqe_prev = NULL; @@ -193,7 +289,11 @@ hal_timer_chk_queue(struct nrf54l_hal_timer *bsptimer) if (timer) { nrf_timer_set_ocmp(bsptimer, timer->expiry); } else { - nrf_timer_disable_ocmp(bsptimer->tmr_reg); + if (bsptimer->tmr_rtc) { + nrf_rtc_disable_ocmp((NRF_RTC_Type *)bsptimer->tmr_reg); + } else { + nrf_timer_disable_ocmp(bsptimer->tmr_reg); + } } __HAL_ENABLE_INTERRUPTS(ctx); } @@ -204,7 +304,7 @@ hal_timer_chk_queue(struct nrf54l_hal_timer *bsptimer) * * @param bsptimer Pointer to timer. */ -#if (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(TIMER_2) || \ +#if (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(TIMER_2) || \ MYNEWT_VAL(TIMER_3) || MYNEWT_VAL(TIMER_4)) static void hal_timer_irq_handler(struct nrf54l_hal_timer *bsptimer) @@ -243,6 +343,61 @@ hal_timer_irq_handler(struct nrf54l_hal_timer *bsptimer) } #endif +/** + * Generic HAL RTC timer irq handler. + * + * @param bsptimer Pointer to timer. + */ +#if MYNEWT_VAL(TIMER_5) +static void +hal_rtc_timer_irq_handler(struct nrf54l_hal_timer *bsptimer) +{ + uint32_t overflow; + uint32_t compare; + uint32_t tick; + NRF_RTC_Type *rtctimer; + + os_trace_isr_enter(); + + /* Check interrupt source. If set, clear them */ + rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg; + compare = rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT]; + if (compare) { + rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT] = 0; + } + + tick = rtctimer->EVENTS_TICK; + if (tick) { + rtctimer->EVENTS_TICK = 0; + } + + overflow = rtctimer->EVENTS_OVRFLW; + if (overflow) { + rtctimer->EVENTS_OVRFLW = 0; + bsptimer->tmr_cntr += (1UL << 24); + } + + /* Count # of timer isrs */ + ++bsptimer->timer_isrs; + + /* + * NOTE: we dont check the 'compare' variable here due to how the timer + * is implemented on this chip. There is no way to force an output + * compare, so if we are late setting the output compare (i.e. the timer + * counter is already passed the output compare value), we use the NVIC + * to set a pending interrupt. This means that there will be no compare + * flag set, so all we do is check to see if the compare interrupt is + * enabled. + */ + hal_timer_chk_queue(bsptimer); + + /* Recommended by nordic to make sure interrupts are cleared */ + compare = rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT]; + + os_trace_isr_exit(); +} +#endif + #if MYNEWT_VAL(TIMER_0) void nrf54l_timer0_irq_handler(void) @@ -283,6 +438,14 @@ nrf54l_timer4_irq_handler(void) } #endif +#if MYNEWT_VAL(TIMER_5) +void +nrf54l_timer5_irq_handler(void) +{ + hal_rtc_timer_irq_handler(&nrf54l_hal_timer5); +} +#endif + /** * Initialize platform specific timer items * @@ -343,6 +506,14 @@ hal_timer_init(int timer_num, void *cfg) hwtimer = NRF_TIMER24; irq_isr = nrf54l_timer4_irq_handler; break; +#endif +#if MYNEWT_VAL(TIMER_5) + case 5: + irq_num = RTC10_IRQn; + hwtimer = NRF_RTC10; + irq_isr = nrf54l_timer5_irq_handler; + bsptimer->tmr_rtc = 1; + break; #endif default: hwtimer = NULL; @@ -387,9 +558,50 @@ hal_timer_config(int timer_num, uint32_t freq_hz) uint32_t max_delta; struct nrf54l_hal_timer *bsptimer; NRF_TIMER_Type *hwtimer; +#if MYNEWT_VAL(TIMER_5) + NRF_RTC_Type *rtctimer; +#endif nrf54l_hal_timer_RESOLVE(timer_num, bsptimer); +#if MYNEWT_VAL(TIMER_5) + if (timer_num == 5) { + /* NOTE: we only allow the RTC frequency to be set at 32768 */ + if (bsptimer->tmr_enabled || (freq_hz != 32768) || + (bsptimer->tmr_reg == NULL)) { + rc = EINVAL; + goto err; + } + + bsptimer->tmr_freq = freq_hz; + bsptimer->tmr_enabled = 1; + + __HAL_DISABLE_INTERRUPTS(ctx); + + rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg; + + /* Stop the timer first */ + rtctimer->TASKS_STOP = 1; + rtctimer->TASKS_CLEAR = 1; + + /* Always no prescaler */ + rtctimer->PRESCALER = 0; + + /* Clear overflow events and set overflow interrupt */ + rtctimer->EVENTS_OVRFLW = 0; + rtctimer->INTENSET = RTC_INTENSET_OVRFLW_Msk; + + /* Start the timer */ + rtctimer->TASKS_START = 1; + + /* Set isr in vector table and enable interrupt */ + NVIC_EnableIRQ(bsptimer->tmr_irq_num); + + __HAL_ENABLE_INTERRUPTS(ctx); + return 0; + } +#endif + /* Set timer to desired frequency */ div = NRF54L_MAX_TIMER_FREQ / freq_hz; @@ -479,16 +691,22 @@ hal_timer_deinit(int timer_num) uint32_t ctx; struct nrf54l_hal_timer *bsptimer; NRF_TIMER_Type *hwtimer; + NRF_RTC_Type *rtctimer; rc = 0; nrf54l_hal_timer_RESOLVE(timer_num, bsptimer); __HAL_DISABLE_INTERRUPTS(ctx); - hwtimer = (NRF_TIMER_Type *)bsptimer->tmr_reg; - hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT); - hwtimer->TASKS_STOP = 1; - hwtimer->TASKS_CLEAR = 1; - + if (bsptimer->tmr_rtc) { + rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg; + rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT); + rtctimer->TASKS_STOP = 1; + } else { + hwtimer = (NRF_TIMER_Type *)bsptimer->tmr_reg; + hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT); + hwtimer->TASKS_STOP = 1; + hwtimer->TASKS_CLEAR = 1; + } bsptimer->tmr_enabled = 0; bsptimer->tmr_reg = NULL; __HAL_ENABLE_INTERRUPTS(ctx); @@ -536,8 +754,11 @@ hal_timer_read(int timer_num) struct nrf54l_hal_timer *bsptimer; nrf54l_hal_timer_RESOLVE(timer_num, bsptimer); - - tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg); + if (bsptimer->tmr_rtc) { + tcntr = hal_timer_read_bsptimer(bsptimer); + } else { + tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg); + } return tcntr; @@ -606,7 +827,11 @@ hal_timer_start(struct hal_timer *timer, uint32_t ticks) /* Set the tick value at which the timer should expire */ bsptimer = (struct nrf54l_hal_timer *)timer->bsp_timer; - tick = nrf_read_timer_cntr(bsptimer->tmr_reg) + ticks; + if (bsptimer->tmr_rtc) { + tick = hal_timer_read_bsptimer(bsptimer) + ticks; + } else { + tick = nrf_read_timer_cntr(bsptimer->tmr_reg) + ticks; + } rc = hal_timer_start_at(timer, tick); return rc; } @@ -618,7 +843,8 @@ hal_timer_start_at(struct hal_timer *timer, uint32_t tick) struct hal_timer *entry; struct nrf54l_hal_timer *bsptimer; - if (timer == NULL || timer->link.tqe_prev != NULL || timer->cb_func == NULL) { + if ((timer == NULL) || (timer->link.tqe_prev != NULL) || + (timer->cb_func == NULL)) { return EINVAL; } bsptimer = (struct nrf54l_hal_timer *)timer->bsp_timer; @@ -687,7 +913,11 @@ hal_timer_stop(struct hal_timer *timer) nrf_timer_set_ocmp((struct nrf54l_hal_timer *)entry->bsp_timer, entry->expiry); } else { - nrf_timer_disable_ocmp(bsptimer->tmr_reg); + if (bsptimer->tmr_rtc) { + nrf_rtc_disable_ocmp((NRF_RTC_Type *)bsptimer->tmr_reg); + } else { + nrf_timer_disable_ocmp(bsptimer->tmr_reg); + } } } } diff --git a/hw/mcu/nordic/nrf54lxx/src/nrf54l_periph.c b/hw/mcu/nordic/nrf54lxx/src/nrf54l_periph.c index 7d5e28bfdd..41f1c3515f 100644 --- a/hw/mcu/nordic/nrf54lxx/src/nrf54l_periph.c +++ b/hw/mcu/nordic/nrf54lxx/src/nrf54l_periph.c @@ -83,6 +83,10 @@ nrf54l_periph_create_timers(void) rc = hal_timer_init(4, NULL); assert(rc == 0); #endif +#if MYNEWT_VAL(TIMER_5) + rc = hal_timer_init(5, NULL); + assert(rc == 0); +#endif #if MYNEWT_VAL(OS_CPUTIME_TIMER_NUM) >= 0 rc = os_cputime_init(MYNEWT_VAL(OS_CPUTIME_FREQ)); diff --git a/hw/mcu/nordic/nrf54lxx/syscfg.yml b/hw/mcu/nordic/nrf54lxx/syscfg.yml index 43a5e8edf5..91fae85031 100644 --- a/hw/mcu/nordic/nrf54lxx/syscfg.yml +++ b/hw/mcu/nordic/nrf54lxx/syscfg.yml @@ -127,6 +127,9 @@ syscfg.defs: TIMER_4: description: 'Enable nRF54Lxx Timer 24' value: 0 + TIMER_5: + description: 'Enable nRF54Lxx Timer RTC10' + value: 0 syscfg.vals: OS_TICKS_PER_SEC: 1000