diff --git a/os/common/ext/RP/RP2040/rp2040.h b/os/common/ext/RP/RP2040/rp2040.h index 4ec4f303d..701833407 100644 --- a/os/common/ext/RP/RP2040/rp2040.h +++ b/os/common/ext/RP/RP2040/rp2040.h @@ -230,6 +230,21 @@ typedef struct { __I uint32_t UARTPCELLID2; __I uint32_t UARTPCELLID3; } UART_TypeDef; + +typedef struct { + __IO uint32_t CLKDIVM1; + __IO uint32_t SETUP0; + __IO uint32_t SETUP1; + __IO uint32_t CTRL; + __IO uint32_t IRQSETUP0; + __IO uint32_t IRQSETUP1; + __IO uint32_t RTC1; + __IO uint32_t RTC0; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; +} RTC_TypeDef; /** @} */ /** @@ -248,6 +263,7 @@ typedef struct { #define __UART0_BASE (__APBPERIPH_BASE + 0x00034000U) #define __UART1_BASE (__APBPERIPH_BASE + 0x00038000U) #define __SIO_BASE (__IOPORT_BASE + 0x00000000U) +#define __RTC_BASE (__APBPERIPH_BASE + 0x0005c000U) /** @} */ /** @@ -263,6 +279,7 @@ typedef struct { #define TIMER ((TIMER_TypeDef *) __TIMER_BASE) #define UART0 ((UART_TypeDef *) __UART0_BASE) #define UART1 ((UART_TypeDef *) __UART1_BASE) +#define RTC ((RTC_TypeDef *) __RTC_BASE) /** @} */ /** diff --git a/os/hal/ports/RP/LLD/RTCv1/driver.mk b/os/hal/ports/RP/LLD/RTCv1/driver.mk new file mode 100644 index 000000000..0ec518f5b --- /dev/null +++ b/os/hal/ports/RP/LLD/RTCv1/driver.mk @@ -0,0 +1,9 @@ +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/RP/LLD/RTCv1 diff --git a/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.c b/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.c new file mode 100644 index 000000000..a51f7b267 --- /dev/null +++ b/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.c @@ -0,0 +1,196 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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. +*/ + +/** + * @file hal_rtc_lld.c + * @brief RP2040 RTC subsystem low level driver source. + * + * @addtogroup RTC + * @{ + */ + +#include "hal.h" +#include "hardware/rtc.h" + +#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief RTC driver identifier. + */ +RTCDriver RTCD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Enable access to registers. + * + * @notapi + */ +void rtc_lld_init(void) { + + /* RTC object initialization.*/ + rtcObjectInit(&RTCD1); + + /* RTC pointer initialization.*/ + RTCD1.rtc = RTC; + + clock = hal_lld_get_clock(clk_rtc); + + osalDbgAssert(clock > 0U, "no clock"); + + /* Take RTC out of reset. */ + hal_lld_peripheral_unreset(RESETS_ALLREG_RTC); + + clock -= 1; + osalDbgAssert(clock <= RTC_CLKDIV_M1_BITS, "invalid divide"); + + RTCD1.rtc.CLKDIVM1 = clock; + + /* Callback initially disabled.*/ + RTCD1.callback = NULL; + + /* IRQ vector permanently assigned to this driver.*/ + //nvicEnableVector(STM32_RTC1_NUMBER, STM32_RTC_IRQ_PRIORITY); +} + +/** + * @brief Set current time. + * @note Fractional part will be silently ignored. There is no possibility + * to set it on RP2040 platform. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { + + uint32_t sec = (uint32_t)timespec->millisecond / 1000; + uint32_t hour = sec / 3600; + sec %= 3600; + uint32_t min = sec / 60; + sec %= 60; + + /* Disable RTC. */ + rtcp->rtc->CTRL = 0; + + /* Wait for RTC to become inactive. */ + while (rtccp->rtc->CTRL & RTC_CTRL_RTC_ACTIVE_BITS != 0) + ; + + /* Write to setup registers. */ + rtcp->rtc->SETUP0 = + (timespec->year) << RTC_SETUP_0_YEAR_LSB ) | + (timespec->month) << RTC_SETUP_0_MONTH_LSB) | + (timespec->day) << RTC_SETUP_0_DAY_LSB); + rtcp->rtc->SETUP1 = + (timespec->dayofweek) << RTC_SETUP_1_DOTW_LSB) | + (hour) << RTC_SETUP_1_HOUR_LSB) | + (min) << RTC_SETUP_1_MIN_LSB) | + (sec) << RTC_SETUP_1_SEC_LSB); + + /* Load setup values into RTC clock domain. */ + rtcp->rtc->CTRL = RTC_CTRL_LOAD_BITS; + + /* Enable RTC and wait for it to be active. */ + rtcp->rtc->CTRL = RTC_CTRL_RTC_ENABLE_BITS; + while (rtccp->rtc->CTRL & RTC_CTRL_RTC_ACTIVE_BITS == 0) + ; +} + +/** + * @brief Get current time. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @notapi + */ +void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) { + + (void)rtcp; + (void)timespec; +} + +#if (RTC_ALARMS > 0) || defined(__DOXYGEN__) +/** + * @brief Set alarm time. + * @note Default value after BKP domain reset for both comparators is 0. + * @note Function does not performs any checks of alarm time validity. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure. + * @param[in] alarm alarm identifier. Can be 1 or 2. + * @param[in] alarmspec pointer to a @p RTCAlarm structure. + * + * @notapi + */ +void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec) { + + (void)rtcp; + (void)alarm; + (void)alarmspec; +} + +/** + * @brief Get alarm time. + * @note The function can be called from any context. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier + * @param[out] alarmspec pointer to a @p RTCAlarm structure + * + * @notapi + */ +void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec) { + + (void)rtcp; + (void)alarm; + (void)alarmspec; +} +#endif /* RTC_ALARMS > 0 */ + +#endif /* HAL_USE_RTC */ + +/** @} */ diff --git a/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.h b/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.h new file mode 100644 index 000000000..f87d9a87b --- /dev/null +++ b/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.h @@ -0,0 +1,148 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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. +*/ + +/** + * @file hal_rtc_lld.h + * @brief RP2040 RTC subsystem low level driver header. + * + * @addtogroup RTC + * @{ + */ + +#ifndef HAL_RTC_LLD_H +#define HAL_RTC_LLD_H + +#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Implementation capabilities + * @{ + */ +/** + * @brief Callback support int the driver. + */ +#define RTC_SUPPORTS_CALLBACKS TRUE + +/** + * @brief Number of alarms available. + */ +#define RTC_ALARMS 1 + +/** + * @brief Presence of a local persistent storage. + */ +#define RTC_HAS_STORAGE FALSE +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name PLATFORM configuration options + * @{ + */ +/** + * @brief RTCD1 driver enable switch. + * @details If set to @p TRUE the support for RTC1 is included. + * @note The default is @p FALSE. + */ +#if !defined(PLATFORM_RTC_USE_RTC1) || defined(__DOXYGEN__) +#define PLATFORM_RTC_USE_RTC1 FALSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +#if (RTC_SUPPORTS_CALLBACKS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of an RTC event. + */ +typedef enum { + RTC_EVENT_SECOND = 0 /** Triggered every second. */ +} rtcevent_t; + +/** + * @brief Type of a generic RTC callback. + */ +typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); +#endif + +/** + * @brief Type of a structure representing an RTC alarm time stamp. + */ +typedef struct { + /* End of the mandatory fields.*/ + uint32_t dummy; +} RTCAlarm; + +/** + * @brief Implementation-specific @p RTCDriver fields. + */ +#define rtc_lld_driver_fields \ + /* Pointer to the RTC registers block.*/ \ + RTC_TypeDef *rtc; \ + /* Callback pointer.*/ \ + rtccb_t callback + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (PLATFORM_RTC_USE_RTC1 == TRUE) && !defined(__DOXYGEN__) +extern RTCDriver RTCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void rtc_lld_init(void); + void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec); + void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec); +#if RTC_ALARMS > 0 + void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec); + void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec); +#endif +#if RTC_SUPPORTS_CALLBACKS == TRUE + void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_RTC == TRUE */ + +#endif /* HAL_RTC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2040/rp_registry.h b/os/hal/ports/RP/RP2040/rp_registry.h index 984ceee59..7995f033e 100644 --- a/os/hal/ports/RP/RP2040/rp_registry.h +++ b/os/hal/ports/RP/RP2040/rp_registry.h @@ -49,6 +49,9 @@ /* TIMER attributes.*/ #define RP_HAS_TIMER TRUE +/* RTC attributes.*/ +#define RP_HAS_RTC TRUE + /** @} */ #endif /* RP_REGISTRY_H */