RTC Wake-up Issue SPC560B40L5
Hi,
I am using an SPC560B40L5 with ChibiOS/AutoDevKit Studio.
The hardware design is already finalized, so I cannot change the wake-up circuitry. Because of this limitation, I use the RTC to wake the MCU periodically every 200 ms. After each wake-up, I only check a few GPIOs to determine whether a real wake-up event has occurred. If no event is detected, the MCU immediately enters STOP mode again. No peripherals are reinitialized unless a valid wake-up event is detected.
The sleep/wake-up sequence works correctly during normal operation. However, I am facing a strange issue after reprogramming the MCU.
After downloading new firmware (without removing power), the MCU freezes in:
while (ME.IS.R == 0U)
{
}inside:
SPCSetRunMode(SPC5_RUNMODE_STOP);The board must support in-field reprogramming through the diagnostic interface (without a power cycle), but after programming the MCU usually remains stuck until the power is removed and applied again.
Interestingly, if I disable the periodic RTC wake-up and instead use only an external wake-up pin, both problems disappear:
- The MCU no longer freezes in
SPCSetRunMode(). - Reprogramming works correctly without requiring a power cycle.
My sleep sequence is:
prepareForSleep();
gotoSleep();where prepareForSleep() stops all peripherals (CAN, LIN, ADC, SPI, PWM, watchdog, etc.) and suspends all RTOS tasks.
The relevant part of gotoSleep() is shown below:
void prepareForSleep(void)
{
//stop watchdog
swt_lld_stop(&SWTD1);
//suspend tasks
vTaskSuspend(HandleInput);
vTaskSuspend(HandleCanHighTx);
vTaskSuspend(HandleCanLowTx);
vTaskSuspend(HandleAnti);
vTaskSuspend(HandleEeprom);
vTaskSuspend(HandleRemote);
vTaskSuspend(HandleDiagnostic);
vTaskSuspend(HandleOutput);
//disable inputs
SIU.GPDO[10].R = 0;
//stop pwm
pwm_lld_stop(&PWMD1);
pwm_lld_stop(&PWMD4);
//stop tle
tleStandby(&SPID1);
UJA1078_ENpinSetState(&SPID1,0); //set tle's RST pin to zero -> puts ic in standby mode
//stop uja
UJA1078_EnableCANINT(&SPID1);
UJA1078_GoStandby(&SPID1);
//stop spi1
spi_lld_stop(&SPID1);
//stop adc
adc_lld_stop_conversion(&ADCD1);
vTaskDelay(50);
adc_lld_stop(&ADCD1);
// vTaskDelay(10);
osalThreadDelayMicroseconds(10);
//stop can
can_lld_stop(&CAND1);
// can_lld_stop(&CAND2);
//stop lin
lin_lld_stop(&LD2);
//lin_lld_stop(&LD3);
// stop eeprom
FSL_AbortFunction(&eepromConf);
SIU.GPDO[2].R = 0;
disablePins();
}
void gotoSleep(void)
{
ME.STOP0.B.PDO = 0;
ME.STOP0.B.MVRON = 0;
ME.STOP0.B.DFLAON = 0;
ME.STOP0.B.CFLAON = 0;
ME.STOP0.B.FMPLLON = 0;
ME.STOP0.B.FXOSC0ON = 0;
ME.STOP0.B.FIRCON = 0;
ME.STOP0.B.SYSCLK = 0xF;
ME.LPPC[0].B.STOP0 = 0;
ME.LPPC[1].B.STOP0 = 0;
// set RTC registers for periodic wake-up
RTC.RTCS.B.RTCF = 1;
RTC.RTCC.B.FRZEN = 1;
RTC.RTCC.B.CLKSEL = 1;
RTC.RTCC.B.RTCVAL = 6;
RTC.RTCC.B.APIEN = 1;
RTC.RTCC.B.RTCIE = 1;
RTC.RTCC.B.DIV32EN = 0;
RTC.RTCC.B.DIV512EN = 0;
gotoSTOP:
RTC.RTCC.B.CNTEN = 1;
// RTC.RTCC.R = 0x60069000;
// enable wake-up on RTC interrupt
WKUP.WIFEER.B.IFEE = 0;
WKUP.WIREER.B.IREE = 0x2;
WKUP.WRER.B.WRE = 0x2;
WKUP.WISR.R = 0xFFFFFFFFU;
// enable RTC counter
if (SPCSetRunMode(SPC5_RUNMODE_STOP) == CLOCK_FAILED)
{
SPC5_CLOCK_FAILURE_HOOK();
}
RTC.RTCC.B.CNTEN = 0;
// osalThreadDelayMilliseconds(200);
// ME.MCTL.R = 0xA0005AF0; // Puts uC in Stop mode
// ME.MCTL.R = 0xA000A50F; // Puts uC in Stop mode
// // waits until stop
// while(ME.GS.B.S_MTRANS != 0){}
SIU.PCR[PIN_NUM_INPUT_ENABLE].B.PA = 0; // GPIO
SIU.PCR[PIN_NUM_INPUT_ENABLE].B.OBE = 1; // Output enable
SIU.PCR[PIN_NUM_INPUT_ENABLE].B.IBE = 0; // Input disable
SIU.PCR[PIN_NUM_INPUT_ENABLE].B.ODE = 0; // Push-pull
SIU.PCR[PIN_NUM_INPUT_ENABLE].B.SRC = 1; // Medium slew rate
SIU.GPDO[PIN_NUM_INPUT_ENABLE].R = 1; // PIN_NUM_INPUT_ENABLE high
RTC.RTCS.R = 0xFFFFFFFF;
WKUP.WISR.R = 0xFFFFFFFF;
osalThreadDelayMilliseconds(1);
if(!checkWakeup())
{
SIU.GPDO[PIN_NUM_INPUT_ENABLE].R = 0;
deInitPin(PIN_NUM_INPUT_ENABLE);
goto gotoSTOP;
}
boardInit();
clockInit();
// initCanLowSpeed();
initCanHighSpeed();
startUJA(&SPID1, &spi_config_SPI0);
adc_lld_start(&ADCD1, NULL);
swt_lld_start(&SWTD1, &swt0_config);
pal_lld_setpad(PORT_G, VSEN);
UJA1078_ENpinSetState(&SPID1, 0);
tleInit(&SPID1);
digitalInputs.BrakeOilLevelSwitch = 1;
FSL_InitEeprom(&eepromConf, NULL_CALLBACK);
INPUT_ENABLE();
lin_lld_start(&LD2, &lin_config_LIN1);
RPASensor.tick = xTaskGetTickCount();
// RPAsensor_init(&LD2);
pwm_lld_start(&PWMD1, &pwm_config_ROOFLAMP);
pwm_lld_start(&PWMD4, &pwm_config_BUZZER);
pwm_lld_enable_channel(&PWMD4, 5, 50);
// BUZZER(1);
SET_VECO(0);
vTaskResume(HandleInput);
vTaskResume(HandleCanHighTx);
vTaskResume(HandleCanLowTx);
vTaskResume(HandleAnti);
vTaskResume(HandleEeprom);
vTaskResume(HandleRemote);
vTaskResume(HandleDiagnostic);
vTaskResume(HandleOutput);
}My questions are:
- Is there any known limitation or erratum regarding periodic RTC wake-up followed by repeated STOP mode entries on the SPC560B40L5?
- Is any additional RTC or WKUP register handling required before re-entering STOP mode?
- Could the periodic RTC wake-up interfere with the ME mode transition mechanism, causing
ME.ISnever to be updated?
Any suggestions would be greatly appreciated.
with regard,
Milan.
