From b9523fd58c02dba74239015bf6b2a1983342a06b Mon Sep 17 00:00:00 2001 From: Chris Webb Date: Mon, 25 Aug 2025 15:29:40 +0100 Subject: [PATCH] docs: Document the cross-port Timer hard= option. Update the main machine.Timer specification, and any references to hard/soft interrupts in port-specific documentation. There is a separate copy of the machine.Timer documentation for the pyboard, so update that too to keep everything consistent. Signed-off-by: Chris Webb --- docs/esp32/quickref.rst | 4 ++++ docs/esp8266/quickref.rst | 3 +++ docs/library/machine.Timer.rst | 20 +++++++++++++++++--- docs/library/pyb.Timer.rst | 14 +++++++++++++- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 2c667a0f01..25e52ec32d 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -287,6 +287,10 @@ with a timer ID of 0, 0 and 1, or from 0 to 3 (inclusive):: The period is in milliseconds. When using UART.IRQ_RXIDLE, timer 0 is needed for the IRQ_RXIDLE mechanism and must not be used otherwise. +Timer callbacks are scheduled as soft interrupts on this port; hard +callbacks are not implemented. Specifying ``hard=True`` will raise +a ValueError. + Virtual timers are not currently supported on this port. .. _Pins_and_GPIO: diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst index e17b60f676..95e1fcf976 100644 --- a/docs/esp8266/quickref.rst +++ b/docs/esp8266/quickref.rst @@ -108,6 +108,9 @@ with timer ID of -1:: The period is in milliseconds. +By default, timer callbacks are scheduled as soft interrupts on this port. +Specify ``hard=True`` to run them in hard interrupt context instead. + Pins and GPIO ------------- diff --git a/docs/library/machine.Timer.rst b/docs/library/machine.Timer.rst index 44e6594080..5d228ea7b6 100644 --- a/docs/library/machine.Timer.rst +++ b/docs/library/machine.Timer.rst @@ -18,8 +18,9 @@ Timer callbacks. Memory can't be allocated inside irq handlers (an interrupt) and so exceptions raised within a handler don't give much information. See - :func:`micropython.alloc_emergency_exception_buf` for how to get around this - limitation. + :func:`micropython.alloc_emergency_exception_buf` for how to get around + this limitation, which applies to all callbacks of Timers created with + ``hard=True``. If you are using a WiPy board please refer to :ref:`machine.TimerWiPy ` instead of this class. @@ -38,7 +39,7 @@ Constructors Methods ------- -.. method:: Timer.init(*, mode=Timer.PERIODIC, freq=-1, period=-1, callback=None) +.. method:: Timer.init(*, mode=Timer.PERIODIC, freq=-1, period=-1, callback=None, hard=True) Initialise the timer. Example:: @@ -76,6 +77,19 @@ Methods will occur upon timer expiration: ``TypeError: 'NoneType' object isn't callable`` + - ``hard`` can be one of: + + - ``True`` - The callback will be executed in hard interrupt + context, which minimises delay and jitter but is subject to the + limitations described in :ref:`isr_rules` including being unable + to allocate on the heap. + - ``False`` - The callback will be scheduled as a soft interrupt, + allowing it to allocate but possibly also introducing + garbage-collection delays and jitter. + + The default value of this option is port-specific for historical + reasons. + .. method:: Timer.deinit() Deinitialises the timer. Stops the timer, and disables the timer peripheral. diff --git a/docs/library/pyb.Timer.rst b/docs/library/pyb.Timer.rst index c644e38d78..0e9e49c0ea 100644 --- a/docs/library/pyb.Timer.rst +++ b/docs/library/pyb.Timer.rst @@ -62,7 +62,7 @@ Constructors Methods ------- -.. method:: Timer.init(*, freq, prescaler, period, mode=Timer.UP, div=1, callback=None, deadtime=0, brk=Timer.BRK_OFF) +.. method:: Timer.init(*, freq, prescaler, period, mode=Timer.UP, div=1, callback=None, deadtime=0, brk=Timer.BRK_OFF, hard=True) Initialise the timer. Initialisation must be either by frequency (in Hz) or by prescaler and period:: @@ -115,6 +115,18 @@ Methods ``mode=Pin.ALT, alt=Pin.AFn_TIMx``. The pin's GPIO input features are available in alt mode - ``pull=`` , ``value()`` and ``irq()``. + - ``hard`` can be one of: + + - ``True`` - The callback will be executed in hard interrupt + context, which minimises delay and jitter but is subject to the + limitations described in :ref:`isr_rules` including being unable + to allocate on the heap. + - ``False`` - The callback will be scheduled as a soft interrupt, + allowing it to allocate but possibly also introducing + garbage-collection delays and jitter. + + The default value of this option is True. + You must either specify freq or both of period and prescaler. .. method:: Timer.deinit()