/* RTMEM MODULE Copyright (C) 2019 by Maxim Prokhorov */ #include "rtcmem.h" volatile RtcmemData* Rtcmem = reinterpret_cast(RTCMEM_ADDR); bool _rtcmem_status = false; void _rtcmemErase() { auto ptr = reinterpret_cast(RTCMEM_ADDR); const auto end = ptr + RTCMEM_BLOCKS; DEBUG_MSG_P(PSTR("[RTCMEM] Erasing start=%p end=%p\n"), ptr, end); do { *ptr = 0; } while (++ptr != end); } void _rtcmemInit() { _rtcmemErase(); Rtcmem->magic = RTCMEM_MAGIC; } // Treat memory as dirty on cold boot, hardware wdt reset and rst pin bool _rtcmemStatus() { bool readable; switch (systemResetReason()) { case REASON_EXT_SYS_RST: case REASON_WDT_RST: case REASON_DEFAULT_RST: readable = false; break; default: readable = true; } readable = readable and (RTCMEM_MAGIC == Rtcmem->magic); return readable; } #if TERMINAL_SUPPORT void _rtcmemInitCommands() { terminalRegisterCommand(F("RTCMEM.REINIT"), [](Embedis* e) { _rtcmemInit(); }); #if DEBUG_SUPPORT terminalRegisterCommand(F("RTCMEM.DUMP"), [](Embedis* e) { DEBUG_MSG_P(PSTR("[RTCMEM] boot_status=%u status=%u blocks_used=%u\n"), _rtcmem_status, _rtcmemStatus(), RtcmemSize); String line; line.reserve(96); char buffer[16] = {0}; auto addr = reinterpret_cast(RTCMEM_ADDR); uint8_t block = 1; uint8_t offset = 0; uint8_t start = 0; do { offset = block - 1; snprintf(buffer, sizeof(buffer), "%08x ", *(addr + offset)); line += buffer; if ((block % 8) == 0) { DEBUG_MSG_P(PSTR("%02u %p: %s\n"), start, addr+start, line.c_str()); start = block; line = ""; } ++block; } while (block<(RTCMEM_BLOCKS+1)); }); #endif } #endif bool rtcmemStatus() { return _rtcmem_status; } void rtcmemSetup() { _rtcmem_status = _rtcmemStatus(); if (!_rtcmem_status) { _rtcmemInit(); } #if TERMINAL_SUPPORT _rtcmemInitCommands(); #endif }