Mirror of espurna firmware for wireless switches and more
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

148 lines
3.0 KiB

/*
RTMEM MODULE
Copyright (C) 2019 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
*/
#include "espurna.h"
#include "rtcmem.h"
static constexpr uint32_t RtcmemMagic { RTCMEM_MAGIC };
static constexpr uintptr_t RtcmemBlocks { RTCMEM_BLOCKS };
static constexpr uintptr_t RtcmemBegin { RTCMEM_ADDR };
static constexpr uintptr_t RtcmemEnd { RtcmemBegin + (4 * RtcmemBlocks) };
volatile RtcmemData* Rtcmem = reinterpret_cast<volatile RtcmemData*>(RtcmemBegin);
namespace espurna {
namespace peripherals {
namespace {
namespace rtc {
namespace internal {
bool status = false;
} // namespace internal
void erase() {
DEBUG_MSG_P(PSTR("[RTCMEM] Erasing start=0x%08x end=0x%08x\n"),
RtcmemBegin, RtcmemEnd);
auto begin = reinterpret_cast<volatile uint32_t*>(RtcmemBegin);
auto end = reinterpret_cast<volatile uint32_t*>(RtcmemEnd);
for (auto it = begin; it != end; ++it) {
*it = 0;
}
}
void init() {
erase();
Rtcmem->magic = RtcmemMagic;
}
// Treat memory as dirty on cold boot, hardware wdt reset and rst pin
bool status() {
bool readable;
switch (systemResetReason()) {
case REASON_EXT_SYS_RST:
case REASON_DEFAULT_RST:
readable = false;
break;
default:
readable = true;
}
readable = readable
&& (RtcmemMagic == Rtcmem->magic);
return readable;
}
#if TERMINAL_SUPPORT
namespace terminal {
PROGMEM_STRING(Init, "RTCMEM.INIT");
void init(::terminal::CommandContext&& ctx) {
rtc::init();
terminalOK(ctx);
}
PROGMEM_STRING(Dump, "RTCMEM.DUMP");
void dump(::terminal::CommandContext&& ctx) {
ctx.output.printf_P(PSTR("boot_status=%s status=%s\n"),
internal::status ? "OK" : "INIT",
status() ? "OK" : "INIT");
constexpr size_t BytesPerBlock = sizeof(uint32_t);
constexpr size_t BlocksPerLine = 8;
alignas(4) uint8_t buffer[BytesPerBlock * BlocksPerLine];
String line;
for (auto addr = RtcmemBegin; addr < RtcmemEnd; addr += std::size(buffer)) {
std::memcpy(&buffer[0], reinterpret_cast<uint32_t*>(addr), std::size(buffer));
line += PSTR("0x");
line += String(addr, 16);
line += ':';
for (auto it = std::begin(buffer); it != std::end(buffer); it += BytesPerBlock) {
line += PSTR(" ");
line += hexEncode(it, it + BytesPerBlock);
}
line += '\n';
ctx.output.print(line);
line = "";
}
}
static constexpr ::terminal::Command Commands[] PROGMEM {
{Init, init},
{Dump, dump},
};
void setup() {
espurna::terminal::add(Commands);
}
} // namespace terminal
#endif
bool current_status() {
return internal::status;
}
void setup() {
#if TERMINAL_SUPPORT
terminal::setup();
#endif
internal::status = status();
if (!internal::status) {
init();
}
}
} // namespace rtc
} // namespace
} // namespace peripherals
} // namespace espurna
bool rtcmemStatus() {
return espurna::peripherals::rtc::current_status();
}
void rtcmemSetup() {
espurna::peripherals::rtc::setup();
}