← index #6701Issue #1490
Related · high · value 0.324
QUERY · ISSUE

RTC wakeup callback should be executed immediately rather than deferred

openby acutetechopened 2020-12-17updated 2024-09-13
port-stm32

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

`

CANDIDATE · ISSUE

rtc.wakeup() behaves anomalously

closedby peterhinchopened 2015-10-06updated 2015-10-06

The following sample does not behave as expected. The first and last LED flashes are of the correct duration, but the middle one is about 25% of that programmed. The problem seems to occur when a short delay is followed by a long one. Note that if in line 6 True is changed to False, the duration of the long flash is correct.

import pyb
rtc = pyb.RTC()
leds = tuple(pyb.LED(x) for x in range(1, 5))   # rgyb
for led in leds:
    led.off()
if True:
    x = 0
    leds[x].on()
    rtc.wakeup(1000)
    pyb.stop()
    rtc.wakeup(None)
    leds[x].off()

x = 1
leds[x].on()
rtc.wakeup(15000) # far too short
pyb.stop()
rtc.wakeup(None)
leds[x].off()

x = 2
leds[x].on()
rtc.wakeup(400)
pyb.stop()
rtc.wakeup(None)
leds[x].off()

[edit]
The error is on this line

        // set WUTIE to enable wakeup interrupts
        // set WUTE to enable wakeup
        // program WUCKSEL
        RTC->CR |= (1 << 14) | (1 << 10) | (wucksel & 7);

Oring wucksel & 7 is leaving some bits set. This fixes it.

        RTC->CR &= ~7;
        RTC->CR |= (1 << 14) | (1 << 10) | (wucksel & 7);

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied