diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/develop/cmodules.rst | 163 | ||||
-rw-r--r-- | docs/develop/index.rst | 15 | ||||
-rw-r--r-- | docs/index.rst | 1 | ||||
-rw-r--r-- | docs/reference/cmodules.rst | 86 | ||||
-rw-r--r-- | docs/reference/index.rst | 8 |
5 files changed, 179 insertions, 94 deletions
diff --git a/docs/develop/cmodules.rst b/docs/develop/cmodules.rst new file mode 100644 index 000000000..c3de90a0f --- /dev/null +++ b/docs/develop/cmodules.rst @@ -0,0 +1,163 @@ +MicroPython external C modules +============================== + +When developing modules for use with MicroPython you may find you run into +limitations with the Python environment, often due to an inability to access +certain hardware resources or Python speed limitations. + +If your limitations can't be resolved with suggestions in :ref:`speed_python`, +writing some or all of your module in C is a viable option. + +If your module is designed to access or work with commonly available +hardware or libraries please consider implementing it inside the MicroPython +source tree alongside similar modules and submitting it as a pull request. +If however you're targeting obscure or proprietary systems it may make +more sense to keep this external to the main MicroPython repository. + +This chapter describes how to compile such external modules into the +MicroPython executable or firmware image. + + +Structure of an external C module +--------------------------------- + +A MicroPython user C module is a directory with the following files: + +* ``*.c`` and/or ``*.h`` source code files for your module. + + These will typically include the low level functionality being implemented and + the MicroPython binding functions to expose the functions and module(s). + + Currently the best reference for writing these functions/modules is + to find similar modules within the MicroPython tree and use them as examples. + +* ``micropython.mk`` contains the Makefile fragment for this module. + + ``$(USERMOD_DIR)`` is available in ``micropython.mk`` as the path to your + module directory. As it's redefined for each c module, is should be expanded + in your ``micropython.mk`` to a local make variable, + eg ``EXAMPLE_MOD_DIR := $(USERMOD_DIR)`` + + Your ``micropython.mk`` must add your modules C files relative to your + expanded copy of ``$(USERMOD_DIR)`` to ``SRC_USERMOD``, eg + ``SRC_USERMOD += $(EXAMPLE_MOD_DIR)/example.c`` + + If you have custom ``CFLAGS`` settings or include folders to define, these + should be added to ``CFLAGS_USERMOD``. + + See below for full usage example. + + +Basic Example +------------- + +This simple module named ``example`` provides a single function +``example.add_ints(a, b)`` which adds the two integer args together and returns +the result. + +Directory:: + + example/ + ├── example.c + └── micropython.mk + + +``example.c`` + +.. code-block:: c + + // Include required definitions first. + #include "py/obj.h" + #include "py/runtime.h" + #include "py/builtin.h" + + #define MODULE_EXAMPLE_ENABLED (1) + + // This is the function which will be called from Python as example.add_ints(a, b). + STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_tab_obj) { + // Extract the ints from the micropython input objects + int a = mp_obj_get_int(a_obj); + int b = mp_obj_get_int(b_obj); + + // Calculate the addition and convert to MicroPython object. + return mp_obj_new_int(a + b); + } + // Define a Python reference to the function above + STATIC MP_DEFINE_CONST_FUN_OBJ_1(example_add_ints_obj, example_add_ints); + + // Define all properties of the example module. + // Table entries are key/value pairs of the attribute name (a string) + // and the MicroPython object reference. + // All identifiers and strings are written as MP_QSTR_xxx and will be + // optimized to word-sized integers by the build system (interned strings). + STATIC const mp_rom_map_elem_t example_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example) }, + { MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) }, + }; + STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table); + + // Define module object. + const mp_obj_module_t example_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&example_module_globals, + }; + + // Register the module to make it available in Python + MP_REGISTER_MODULE(MP_QSTR_example, example_user_cmodule, MODULE_EXAMPLE_ENABLED); + + +``micropython.mk`` + +.. code-block:: make + + EXAMPLE_MOD_DIR := $(USERMOD_DIR) + + # Add all C files to SRC_USERMOD. + SRC_USERMOD += $(EXAMPLE_MOD_DIR)/example.c + + # We can add our module folder to include paths if needed + # This is not actually needed in this example. + CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR) + + +Compiling the cmodule into MicroPython +-------------------------------------- + +To build such a module, compile MicroPython (see `getting started +<https://github.com/micropython/micropython/wiki/Getting-Started>`_) with an +extra ``make`` flag named ``USER_C_MODULES`` set to the directory containing +all modules you want included (not to the module itself). For example: + + +Directory:: + + my_project/ + ├── modules/ + │ └──example/ + │ ├──example.c + │ └──micropython.mk + └── micropython/ + ├──ports/ + ... ├──stm32/ + ... + +Building for stm32 port: + +.. code-block:: bash + + cd my_project/micropython/ports/stm32 + make USER_C_MODULES=../../../modules all + + +Module usage in MicroPython +--------------------------- + +Once built into your copy of MicroPython, the module implemented +in ``example.c`` above can now be accessed in Python just +like any other builtin module, eg + +.. code-block:: python + + import example + print(example.add_ints(1, 3)) + # should display 4 diff --git a/docs/develop/index.rst b/docs/develop/index.rst new file mode 100644 index 000000000..6b7b3c391 --- /dev/null +++ b/docs/develop/index.rst @@ -0,0 +1,15 @@ +Developing and building MicroPython +=================================== + +This chapter describes modules (function and class libraries) which are built +into MicroPython. There are a few categories of such modules: + +This chapter describes some options for extending MicroPython in C. Note +that it doesn't aim to be a complete guide for developing with MicroPython. +See the `getting started guide +<https://github.com/micropython/micropython/wiki/Getting-Started>`_ for further information. + +.. toctree:: + :maxdepth: 1 + + cmodules.rst diff --git a/docs/index.rst b/docs/index.rst index 235185b6c..c0417c227 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,6 +6,7 @@ MicroPython documentation and references library/index.rst reference/index.rst genrst/index.rst + develop/index.rst license.rst pyboard/quickref.rst esp8266/quickref.rst diff --git a/docs/reference/cmodules.rst b/docs/reference/cmodules.rst deleted file mode 100644 index f361af4a3..000000000 --- a/docs/reference/cmodules.rst +++ /dev/null @@ -1,86 +0,0 @@ -Extending MicroPython with C -============================ - -Some specialized code would be unacceptably slow or needs to access hardware in -a way that cannot be done from MicroPython. Therefore, it supports a way of -extending the language with custom modules written in C. But before you consider -writing a module in C, please take a look at :ref:`speed_python`. - -`Unlike CPython <https://docs.python.org/3/extending/building.html>`_, these -modules are (currently) embedded directly in the program image instead of being -dynamically loaded. This requires a `custom build of MicroPython -<https://github.com/micropython/micropython/wiki/Getting-Started>`_. - - -Writing a module ----------------- - -A module is a directory with the following files: - - * ``micropython.mk``, which contains the Makefile fragment for this module. - * All C files you would like included. - -Put the required build commands in ``micropython.mk``. For a simple module, you -will only have to add the file paths to ``SRC_MOD``, which will include these C -files in the build: - -.. highlight:: make -.. code:: - - # Add all C files to SRC_MOD. - SRC_MOD += $(USER_C_MODULES)/example/example.c - -This is a very bare bones module named ``example`` that provides -``example.double(x)``. Note that the name of the module must be equal to the -directory name and is also used in the name of the ``mp_obj_module_t`` object at -the bottom. - -.. highlight:: c -.. code:: - - // Include required definitions first. - #include "py/obj.h" - #include "py/runtime.h" - - // This is the function you will call using example.double(n). - STATIC mp_obj_t example_double(mp_obj_t x_obj) { - // Check input value and convert it to a C type. - if (!MP_OBJ_IS_SMALL_INT(x_obj)) { - mp_raise_ValueError("x is not a small int"); - } - int x = mp_obj_int_get_truncated(x_obj); - - // Calculate the double, and convert back to MicroPython object. - return mp_obj_new_int(x + x); - } - STATIC MP_DEFINE_CONST_FUN_OBJ_1(example_double_obj, example_double); - - // Define all properties of the example module, which currently are the name (a - // string) and a function. - // All identifiers and strings are written as MP_QSTR_xxx and will be - // optimized to word-sized integers by the build system (interned strings). - STATIC const mp_rom_map_elem_t example_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example) }, - { MP_ROM_QSTR(MP_QSTR_double), MP_ROM_PTR(&example_double_obj) }, - }; - STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table); - - // Define module object. - const mp_obj_module_t example_user_cmodule = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&example_module_globals, - }; - - -Using a module --------------- - -To build such a module, compile MicroPython (see `getting started -<https://github.com/micropython/micropython/wiki/Getting-Started>`_) with an -extra ``make`` flag named ``USER_C_MODULES`` set to the directory containing -all modules you want included (not to the module itself!). For example: - -.. highlight:: shell -.. code:: - - $ make USER_C_MODULES=path-to-modules-folder all diff --git a/docs/reference/index.rst b/docs/reference/index.rst index e2e08a7f7..d0c7f69de 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -26,11 +26,3 @@ implementation and the best practices to use them. constrained.rst packages.rst asm_thumb2_index.rst - cmodules.rst - -.. only:: port_pyboard - - .. toctree:: - :maxdepth: 1 - - asm_thumb2_index.rst |