diff --git a/drivers/include/drivers/RealTimeClock.h b/drivers/include/drivers/RealTimeClock.h index cbd61b98bd2..818981d6a2c 100644 --- a/drivers/include/drivers/RealTimeClock.h +++ b/drivers/include/drivers/RealTimeClock.h @@ -73,10 +73,16 @@ class RealTimeClock { return rtc_free(); } - /** Check if the RTC has the time set and is counting + /** Check if the RTC has been initialized and is counting * * @retval false The time reported by the RTC is not valid - * @retval true The time has been set and the RTC is counting + * @retval true The RTC has been initialized and is counting + * + * @note In versions of Mbed before 7.0, this function claimed to return false "if the time had not been set." + * However, this was flawed because, in most implementations, it only returned true if the time had been + * set *on this boot*. There wasn't, and isn't, a way to detect whether the time was set correctly by a previous + * boot. To answer that question, you may wish to check if the time is approximately valid (in the 21st + * century), or add another flag at the application level. * * @see ::rtc_isenabled */ diff --git a/hal/include/hal/rtc_api.h b/hal/include/hal/rtc_api.h index 6c66d939822..2c59d7fba25 100644 --- a/hal/include/hal/rtc_api.h +++ b/hal/include/hal/rtc_api.h @@ -44,8 +44,7 @@ extern "C" { * * Shutdown mode doesn't stop RTC from counting - Not verified. * * The functions ::rtc_write/::rtc_read provides availability to set/get RTC time * - Verified by test rtc_write_read_test. - * * The functions ::rtc_isenabled returns 1 if the RTC is counting and the time has been set, - * 0 otherwise - Verified by test rtc_enabled_test. + * * The function ::rtc_isenabled returns 1 if the RTC has been initialized and 0 otherwise - Verified by test rtc_enabled_test. * * ::rtc_read may be called before rtc_write. If the RTC time has not been set, this will return the * time since some arbitrary epoch. If the RTC time was set on a previous boot, this will return time * based on what was set then. @@ -115,13 +114,23 @@ void rtc_init(void); * POWER_CTRL &= ~POWER_CTRL_RTC_Msk; * } * @endcode + * + * @note Implementations are allowed to not implement this function if it's impossible or there is + * no significant benefit to disabling the RTC. As such, the RTC is allowed to remain initialized + * after this function is called if freeing the RTC is not implemented. */ void rtc_free(void); -/** Check if the RTC has the time set and is counting +/** Check if the RTC has been initialized and is counting * * @retval 0 The time reported by the RTC is not valid - * @retval 1 The time has been set the RTC is counting + * @retval 1 The RTC has been initialized and is counting + * + * @note In versions of Mbed before 7.0, this function claimed to return false "if the time had not been set." + * However, this was flawed because, in most implementations, it only returned true if the time had been + * set *on this boot*. There wasn't, and isn't, a way to detect whether the time was set correctly by a previous + * boot. To answer that question, you may wish to check if the time is approximately valid (in the 21st + * century), or add another flag at the application level. * * Example Implementation Pseudo Code: * @code diff --git a/hal/tests/TESTS/mbed_hal/rtc_reset/CMakeLists.txt b/hal/tests/TESTS/mbed_hal/rtc_reset/CMakeLists.txt index 594de38b6b7..a635e96fb02 100644 --- a/hal/tests/TESTS/mbed_hal/rtc_reset/CMakeLists.txt +++ b/hal/tests/TESTS/mbed_hal/rtc_reset/CMakeLists.txt @@ -5,6 +5,11 @@ if(NOT "DEVICE_RTC=1" IN_LIST MBED_TARGET_DEFINITIONS) set(TEST_SKIPPED "RTC is not supported for this target") endif() +if(NOT "TARGET_K64F" IN_LIST MBED_TARGET_DEFINITIONS) + # Currently this test works OK, but causes the next 5-10 programming operations with OpenOCD to fail + set(TEST_SKIPPED "This test causes issues with this target's debug interface") +endif() + mbed_greentea_add_test( TEST_NAME mbed-hal-rtc-reset diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/rtc_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/rtc_api.c index 1165230eb80..5c95bbcef04 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/rtc_api.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/rtc_api.c @@ -22,24 +22,31 @@ #include "fsl_rtc.h" #include "PeripheralPins.h" -static bool rtc_time_set = false; +static bool rtc_enabled = false; void rtc_init(void) { rtc_config_t rtcConfig; - RTC_GetDefaultConfig(&rtcConfig); - RTC_Init(RTC, &rtcConfig); + if (!rtc_enabled) { + RTC_GetDefaultConfig(&rtcConfig); + RTC_Init(RTC, &rtcConfig); - RTC_StartTimer(RTC); + RTC_StartTimer(RTC); + } + + rtc_enabled = true; } void rtc_free(void) { + if (rtc_enabled) { #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) - /* Gate the module clock */ - CLOCK_DisableClock(kCLOCK_Rtc0); + /* Gate the module clock */ + CLOCK_DisableClock(kCLOCK_Rtc0); #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + rtc_enabled = false; + } } /* @@ -48,18 +55,7 @@ void rtc_free(void) */ int rtc_isenabled(void) { -#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) - CLOCK_EnableClock(kCLOCK_Rtc0); -#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ - - const bool rtc_init_done = ((RTC->SR & RTC_SR_TCE_MASK) >> RTC_SR_TCE_SHIFT); - - /* If RTC is not initialized, then disable the clock gate on exit. */ - if(!rtc_init_done) { - rtc_free(); - } - - return (rtc_init_done & rtc_time_set); + return rtc_enabled; } time_t rtc_read(void) @@ -72,8 +68,6 @@ void rtc_write(time_t t) RTC_StopTimer(RTC); RTC->TSR = t; RTC_StartTimer(RTC); - - rtc_time_set = true; } #endif diff --git a/targets/TARGET_NXP/TARGET_LPC17XX/CMakeLists.txt b/targets/TARGET_NXP/TARGET_LPC17XX/CMakeLists.txt index f56be84a76f..e0532c9abec 100644 --- a/targets/TARGET_NXP/TARGET_LPC17XX/CMakeLists.txt +++ b/targets/TARGET_NXP/TARGET_LPC17XX/CMakeLists.txt @@ -39,6 +39,7 @@ target_sources(mbed-lpc17xx spi_api.c us_ticker.c watchdog_api.c + mbed_overrides.c device/CRP.c device/flash_api.c diff --git a/targets/TARGET_NXP/TARGET_LPC17XX/mbed_overrides.c b/targets/TARGET_NXP/TARGET_LPC17XX/mbed_overrides.c new file mode 100644 index 00000000000..69d9399c3fd --- /dev/null +++ b/targets/TARGET_NXP/TARGET_LPC17XX/mbed_overrides.c @@ -0,0 +1,24 @@ +/* mbed Microcontroller Library + * Copyright (c) 2025 Jamie Smith + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#include + +void mbed_sdk_init(void) +{ + // RTC register block is on at boot, so turn it off until we need it (this is also needed to pass RTC tests). + rtc_free(); +} \ No newline at end of file diff --git a/targets/TARGET_NXP/TARGET_LPC17XX/rtc_api.c b/targets/TARGET_NXP/TARGET_LPC17XX/rtc_api.c index 40591259605..1fb9bbb718b 100644 --- a/targets/TARGET_NXP/TARGET_LPC17XX/rtc_api.c +++ b/targets/TARGET_NXP/TARGET_LPC17XX/rtc_api.c @@ -17,7 +17,8 @@ #include "rtc_api.h" #include "mbed_mktime.h" -// ensure rtc is running (unchanged if already running) +// RTC Power/Clock Control bit +#define LPC_SC_PCONP_PCRTC (1 << 9) /* Setup the RTC based on a time structure, ensuring RTC is enabled * @@ -36,14 +37,19 @@ * without impacting if it is the case */ void rtc_init(void) { - LPC_SC->PCONP |= 0x200; // Ensure power is on - LPC_RTC->CCR = 0x00; - - LPC_RTC->CCR |= 1 << 0; // Ensure the RTC is enabled + if(!rtc_isenabled()) { + LPC_SC->PCONP |= LPC_SC_PCONP_PCRTC; // Ensure power is on + LPC_RTC->CCR = 0x00; + + LPC_RTC->CCR |= 1 << 0; // Ensure the RTC is enabled + } } void rtc_free(void) { - // [TODO] + // Turn off power for RTC register block. + // The datasheet is not very clear, but in my testing, this does not impact the ability of the RTC + // to count the time. + LPC_SC->PCONP &= ~LPC_SC_PCONP_PCRTC; } /* @@ -54,7 +60,7 @@ void rtc_free(void) { * */ int rtc_isenabled(void) { - return(((LPC_RTC->CCR) & 0x01) != 0); + return (LPC_SC->PCONP & LPC_SC_PCONP_PCRTC) && (LPC_RTC->CCR & 0x01); } /* diff --git a/targets/TARGET_STM/rtc_api.c b/targets/TARGET_STM/rtc_api.c index 3fb6cc73209..ef5ac309ad1 100644 --- a/targets/TARGET_STM/rtc_api.c +++ b/targets/TARGET_STM/rtc_api.c @@ -294,11 +294,7 @@ void rtc_write(time_t t) int rtc_isenabled(void) { -#if defined (RTC_FLAG_INITS) /* all STM32 except STM32F1 */ - return LL_RTC_IsActiveFlag_INITS(RTC); -#else /* RTC_FLAG_INITS */ /* TARGET_STM32F1 */ - return ((RTC->CRL & RTC_CRL_RSF) == RTC_CRL_RSF); -#endif /* RTC_FLAG_INITS */ + return RTC_inited; }