disk91 / stm32-it-sdk

Disk91 STM32 IoT SDK
https://www.disk91.com
GNU General Public License v3.0
45 stars 19 forks source link

lowPower mode duration #48

Closed zokl closed 4 years ago

zokl commented 4 years ago

Hello Paul,

is it possible to be in lowpower longer than hundreds of ms? Maybe hours or days? I try to increase ITSDK_LOWPOWER_RTC_MS to tens of seconds but MCU reboots after a few seconds. Is it a bug or common behavior?

In my other IoT applications based on HAL STM32, I used deep sleep mode and RTC woke up the system after hours and days without a problem.

Thank you, Zbynek Kocur

disk91 commented 4 years ago

I don't see any issue with having longer time (I don't remind what is the RTC overflow period) You can also remove the RTC wakeup and only wakeup on interrupts. Don't forget to stop the watchdog in a such case. Some features like software timer, task or state machine needs regular wakeup, so you be able to use them.

zokl commented 4 years ago

Thank you for a tip to the watchdog. Watchdog makes a restart.

zokl commented 4 years ago

I have tried to measure the sleep and I am not able to sleep longer than approx 30 seconds.

define ITSDK_LOWPOWER_RTC_MS 60000

log from project_loop in ms:

Wakeups : 4426 Wakeups : 32440 Wakeups : 60463 Wakeups : 88487 Wakeups : 116510 Wakeups : 144534 Wakeups : 172557 Wakeups : 200581

zokl commented 4 years ago

I am so sorry but I am not able to sleep longer than 28 s. I try to modify several parts of config files but without success. For now, I have set:

#define ITSDK_WITH_RTC              __RTC_ENABLED                           // The Rtc is usd in the firmware
#define ITSDK_WITH_CLK_ADJUST       __ENABLE                                // The RTC (and wtachdog) is calibrated
#define ITSDK_RTC_CLKFREQ           32768                                   // RTC clock source frequency
#define ITSDK_CLK_BEST_SOURCE       __CLK_BEST_SRC_RTC                      // The RTC is the most accurate clk source to ADJUST Others
#define ITSDK_CLK_CORRECTION        1000                                    // correct clock with 1200 o/oo (+20%) of the ticks (used when clk_adjust = 0 or for RTC when CLK_BEST_SRC_RTC)

#define ITSDK_LOWPOWER_MINDUR_MS    5                                       // Under 5 ms sleep request, no need to sleep
#define ITSDK_LOWPOWER_RTC_MS       60000                                       // RTC wake up after 10s

I would like to wakeup after 60 s but the system wake up after 28s. WatchDog is disabled.

I made a wakeup measurement:

...
void project_loop() {

    log_info("Wakeup after %d ms \r\n", (uint32_t)itsdk_time_get_ms() - timeDiff);
    timeDiff = (uint32_t)itsdk_time_get_ms();

}

with the following result:

Wakeup after 27996 ms
Wakeup after 28005 ms
Wakeup after 28002 ms
Wakeup after 28001 ms
Wakeup after 28006 ms
Wakeup after 28001 ms

I try to find the problem point and maybe rtc.c and ticks calculation?

/**
 * Configure the RTC source clock for running LowPower
 */
void rtc_configure4LowPower(uint16_t ms) {
        rtc_prepareSleepTime();
    if ( ms > 0 ) {
        rtc_runRtcUntil(ms);
    }
}

/**
 * Deactivate the WakeUpTimer for not having the IRQ looping
 */
void rtc_disable4LowPower() {
    rtc_disableWakeUp();
    rtc_updateTimeAfterSleepTime();
}

/**
 * Run Rtc for a given time in ticks
 * Max is 16s
 */
void rtc_runRtcUntil(uint16_t ms) {
    rtc_runRtcUntilTicks(rtc_getTicksFromDuration((uint32_t)ms));
}

/*
 * Convert a duration in ticks (Wake-Up Clock only)
 */
uint32_t rtc_getTicksFromDuration(uint32_t ms) {
    return (ms * (ITSDK_RTC_CLKFREQ/16)) / 1000;
}

/*
 * Convert a tick duration in ms (Wake-Up Clock only)
 */
int32_t rtc_getMsFromTicks(uint32_t ticks) {
    return (ticks * 1000) / (ITSDK_RTC_CLKFREQ/16);
}

/**
 * Run the RTC for a given number of tics
 */
void rtc_runRtcUntilTicks(uint32_t ticks) {
    HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, ticks, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
}
zokl commented 4 years ago

I made several tests and I found the solution to my problem with long sleep duration. Long sleep is longer than 1s :-).

You use in rtc.c for wakeup HAL_RTCEx_SetWakeUpTimer_IT with wakeup clock RTC_WAKEUPCLOCK_RTCCLK_DIV16. This is a 16 bit counter. The maximum time is about 32 s.

If you use RTC_WAKEUPCLOCK_CK_SPRE_16BITS, this is the wakeup counter clock source that is set to CalendarCLK, then the WakeUpCounter is in seconds and you are able to sleep up to 48 days.

For my purposes will be good if I have a function like this:

void rtc_runRtcUntilSeconds(uint32_t s) {
    HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, ms, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
}

Is it possible to extend our SDK to this function?

disk91 commented 4 years ago

Thank you for you proposal, I'm going to review that to ensure it will not have side effect. It make sense to be able to increase the RTC wake up over 32s.

disk91 commented 4 years ago

I've just push a commit on the devel branch. Please test and let me know if this works and fixed your issue.

zokl commented 4 years ago

I've just push a commit on the devel branch. Please test and let me know if this works and fixed your issue.

I have tried it and it working.

There could be a potential problem with a watchdog. If you use a longer sleep period and you have activated watchdog (in common configuration) it makes a restart early. For now, I don't know how to resolve it in an easy way. Maybe note in the comment?

zokl commented 4 years ago

Hello, I apologize for thoroughly testing your patch. It does not work as expected. There is still a restriction in the form of uint16_t for the rtc_configure4LowPower and rtc_runRtcUntil function parameters. Can you please change the data type to uint32_t?

Thank you.

disk91 commented 4 years ago

I'll take a look to it, the RTC is 16bits, so even if 32b is use, the time is limited to 16bits ticks.

zokl commented 4 years ago

I'll take a look to it, the RTC is 16bits, so even if 32b is use, the time is limited to 16bits ticks.

Yes, it is 16bit but it differ if you use tics or seconds ...

disk91 commented 4 years ago

Fixed in commit #58 including the watchdog error reporting in the config.h.template file. Thank you for your issue submission.