summaryrefslogtreecommitdiff
path: root/docs/reference
diff options
context:
space:
mode:
Diffstat (limited to 'docs/reference')
-rw-r--r--docs/reference/asm_thumb2_arith.rst50
-rw-r--r--docs/reference/asm_thumb2_compare.rst90
-rw-r--r--docs/reference/asm_thumb2_directives.rst36
-rw-r--r--docs/reference/asm_thumb2_float.rst77
-rw-r--r--docs/reference/asm_thumb2_hints_tips.rst244
-rw-r--r--docs/reference/asm_thumb2_index.rst73
-rw-r--r--docs/reference/asm_thumb2_label_branch.rst85
-rw-r--r--docs/reference/asm_thumb2_ldr.rst23
-rw-r--r--docs/reference/asm_thumb2_logical_bit.rst53
-rw-r--r--docs/reference/asm_thumb2_misc.rst13
-rw-r--r--docs/reference/asm_thumb2_mov.rst27
-rw-r--r--docs/reference/asm_thumb2_stack.rst20
-rw-r--r--docs/reference/asm_thumb2_str.rst21
-rw-r--r--docs/reference/constrained.rst456
-rw-r--r--docs/reference/glossary.rst105
-rw-r--r--docs/reference/index.rst33
-rw-r--r--docs/reference/isr_rules.rst353
-rw-r--r--docs/reference/repl.rst211
-rw-r--r--docs/reference/speed_python.rst342
19 files changed, 0 insertions, 2312 deletions
diff --git a/docs/reference/asm_thumb2_arith.rst b/docs/reference/asm_thumb2_arith.rst
deleted file mode 100644
index da4a68852..000000000
--- a/docs/reference/asm_thumb2_arith.rst
+++ /dev/null
@@ -1,50 +0,0 @@
-Arithmetic instructions
-=======================
-
-Document conventions
---------------------
-
-Notation: ``Rd, Rm, Rn`` denote ARM registers R0-R7. ``immN`` denotes an immediate
-value having a width of N bits e.g. ``imm8``, ``imm3``. ``carry`` denotes
-the carry condition flag, ``not(carry)`` denotes its complement. In the case of instructions
-with more than one register argument, it is permissible for some to be identical. For example
-the following will add the contents of R0 to itself, placing the result in R0:
-
-* add(r0, r0, r0)
-
-Arithmetic instructions affect the condition flags except where stated.
-
-Addition
---------
-
-* add(Rdn, imm8) ``Rdn = Rdn + imm8``
-* add(Rd, Rn, imm3) ``Rd = Rn + imm3``
-* add(Rd, Rn, Rm) ``Rd = Rn +Rm``
-* adc(Rd, Rn) ``Rd = Rd + Rn + carry``
-
-Subtraction
------------
-
-* sub(Rdn, imm8) ``Rdn = Rdn - imm8``
-* sub(Rd, Rn, imm3) ``Rd = Rn - imm3``
-* sub(Rd, Rn, Rm) ``Rd = Rn - Rm``
-* sbc(Rd, Rn) ``Rd = Rd - Rn - not(carry)``
-
-Negation
---------
-
-* neg(Rd, Rn) ``Rd = -Rn``
-
-Multiplication and division
----------------------------
-
-* mul(Rd, Rn) ``Rd = Rd * Rn``
-
-This produces a 32 bit result with overflow lost. The result may be treated as
-signed or unsigned according to the definition of the operands.
-
-* sdiv(Rd, Rn, Rm) ``Rd = Rn / Rm``
-* udiv(Rd, Rn, Rm) ``Rd = Rn / Rm``
-
-These functions perform signed and unsigned division respectively. Condition flags
-are not affected.
diff --git a/docs/reference/asm_thumb2_compare.rst b/docs/reference/asm_thumb2_compare.rst
deleted file mode 100644
index 521af69da..000000000
--- a/docs/reference/asm_thumb2_compare.rst
+++ /dev/null
@@ -1,90 +0,0 @@
-Comparison instructions
-=======================
-
-These perform an arithmetic or logical instruction on two arguments, discarding the result
-but setting the condition flags. Typically these are used to test data values without changing
-them prior to executing a conditional branch.
-
-Document conventions
---------------------
-
-Notation: ``Rd, Rm, Rn`` denote ARM registers R0-R7. ``imm8`` denotes an immediate
-value having a width of 8 bits.
-
-The Application Program Status Register (APSR)
-----------------------------------------------
-
-This contains four bits which are tested by the conditional branch instructions. Typically a
-conditional branch will test multiple bits, for example ``bge(LABEL)``. The meaning of
-condition codes can depend on whether the operands of an arithmetic instruction are viewed as
-signed or unsigned integers. Thus ``bhi(LABEL)`` assumes unsigned numbers were processed while
-``bgt(LABEL)`` assumes signed operands.
-
-APSR Bits
----------
-
-* Z (zero)
-
-This is set if the result of an operation is zero or the operands of a comparison are equal.
-
-* N (negative)
-
-Set if the result is negative.
-
-* C (carry)
-
-An addition sets the carry flag when the result overflows out of the MSB, for example adding
-0x80000000 and 0x80000000. By the nature of two's complement arithmetic this behaviour is reversed
-on subtraction, with a borrow indicated by the carry bit being clear. Thus 0x10 - 0x01 is executed
-as 0x10 + 0xffffffff which will set the carry bit.
-
-* V (overflow)
-
-The overflow flag is set if the result, viewed as a two's compliment number, has the "wrong" sign
-in relation to the operands. For example adding 1 to 0x7fffffff will set the overflow bit because
-the result (0x8000000), viewed as a two's complement integer, is negative. Note that in this instance
-the carry bit is not set.
-
-Comparison instructions
------------------------
-
-These set the APSR (Application Program Status Register) N (negative), Z (zero), C (carry) and V
-(overflow) flags.
-
-* cmp(Rn, imm8) ``Rn - imm8``
-* cmp(Rn, Rm) ``Rn - Rm``
-* cmn(Rn, Rm) ``Rn + Rm``
-* tst(Rn, Rm) ``Rn & Rm``
-
-Conditional execution
----------------------
-
-The ``it`` and ``ite`` instructions provide a means of conditionally executing from one to four subsequent
-instructions without the need for a label.
-
-* it(<condition>) If then
-
-Execute the next instruction if <condition> is true:
-
-::
-
- cmp(r0, r1)
- it(eq)
- mov(r0, 100) # runs if r0 == r1
- # execution continues here
-
-* ite(<condition>) If then else
-
-If <condtion> is true, execute the next instruction, otherwise execute the
-subsequent one. Thus:
-
-::
-
- cmp(r0, r1)
- ite(eq)
- mov(r0, 100) # runs if r0 == r1
- mov(r0, 200) # runs if r0 != r1
- # execution continues here
-
-This may be extended to control the execution of upto four subsequent instructions: it[x[y[z]]]
-where x,y,z=t/e; e.g. itt, itee, itete, ittte, itttt, iteee, etc.
diff --git a/docs/reference/asm_thumb2_directives.rst b/docs/reference/asm_thumb2_directives.rst
deleted file mode 100644
index 95acd7781..000000000
--- a/docs/reference/asm_thumb2_directives.rst
+++ /dev/null
@@ -1,36 +0,0 @@
-Assembler Directives
-====================
-
-Labels
-------
-
-* label(INNER1)
-
-This defines a label for use in a branch instruction. Thus elsewhere in the code a ``b(INNER1)``
-will cause execution to continue with the instruction after the label directive.
-
-Defining inline data
---------------------
-
-The following assembler directives facilitate embedding data in an assembler code block.
-
-* data(size, d0, d1 .. dn)
-
-The data directive creates n array of data values in memory. The first argument specifies the
-size in bytes of the subsequent arguments. Hence the first statement below will cause the
-assembler to put three bytes (with values 2, 3 and 4) into consecutive memory locations
-while the second will cause it to emit two four byte words.
-
-::
-
- data(1, 2, 3, 4)
- data(4, 2, 100000)
-
-Data values longer than a single byte are stored in memory in little-endian format.
-
-* align(nBytes)
-
-Align the following instruction to an nBytes value. ARM Thumb-2 instructions must be two
-byte aligned, hence it's advisable to issue ``align(2)`` after ``data`` directives and
-prior to any subsequent code. This ensures that the code will run irrespective of the
-size of the data array.
diff --git a/docs/reference/asm_thumb2_float.rst b/docs/reference/asm_thumb2_float.rst
deleted file mode 100644
index 4acb734ee..000000000
--- a/docs/reference/asm_thumb2_float.rst
+++ /dev/null
@@ -1,77 +0,0 @@
-Floating Point instructions
-==============================
-
-These instructions support the use of the ARM floating point coprocessor
-(on platforms such as the Pyboard which are equipped with one). The FPU
-has 32 registers known as ``s0-s31`` each of which can hold a single
-precision float. Data can be passed between the FPU registers and the
-ARM core registers with the ``vmov`` instruction.
-
-Note that MicroPython doesn't support passing floats to
-assembler functions, nor can you put a float into ``r0`` and expect a
-reasonable result. There are two ways to overcome this. The first is to
-use arrays, and the second is to pass and/or return integers and convert
-to and from floats in code.
-
-Document conventions
---------------------
-
-Notation: ``Sd, Sm, Sn`` denote FPU registers, ``Rd, Rm, Rn`` denote ARM core
-registers. The latter can be any ARM core register although registers
-``R13-R15`` are unlikely to be appropriate in this context.
-
-Arithmetic
-----------
-
-* vadd(Sd, Sn, Sm) ``Sd = Sn + Sm``
-* vsub(Sd, Sn, Sm) ``Sd = Sn - Sm``
-* vneg(Sd, Sm) ``Sd = -Sm``
-* vmul(Sd, Sn, Sm) ``Sd = Sn * Sm``
-* vdiv(Sd, Sn, Sm) ``Sd = Sn / Sm``
-* vsqrt(Sd, Sm) ``Sd = sqrt(Sm)``
-
-Registers may be identical: ``vmul(S0, S0, S0)`` will execute ``S0 = S0*S0``
-
-Move between ARM core and FPU registers
----------------------------------------
-
-* vmov(Sd, Rm) ``Sd = Rm``
-* vmov(Rd, Sm) ``Rd = Sm``
-
-The FPU has a register known as FPSCR, similar to the ARM core's APSR, which stores condition
-codes plus other data. The following instructions provide access to this.
-
-* vmrs(APSR\_nzcv, FPSCR)
-
-Move the floating-point N, Z, C, and V flags to the APSR N, Z, C, and V flags.
-
-This is done after an instruction such as an FPU
-comparison to enable the condition codes to be tested by the assembler
-code. The following is a more general form of the instruction.
-
-* vmrs(Rd, FPSCR) ``Rd = FPSCR``
-
-Move between FPU register and memory
-------------------------------------
-
-* vldr(Sd, [Rn, offset]) ``Sd = [Rn + offset]``
-* vstr(Sd, [Rn, offset]) ``[Rn + offset] = Sd``
-
-Where ``[Rn + offset]`` denotes the memory address obtained by adding Rn to the offset. This
-is specified in bytes. Since each float value occupies a 32 bit word, when accessing arrays of
-floats the offset must always be a multiple of four bytes.
-
-Data Comparison
----------------
-
-* vcmp(Sd, Sm)
-
-Compare the values in Sd and Sm and set the FPU N, Z,
-C, and V flags. This would normally be followed by ``vmrs(APSR_nzcv, FPSCR)``
-to enable the results to be tested.
-
-Convert between integer and float
----------------------------------
-
-* vcvt\_f32\_s32(Sd, Sm) ``Sd = float(Sm)``
-* vcvt\_s32\_f32(Sd, Sm) ``Sd = int(Sm)``
diff --git a/docs/reference/asm_thumb2_hints_tips.rst b/docs/reference/asm_thumb2_hints_tips.rst
deleted file mode 100644
index 062a3c844..000000000
--- a/docs/reference/asm_thumb2_hints_tips.rst
+++ /dev/null
@@ -1,244 +0,0 @@
-Hints and tips
-==============
-
-The following are some examples of the use of the inline assembler and some
-information on how to work around its limitations. In this document the term
-"assembler function" refers to a function declared in Python with the
-``@micropython.asm_thumb`` decorator, whereas "subroutine" refers to assembler
-code called from within an assembler function.
-
-Code branches and subroutines
------------------------------
-
-It is important to appreciate that labels are local to an assembler function.
-There is currently no way for a subroutine defined in one function to be called
-from another.
-
-To call a subroutine the instruction ``bl(LABEL)`` is issued. This transfers
-control to the instruction following the ``label(LABEL)`` directive and stores
-the return address in the link register (``lr`` or ``r14``). To return the
-instruction ``bx(lr)`` is issued which causes execution to continue with
-the instruction following the subroutine call. This mechanism implies that, if
-a subroutine is to call another, it must save the link register prior to
-the call and restore it before terminating.
-
-The following rather contrived example illustrates a function call. Note that
-it's necessary at the start to branch around all subroutine calls: subroutines
-end execution with ``bx(lr)`` while the outer function simply "drops off the end"
-in the style of Python functions.
-
-::
-
- @micropython.asm_thumb
- def quad(r0):
- b(START)
- label(DOUBLE)
- add(r0, r0, r0)
- bx(lr)
- label(START)
- bl(DOUBLE)
- bl(DOUBLE)
-
- print(quad(10))
-
-The following code example demonstrates a nested (recursive) call: the classic
-Fibonacci sequence. Here, prior to a recursive call, the link register is saved
-along with other registers which the program logic requires to be preserved.
-
-::
-
- @micropython.asm_thumb
- def fib(r0):
- b(START)
- label(DOFIB)
- push({r1, r2, lr})
- cmp(r0, 1)
- ble(FIBDONE)
- sub(r0, 1)
- mov(r2, r0) # r2 = n -1
- bl(DOFIB)
- mov(r1, r0) # r1 = fib(n -1)
- sub(r0, r2, 1)
- bl(DOFIB) # r0 = fib(n -2)
- add(r0, r0, r1)
- label(FIBDONE)
- pop({r1, r2, lr})
- bx(lr)
- label(START)
- bl(DOFIB)
-
- for n in range(10):
- print(fib(n))
-
-Argument passing and return
----------------------------
-
-The tutorial details the fact that assembler functions can support from zero to
-three arguments, which must (if used) be named ``r0``, ``r1`` and ``r2``. When
-the code executes the registers will be initialised to those values.
-
-The data types which can be passed in this way are integers and memory
-addresses. With current firmware all possible 32 bit values may be passed and
-returned. If the return value may have the most significant bit set a Python
-type hint should be employed to enable MicroPython to determine whether the
-value should be interpreted as a signed or unsigned integer: types are
-``int`` or ``uint``.
-
-::
-
- @micropython.asm_thumb
- def uadd(r0, r1) -> uint:
- add(r0, r0, r1)
-
-``hex(uadd(0x40000000,0x40000000))`` will return 0x80000000, demonstrating the
-passing and return of integers where bits 30 and 31 differ.
-
-The limitations on the number of arguments and return values can be overcome by means
-of the ``array`` module which enables any number of values of any type to be accessed.
-
-Multiple arguments
-~~~~~~~~~~~~~~~~~~
-
-If a Python array of integers is passed as an argument to an assembler
-function, the function will receive the address of a contiguous set of integers.
-Thus multiple arguments can be passed as elements of a single array. Similarly a
-function can return multiple values by assigning them to array elements.
-Assembler functions have no means of determining the length of an array:
-this will need to be passed to the function.
-
-This use of arrays can be extended to enable more than three arrays to be used.
-This is done using indirection: the ``uctypes`` module supports ``addressof()``
-which will return the address of an array passed as its argument. Thus you can
-populate an integer array with the addresses of other arrays:
-
-::
-
- from uctypes import addressof
- @micropython.asm_thumb
- def getindirect(r0):
- ldr(r0, [r0, 0]) # Address of array loaded from passed array
- ldr(r0, [r0, 4]) # Return element 1 of indirect array (24)
-
- def testindirect():
- a = array.array('i',[23, 24])
- b = array.array('i',[0,0])
- b[0] = addressof(a)
- print(getindirect(b))
-
-Non-integer data types
-~~~~~~~~~~~~~~~~~~~~~~
-
-These may be handled by means of arrays of the appropriate data type. For
-example, single precision floating point data may be processed as follows.
-This code example takes an array of floats and replaces its contents with
-their squares.
-
-::
-
- from array import array
-
- @micropython.asm_thumb
- def square(r0, r1):
- label(LOOP)
- vldr(s0, [r0, 0])
- vmul(s0, s0, s0)
- vstr(s0, [r0, 0])
- add(r0, 4)
- sub(r1, 1)
- bgt(LOOP)
-
- a = array('f', (x for x in range(10)))
- square(a, len(a))
- print(a)
-
-The uctypes module supports the use of data structures beyond simple
-arrays. It enables a Python data structure to be mapped onto a bytearray
-instance which may then be passed to the assembler function.
-
-Named constants
----------------
-
-Assembler code may be made more readable and maintainable by using named
-constants rather than littering code with numbers. This may be achieved
-thus:
-
-::
-
- MYDATA = const(33)
-
- @micropython.asm_thumb
- def foo():
- mov(r0, MYDATA)
-
-The const() construct causes MicroPython to replace the variable name
-with its value at compile time. If constants are declared in an outer
-Python scope they can be shared between multiple assembler functions and
-with Python code.
-
-Assembler code as class methods
--------------------------------
-
-MicroPython passes the address of the object instance as the first argument
-to class methods. This is normally of little use to an assembler function.
-It can be avoided by declaring the function as a static method thus:
-
-::
-
- class foo:
- @staticmethod
- @micropython.asm_thumb
- def bar(r0):
- add(r0, r0, r0)
-
-Use of unsupported instructions
--------------------------------
-
-These can be coded using the data statement as shown below. While
-``push()`` and ``pop()`` are supported the example below illustrates the
-principle. The necessary machine code may be found in the ARM v7-M
-Architecture Reference Manual. Note that the first argument of data
-calls such as
-
-::
-
- data(2, 0xe92d, 0x0f00) # push r8,r9,r10,r11
-
-indicates that each subsequent argument is a two byte quantity.
-
-Overcoming MicroPython's integer restriction
---------------------------------------------
-
-The Pyboard chip includes a CRC generator. Its use presents a problem in
-MicroPython because the returned values cover the full gamut of 32 bit
-quantities whereas small integers in MicroPython cannot have differing values
-in bits 30 and 31. This limitation is overcome with the following code, which
-uses assembler to put the result into an array and Python code to
-coerce the result into an arbitrary precision unsigned integer.
-
-::
-
- from array import array
- import stm
-
- def enable_crc():
- stm.mem32[stm.RCC + stm.RCC_AHB1ENR] |= 0x1000
-
- def reset_crc():
- stm.mem32[stm.CRC+stm.CRC_CR] = 1
-
- @micropython.asm_thumb
- def getval(r0, r1):
- movwt(r3, stm.CRC + stm.CRC_DR)
- str(r1, [r3, 0])
- ldr(r2, [r3, 0])
- str(r2, [r0, 0])
-
- def getcrc(value):
- a = array('i', [0])
- getval(a, value)
- return a[0] & 0xffffffff # coerce to arbitrary precision
-
- enable_crc()
- reset_crc()
- for x in range(20):
- print(hex(getcrc(0)))
diff --git a/docs/reference/asm_thumb2_index.rst b/docs/reference/asm_thumb2_index.rst
deleted file mode 100644
index f066e6ace..000000000
--- a/docs/reference/asm_thumb2_index.rst
+++ /dev/null
@@ -1,73 +0,0 @@
-.. _asm_thumb2_index:
-
-Inline Assembler for Thumb2 architectures
-=========================================
-
-This document assumes some familiarity with assembly language programming and should be read after studying
-the :ref:`tutorial <pyboard_tutorial_assembler>`. For a detailed description of the instruction set consult the
-Architecture Reference Manual detailed below.
-The inline assembler supports a subset of the ARM Thumb-2 instruction set described here. The syntax tries
-to be as close as possible to that defined in the above ARM manual, converted to Python function calls.
-
-Instructions operate on 32 bit signed integer data except where stated otherwise. Most supported instructions
-operate on registers ``R0-R7`` only: where ``R8-R15`` are supported this is stated. Registers ``R8-R12`` must be
-restored to their initial value before return from a function. Registers ``R13-R15`` constitute the Link Register,
-Stack Pointer and Program Counter respectively.
-
-Document conventions
---------------------
-
-Where possible the behaviour of each instruction is described in Python, for example
-
-* add(Rd, Rn, Rm) ``Rd = Rn + Rm``
-
-This enables the effect of instructions to be demonstrated in Python. In certain case this is impossible
-because Python doesn't support concepts such as indirection. The pseudocode employed in such cases is
-described on the relevant page.
-
-Instruction Categories
-----------------------
-
-The following sections details the subset of the ARM Thumb-2 instruction set supported by MicroPython.
-
-.. toctree::
- :maxdepth: 1
- :numbered:
-
- asm_thumb2_mov.rst
- asm_thumb2_ldr.rst
- asm_thumb2_str.rst
- asm_thumb2_logical_bit.rst
- asm_thumb2_arith.rst
- asm_thumb2_compare.rst
- asm_thumb2_label_branch.rst
- asm_thumb2_stack.rst
- asm_thumb2_misc.rst
- asm_thumb2_float.rst
- asm_thumb2_directives.rst
-
-Usage examples
---------------
-
-These sections provide further code examples and hints on the use of the assembler.
-
-.. toctree::
- :maxdepth: 1
- :numbered:
-
- asm_thumb2_hints_tips.rst
-
-References
-----------
-
-- :ref:`Assembler Tutorial <pyboard_tutorial_assembler>`
-- `Wiki hints and tips
- <http://wiki.micropython.org/platforms/boards/pyboard/assembler>`__
-- `uPy Inline Assembler source-code,
- emitinlinethumb.c <https://github.com/micropython/micropython/blob/master/py/emitinlinethumb.c>`__
-- `ARM Thumb2 Instruction Set Quick Reference
- Card <http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf>`__
-- `RM0090 Reference
- Manual <http://www.google.ae/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&sqi=2&ved=0CBoQFjAA&url=http%3A%2F%2Fwww.st.com%2Fst-web-ui%2Fstatic%2Factive%2Fen%2Fresource%2Ftechnical%2Fdocument%2Freference_manual%2FDM00031020.pdf&ei=G0rSU66xFeuW0QWYwoD4CQ&usg=AFQjCNFuW6TgzE4QpahO_U7g3f3wdwecAg&sig2=iET-R0y9on_Pbflzf9aYDw&bvm=bv.71778758,bs.1,d.bGQ>`__
-- ARM v7-M Architecture Reference Manual (Available on the
- ARM site after a simple registration procedure. Also available on academic sites but beware of out of date versions.)
diff --git a/docs/reference/asm_thumb2_label_branch.rst b/docs/reference/asm_thumb2_label_branch.rst
deleted file mode 100644
index 8c85e55f0..000000000
--- a/docs/reference/asm_thumb2_label_branch.rst
+++ /dev/null
@@ -1,85 +0,0 @@
-Branch instructions
-===================
-
-These cause execution to jump to a target location usually specified by a label (see the ``label``
-assembler directive). Conditional branches and the ``it`` and ``ite`` instructions test
-the Application Program Status Register (APSR) N (negative), Z (zero), C (carry) and V
-(overflow) flags to determine whether the branch should be executed.
-
-Most of the exposed assembler instructions (including move operations) set the flags but
-there are explicit comparison instructions to enable values to be tested.
-
-Further detail on the meaning of the condition flags is provided in the section
-describing comparison functions.
-
-Document conventions
---------------------
-
-Notation: ``Rm`` denotes ARM registers R0-R15. ``LABEL`` denotes a label defined with the
-``label()`` assembler directive. ``<condition>`` indicates one of the following condition
-specifiers:
-
-* eq Equal to (result was zero)
-* ne Not equal
-* cs Carry set
-* cc Carry clear
-* mi Minus (negative)
-* pl Plus (positive)
-* vs Overflow set
-* vc Overflow clear
-* hi > (unsigned comparison)
-* ls <= (unsigned comparison)
-* ge >= (signed comparison)
-* lt < (signed comparison)
-* gt > (signed comparison)
-* le <= (signed comparison)
-
-Branch to label
----------------
-
-* b(LABEL) Unconditional branch
-* beq(LABEL) branch if equal
-* bne(LABEL) branch if not equal
-* bge(LABEL) branch if greater than or equal
-* bgt(LABEL) branch if greater than
-* blt(LABEL) branch if less than (<) (signed)
-* ble(LABEL) branch if less than or equal to (<=) (signed)
-* bcs(LABEL) branch if carry flag is set
-* bcc(LABEL) branch if carry flag is clear
-* bmi(LABEL) branch if negative
-* bpl(LABEL) branch if positive
-* bvs(LABEL) branch if overflow flag set
-* bvc(LABEL) branch if overflow flag is clear
-* bhi(LABEL) branch if higher (unsigned)
-* bls(LABEL) branch if lower or equal (unsigned)
-
-Long branches
--------------
-
-The code produced by the branch instructions listed above uses a fixed bit width to specify the
-branch destination, which is PC relative. Consequently in long programs where the
-branch instruction is remote from its destination the assembler will produce a "branch not in
-range" error. This can be overcome with the "wide" variants such as
-
-* beq\_w(LABEL) long branch if equal
-
-Wide branches use 4 bytes to encode the instruction (compared with 2 bytes for standard branch instructions).
-
-Subroutines (functions)
------------------------
-
-When entering a subroutine the processor stores the return address in register r14, also
-known as the link register (lr). Return to the instruction after the subroutine call is
-performed by updating the program counter (r15 or pc) from the link register, This
-process is handled by the following instructions.
-
-* bl(LABEL)
-
-Transfer execution to the instruction after ``LABEL`` storing the return address in
-the link register (r14).
-
-* bx(Rm) Branch to address specified by Rm.
-
-Typically ``bx(lr)`` is issued to return from a subroutine. For nested subroutines the
-link register of outer scopes must be saved (usually on the stack) before performing
-inner subroutine calls.
diff --git a/docs/reference/asm_thumb2_ldr.rst b/docs/reference/asm_thumb2_ldr.rst
deleted file mode 100644
index 16b772959..000000000
--- a/docs/reference/asm_thumb2_ldr.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-Load register from memory
-=========================
-
-Document conventions
---------------------
-
-Notation: ``Rt, Rn`` denote ARM registers R0-R7 except where stated. ``immN`` represents an immediate
-value having a width of N bits hence ``imm5`` is constrained to the range 0-31. ``[Rn + immN]`` is the contents
-of the memory address obtained by adding Rn and the offset ``immN``. Offsets are measured in
-bytes. These instructions affect the condition flags.
-
-Register Load
--------------
-
-* ldr(Rt, [Rn, imm7]) ``Rt = [Rn + imm7]`` Load a 32 bit word
-* ldrb(Rt, [Rn, imm5]) ``Rt = [Rn + imm5]`` Load a byte
-* ldrh(Rt, [Rn, imm6]) ``Rt = [Rn + imm6]`` Load a 16 bit half word
-
-Where a byte or half word is loaded, it is zero-extended to 32 bits.
-
-The specified immediate offsets are measured in bytes. Hence in the case of ``ldr`` the 7 bit value
-enables 32 bit word aligned values to be accessed with a maximum offset of 31 words. In the case of ``ldrh`` the
-6 bit value enables 16 bit half-word aligned values to be accessed with a maximum offset of 31 half-words.
diff --git a/docs/reference/asm_thumb2_logical_bit.rst b/docs/reference/asm_thumb2_logical_bit.rst
deleted file mode 100644
index 8c51feaf4..000000000
--- a/docs/reference/asm_thumb2_logical_bit.rst
+++ /dev/null
@@ -1,53 +0,0 @@
-Logical & Bitwise instructions
-==============================
-
-Document conventions
---------------------
-
-Notation: ``Rd, Rn`` denote ARM registers R0-R7 except in the case of the
-special instructions where R0-R15 may be used. ``Rn<a-b>`` denotes an ARM register
-whose contents must lie in range ``a <= contents <= b``. In the case of instructions
-with two register arguments, it is permissible for them to be identical. For example
-the following will zero R0 (Python ``R0 ^= R0``) regardless of its initial contents.
-
-* eor(r0, r0)
-
-These instructions affect the condition flags except where stated.
-
-Logical instructions
---------------------
-
-* and\_(Rd, Rn) ``Rd &= Rn``
-* orr(Rd, Rn) ``Rd |= Rn``
-* eor(Rd, Rn) ``Rd ^= Rn``
-* mvn(Rd, Rn) ``Rd = Rn ^ 0xffffffff`` i.e. Rd = 1's complement of Rn
-* bic(Rd, Rn) ``Rd &= ~Rn`` bit clear Rd using mask in Rn
-
-Note the use of "and\_" instead of "and", because "and" is a reserved keyword in Python.
-
-Shift and rotation instructions
--------------------------------
-
-* lsl(Rd, Rn<0-31>) ``Rd <<= Rn``
-* lsr(Rd, Rn<1-32>) ``Rd = (Rd & 0xffffffff) >> Rn`` Logical shift right
-* asr(Rd, Rn<1-32>) ``Rd >>= Rn`` arithmetic shift right
-* ror(Rd, Rn<1-31>) ``Rd = rotate_right(Rd, Rn)`` Rd is rotated right Rn bits.
-
-A rotation by (for example) three bits works as follows. If Rd initially
-contains bits ``b31 b30..b0`` after rotation it will contain ``b2 b1 b0 b31 b30..b3``
-
-Special instructions
---------------------
-
-Condition codes are unaffected by these instructions.
-
-* clz(Rd, Rn) ``Rd = count_leading_zeros(Rn)``
-
-count_leading_zeros(Rn) returns the number of binary zero bits before the first binary one bit in Rn.
-
-* rbit(Rd, Rn) ``Rd = bit_reverse(Rn)``
-
-bit_reverse(Rn) returns the bit-reversed contents of Rn. If Rn contains bits ``b31 b30..b0`` Rd will be set
-to ``b0 b1 b2..b31``
-
-Trailing zeros may be counted by performing a bit reverse prior to executing clz.
diff --git a/docs/reference/asm_thumb2_misc.rst b/docs/reference/asm_thumb2_misc.rst
deleted file mode 100644
index ca3f878cc..000000000
--- a/docs/reference/asm_thumb2_misc.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-Miscellaneous instructions
-==========================
-
-* nop() ``pass`` no operation.
-* wfi() Suspend execution in a low power state until an interrupt occurs.
-* cpsid(flags) set the Priority Mask Register - disable interrupts.
-* cpsie(flags) clear the Priority Mask Register - enable interrupts.
-* mrs(Rd, special_reg) ``Rd = special_reg`` copy a special register to a general register. The special register
- may be IPSR (Interrupt Status Register) or BASEPRI (Base Priority Register). The IPSR provides a means of determining
- the exception number of an interrupt being processed. It contains zero if no interrupt is being processed.
-
-Currently the ``cpsie()`` and ``cpsid()`` functions are partially implemented.
-They require but ignore the flags argument and serve as a means of enabling and disabling interrupts.
diff --git a/docs/reference/asm_thumb2_mov.rst b/docs/reference/asm_thumb2_mov.rst
deleted file mode 100644
index 900bf957b..000000000
--- a/docs/reference/asm_thumb2_mov.rst
+++ /dev/null
@@ -1,27 +0,0 @@
-Register move instructions
-==========================
-
-Document conventions
---------------------
-
-Notation: ``Rd, Rn`` denote ARM registers R0-R15. ``immN`` denotes an immediate
-value having a width of N bits. These instructions affect the condition flags.
-
-Register moves
---------------
-
-Where immediate values are used, these are zero-extended to 32 bits. Thus
-``mov(R0, 0xff)`` will set R0 to 255.
-
-* mov(Rd, imm8) ``Rd = imm8``
-* mov(Rd, Rn) ``Rd = Rn``
-* movw(Rd, imm16) ``Rd = imm16``
-* movt(Rd, imm16) ``Rd = (Rd & 0xffff) | (imm16 << 16)``
-
-movt writes an immediate value to the top halfword of the destination register.
-It does not affect the contents of the bottom halfword.
-
-* movwt(Rd, imm32) ``Rd = imm32``
-
-movwt is a pseudo-instruction: the MicroPython assembler emits a ``movw`` followed
-by a ``movt`` to move a 32-bit value into Rd.
diff --git a/docs/reference/asm_thumb2_stack.rst b/docs/reference/asm_thumb2_stack.rst
deleted file mode 100644
index bffbab277..000000000
--- a/docs/reference/asm_thumb2_stack.rst
+++ /dev/null
@@ -1,20 +0,0 @@
-Stack push and pop
-==================
-
-Document conventions
---------------------
-
-The ``push()`` and ``pop()`` instructions accept as their argument a register set containing
-a subset, or possibly all, of the general-purpose registers R0-R12 and the link register (lr or R14).
-As with any Python set the order in which the registers are specified is immaterial. Thus the
-in the following example the pop() instruction would restore R1, R7 and R8 to their contents prior
-to the push():
-
-* push({r1, r8, r7}) Save three registers on the stack.
-* pop({r7, r1, r8}) Restore them
-
-Stack operations
-----------------
-
-* push({regset}) Push a set of registers onto the stack
-* pop({regset}) Restore a set of registers from the stack
diff --git a/docs/reference/asm_thumb2_str.rst b/docs/reference/asm_thumb2_str.rst
deleted file mode 100644
index 5a88b091b..000000000
--- a/docs/reference/asm_thumb2_str.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-Store register to memory
-========================
-
-Document conventions
---------------------
-
-Notation: ``Rt, Rn`` denote ARM registers R0-R7 except where stated. ``immN`` represents an immediate
-value having a width of N bits hence ``imm5`` is constrained to the range 0-31. ``[Rn + imm5]`` is the
-contents of the memory address obtained by adding Rn and the offset ``imm5``. Offsets are measured in
-bytes. These instructions do not affect the condition flags.
-
-Register Store
---------------
-
-* str(Rt, [Rn, imm7]) ``[Rn + imm7] = Rt`` Store a 32 bit word
-* strb(Rt, [Rn, imm5]) ``[Rn + imm5] = Rt`` Store a byte (b0-b7)
-* strh(Rt, [Rn, imm6]) ``[Rn + imm6] = Rt`` Store a 16 bit half word (b0-b15)
-
-The specified immediate offsets are measured in bytes. Hence in the case of ``str`` the 7 bit value
-enables 32 bit word aligned values to be accessed with a maximum offset of 31 words. In the case of ``strh`` the
-6 bit value enables 16 bit half-word aligned values to be accessed with a maximum offset of 31 half-words.
diff --git a/docs/reference/constrained.rst b/docs/reference/constrained.rst
deleted file mode 100644
index e7de459bc..000000000
--- a/docs/reference/constrained.rst
+++ /dev/null
@@ -1,456 +0,0 @@
-.. _constrained:
-
-MicroPython on Microcontrollers
-===============================
-
-MicroPython is designed to be capable of running on microcontrollers. These
-have hardware limitations which may be unfamiliar to programmers more familiar
-with conventional computers. In particular the amount of RAM and nonvolatile
-"disk" (flash memory) storage is limited. This tutorial offers ways to make
-the most of the limited resources. Because MicroPython runs on controllers
-based on a variety of architectures, the methods presented are generic: in some
-cases it will be necessary to obtain detailed information from platform specific
-documentation.
-
-Flash Memory
-------------
-
-On the Pyboard the simple way to address the limited capacity is to fit a micro
-SD card. In some cases this is impractical, either because the device does not
-have an SD card slot or for reasons of cost or power consumption; hence the
-on-chip flash must be used. The firmware including the MicroPython subsystem is
-stored in the onboard flash. The remaining capacity is available for use. For
-reasons connected with the physical architecture of the flash memory part of
-this capacity may be inaccessible as a filesystem. In such cases this space may
-be employed by incorporating user modules into a firmware build which is then
-flashed to the device.
-
-There are two ways to achieve this: frozen modules and frozen bytecode. Frozen
-modules store the Python source with the firmware. Frozen bytecode uses the
-cross compiler to convert the source to bytecode which is then stored with the
-firmware. In either case the module may be accessed with an import statement:
-
-.. code::
-
- import mymodule
-
-The procedure for producing frozen modules and bytecode is platform dependent;
-instructions for building the firmware can be found in the README files in the
-relevant part of the source tree.
-
-In general terms the steps are as follows:
-
-* Clone the MicroPython `repository <https://github.com/micropython/micropython>`_.
-* Acquire the (platform specific) toolchain to build the firmware.
-* Build the cross compiler.
-* Place the modules to be frozen in a specified directory (dependent on whether
- the module is to be frozen as source or as bytecode).
-* Build the firmware. A specific command may be required to build frozen
- code of either type - see the platform documentation.
-* Flash the firmware to the device.
-
-RAM
----
-
-When reducing RAM usage there are two phases to consider: compilation and
-execution. In addition to memory consumption, there is also an issue known as
-heap fragmentation. In general terms it is best to minimise the repeated
-creation and destruction of objects. The reason for this is covered in the
-section covering the `heap`_.
-
-Compilation Phase
-~~~~~~~~~~~~~~~~~
-
-When a module is imported, MicroPython compiles the code to bytecode which is
-then executed by the MicroPython virtual machine (VM). The bytecode is stored
-in RAM. The compiler itself requires RAM, but this becomes available for use
-when the compilation has completed.
-
-If a number of modules have already been imported the situation can arise where
-there is insufficient RAM to run the compiler. In this case the import
-statement will produce a memory exception.
-
-If a module instantiates global objects on import it will consume RAM at the
-time of import, which is then unavailable for the compiler to use on subsequent
-imports. In general it is best to avoid code which runs on import; a better
-approach is to have initialisation code which is run by the application after
-all modules have been imported. This maximises the RAM available to the
-compiler.
-
-If RAM is still insufficient to compile all modules one solution is to
-precompile modules. MicroPython has a cross compiler capable of compiling Python
-modules to bytecode (see the README in the mpy-cross directory). The resulting
-bytecode file has a .mpy extension; it may be copied to the filesystem and
-imported in the usual way. Alternatively some or all modules may be implemented
-as frozen bytecode: on most platforms this saves even more RAM as the bytecode
-is run directly from flash rather than being stored in RAM.
-
-Execution Phase
-~~~~~~~~~~~~~~~
-
-There are a number of coding techniques for reducing RAM usage.
-
-**Constants**
-
-MicroPython provides a ``const`` keyword which may be used as follows:
-
-.. code::
-
- from micropython import const
- ROWS = const(33)
- _COLS = const(0x10)
- a = ROWS
- b = _COLS
-
-In both instances where the constant is assigned to a variable the compiler
-will avoid coding a lookup to the name of the constant by substituting its
-literal value. This saves bytecode and hence RAM. However the ``ROWS`` value
-will occupy at least two machine words, one each for the key and value in the
-globals dictionary. The presence in the dictionary is necessary because another
-module might import or use it. This RAM can be saved by prepending the name
-with an underscore as in ``_COLS``: this symbol is not visible outside the
-module so will not occupy RAM.
-
-The argument to ``const()`` may be anything which, at compile time, evaluates
-to an integer e.g. ``0x100`` or ``1 << 8``. It can even include other const
-symbols that have already been defined, e.g. ``1 << BIT``.
-
-**Constant data structures**
-
-Where there is a substantial volume of constant data and the platform supports
-execution from Flash, RAM may be saved as follows. The data should be located in
-Python modules and frozen as bytecode. The data must be defined as `bytes`
-objects. The compiler 'knows' that `bytes` objects are immutable and ensures
-that the objects remain in flash memory rather than being copied to RAM. The
-`ustruct` module can assist in converting between `bytes` types and other
-Python built-in types.
-
-When considering the implications of frozen bytecode, note that in Python
-strings, floats, bytes, integers and complex numbers are immutable. Accordingly
-these will be frozen into flash. Thus, in the line
-
-.. code::
-
- mystring = "The quick brown fox"
-
-the actual string "The quick brown fox" will reside in flash. At runtime a
-reference to the string is assigned to the *variable* ``mystring``. The reference
-occupies a single machine word. In principle a long integer could be used to
-store constant data:
-
-.. code::
-
- bar = 0xDEADBEEF0000DEADBEEF
-
-As in the string example, at runtime a reference to the arbitrarily large
-integer is assigned to the variable ``bar``. That reference occupies a
-single machine word.
-
-It might be expected that tuples of integers could be employed for the purpose
-of storing constant data with minimal RAM use. With the current compiler this
-is ineffective (the code works, but RAM is not saved).
-
-.. code::
-
- foo = (1, 2, 3, 4, 5, 6, 100000)
-
-At runtime the tuple will be located in RAM. This may be subject to future
-improvement.
-
-**Needless object creation**
-
-There are a number of situations where objects may unwittingly be created and
-destroyed. This can reduce the usability of RAM through fragmentation. The
-following sections discuss instances of this.
-
-**String concatenation**
-
-Consider the following code fragments which aim to produce constant strings:
-
-.. code::
-
- var = "foo" + "bar"
- var1 = "foo" "bar"
- var2 = """\
- foo\
- bar"""
-
-Each produces the same outcome, however the first needlessly creates two string
-objects at runtime, allocates more RAM for concatenation before producing the
-third. The others perform the concatenation at compile time which is more
-efficient, reducing fragmentation.
-
-Where strings must be dynamically created before being fed to a stream such as
-a file it will save RAM if this is done in a piecemeal fashion. Rather than
-creating a large string object, create a substring and feed it to the stream
-before dealing with the next.
-
-The best way to create dynamic strings is by means of the string `format`
-method:
-
-.. code::
-
- var = "Temperature {:5.2f} Pressure {:06d}\n".format(temp, press)
-
-**Buffers**
-
-When accessing devices such as instances of UART, I2C and SPI interfaces, using
-pre-allocated buffers avoids the creation of needless objects. Consider these
-two loops:
-
-.. code::
-
- while True:
- var = spi.read(100)
- # process data
-
- buf = bytearray(100)
- while True:
- spi.readinto(buf)
- # process data in buf
-
-The first creates a buffer on each pass whereas the second re-uses a pre-allocated
-buffer; this is both faster and more efficient in terms of memory fragmentation.
-
-**Bytes are smaller than ints**
-
-On most platforms an integer consumes four bytes. Consider the two calls to the
-function ``foo()``:
-
-.. code::
-
- def foo(bar):
- for x in bar:
- print(x)
- foo((1, 2, 0xff))
- foo(b'\1\2\xff')
-
-In the first call a tuple of integers is created in RAM. The second efficiently
-creates a `bytes` object consuming the minimum amount of RAM. If the module
-were frozen as bytecode, the `bytes` object would reside in flash.
-
-**Strings Versus Bytes**
-
-Python3 introduced Unicode support. This introduced a distinction between a
-string and an array of bytes. MicroPython ensures that Unicode strings take no
-additional space so long as all characters in the string are ASCII (i.e. have
-a value < 126). If values in the full 8-bit range are required `bytes` and
-`bytearray` objects can be used to ensure that no additional space will be
-required. Note that most string methods (e.g. :meth:`str.strip()`) apply also to `bytes`
-instances so the process of eliminating Unicode can be painless.
-
-.. code::
-
- s = 'the quick brown fox' # A string instance
- b = b'the quick brown fox' # A bytes instance
-
-Where it is necessary to convert between strings and bytes the :meth:`str.encode`
-and the :meth:`bytes.decode` methods can be used. Note that both strings and bytes
-are immutable. Any operation which takes as input such an object and produces
-another implies at least one RAM allocation to produce the result. In the
-second line below a new bytes object is allocated. This would also occur if ``foo``
-were a string.
-
-.. code::
-
- foo = b' empty whitespace'
- foo = foo.lstrip()
-
-**Runtime compiler execution**
-
-The Python funcitons `eval` and `exec` invoke the compiler at runtime, which
-requires significant amounts of RAM. Note that the `pickle` library from
-`micropython-lib` employs `exec`. It may be more RAM efficient to use the
-`ujson` library for object serialisation.
-
-**Storing strings in flash**
-
-Python strings are immutable hence have the potential to be stored in read only
-memory. The compiler can place in flash strings defined in Python code. As with
-frozen modules it is necessary to have a copy of the source tree on the PC and
-the toolchain to build the firmware. The procedure will work even if the
-modules have not been fully debugged, so long as they can be imported and run.
-
-After importing the modules, execute:
-
-.. code::
-
- micropython.qstr_info(1)
-
-Then copy and paste all the Q(xxx) lines into a text editor. Check for and
-remove lines which are obviously invalid. Open the file qstrdefsport.h which
-will be found in ports/stm32 (or the equivalent directory for the architecture in
-use). Copy and paste the corrected lines at the end of the file. Save the file,
-rebuild and flash the firmware. The outcome can be checked by importing the
-modules and again issuing:
-
-.. code::
-
- micropython.qstr_info(1)
-
-The Q(xxx) lines should be gone.
-
-.. _heap:
-
-The Heap
---------
-
-When a running program instantiates an object the necessary RAM is allocated
-from a fixed size pool known as the heap. When the object goes out of scope (in
-other words becomes inaccessible to code) the redundant object is known as
-"garbage". A process known as "garbage collection" (GC) reclaims that memory,
-returning it to the free heap. This process runs automatically, however it can
-be invoked directly by issuing `gc.collect()`.
-
-The discourse on this is somewhat involved. For a 'quick fix' issue the
-following periodically:
-
-.. code::
-
- gc.collect()
- gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())
-
-Fragmentation
-~~~~~~~~~~~~~
-
-Say a program creates an object ``foo``, then an object ``bar``. Subsequently
-``foo`` goes out of scope but ``bar`` remains. The RAM used by ``foo`` will be
-reclaimed by GC. However if ``bar`` was allocated to a higher address, the
-RAM reclaimed from ``foo`` will only be of use for objects no bigger than
-``foo``. In a complex or long running program the heap can become fragmented:
-despite there being a substantial amount of RAM available, there is insufficient
-contiguous space to allocate a particular object, and the program fails with a
-memory error.
-
-The techniques outlined above aim to minimise this. Where large permanent buffers
-or other objects are required it is best to instantiate these early in the
-process of program execution before fragmentation can occur. Further improvements
-may be made by monitoring the state of the heap and by controlling GC; these are
-outlined below.
-
-Reporting
-~~~~~~~~~
-
-A number of library functions are available to report on memory allocation and
-to control GC. These are to be found in the `gc` and `micropython` modules.
-The following example may be pasted at the REPL (``ctrl e`` to enter paste mode,
-``ctrl d`` to run it).
-
-.. code::
-
- import gc
- import micropython
- gc.collect()
- micropython.mem_info()
- print('-----------------------------')
- print('Initial free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
- def func():
- a = bytearray(10000)
- gc.collect()
- print('Func definition: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
- func()
- print('Func run free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
- gc.collect()
- print('Garbage collect free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
- print('-----------------------------')
- micropython.mem_info(1)
-
-Methods employed above:
-
-* `gc.collect()` Force a garbage collection. See footnote.
-* `micropython.mem_info()` Print a summary of RAM utilisation.
-* `gc.mem_free()` Return the free heap size in bytes.
-* `gc.mem_alloc()` Return the number of bytes currently allocated.
-* ``micropython.mem_info(1)`` Print a table of heap utilisation (detailed below).
-
-The numbers produced are dependent on the platform, but it can be seen that
-declaring the function uses a small amount of RAM in the form of bytecode
-emitted by the compiler (the RAM used by the compiler has been reclaimed).
-Running the function uses over 10KiB, but on return ``a`` is garbage because it
-is out of scope and cannot be referenced. The final `gc.collect()` recovers
-that memory.
-
-The final output produced by ``micropython.mem_info(1)`` will vary in detail but
-may be interpreted as follows:
-
-====== =================
-Symbol Meaning
-====== =================
- . free block
- h head block
- = tail block
- m marked head block
- T tuple
- L list
- D dict
- F float
- B byte code
- M module
-====== =================
-
-Each letter represents a single block of memory, a block being 16 bytes. So each
-line of the heap dump represents 0x400 bytes or 1KiB of RAM.
-
-Control of Garbage Collection
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A GC can be demanded at any time by issuing `gc.collect()`. It is advantageous
-to do this at intervals, firstly to pre-empt fragmentation and secondly for
-performance. A GC can take several milliseconds but is quicker when there is
-little work to do (about 1ms on the Pyboard). An explicit call can minimise that
-delay while ensuring it occurs at points in the program when it is acceptable.
-
-Automatic GC is provoked under the following circumstances. When an attempt at
-allocation fails, a GC is performed and the allocation re-tried. Only if this
-fails is an exception raised. Secondly an automatic GC will be triggered if the
-amount of free RAM falls below a threshold. This threshold can be adapted as
-execution progresses:
-
-.. code::
-
- gc.collect()
- gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())
-
-This will provoke a GC when more than 25% of the currently free heap becomes
-occupied.
-
-In general modules should instantiate data objects at runtime using constructors
-or other initialisation functions. The reason is that if this occurs on
-initialisation the compiler may be starved of RAM when subsequent modules are
-imported. If modules do instantiate data on import then `gc.collect()` issued
-after the import will ameliorate the problem.
-
-String Operations
------------------
-
-MicroPython handles strings in an efficient manner and understanding this can
-help in designing applications to run on microcontrollers. When a module
-is compiled, strings which occur multiple times are stored once only, a process
-known as string interning. In MicroPython an interned string is known as a ``qstr``.
-In a module imported normally that single instance will be located in RAM, but
-as described above, in modules frozen as bytecode it will be located in flash.
-
-String comparisons are also performed efficiently using hashing rather than
-character by character. The penalty for using strings rather than integers may
-hence be small both in terms of performance and RAM usage - a fact which may
-come as a surprise to C programmers.
-
-Postscript
-----------
-
-MicroPython passes, returns and (by default) copies objects by reference. A
-reference occupies a single machine word so these processes are efficient in
-RAM usage and speed.
-
-Where variables are required whose size is neither a byte nor a machine word
-there are standard libraries which can assist in storing these efficiently and
-in performing conversions. See the `array`, `ustruct` and `uctypes`
-modules.
-
-Footnote: gc.collect() return value
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-On Unix and Windows platforms the `gc.collect()` method returns an integer
-which signifies the number of distinct memory regions that were reclaimed in the
-collection (more precisely, the number of heads that were turned into frees). For
-efficiency reasons bare metal ports do not return this value.
diff --git a/docs/reference/glossary.rst b/docs/reference/glossary.rst
deleted file mode 100644
index 4cd3d84cc..000000000
--- a/docs/reference/glossary.rst
+++ /dev/null
@@ -1,105 +0,0 @@
-Glossary
-========
-
-.. glossary::
-
- baremetal
- A system without (full-fledged) OS, like an :term:`MCU`. When
- running on a baremetal system, MicroPython effectively becomes
- its user-facing OS with a command interpreter (REPL).
-
- board
- A PCB board. Oftentimes, the term is used to denote a particular
- model of an :term:`MCU` system. Sometimes, it is used to actually
- refer to :term:`MicroPython port` to a particular board (and then
- may also refer to "boardless" ports like
- :term:`Unix port <MicroPython Unix port>`).
-
- CPython
- CPython is the reference implementation of Python programming
- language, and the most well-known one, which most of the people
- run. It is however one of many implementations (among which
- Jython, IronPython, PyPy, and many more, including MicroPython).
- As there is no formal specification of the Python language, only
- CPython documentation, it is not always easy to draw a line
- between Python the language and CPython its particular
- implementation. This however leaves more freedom for other
- implementations. For example, MicroPython does a lot of things
- differently than CPython, while still aspiring to be a Python
- language implementation.
-
- GPIO
- General-purpose input/output. The simplest means to control
- electrical signals. With GPIO, user can configure hardware
- signal pin to be either input or output, and set or get
- its digital signal value (logical "0" or "1"). MicroPython
- abstracts GPIO access using :class:`machine.Pin` and :class:`machine.Signal`
- classes.
-
- GPIO port
- A group of :term:`GPIO` pins, usually based on hardware
- properties of these pins (e.g. controllable by the same
- register).
-
- MCU
- Microcontroller. Microcontrollers usually have much less resources
- than a full-fledged computing system, but smaller, cheaper and
- require much less power. MicroPython is designed to be small and
- optimized enough to run on an average modern microcontroller.
-
- micropython-lib
- MicroPython is (usually) distributed as a single executable/binary
- file with just few builtin modules. There is no extensive standard
- library comparable with :term:`CPython`. Instead, there is a related, but
- separate project
- `micropython-lib <https://github.com/micropython/micropython-lib>`_
- which provides implementations for many modules from CPython's
- standard library. However, large subset of these modules require
- POSIX-like environment (Linux, MacOS, Windows may be partially
- supported), and thus would work or make sense only with
- `MicroPython Unix port`. Some subset of modules is however usable
- for `baremetal` ports too.
-
- Unlike monolithic :term:`CPython` stdlib, micropython-lib modules
- are intended to be installed individually - either using manual
- copying or using :term:`upip`.
-
- MicroPython port
- MicroPython supports different :term:`boards <board>`, RTOSes,
- and OSes, and can be relatively easily adapted to new systems.
- MicroPython with support for a particular system is called a
- "port" to that system. Different ports may have widely different
- functionality. This documentation is intended to be a reference
- of the generic APIs available across different ports ("MicroPython
- core"). Note that some ports may still omit some APIs described
- here (e.g. due to resource constraints). Any such differences,
- and port-specific extensions beyond MicroPython core functionality,
- would be described in the separate port-specific documentation.
-
- MicroPython Unix port
- Unix port is one of the major :term:`MicroPython ports <MicroPython port>`.
- It is intended to run on POSIX-compatible operating systems, like
- Linux, MacOS, FreeBSD, Solaris, etc. It also serves as the basis
- of Windows port. The importance of Unix port lies in the fact
- that while there are many different :term:`boards <board>`, so
- two random users unlikely have the same board, almost all modern
- OSes have some level of POSIX compatibility, so Unix port serves
- as a kind of "common ground" to which any user can have access.
- So, Unix port is used for initial prototyping, different kinds
- of testing, development of machine-independent features, etc.
- All users of MicroPython, even those which are interested only
- in running MicroPython on :term:`MCU` systems, are recommended
- to be familiar with Unix (or Windows) port, as it is important
- productivity helper and a part of normal MicroPython workflow.
-
- port
- Either :term:`MicroPython port` or :term:`GPIO port`. If not clear
- from context, it's recommended to use full specification like one
- of the above.
-
- upip
- (Literally, "micro pip"). A package manage for MicroPython, inspired
- by :term:`CPython`'s pip, but much smaller and with reduced functionality.
- upip runs both on :term:`Unix port <MicroPython Unix port>` and on
- :term:`baremetal` ports (those which offer filesystem and networking
- support).
diff --git a/docs/reference/index.rst b/docs/reference/index.rst
deleted file mode 100644
index 4d822d6fa..000000000
--- a/docs/reference/index.rst
+++ /dev/null
@@ -1,33 +0,0 @@
-The MicroPython language
-========================
-
-MicroPython aims to implement the Python 3.4 standard (with selected
-features from later versions) with respect to language syntax, and most
-of the features of MicroPython are identical to those described by the
-"Language Reference" documentation at
-`docs.python.org <https://docs.python.org/3/reference/index.html>`_.
-
-The MicroPython standard library is described in the
-:ref:`corresponding chapter <micropython_lib>`. The :ref:`cpython_diffs`
-chapter describes differences between MicroPython and CPython (which
-mostly concern standard library and types, but also some language-level
-features).
-
-This chapter describes features and peculiarities of MicroPython
-implementation and the best practices to use them.
-
-.. toctree::
- :maxdepth: 1
-
- glossary.rst
- repl.rst
- isr_rules.rst
- speed_python.rst
- constrained.rst
-
-.. only:: port_pyboard
-
- .. toctree::
- :maxdepth: 1
-
- asm_thumb2_index.rst
diff --git a/docs/reference/isr_rules.rst b/docs/reference/isr_rules.rst
deleted file mode 100644
index 2db261c09..000000000
--- a/docs/reference/isr_rules.rst
+++ /dev/null
@@ -1,353 +0,0 @@
-.. _isr_rules:
-
-Writing interrupt handlers
-==========================
-
-On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers
-- also known as interrupt service routines (ISR's) - are defined as callback functions. These are executed
-in response to an event such as a timer trigger or a voltage change on a pin. Such events can occur at any point
-in the execution of the program code. This carries significant consequences, some specific to the MicroPython
-language. Others are common to all systems capable of responding to real time events. This document covers
-the language specific issues first, followed by a brief introduction to real time programming for those new to it.
-
-This introduction uses vague terms like "slow" or "as fast as possible". This is deliberate, as speeds are
-application dependent. Acceptable durations for an ISR are dependent on the rate at which interrupts occur,
-the nature of the main program, and the presence of other concurrent events.
-
-Tips and recommended practices
-------------------------------
-
-This summarises the points detailed below and lists the principal recommendations for interrupt handler code.
-
-* Keep the code as short and simple as possible.
-* Avoid memory allocation: no appending to lists or insertion into dictionaries, no floating point.
-* Consider using ``micropython.schedule`` to work around the above constraint.
-* Where an ISR returns multiple bytes use a pre-allocated ``bytearray``. If multiple integers are to be
- shared between an ISR and the main program consider an array (``array.array``).
-* Where data is shared between the main program and an ISR, consider disabling interrupts prior to accessing
- the data in the main program and re-enabling them immediately afterwards (see Critical Sections).
-* Allocate an emergency exception buffer (see below).
-
-
-MicroPython Issues
-------------------
-
-The emergency exception buffer
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If an error occurs in an ISR, MicroPython is unable to produce an error report unless a special buffer is created
-for the purpose. Debugging is simplified if the following code is included in any program using interrupts.
-
-.. code:: python
-
- import micropython
- micropython.alloc_emergency_exception_buf(100)
-
-Simplicity
-~~~~~~~~~~
-
-For a variety of reasons it is important to keep ISR code as short and simple as possible. It should do only what
-has to be done immediately after the event which caused it: operations which can be deferred should be delegated
-to the main program loop. Typically an ISR will deal with the hardware device which caused the interrupt, making
-it ready for the next interrupt to occur. It will communicate with the main loop by updating shared data to indicate
-that the interrupt has occurred, and it will return. An ISR should return control to the main loop as quickly
-as possible. This is not a specific MicroPython issue so is covered in more detail :ref:`below <ISR>`.
-
-Communication between an ISR and the main program
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Normally an ISR needs to communicate with the main program. The simplest means of doing this is via one or more
-shared data objects, either declared as global or shared via a class (see below). There are various restrictions
-and hazards around doing this, which are covered in more detail below. Integers, ``bytes`` and ``bytearray`` objects
-are commonly used for this purpose along with arrays (from the array module) which can store various data types.
-
-The use of object methods as callbacks
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-MicroPython supports this powerful technique which enables an ISR to share instance variables with the underlying
-code. It also enables a class implementing a device driver to support multiple device instances. The following
-example causes two LED's to flash at different rates.
-
-.. code:: python
-
- import pyb, micropython
- micropython.alloc_emergency_exception_buf(100)
- class Foo(object):
- def __init__(self, timer, led):
- self.led = led
- timer.callback(self.cb)
- def cb(self, tim):
- self.led.toggle()
-
- red = Foo(pyb.Timer(4, freq=1), pyb.LED(1))
- green = Foo(pyb.Timer(2, freq=0.8), pyb.LED(2))
-
-In this example the ``red`` instance associates timer 4 with LED 1: when a timer 4 interrupt occurs ``red.cb()``
-is called causing LED 1 to change state. The ``green`` instance operates similarly: a timer 2 interrupt
-results in the execution of ``green.cb()`` and toggles LED 2. The use of instance methods confers two
-benefits. Firstly a single class enables code to be shared between multiple hardware instances. Secondly, as
-a bound method the callback function's first argument is ``self``. This enables the callback to access instance
-data and to save state between successive calls. For example, if the class above had a variable ``self.count``
-set to zero in the constructor, ``cb()`` could increment the counter. The ``red`` and ``green`` instances would
-then maintain independent counts of the number of times each LED had changed state.
-
-Creation of Python objects
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-ISR's cannot create instances of Python objects. This is because MicroPython needs to allocate memory for the
-object from a store of free memory block called the heap. This is not permitted in an interrupt handler because
-heap allocation is not re-entrant. In other words the interrupt might occur when the main program is part way
-through performing an allocation - to maintain the integrity of the heap the interpreter disallows memory
-allocations in ISR code.
-
-A consequence of this is that ISR's can't use floating point arithmetic; this is because floats are Python objects. Similarly
-an ISR can't append an item to a list. In practice it can be hard to determine exactly which code constructs will
-attempt to perform memory allocation and provoke an error message: another reason for keeping ISR code short and simple.
-
-One way to avoid this issue is for the ISR to use pre-allocated buffers. For example a class constructor
-creates a ``bytearray`` instance and a boolean flag. The ISR method assigns data to locations in the buffer and sets
-the flag. The memory allocation occurs in the main program code when the object is instantiated rather than in the ISR.
-
-The MicroPython library I/O methods usually provide an option to use a pre-allocated buffer. For
-example ``pyb.i2c.recv()`` can accept a mutable buffer as its first argument: this enables its use in an ISR.
-
-A means of creating an object without employing a class or globals is as follows:
-
-.. code:: python
-
- def set_volume(t, buf=bytearray(3)):
- buf[0] = 0xa5
- buf[1] = t >> 4
- buf[2] = 0x5a
- return buf
-
-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).
-
-Use of Python objects
-~~~~~~~~~~~~~~~~~~~~~
-
-A further restriction on objects arises because of the way Python works. When an ``import`` statement is executed the
-Python code is compiled to bytecode, with one line of code typically mapping to multiple bytecodes. When the code
-runs the interpreter reads each bytecode and executes it as a series of machine code instructions. Given that an
-interrupt can occur at any time between machine code instructions, the original line of Python code may be only
-partially executed. Consequently a Python object such as a set, list or dictionary modified in the main loop
-may lack internal consistency at the moment the interrupt occurs.
-
-A typical outcome is as follows. On rare occasions the ISR will run at the precise moment in time when the object
-is partially updated. When the ISR tries to read the object, a crash results. Because such problems typically occur
-on rare, random occasions they can be hard to diagnose. There are ways to circumvent this issue, described in
-:ref:`Critical Sections <Critical>` below.
-
-It is important to be clear about what constitutes the modification of an object. An alteration to a built-in type
-such as a dictionary is problematic. Altering the contents of an array or bytearray is not. This is because bytes
-or words are written as a single machine code instruction which is not interruptible: in the parlance of real time
-programming the write is atomic. A user defined object might instantiate an integer, array or bytearray. It is valid
-for both the main loop and the ISR to alter the contents of these.
-
-MicroPython supports integers of arbitrary precision. Values between 2**30 -1 and -2**30 will be stored in
-a single machine word. Larger values are stored as Python objects. Consequently changes to long integers cannot
-be considered atomic. The use of long integers in ISR's is unsafe because memory allocation may be
-attempted as the variable's value changes.
-
-Overcoming the float limitation
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-In general it is best to avoid using floats in ISR code: hardware devices normally handle integers and conversion
-to floats is normally done in the main loop. However there are a few DSP algorithms which require floating point.
-On platforms with hardware floating point (such as the Pyboard) the inline ARM Thumb assembler can be used to work
-round this limitation. This is because the processor stores float values in a machine word; values can be shared
-between the ISR and main program code via an array of floats.
-
-Using micropython.schedule
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This function enables an ISR to schedule a callback for execution "very soon". The callback is queued for
-execution which will take place at a time when the heap is not locked. Hence it can create Python objects
-and use floats. The callback is also guaranteed to run at a time when the main program has completed any
-update of Python objects, so the callback will not encounter partially updated objects.
-
-Typical usage is to handle sensor hardware. The ISR acquires data from the hardware and enables it to
-issue a further interrupt. It then schedules a callback to process the data.
-
-Scheduled callbacks should comply with the principles of interrupt handler design outlined below. This is to
-avoid problems resulting from I/O activity and the modification of shared data which can arise in any code
-which pre-empts the main program loop.
-
-Execution time needs to be considered in relation to the frequency with which interrupts can occur. If an
-interrupt occurs while the previous callback is executing, a further instance of the callback will be queued
-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``.
-
-Exceptions
-----------
-
-If an ISR raises an exception it will not propagate to the main loop. The interrupt will be disabled unless the
-exception is handled by the ISR code.
-
-General Issues
---------------
-
-This is merely a brief introduction to the subject of real time programming. Beginners should note
-that design errors in real time programs can lead to faults which are particularly hard to diagnose. This is because
-they can occur rarely and at intervals which are essentially random. It is crucial to get the initial design right and
-to anticipate issues before they arise. Both interrupt handlers and the main program need to be designed
-with an appreciation of the following issues.
-
-.. _ISR:
-
-Interrupt Handler Design
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-As mentioned above, ISR's should be designed to be as simple as possible. They should always return in a short,
-predictable period of time. This is important because when the ISR is running, the main loop is not: inevitably
-the main loop experiences pauses in its execution at random points in the code. Such pauses can be a source of hard
-to diagnose bugs particularly if their duration is long or variable. In order to understand the implications of
-ISR run time, a basic grasp of interrupt priorities is required.
-
-Interrupts are organised according to a priority scheme. ISR code may itself be interrupted by a higher priority
-interrupt. This has implications if the two interrupts share data (see Critical Sections below). If such an interrupt
-occurs it interposes a delay into the ISR code. If a lower priority interrupt occurs while the ISR is running, it
-will be delayed until the ISR is complete: if the delay is too long, the lower priority interrupt may fail. A
-further issue with slow ISR's is the case where a second interrupt of the same type occurs during its execution.
-The second interrupt will be handled on termination of the first. However if the rate of incoming interrupts
-consistently exceeds the capacity of the ISR to service them the outcome will not be a happy one.
-
-Consequently looping constructs should be avoided or minimised. I/O to devices other than to the interrupting device
-should normally be avoided: I/O such as disk access, ``print`` statements and UART access is relatively slow, and
-its duration may vary. A further issue here is that filesystem functions are not reentrant: using filesystem I/O
-in an ISR and the main program would be hazardous. Crucially ISR code should not wait on an event. I/O is acceptable
-if the code can be guaranteed to return in a predictable period, for example toggling a pin or LED. Accessing the
-interrupting device via I2C or SPI may be necessary but the time taken for such accesses should be calculated or
-measured and its impact on the application assessed.
-
-There is usually a need to share data between the ISR and the main loop. This may be done either through global
-variables or via class or instance variables. Variables are typically integer or boolean types, or integer or byte
-arrays (a pre-allocated integer array offers faster access than a list). Where multiple values are modified by
-the ISR it is necessary to consider the case where the interrupt occurs at a time when the main program has
-accessed some, but not all, of the values. This can lead to inconsistencies.
-
-Consider the following design. An ISR stores incoming data in a bytearray, then adds the number of bytes
-received to an integer representing total bytes ready for processing. The main program reads the number of bytes,
-processes the bytes, then clears down the number of bytes ready. This will work until an interrupt occurs just
-after the main program has read the number of bytes. The ISR puts the added data into the buffer and updates
-the number received, but the main program has already read the number, so processes the data originally received.
-The newly arrived bytes are lost.
-
-There are various ways of avoiding this hazard, the simplest being to use a circular buffer. If it is not possible
-to use a structure with inherent thread safety other ways are described below.
-
-Reentrancy
-~~~~~~~~~~
-
-A potential hazard may occur if a function or method is shared between the main program and one or more ISR's or
-between multiple ISR's. The issue here is that the function may itself be interrupted and a further instance of
-that function run. If this is to occur, the function must be designed to be reentrant. How this is done is an
-advanced topic beyond the scope of this tutorial.
-
-.. _Critical:
-
-Critical Sections
-~~~~~~~~~~~~~~~~~
-
-An example of a critical section of code is one which accesses more than one variable which can be affected by an ISR. If
-the interrupt happens to occur between accesses to the individual variables, their values will be inconsistent. This is
-an instance of a hazard known as a race condition: the ISR and the main program loop race to alter the variables. To
-avoid inconsistency a means must be employed to ensure that the ISR does not alter the values for the duration of
-the critical section. One way to achieve this is to issue ``pyb.disable_irq()`` before the start of the section, and
-``pyb.enable_irq()`` at the end. Here is an example of this approach:
-
-.. code:: python
-
- import pyb, micropython, array
- micropython.alloc_emergency_exception_buf(100)
-
- class BoundsException(Exception):
- pass
-
- ARRAYSIZE = const(20)
- index = 0
- data = array.array('i', 0 for x in range(ARRAYSIZE))
-
- def callback1(t):
- global data, index
- for x in range(5):
- data[index] = pyb.rng() # simulate input
- index += 1
- if index >= ARRAYSIZE:
- raise BoundsException('Array bounds exceeded')
-
- tim4 = pyb.Timer(4, freq=100, callback=callback1)
-
- for loop in range(1000):
- if index > 0:
- irq_state = pyb.disable_irq() # Start of critical section
- for x in range(index):
- print(data[x])
- index = 0
- pyb.enable_irq(irq_state) # End of critical section
- print('loop {}'.format(loop))
- pyb.delay(1)
-
- tim4.callback(None)
-
-A critical section can comprise a single line of code and a single variable. Consider the following code fragment.
-
-.. code:: python
-
- count = 0
- def cb(): # An interrupt callback
- count +=1
- def main():
- # Code to set up the interrupt callback omitted
- while True:
- count += 1
-
-This example illustrates a subtle source of bugs. The line ``count += 1`` in the main loop carries a specific race
-condition hazard known as a read-modify-write. This is a classic cause of bugs in real time systems. In the main loop
-MicroPython reads the value of ``t.counter``, adds 1 to it, and writes it back. On rare occasions the interrupt occurs
-after the read and before the write. The interrupt modifies ``t.counter`` but its change is overwritten by the main
-loop when the ISR returns. In a real system this could lead to rare, unpredictable failures.
-
-As mentioned above, care should be taken if an instance of a Python built in type is modified in the main code and
-that instance is accessed in an ISR. The code performing the modification should be regarded as a critical
-section to ensure that the instance is in a valid state when the ISR runs.
-
-Particular care needs to be taken if a dataset is shared between different ISR's. The hazard here is that the higher
-priority interrupt may occur when the lower priority one has partially updated the shared data. Dealing with this
-situation is an advanced topic beyond the scope of this introduction other than to note that mutex objects described
-below can sometimes be used.
-
-Disabling interrupts for the duration of a critical section is the usual and simplest way to proceed, but it disables
-all interrupts rather than merely the one with the potential to cause problems. It is generally undesirable to disable
-an interrupt for long. In the case of timer interrupts it introduces variability to the time when a callback occurs.
-In the case of device interrupts, it can lead to the device being serviced too late with possible loss of data or
-overrun errors in the device hardware. Like ISR's, a critical section in the main code should have a short, predictable
-duration.
-
-An approach to dealing with critical sections which radically reduces the time for which interrupts are disabled is to
-use an object termed a mutex (name derived from the notion of mutual exclusion). The main program locks the mutex
-before running the critical section and unlocks it at the end. The ISR tests whether the mutex is locked. If it is,
-it avoids the critical section and returns. The design challenge is defining what the ISR should do in the event
-that access to the critical variables is denied. A simple example of a mutex may be found
-`here <https://github.com/peterhinch/micropython-samples.git>`_. Note that the mutex code does disable interrupts,
-but only for the duration of eight machine instructions: the benefit of this approach is that other interrupts are
-virtually unaffected.
-
-Interrupts and the REPL
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Interrupt handlers, such as those associated with timers, can continue to run
-after a program terminates. This may produce unexpected results where you might
-have expected the object raising the callback to have gone out of scope. For
-example on the Pyboard:
-
-.. code:: python
-
- def bar():
- foo = pyb.Timer(2, freq=4, callback=lambda t: print('.', end=''))
-
- bar()
-
-This continues to run until the timer is explicitly disabled or the board is
-reset with ``ctrl D``.
diff --git a/docs/reference/repl.rst b/docs/reference/repl.rst
deleted file mode 100644
index 7a683ca22..000000000
--- a/docs/reference/repl.rst
+++ /dev/null
@@ -1,211 +0,0 @@
-The MicroPython Interactive Interpreter Mode (aka REPL)
-=======================================================
-
-This section covers some characteristics of the MicroPython Interactive
-Interpreter Mode. A commonly used term for this is REPL (read-eval-print-loop)
-which will be used to refer to this interactive prompt.
-
-Auto-indent
------------
-
-When typing python statements which end in a colon (for example if, for, while)
-then the prompt will change to three dots (...) and the cursor will be indented
-by 4 spaces. When you press return, the next line will continue at the same
-level of indentation for regular statements or an additional level of indentation
-where appropriate. If you press the backspace key then it will undo one
-level of indentation.
-
-If your cursor is all the way back at the beginning, pressing RETURN will then
-execute the code that you've entered. The following shows what you'd see
-after entering a for statement (the underscore shows where the cursor winds up):
-
- >>> for i in range(3):
- ... _
-
-If you then enter an if statement, an additional level of indentation will be
-provided:
-
- >>> for i in range(30):
- ... if i > 3:
- ... _
-
-Now enter ``break`` followed by RETURN and press BACKSPACE:
-
- >>> for i in range(30):
- ... if i > 3:
- ... break
- ... _
-
-Finally type ``print(i)``, press RETURN, press BACKSPACE and press RETURN again:
-
- >>> for i in range(30):
- ... if i > 3:
- ... break
- ... print(i)
- ...
- 0
- 1
- 2
- 3
- >>>
-
-Auto-indent won't be applied if the previous two lines were all spaces. This
-means that you can finish entering a compound statement by pressing RETURN
-twice, and then a third press will finish and execute.
-
-Auto-completion
----------------
-
-While typing a command at the REPL, if the line typed so far corresponds to
-the beginning of the name of something, then pressing TAB will show
-possible things that could be entered. For example type ``m`` and press TAB
-and it should expand to ``machine``. Enter a dot ``.`` and press TAB again. You
-should see something like:
-
- >>> machine.
- __name__ info unique_id reset
- bootloader freq rng idle
- sleep deepsleep disable_irq enable_irq
- Pin
-
-The word will be expanded as much as possible until multiple possibilities exist.
-For example, type ``machine.Pin.AF3`` and press TAB and it will expand to
-``machine.Pin.AF3_TIM``. Pressing TAB a second time will show the possible
-expansions:
-
- >>> machine.Pin.AF3_TIM
- AF3_TIM10 AF3_TIM11 AF3_TIM8 AF3_TIM9
- >>> machine.Pin.AF3_TIM
-
-Interrupting a running program
-------------------------------
-
-You can interrupt a running program by pressing Ctrl-C. This will raise a KeyboardInterrupt
-which will bring you back to the REPL, providing your program doesn't intercept the
-KeyboardInterrupt exception.
-
-For example:
-
- >>> for i in range(1000000):
- ... print(i)
- ...
- 0
- 1
- 2
- 3
- ...
- 6466
- 6467
- 6468
- Traceback (most recent call last):
- File "<stdin>", line 2, in <module>
- KeyboardInterrupt:
- >>>
-
-Paste Mode
-----------
-
-If you want to paste some code into your terminal window, the auto-indent feature
-will mess things up. For example, if you had the following python code: ::
-
- def foo():
- print('This is a test to show paste mode')
- print('Here is a second line')
- foo()
-
-and you try to paste this into the normal REPL, then you will see something like
-this:
-
- >>> def foo():
- ... print('This is a test to show paste mode')
- ... print('Here is a second line')
- ... foo()
- ...
- Traceback (most recent call last):
- File "<stdin>", line 3
- IndentationError: unexpected indent
-
-If you press Ctrl-E, then you will enter paste mode, which essentially turns off
-the auto-indent feature, and changes the prompt from ``>>>`` to ``===``. For example:
-
- >>>
- paste mode; Ctrl-C to cancel, Ctrl-D to finish
- === def foo():
- === print('This is a test to show paste mode')
- === print('Here is a second line')
- === foo()
- ===
- This is a test to show paste mode
- Here is a second line
- >>>
-
-Paste Mode allows blank lines to be pasted. The pasted text is compiled as if
-it were a file. Pressing Ctrl-D exits paste mode and initiates the compilation.
-
-Soft Reset
-----------
-
-A soft reset will reset the python interpreter, but tries not to reset the
-method by which you're connected to the MicroPython board (USB-serial, or Wifi).
-
-You can perform a soft reset from the REPL by pressing Ctrl-D, or from your python
-code by executing: ::
-
- raise SystemExit
-
-For example, if you reset your MicroPython board, and you execute a dir()
-command, you'd see something like this:
-
- >>> dir()
- ['__name__', 'pyb']
-
-Now create some variables and repeat the dir() command:
-
- >>> i = 1
- >>> j = 23
- >>> x = 'abc'
- >>> dir()
- ['j', 'x', '__name__', 'pyb', 'i']
- >>>
-
-Now if you enter Ctrl-D, and repeat the dir() command, you'll see that your
-variables no longer exist:
-
-.. code-block:: python
-
- PYB: sync filesystems
- PYB: soft reboot
- MicroPython v1.5-51-g6f70283-dirty on 2015-10-30; PYBv1.0 with STM32F405RG
- Type "help()" for more information.
- >>> dir()
- ['__name__', 'pyb']
- >>>
-
-The special variable _ (underscore)
------------------------------------
-
-When you use the REPL, you may perform computations and see the results.
-MicroPython stores the results of the previous statement in the variable _ (underscore).
-So you can use the underscore to save the result in a variable. For example:
-
- >>> 1 + 2 + 3 + 4 + 5
- 15
- >>> x = _
- >>> x
- 15
- >>>
-
-Raw Mode
---------
-
-Raw mode is not something that a person would normally use. It is intended for
-programmatic use. It essentially behaves like paste mode with echo turned off.
-
-Raw mode is entered using Ctrl-A. You then send your python code, followed by
-a Ctrl-D. The Ctrl-D will be acknowledged by 'OK' and then the python code will
-be compiled and executed. Any output (or errors) will be sent back. Entering
-Ctrl-B will leave raw mode and return the the regular (aka friendly) REPL.
-
-The ``tools/pyboard.py`` program uses the raw REPL to execute python files on the
-MicroPython board.
-
diff --git a/docs/reference/speed_python.rst b/docs/reference/speed_python.rst
deleted file mode 100644
index 279a1bbcd..000000000
--- a/docs/reference/speed_python.rst
+++ /dev/null
@@ -1,342 +0,0 @@
-Maximising MicroPython Speed
-============================
-
-.. contents::
-
-This tutorial describes ways of improving the performance of MicroPython code.
-Optimisations involving other languages are covered elsewhere, namely the use
-of modules written in C and the MicroPython inline assembler.
-
-The process of developing high performance code comprises the following stages
-which should be performed in the order listed.
-
-* Design for speed.
-* Code and debug.
-
-Optimisation steps:
-
-* Identify the slowest section of code.
-* Improve the efficiency of the Python code.
-* Use the native code emitter.
-* Use the viper code emitter.
-* Use hardware-specific optimisations.
-
-Designing for speed
--------------------
-
-Performance issues should be considered at the outset. This involves taking a view
-on the sections of code which are most performance critical and devoting particular
-attention to their design. The process of optimisation begins when the code has
-been tested: if the design is correct at the outset optimisation will be
-straightforward and may actually be unnecessary.
-
-Algorithms
-~~~~~~~~~~
-
-The most important aspect of designing any routine for performance is ensuring that
-the best algorithm is employed. This is a topic for textbooks rather than for a
-MicroPython guide but spectacular performance gains can sometimes be achieved
-by adopting algorithms known for their efficiency.
-
-RAM Allocation
-~~~~~~~~~~~~~~
-
-To design efficient MicroPython code it is necessary to have an understanding of the
-way the interpreter allocates RAM. When an object is created or grows in size
-(for example where an item is appended to a list) the necessary RAM is allocated
-from a block known as the heap. This takes a significant amount of time;
-further it will on occasion trigger a process known as garbage collection which
-can take several milliseconds.
-
-Consequently the performance of a function or method can be improved if an object is created
-once only and not permitted to grow in size. This implies that the object persists
-for the duration of its use: typically it will be instantiated in a class constructor
-and used in various methods.
-
-This is covered in further detail :ref:`Controlling garbage collection <controlling_gc>` below.
-
-Buffers
-~~~~~~~
-
-An example of the above is the common case where a buffer is required, such as one
-used for communication with a device. A typical driver will create the buffer in the
-constructor and use it in its I/O methods which will be called repeatedly.
-
-The MicroPython libraries typically provide support for pre-allocated buffers. For
-example, objects which support stream interface (e.g., file or UART) provide `read()`
-method which allocates new buffer for read data, but also a `readinto()` method
-to read data into an existing buffer.
-
-Floating Point
-~~~~~~~~~~~~~~
-
-Some MicroPython ports allocate floating point numbers on heap. Some other ports
-may lack dedicated floating-point coprocessor, and perform arithmetic operations
-on them in "software" at considerably lower speed than on integers. Where
-performance is important, use integer operations and restrict the use of floating
-point to sections of the code where performance is not paramount. For example,
-capture ADC readings as integers values to an array in one quick go, and only then
-convert them to floating-point numbers for signal processing.
-
-Arrays
-~~~~~~
-
-Consider the use of the various types of array classes as an alternative to lists.
-The `array` module supports various element types with 8-bit elements supported
-by Python's built in `bytes` and `bytearray` classes. These data structures all store
-elements in contiguous memory locations. Once again to avoid memory allocation in critical
-code these should be pre-allocated and passed as arguments or as bound objects.
-
-When passing slices of objects such as `bytearray` instances, Python creates
-a copy which involves allocation of the size proportional to the size of slice.
-This can be alleviated using a `memoryview` object. `memoryview` itself
-is allocated on heap, but is a small, fixed-size object, regardless of the size
-of slice it points too.
-
-.. code:: python
-
- ba = bytearray(10000) # big array
- func(ba[30:2000]) # a copy is passed, ~2K new allocation
- mv = memoryview(ba) # small object is allocated
- func(mv[30:2000]) # a pointer to memory is passed
-
-A `memoryview` can only be applied to objects supporting the buffer protocol - this
-includes arrays but not lists. Small caveat is that while memoryview object is live,
-it also keeps alive the original buffer object. So, a memoryview isn't a universal
-panacea. For instance, in the example above, if you are done with 10K buffer and
-just need those bytes 30:2000 from it, it may be better to make a slice, and let
-the 10K buffer go (be ready for garbage collection), instead of making a
-long-living memoryview and keeping 10K blocked for GC.
-
-Nonetheless, `memoryview` is indispensable for advanced preallocated buffer
-management. `readinto()` method discussed above puts data at the beginning
-of buffer and fills in entire buffer. What if you need to put data in the
-middle of existing buffer? Just create a memoryview into the needed section
-of buffer and pass it to `readinto()`.
-
-Identifying the slowest section of code
----------------------------------------
-
-This is a process known as profiling and is covered in textbooks and
-(for standard Python) supported by various software tools. For the type of
-smaller embedded application likely to be running on MicroPython platforms
-the slowest function or method can usually be established by judicious use
-of the timing ``ticks`` group of functions documented in `utime`.
-Code execution time can be measured in ms, us, or CPU cycles.
-
-The following enables any function or method to be timed by adding an
-``@timed_function`` decorator:
-
-.. code:: python
-
- def timed_function(f, *args, **kwargs):
- myname = str(f).split(' ')[1]
- def new_func(*args, **kwargs):
- t = utime.ticks_us()
- result = f(*args, **kwargs)
- delta = utime.ticks_diff(utime.ticks_us(), t)
- print('Function {} Time = {:6.3f}ms'.format(myname, delta/1000))
- return result
- return new_func
-
-MicroPython code improvements
------------------------------
-
-The const() declaration
-~~~~~~~~~~~~~~~~~~~~~~~
-
-MicroPython provides a ``const()`` declaration. This works in a similar way
-to ``#define`` in C in that when the code is compiled to bytecode the compiler
-substitutes the numeric value for the identifier. This avoids a dictionary
-lookup at runtime. The argument to ``const()`` may be anything which, at
-compile time, evaluates to an integer e.g. ``0x100`` or ``1 << 8``.
-
-.. _Caching:
-
-Caching object references
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Where a function or method repeatedly accesses objects performance is improved
-by caching the object in a local variable:
-
-.. code:: python
-
- class foo(object):
- def __init__(self):
- ba = bytearray(100)
- def bar(self, obj_display):
- ba_ref = self.ba
- fb = obj_display.framebuffer
- # iterative code using these two objects
-
-This avoids the need repeatedly to look up ``self.ba`` and ``obj_display.framebuffer``
-in the body of the method ``bar()``.
-
-.. _controlling_gc:
-
-Controlling garbage collection
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When memory allocation is required, MicroPython attempts to locate an adequately
-sized block on the heap. This may fail, usually because the heap is cluttered
-with objects which are no longer referenced by code. If a failure occurs, the
-process known as garbage collection reclaims the memory used by these redundant
-objects and the allocation is then tried again - a process which can take several
-milliseconds.
-
-There may be benefits in pre-empting this by periodically issuing `gc.collect()`.
-Firstly doing a collection before it is actually required is quicker - typically on the
-order of 1ms if done frequently. Secondly you can determine the point in code
-where this time is used rather than have a longer delay occur at random points,
-possibly in a speed critical section. Finally performing collections regularly
-can reduce fragmentation in the heap. Severe fragmentation can lead to
-non-recoverable allocation failures.
-
-The Native code emitter
------------------------
-
-This causes the MicroPython compiler to emit native CPU opcodes rather than
-bytecode. It covers the bulk of the MicroPython functionality, so most functions will require
-no adaptation (but see below). It is invoked by means of a function decorator:
-
-.. code:: python
-
- @micropython.native
- def foo(self, arg):
- buf = self.linebuf # Cached object
- # code
-
-There are certain limitations in the current implementation of the native code emitter.
-
-* Context managers are not supported (the ``with`` statement).
-* Generators are not supported.
-* If ``raise`` is used an argument must be supplied.
-
-The trade-off for the improved performance (roughly twices as fast as bytecode) is an
-increase in compiled code size.
-
-The Viper code emitter
-----------------------
-
-The optimisations discussed above involve standards-compliant Python code. The
-Viper code emitter is not fully compliant. It supports special Viper native data types
-in pursuit of performance. Integer processing is non-compliant because it uses machine
-words: arithmetic on 32 bit hardware is performed modulo 2**32.
-
-Like the Native emitter Viper produces machine instructions but further optimisations
-are performed, substantially increasing performance especially for integer arithmetic and
-bit manipulations. It is invoked using a decorator:
-
-.. code:: python
-
- @micropython.viper
- def foo(self, arg: int) -> int:
- # code
-
-As the above fragment illustrates it is beneficial to use Python type hints to assist the Viper optimiser.
-Type hints provide information on the data types of arguments and of the return value; these
-are a standard Python language feature formally defined here `PEP0484 <https://www.python.org/dev/peps/pep-0484/>`_.
-Viper supports its own set of types namely ``int``, ``uint`` (unsigned integer), ``ptr``, ``ptr8``,
-``ptr16`` and ``ptr32``. The ``ptrX`` types are discussed below. Currently the ``uint`` type serves
-a single purpose: as a type hint for a function return value. If such a function returns ``0xffffffff``
-Python will interpret the result as 2**32 -1 rather than as -1.
-
-In addition to the restrictions imposed by the native emitter the following constraints apply:
-
-* Functions may have up to four arguments.
-* Default argument values are not permitted.
-* Floating point may be used but is not optimised.
-
-Viper provides pointer types to assist the optimiser. These comprise
-
-* ``ptr`` Pointer to an object.
-* ``ptr8`` Points to a byte.
-* ``ptr16`` Points to a 16 bit half-word.
-* ``ptr32`` Points to a 32 bit machine word.
-
-The concept of a pointer may be unfamiliar to Python programmers. It has similarities
-to a Python `memoryview` object in that it provides direct access to data stored in memory.
-Items are accessed using subscript notation, but slices are not supported: a pointer can return
-a single item only. Its purpose is to provide fast random access to data stored in contiguous
-memory locations - such as data stored in objects which support the buffer protocol, and
-memory-mapped peripheral registers in a microcontroller. It should be noted that programming
-using pointers is hazardous: bounds checking is not performed and the compiler does nothing to
-prevent buffer overrun errors.
-
-Typical usage is to cache variables:
-
-.. code:: python
-
- @micropython.viper
- def foo(self, arg: int) -> int:
- buf = ptr8(self.linebuf) # self.linebuf is a bytearray or bytes object
- for x in range(20, 30):
- bar = buf[x] # Access a data item through the pointer
- # code omitted
-
-In this instance the compiler "knows" that ``buf`` is the address of an array of bytes;
-it can emit code to rapidly compute the address of ``buf[x]`` at runtime. Where casts are
-used to convert objects to Viper native types these should be performed at the start of
-the function rather than in critical timing loops as the cast operation can take several
-microseconds. The rules for casting are as follows:
-
-* Casting operators are currently: ``int``, ``bool``, ``uint``, ``ptr``, ``ptr8``, ``ptr16`` and ``ptr32``.
-* The result of a cast will be a native Viper variable.
-* Arguments to a cast can be a Python object or a native Viper variable.
-* If argument is a native Viper variable, then cast is a no-op (i.e. costs nothing at runtime)
- that just changes the type (e.g. from ``uint`` to ``ptr8``) so that you can then store/load
- using this pointer.
-* If the argument is a Python object and the cast is ``int`` or ``uint``, then the Python object
- must be of integral type and the value of that integral object is returned.
-* The argument to a bool cast must be integral type (boolean or integer); when used as a return
- type the viper function will return True or False objects.
-* If the argument is a Python object and the cast is ``ptr``, ``ptr``, ``ptr16`` or ``ptr32``,
- then the Python object must either have the buffer protocol with read-write capabilities
- (in which case a pointer to the start of the buffer is returned) or it must be of integral
- type (in which case the value of that integral object is returned).
-
-The following example illustrates the use of a ``ptr16`` cast to toggle pin X1 ``n`` times:
-
-.. code:: python
-
- BIT0 = const(1)
- @micropython.viper
- def toggle_n(n: int):
- odr = ptr16(stm.GPIOA + stm.GPIO_ODR)
- for _ in range(n):
- odr[0] ^= BIT0
-
-A detailed technical description of the three code emitters may be found
-on Kickstarter here `Note 1 <https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers/posts/664832>`_
-and here `Note 2 <https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers/posts/665145>`_
-
-Accessing hardware directly
----------------------------
-
-.. note::
-
- Code examples in this section are given for the Pyboard. The techniques
- described however may be applied to other MicroPython ports too.
-
-This comes into the category of more advanced programming and involves some knowledge
-of the target MCU. Consider the example of toggling an output pin on the Pyboard. The
-standard approach would be to write
-
-.. code:: python
-
- mypin.value(mypin.value() ^ 1) # mypin was instantiated as an output pin
-
-This involves the overhead of two calls to the `Pin` instance's :meth:`~machine.Pin.value()`
-method. This overhead can be eliminated by performing a read/write to the relevant bit
-of the chip's GPIO port output data register (odr). To facilitate this the ``stm``
-module provides a set of constants providing the addresses of the relevant registers.
-A fast toggle of pin ``P4`` (CPU pin ``A14``) - corresponding to the green LED -
-can be performed as follows:
-
-.. code:: python
-
- import machine
- import stm
-
- BIT14 = const(1 << 14)
- machine.mem16[stm.GPIOA + stm.GPIO_ODR] ^= BIT14