From aa6a26a4504f122415b4950ffcf8b16b4d9d59ca Mon Sep 17 00:00:00 2001 From: Magdalena Kasenberg Date: Wed, 15 Apr 2026 20:22:38 +0200 Subject: [PATCH 1/2] hw/mcu/nrf54l: Use RTC10 as a hal timer TIMER_5 Nimble LL requires a cputime that runs on 32768Hz. --- hw/bsp/nordic_pca10156/syscfg.yml | 7 + hw/mcu/nordic/nrf54lxx/src/hal_timer.c | 283 +++++++++++++++++++-- hw/mcu/nordic/nrf54lxx/src/nrf54l_periph.c | 4 + hw/mcu/nordic/nrf54lxx/syscfg.yml | 3 + 4 files changed, 270 insertions(+), 27 deletions(-) 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/src/hal_timer.c b/hw/mcu/nordic/nrf54lxx/src/hal_timer.c index 549238aced..92acd3b4b8 100644 --- a/hw/mcu/nordic/nrf54lxx/src/hal_timer.c +++ b/hw/mcu/nordic/nrf54lxx/src/hal_timer.c @@ -46,6 +46,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 +70,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 +100,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 +146,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 +224,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 +269,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 +288,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 +303,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 +342,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 +437,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 +505,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 +557,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 +690,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 +753,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 +826,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 +842,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 +912,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 From dca5b1bb890e1c540a04a3c2807aff6eddce05a5 Mon Sep 17 00:00:00 2001 From: Magdalena Kasenberg Date: Wed, 13 May 2026 20:58:43 +0200 Subject: [PATCH 2/2] hw/mcu/nrf54l: Add workaround to use RTC10 on nrf 3.14.0 The RTC for nRF54L15 has been removed since nrfx 3.10.0, but at least older board revisions (like 1.0.0) can still handle RTC at the old address. --- .../nrf54lxx/include/mcu/nrf54l15_rtc.h | 109 ++++++++++++++++++ hw/mcu/nordic/nrf54lxx/src/hal_os_tick.c | 1 + hw/mcu/nordic/nrf54lxx/src/hal_timer.c | 1 + 3 files changed, 111 insertions(+) create mode 100644 hw/mcu/nordic/nrf54lxx/include/mcu/nrf54l15_rtc.h 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 92acd3b4b8..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);