RTC initialisation and wakeup from external events
If the Pyboard is woken from standby by the tamper pin X18, the RTC is reset to 1st January 2014 regardless of any setting performed in code.
It appears impossible to prevent this from Python as it occurs in rtc_init() which is called from main.c. The problem occurs because rtc_init() checks backup register 0 for a specific value 0x32f2 to see if the RTC has already been set. If the value is not correct it assumes the Pyboard has been powered up, sets the RTC to that date, and sets the value of backup register 0 to 0x32f2 to ensure that the RTC continues to run through reset events.
Unfortunately the tamper pin clears the backup registers, so on recovery from standby rtc_init() runs again, detects that the register does not hold 0x32f2 and resets the RTC.
I have produced a build where RTC initialisation occurs in the constructor. This has a boolean argument defaulting True: if present and set False, initialisation is inhibited. This allows the user to take control of the detection of boot events and initialisation of the RTC (power up can be detected by checking the contents of backup RAM which are unaffected by tamper events).
If the argument is absent or True initialisation and boot detection work as at present so existing code should be unaffected.
If this approach meets with approval I can submit a PR.
RTC wakeup callback should be executed immediately rather than deferred
AFAIK the callback invoked by RTC.wakeup is scheduled for later execution rather than being executed immediately, as the pin interrupts are.
See: https://github.com/micropython/micropython/blob/master/ports/stm32/extint.c#L657
IMHO this is undesirable behaviour. If the RTC is used to (a) wake the processor after machine.sleep() and (b) set a flag to be inspected by the main thread, then it has the effect that the flag may not be ready for inspection.
The code below illustrated the problem. I find that for correct operation it is necessary to add a delay after execution resumes and before inspecting variables changed by the callback. Commenting out the delay at line 17 results in undesirable behaviour.
I ran this on an OpenMV camera and the OpenMV github issue here provides more details of how I found this bug/feature, and some further analysis https://github.com/openmv/openmv/issues/1032
`
import machine, pyb, time
global triggered
triggered = False
def callback(arg):
global triggered
triggered = True
pyb.RTC().wakeup(1000, callback)
while (True):
machine.sleep()
# At this point the RTC will have woken us but the callback may not have been executed.
# This delay is essential to allow the callback to execute and update 'triggered'
time.sleep_ms(1) # Required minimum delay is not known. Do not use sleep_us()
if (triggered):
# Toggle green LED to indicate correct behaviour.
# 'triggered' is seen as having changed
pyb.LED(2).toggle()
else:
# Toggle red LED to indicate incorrect behaviour.
# 'triggered' is NOT seen as having changed
pyb.LED(1).toggle()
triggered = False
`