diff --git a/os/hal/include/hal_persistent.h b/os/hal/include/hal_persistent.h index f0aed89b9..f6ba14e82 100644 --- a/os/hal/include/hal_persistent.h +++ b/os/hal/include/hal_persistent.h @@ -118,6 +118,17 @@ typedef struct { */ #define getBasePersistentStorage(ip) ((BasePersistentStorage *)&(ip)->vmt) +/** + * @brief Get storage size. + * + * @param[in] ip pointer to a @p BasePersistentStorage or derived class + * @return The storage size in bytes. + * + * @api + */ +#define psGetStorageSize(ip) \ + (ip)->vmt->getsize(ip) + /** * @brief Read operation. * @@ -140,7 +151,7 @@ typedef struct { * * @param[in] ip pointer to a @p BasePersistentStorage or derived class * @param[in] offset persistent storage offset - * @param[in] n number of bytes to be programmed + * @param[in] n number of bytes to be written * @param[in] wp pointer to the data buffer * @return An error code. * @retval PS_NO_ERROR if there is no erase operation in progress. diff --git a/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c b/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c index a7c212b00..763ebf851 100644 --- a/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c +++ b/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c @@ -200,33 +200,59 @@ static uint32_t rtc_encode_date(const RTCDateTime *timespec) { } #if RTC_HAS_STORAGE == TRUE -/* TODO: Map on the backup SRAM on devices that have it.*/ -static size_t _read(void *instance, ps_offset_t offset, - size_t n, uint8_t *rp) { +static size_t _getsize(void *instance) { (void)instance; - (void)offset; - (void)n; - (void)rp; - return 0; + return (size_t)STM32_RTC_STORAGE_SIZE; +} + +static ps_error_t _read(void *instance, ps_offset_t offset, + size_t n, uint8_t *rp) { + volatile uint32_t *bkpr = &((RTCDriver *)instance)->rtc->BKP0R; + unsigned i; + + chDbgCheck((instance != NULL) && (rp != NULL)); + chDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE)); + chDbgCheck((offset < STM32_RTC_STORAGE_SIZE) && + (offset + n <= STM32_RTC_STORAGE_SIZE)); + + for (i = 0; i < (unsigned)n; i++) { + unsigned index = ((unsigned)offset + i) / sizeof (uint32_t); + unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t); + *rp++ = (uint8_t)(bkpr[index] >> (shift * 8U)); + } + + return PS_NO_ERROR; } static ps_error_t _write(void *instance, ps_offset_t offset, size_t n, const uint8_t *wp) { + volatile uint32_t *bkpr = &((RTCDriver *)instance)->rtc->BKP0R; + unsigned i; - (void)instance; - (void)offset; - (void)n; - (void)wp; + chDbgCheck((instance != NULL) && (wp != NULL)); + chDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE)); + chDbgCheck((offset < STM32_RTC_STORAGE_SIZE) && + (offset + n <= STM32_RTC_STORAGE_SIZE)); - return 0; + for (i = 0; i < (unsigned)n; i++) { + unsigned index = ((unsigned)offset + i) / sizeof (uint32_t); + unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t); + uint32_t regval = bkpr[index]; + regval &= ~(0xFFU << (shift * 8U)); + regval |= (uint32_t)*wp++ << (shift * 8U); + bkpr[index] = regval; + } + + return PS_NO_ERROR; } /** * @brief VMT for the RTC storage file interface. */ struct RTCDriverVMT _rtc_lld_vmt = { + (size_t)0, _getsize, _read, _write }; #endif /* RTC_HAS_STORAGE == TRUE */ @@ -493,10 +519,11 @@ void rtc_lld_init(void) { rtc_enter_init(); - RTCD1.rtc->CR = STM32_RTC_CR_INIT; - RTCD1.rtc->ISR = RTC_ISR_INIT; /* Clearing all but RTC_ISR_INIT. */ - RTCD1.rtc->PRER = STM32_RTC_PRER_BITS; - RTCD1.rtc->PRER = STM32_RTC_PRER_BITS; + RTCD1.rtc->CR = STM32_RTC_CR_INIT; + RTCD1.rtc->TAMPCR = STM32_RTC_TAMPCR_INIT; + RTCD1.rtc->ISR = RTC_ISR_INIT; /* Clearing all but RTC_ISR_INIT. */ + RTCD1.rtc->PRER = STM32_RTC_PRER_BITS; + RTCD1.rtc->PRER = STM32_RTC_PRER_BITS; rtc_exit_init(); } diff --git a/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.h b/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.h index 5aae1ab99..3badc3d1d 100644 --- a/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.h +++ b/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.h @@ -51,7 +51,7 @@ /** * @brief Presence of a local persistent storage. */ -#define RTC_HAS_STORAGE FALSE +#define RTC_HAS_STORAGE TRUE /** @} */ /** @@ -115,6 +115,15 @@ #if !defined(STM32_RTC_CR_INIT) || defined(__DOXYGEN__) #define STM32_RTC_CR_INIT 0 #endif + +/** + * @brief RTC TAMPCR register initialization value. + * @note Use this value to initialize features not directly handled by + * the RTC driver. + */ +#if !defined(STM32_RTC_TAMPCR_INIT) || defined(__DOXYGEN__) +#define STM32_RTC_TAMPCR_INIT 0 +#endif /** @} */ /*===========================================================================*/ diff --git a/os/hal/ports/STM32/STM32L4xx+/stm32_registry.h b/os/hal/ports/STM32/STM32L4xx+/stm32_registry.h index 590db30f0..735af3781 100644 --- a/os/hal/ports/STM32/STM32L4xx+/stm32_registry.h +++ b/os/hal/ports/STM32/STM32L4xx+/stm32_registry.h @@ -46,6 +46,7 @@ #define STM32_RTC_HAS_SUBSECONDS TRUE #define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE #define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 128 #define STM32_RTC_TAMP_STAMP_HANDLER Vector48 #define STM32_RTC_WKUP_HANDLER Vector49 #define STM32_RTC_ALARM_HANDLER VectorE4 diff --git a/os/hal/ports/STM32/STM32L4xx/stm32_registry.h b/os/hal/ports/STM32/STM32L4xx/stm32_registry.h index a6c8ac5c8..9c22b96f2 100644 --- a/os/hal/ports/STM32/STM32L4xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32L4xx/stm32_registry.h @@ -46,6 +46,7 @@ #define STM32_RTC_HAS_SUBSECONDS TRUE #define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE #define STM32_RTC_NUM_ALARMS 2 +#define STM32_RTC_STORAGE_SIZE 128 #define STM32_RTC_TAMP_STAMP_HANDLER Vector48 #define STM32_RTC_WKUP_HANDLER Vector49 #define STM32_RTC_ALARM_HANDLER VectorE4 diff --git a/readme.txt b/readme.txt index 5180ee598..6ee109cd1 100644 --- a/readme.txt +++ b/readme.txt @@ -75,6 +75,7 @@ ***************************************************************************** *** Next *** +- NEW: Added persistent storage interface to the STM32 RTCv2 driver. - NEW: STM32 RTCv2 driver now supports callbacks on events. - NEW: Added an EXTI helper driver for STM32. - NEW: Added demo for STM32L4R9I-Discovery board. diff --git a/testhal/STM32/multi/RTC/debug/STM32-RTC (Select ELF file)(OpenOCD, Just Run).launch b/testhal/STM32/multi/RTC/debug/STM32-RTC (Select ELF file)(OpenOCD, Just Run).launch index 835e7d705..3bd927aff 100644 --- a/testhal/STM32/multi/RTC/debug/STM32-RTC (Select ELF file)(OpenOCD, Just Run).launch +++ b/testhal/STM32/multi/RTC/debug/STM32-RTC (Select ELF file)(OpenOCD, Just Run).launch @@ -33,7 +33,7 @@ - + diff --git a/testhal/STM32/multi/RTC/main.c b/testhal/STM32/multi/RTC/main.c index 3c273c238..f4dfb5334 100644 --- a/testhal/STM32/multi/RTC/main.c +++ b/testhal/STM32/multi/RTC/main.c @@ -39,7 +39,7 @@ static void cmd_date(BaseSequentialStream *chp, int argc, char *argv[]) { } rtcGetTime(&RTCD1, ×pec); - chprintf(chp, "%02d:%02d:%02d (%02d) - %02d-%02d-%04d\r\n", + chprintf(chp, "%02d:%02d:%02d:%03d - %02d-%02d-%04d\r\n", timespec.millisecond / 3600000U, (timespec.millisecond % 3600000U) / 60000U, (timespec.millisecond % 60000U) / 1000U, @@ -49,8 +49,30 @@ static void cmd_date(BaseSequentialStream *chp, int argc, char *argv[]) { timespec.year + 1980U); } +static void cmd_storage(BaseSequentialStream *chp, int argc, char *argv[]) { + size_t storage_size = psGetStorageSize(&RTCD1); + ps_offset_t i; + + (void)argv; + + if (argc > 0) { + chprintf(chp, "Usage: storage\r\n"); + return; + } + + for (i = 0U; i < (ps_offset_t)storage_size; i++) { + uint8_t val; + psRead(&RTCD1, i, 1U, &val); + chprintf(chp, "%02x ", val); + if (((i + 1) & 15) == 0U) { + chprintf(chp, "\r\n"); + } + } +} + static const ShellCommand commands[] = { {"date", cmd_date}, + {"storage", cmd_storage}, {NULL, NULL} }; @@ -140,6 +162,7 @@ int main(void) { rtcSetAlarm(&RTCD1, 0, &alarm1); rtcSetAlarm(&RTCD1, 1, &alarm2); rtcSetCallback(&RTCD1, alarmcb); + psWrite(&RTCD1, 0U, 12U, (const uint8_t *)"Hello World!"); /* Normal main() thread activity, spawning shells.*/ while (true) {