cancel
Showing results for 
Search instead for 
Did you mean: 

Shutdown and wake (RTC / WKUP) work in debug / run but NOT in standalone after power loss

freeflyer
Senior

I have developed code (on the NUCLEO-L433RC-P) that uses shutdown and wake.

The code works when I debug or run, but it stops working after a cold restart (power removed then reconnected).

After a cold restart, the software runs correctly until the first shutdown is called.  Once shutdown is called, it seems to crash and I have to perform a reset.

From power up, the MCU should run as follows...

  1. Run for 10 seconds
  2. Shutdown for 5 seconds
  3. Run for 10 seconds
  4. Shutdown for 5 seconds
  5. And so on.....
  6. This cycle should continue until 60 seconds is reached, when it should shutdown and stay shutdown.
  7. It should not wake again until the WKUP pin is pressed

Why does it seem to crash after the first shutdown (step 2 above) ?

I am aware that RTC backup registers are lost when power is removed, but I cannot see this causing the problem.

I have attached a flowchart diagram (wake_shutdown.png) to show how my code works.

The relevant code is also below

  • main
  • MX_RTC_Init
  • wakeConfigReset
  • wakeConfigUpdate
  • mcuSleep
  • mcuPowerdown

 

int main(void)
{
	/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
	HAL_Init();
	/* Configure the system clock */
	SystemClock_Config();
	/* Initialize all configured peripherals */
	MX_GPIO_Init();
	MX_DMA_Init();
	MX_DAC1_Init();
	MX_TIM6_Init();
	MX_SPI2_Init();
	MX_LPUART1_UART_Init();
	MX_SPI1_Init();
	MX_I2C1_Init();
	MX_USART3_UART_Init();
	MX_ADC1_Init();
	MX_TIM7_Init();
	MX_RTC_Init();

	if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB)) {
		// woken from low power mode
		__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);

		// read wake marker from RTC backup register to determine if woken from sleep or shutdown
		wake_marker = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);

		if (wake_marker == WAKE_FROM_SLEEP_RTC) {
			// woken from sleep (RTC wake)
			wakeConfigUpdate(); // get time and date and restore reference pressure from RTC backup register

			uint32_t tmp = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3); // restore power switch state from RTC backup register
			powerSeq = *(uint8_t*)&tmp;

			// check if elapsed time is greater then shutdown time
			if (elapsedSeconds >= RTC_SHUTDOWN_S) {
				mcuPowerdown();
			}

		} else if (wake_marker == WAKE_FROM_SHUTDOWN_WKUP) {
			// woken from shutdown (power switch pressed during shutdown)

			wakeConfigReset(); // reset time and date and set default reference pressure
		}
	}
	else
	{
		// woken from reset
		wakeConfigReset();	// reset time and date and set default reference pressure
		// store value in RTC backup register to indicate mcu was reset
		HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, WAKE_FROM_RESET);
	}
	while (1) {
	}
}

 

static void MX_RTC_Init(void)
{
	/** Initialize RTC Only
	 */
	hrtc.Instance = RTC;
	hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
	hrtc.Init.AsynchPrediv = 127;
	hrtc.Init.SynchPrediv = 255;
	hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
	hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
	hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
	hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
	if (HAL_RTC_Init(&hrtc) != HAL_OK)
	{
		Error_Handler();
	}
}

 

void wakeConfigReset (void) {
	// set reference pressure to default value
	pressure_ref = REF_PRESS_DEFAULT;

	/** Initialize RTC and set the Time and Date
	 */
	sTime.Hours = 0x0;
	sTime.Minutes = 0x0;
	sTime.Seconds = 0x0;
	sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
	sTime.StoreOperation = RTC_STOREOPERATION_RESET;
	if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
	{
		Error_Handler();
	}
	sDate.WeekDay = RTC_WEEKDAY_MONDAY;
	sDate.Month = RTC_MONTH_JANUARY;
	sDate.Date = 0x1;
	sDate.Year = 0x0;

	if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
	{
		Error_Handler();
	}
	// get time and date
	HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
	HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);

	// convert start time and date to unix time
	startSeconds = RTC_to_unix(&sTime, &sDate);

	// store start time in RTC backup register
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, startSeconds);
}

 

void wakeConfigUpdate (void) {

	// Restore pressure reference after wake
	uint32_t tmp = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0);
	pressure_ref = *(float*)&tmp;

	// get time and date
	HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
	HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);

	// convert time and date to unix time
	currentSeconds = RTC_to_unix(&sTime, &sDate);

	// read unix start time from RTC backup register
	startSeconds = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1);

	// calculate elapsed time
	elapsedSeconds = currentSeconds - startSeconds;
}

 

void mcuSleep (void){
	/* The Following Wakeup sequence is highly recommended prior to each Standby mode entry
	    mainly  when using more than one wakeup source this is to not miss any wakeup event.
	    - Disable all used wakeup sources,
	    - Clear all related wakeup flags,
	    - Re-enable all used wakeup sources,
	    - Enter the shutdown mode.
	 */

	// write pressure to RTC backup register
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, *(uint32_t*)&pressure_bak);

	// write value to RTC backup register to indicate mcu was in sleep
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, WAKE_FROM_SLEEP_RTC);

	// write power switch state to RTC backup register
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, *(uint32_t*)&powerSeq);

	// Disable all used wakeup sources
	HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
	HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, RTC_WAKE_SEC, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);

	// Clear all related wakeup flags
	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

	// shutdown the audio amplifier
	ampPowerDown();

	// Call sleep  (note that the terms 'sleep' and 'powerdown' are only used for readability, both call shutdown mode)
	HAL_PWREx_EnterSHUTDOWNMode();
}

 

void mcuPowerdown (void){

	// write value to RTC backup register to indicate mcu was in shutdown
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, WAKE_FROM_SHUTDOWN_WKUP);

	// disable RTC wakeup
	HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
	Enable_PC13_Wakeup();

	// shutdown the audio amplifier
	ampPowerDown();

	// Call power down (note that the terms 'sleep' and 'powerdown' are only used for readability, both call shutdown mode)
	HAL_PWREx_EnterSHUTDOWNMode();
}

 

0 REPLIES 0