I face the following task:
1) run program for say 1 min.
2) stop Teensy for say 10 min (lowest possible consumption)
3) wakeup using RTC alarm
4) continue with 1)
OK, I could use Snooze.
BUT, I wanted to understand first the principle.
Unfortunately, Snooze handles all possible wake-up sources and becomes difficult to understand.
So, I searched the forum and Freescale's AN4503 among others and generated the following program
Obviously, program does not work. The program never continues after the "wfi" statement.
The LED flashes once for 200 ms so the rtcISR is called, but goSleep never returns and the 1s LED is never happening.
Commenting the goSleep() statement in loop lets the led flash as designed, so RTC-Alarm setup is working.
I have the feeling that I miss somewhere an instruction to tell the system to use the RTC alarm as wakeup source.
Unfortunately, the simple 'tutorials' or examples, I found, use mostly external interrupts, and not RTC alarms.
Any help to get this program running is appreciated.
1) run program for say 1 min.
2) stop Teensy for say 10 min (lowest possible consumption)
3) wakeup using RTC alarm
4) continue with 1)
OK, I could use Snooze.
BUT, I wanted to understand first the principle.
Unfortunately, Snooze handles all possible wake-up sources and becomes difficult to understand.
So, I searched the forum and Freescale's AN4503 among others and generated the following program
Code:
/* Seting Alarm */
#define RTC_IER_TAIE_MASK 0x4u
static void rtcISR( void )
{
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
NVIC_DISABLE_IRQ( IRQ_RTC_ALARM );
RTC_IER = 0;
}
void rtcSetup(void)
{
SIM_SCGC6 |= SIM_SCGC6_RTC;// enable RTC clock
RTC_CR |= RTC_CR_OSCE;// enable RTC
attachInterruptVector( IRQ_RTC_ALARM, rtcISR );
}
void rtcSetAlarm(uint32_t nsec)
{
RTC_TAR = RTC_TSR + nsec;
RTC_IER = RTC_IER_TAIE_MASK;
NVIC_ENABLE_IRQ( IRQ_RTC_ALARM );
}
/******************LLWU********************/
#define LLWU_PIN_ANY 0x03
#define LLWU_PE3_WUPE9_MASK 0xCu
#define LLWU_PE3_WUPE9_SHIFT 2
#define LLWU_PE3_WUPE9(x) ((uint8_t)(((uint8_t)(x))<<LLWU_PE3_WUPE9_SHIFT))
#define LLWU_ME_WUME5_MASK 0x20u
static void llwuISR(void)
{
NVIC_DISABLE_IRQ( IRQ_LLWU ); // disable wakeup isr
rtcISR();
}
void llwuSetup(void)
{
attachInterruptVector( IRQ_LLWU, llwuISR );
NVIC_SET_PRIORITY( IRQ_LLWU, 2*16 );
}
void llwuEnable(void)
{
NVIC_CLEAR_PENDING( IRQ_LLWU );
NVIC_ENABLE_IRQ( IRQ_LLWU );
//
LLWU_PE1 = 0;
LLWU_PE2 = 0;
LLWU_PE3 = LLWU_PE3_WUPE9 ( LLWU_PIN_ANY ); // rtc alarm
LLWU_PE4 = 0;
LLWU_ME = LLWU_ME_WUME5_MASK; //rtc alarm
}
void llwuDisable(void)
{ LLWU_PE1 = 0;
LLWU_PE2 = 0;
LLWU_PE3 = 0;
LLWU_PE4 = 0;
LLWU_ME = 0;
}
/********************* go to deep sleep *********************/
#define SMC_PMPROT_AVLLS_MASK 0x2u
#define SMC_PMCTRL_STOPM_MASK 0x7u
#define SCB_SCR_SLEEPDEEP_MASK 0x4u
void goSleep(void)
{ /* Make sure clock monitor is off so we don't get spurious reset */
MCG_C6 &= ~MCG_C6_CME0;
/* Write to PMPROT to allow all possible power modes */
SMC_PMPROT = SMC_PMPROT_AVLLS_MASK;
/* Set the STOPM field to 0b100 for VLLSx mode */
SMC_PMCTRL &= ~SMC_PMCTRL_STOPM_MASK;
SMC_PMCTRL |= SMC_PMCTRL_STOPM(0x4); // VLLSx
SMC_VLLSCTRL = SMC_VLLSCTRL_VLLSM(0x3); // VLLS3
/*wait for write to complete to SMC before stopping core */
(void) SMC_VLLSCTRL;
SYST_CSR &= ~SYST_CSR_TICKINT; // disable systick timer interrupt
SCB_SCR |= SCB_SCR_SLEEPDEEP_MASK; // Set the SLEEPDEEP bit to enable deep sleep mode (STOP)
asm volatile( "wfi" ); // WFI instruction will start entry into STOP mode
SCB_SCR &= ~SCB_SCR_SLEEPDEEP_MASK; // Clear the SLEEPDEEP bit
SYST_CSR |= SYST_CSR_TICKINT; // renable systick timer interrupt
//
/* Turn back on external clock monitor */
MCG_C6 |= MCG_C6_CME0;
}
void setup() {
// put your setup code here, to run once:
pinMode(LED_BUILTIN, OUTPUT);
rtcSetup();
llwuSetup();
}
void loop() {
// put your main code here, to run repeatedly:
//
rtcSetAlarm(5);
//
llwuEnable();
goSleep();
llwuDisable();
//
delay(10000);
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
}
Obviously, program does not work. The program never continues after the "wfi" statement.
The LED flashes once for 200 ms so the rtcISR is called, but goSleep never returns and the 1s LED is never happening.
Commenting the goSleep() statement in loop lets the led flash as designed, so RTC-Alarm setup is working.
I have the feeling that I miss somewhere an instruction to tell the system to use the RTC alarm as wakeup source.
Unfortunately, the simple 'tutorials' or examples, I found, use mostly external interrupts, and not RTC alarms.
Any help to get this program running is appreciated.