// WMXZ :: SLEEP RTC
// https://forum.pjrc.com/threads/58484-issue-to-reporogram-T4-0?p=222073&viewfull=1#post222073
#include "core_pins.h"
#include "TimeLib.h"
/******************* Seting Alarm ***************/
#define SNVS_LPSR_PGD_MASK (0x8U)
#define SNVS_LPCR_LPTA_EN_MASK (0x2U)
void rtc_init()
{
CCM_CCGR2 |= CCM_CCGR2_IOMUXC_SNVS(CCM_CCGR_ON);
SNVS_LPGPR = SNVS_DEFAULT_PGD_VALUE;
SNVS_LPSR = SNVS_LPSR_PGD_MASK;
// ? calibration
// ? tamper pins
SNVS_LPCR &= ~SNVS_LPCR_LPTA_EN_MASK; // clear alarm
while (SNVS_LPCR & SNVS_LPCR_LPTA_EN_MASK);
SNVS_LPTAR = 0;
SNVS_LPCR |= 1; // start RTC
while (!(SNVS_LPCR & 1));
}
void rtc_set_time(uint32_t secs)
{ //uint32_t secs = 1547051415;
SNVS_LPCR &= ~1; // stop RTC
while (SNVS_LPCR & 1);
SNVS_LPSRTCMR = (uint32_t)(secs >> 17U);
SNVS_LPSRTCLR = (uint32_t)(secs << 15U);
SNVS_LPCR |= 1; // start RTC
while (!(SNVS_LPCR & 1));
}
uint32_t rtc_secs() {
uint32_t seconds = 0;
uint32_t tmp = 0;
/* Do consecutive reads until value is correct */
do
{ seconds = tmp;
tmp = (SNVS_LPSRTCMR << 17U) | (SNVS_LPSRTCLR >> 15U);
} while (tmp != seconds);
return seconds;
}
//PROGMEM
void rtc_resetAlarm()
{
SNVS_LPCR &= ~SNVS_LPCR_LPTA_EN_MASK;
while (SNVS_LPCR & SNVS_LPCR_LPTA_EN_MASK);
}
//PROGMEM
void rtc_stopAlarm()
{
SNVS_LPSR |= 1;
rtc_resetAlarm();
}
//PROGMEM
void rtc_isr(void)
{
//rtc_stopAlarm();
SNVS_LPSR |= 1;
// Serial.println("Alarm");
asm volatile ("DSB");
}
void rtc_initAlarm(uint32_t prio = 13)
{
SNVS_LPSR |= 1;
attachInterruptVector(IRQ_SNVS_IRQ, rtc_isr);
NVIC_SET_PRIORITY(IRQ_SNVS_IRQ, prio * 16); // 8 is normal priority
NVIC_DISABLE_IRQ(IRQ_SNVS_IRQ);
}
void rtc_setAlarm(uint32_t alarmSeconds)
{ uint32_t tmp = SNVS_LPCR; //save control register
/* disable SRTC alarm interrupt */
rtc_stopAlarm();
SNVS_LPTAR = alarmSeconds;
while (SNVS_LPTAR != alarmSeconds);
NVIC_ENABLE_IRQ(IRQ_SNVS_IRQ);
SNVS_LPCR = tmp | SNVS_LPCR_LPTA_EN_MASK; // restore control register and set alarm
while (!(SNVS_LPCR & SNVS_LPCR_LPTA_EN_MASK));
}
uint32_t rtc_getAlarm()
{
return SNVS_LPTAR;
}
void doShutdown(void)
{
// SNVS_LPCR |=(1<<3) ; // enable wake-up
SNVS_LPCR |= (1 << 6) ; // turn off power
while (1) continue;
}
void setWakeupCallandSleep(uint32_t nsec)
{
uint32_t to = now();
if (!(SNVS_LPCR & 1))
{ rtc_init();
rtc_set_time(to); //LPSRTC will start at 0 otherwise
}
rtc_initAlarm(4);
rtc_setAlarm(to + nsec);
doShutdown();
}
uint32_t blink(void)
{ static uint32_t tx0;
if (millis() > tx0 + 1000)
{ digitalWriteFast(13, !digitalReadFast(13));
tx0 = millis();
Serial.print("blink @ms=");
Serial.print(millis());
Serial.print(" :: ");
showTime();
return 1;
}
return 0;
}
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
#if defined(__IMXRT1062__)
Serial.printf("\t F_CPU=%u", F_CPU_ACTUAL );
Serial.printf( "\tdeg C=%u\n" , (uint32_t)tempmonGetTemp() );
#endif
// set the Time library to use Teensy 3.0's RTC to keep time
setSyncProvider(Teensy3Clock.get);
delay(100);
Serial.print("Start :: ");
if (timeStatus() != timeSet)
Serial.println("Unable to sync with the RTC");
else {
Serial.print("RTC has set the system time :: ");
showTime( );
}
rtc_stopAlarm(); [B][COLOR="#FF0000"]// This clears RTC low power wake settings[/COLOR][/B]
pinMode(13, OUTPUT);
}
void loop() {
static uint32_t ic = 0;
ic += blink();
if (ic >= 20 || Serial.available())
{
[COLOR="#FF0000"] if ( Serial.available() ) {
while ( Serial.available() ) Serial.read();
Serial.println("... RESET ..."); Serial.flush();
setWakeupCallandSleep(2);
}[/COLOR]
Serial.printf( "\tdeg C=%u\n" , (uint32_t)tempmonGetTemp() );
Serial.println("End"); Serial.flush();
delay(1000);
setWakeupCallandSleep(10);
}
}
time_t RTCTime;
void showTime() {
Serial.print("[c] ");
Serial.print(hour());
Serial.print(":");
Serial.print(minute());
Serial.print(":");
Serial.print(second());
Serial.print(" ");
Serial.print(month());
Serial.print("/");
Serial.print(day());
Serial.print("/");
Serial.print(year());
Serial.println();
}