summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorPeter Hinch <peter@hinch.me.uk>2017-11-12 06:13:45 +0000
committerDamien George <damien.p.george@gmail.com>2017-11-23 11:35:58 +1100
commitec1e9a10a73d9c5c3771a5797e9eceb62475b197 (patch)
treee6930e9bd631f570fb0b7cf8fa9439ee820f256a
parentdf078e82136de80a6ff2d30db97a7411c45d4085 (diff)
downloadmicropython-ec1e9a10a73d9c5c3771a5797e9eceb62475b197.tar.gz
micropython-ec1e9a10a73d9c5c3771a5797e9eceb62475b197.zip
docs: Add notes on heap allocation caused by bound method refs.
-rw-r--r--docs/library/micropython.rst11
-rw-r--r--docs/reference/isr_rules.rst29
2 files changed, 39 insertions, 1 deletions
diff --git a/docs/library/micropython.rst b/docs/library/micropython.rst
index c13a7391bb..d1f923e31f 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 <isr_rules>` 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 2db261c09d..dfdee048c1 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
----------