From 2167ef52ce557b367b6c3abf15748c19464dda14 Mon Sep 17 00:00:00 2001 From: Peter Hinch Date: Sun, 12 Nov 2017 06:13:45 +0000 Subject: [PATCH] docs/isr_rules docs/micropython Add note on alloc caused by bound method refs. --- docs/library/micropython.rst | 11 ++++++++++- docs/reference/isr_rules.rst | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/docs/library/micropython.rst b/docs/library/micropython.rst index c13a7391bbb1..d1f923e31f0a 100644 --- a/docs/library/micropython.rst +++ b/docs/library/micropython.rst @@ -112,5 +112,14 @@ Functions the heap may be locked) and scheduling a function to call later will lift those restrictions. - There is a finite stack to hold the scheduled functions and `schedule` + Note: If `schedule()` is called from a preempting IRQ, when memory + allocation is not allowed and the callback to be passed to `schedule()` is + a bound method, passing this directly will fail. This is because creating a + reference to a bound method causes memory allocation. A solution is to + create a reference to the method in the class constructor and to pass that + reference to `schedule()`. This is discussed in detail here + :ref:`reference documentation ` under "Creation of Python + objects". + + There is a finite stack to hold the scheduled functions and `schedule()` will raise a `RuntimeError` if the stack is full. diff --git a/docs/reference/isr_rules.rst b/docs/reference/isr_rules.rst index 2db261c09ddf..dfdee048c131 100644 --- a/docs/reference/isr_rules.rst +++ b/docs/reference/isr_rules.rst @@ -124,6 +124,32 @@ A means of creating an object without employing a class or globals is as follows The compiler instantiates the default ``buf`` argument when the function is loaded for the first time (usually when the module it's in is imported). +An instance of object creation occurs when a reference to a bound method is +created. This means that an ISR cannot pass a bound method to a function. One +solution is to create a reference to the bound method in the class constructor +and to pass that reference in the ISR. For example: + +.. code:: python + + class Foo(): + def __init__(self): + self.bar_ref = self.bar # Allocation occurs here + self.x = 0.1 + tim = pyb.Timer(4) + tim.init(freq=2) + tim.callback(self.cb) + + def bar(self, _): + self.x *= 1.2 + print(self.x) + + def cb(self, t): + # Passing self.bar would cause allocation. + micropython.schedule(self.bar_ref, 0) + +Other techniques are to define and instantiate the method in the constructor +or to pass :meth:`Foo.bar` with the argument *self*. + Use of Python objects ~~~~~~~~~~~~~~~~~~~~~ @@ -179,6 +205,9 @@ interrupt occurs while the previous callback is executing, a further instance of for execution; this will run after the current instance has completed. A sustained high interrupt repetition rate therefore carries a risk of unconstrained queue growth and eventual failure with a ``RuntimeError``. +If the callback to be passed to `schedule()` is a bound method, consider the +note in "Creation of Python objects". + Exceptions ----------