|
1 |
| -What is py-esp32-ulp? |
2 |
| ---------------------- |
| 1 | +===================== |
| 2 | +py-esp32-ulp |
| 3 | +===================== |
3 | 4 |
|
4 |
| -It is an assembler toolchain for the ESP32 ULP (Ultra Low-Power) Co-Processor, |
5 |
| -written in MicroPython. |
| 5 | +py-esp32-ulp is an assembler toolchain for the ESP32 ULP (Ultra Low-Power) |
| 6 | +Co-Processor, written in MicroPython. |
6 | 7 |
|
7 |
| -It is able to translate small, simple assembler language programs to a |
8 |
| -loadable/executable machine code binary, at runtime, on the ESP32 |
9 |
| -microcontroller, from projects implemented in MicroPython. |
| 8 | +It can translate small assembly language programs to a loadable/executable |
| 9 | +ULP machine code binary, directly on the ESP32 microcontroller. |
10 | 10 |
|
11 |
| -This is intended as an alternative approach to assembling such programs on a |
12 |
| -development machine using the binutils-esp32ulp toolchain from Espressif. |
| 11 | +This is intended as an alternative approach to assembling such programs using |
| 12 | +the binutils-esp32ulp toolchain from Espressif on a development machine. |
13 | 13 |
|
14 | 14 |
|
15 |
| -Status |
16 |
| ------- |
| 15 | +Installation |
| 16 | +------------ |
17 | 17 |
|
18 |
| -The most commonly used stuff should work. Many ULP code examples found on |
19 |
| -the web will work unmodified. Notably, assembler macros and #include processing |
20 |
| -are not supported. |
| 18 | +On the ESP32, install using upip: |
21 | 19 |
|
22 |
| -Expressions in assembly source code are supported and get evaluated during |
23 |
| -assembling. Only expressions evaluating to a single integer are supported. |
24 |
| -Constants defined with ``.set`` are supported in expressions. |
| 20 | +.. code-block:: python |
25 | 21 |
|
26 |
| -We have some unit tests and also compatibility tests that compare the output |
27 |
| -whether it is identical with binutils-esp32ulp output. |
| 22 | + # ensure the ESP32 is connected to a network with internet connectivity |
| 23 | + import upip |
| 24 | + upip.install('micropython-py-esp32-ulp') |
| 25 | +
|
| 26 | +On a PC, simply ``git clone`` this repo. |
| 27 | + |
| 28 | + |
| 29 | +Getting Started |
| 30 | +--------------- |
| 31 | + |
| 32 | +The quickest way to get started is to try one of the `examples <examples/>`_. |
| 33 | + |
| 34 | +The simplest example is `counter.py <examples/counter.py>`_. It shows how to |
| 35 | +assemble code, load and run the resulting binary and exchange data between the |
| 36 | +ULP and the main CPU. |
| 37 | + |
| 38 | +Run the ``counter.py`` example: |
| 39 | + |
| 40 | +1. Install py-esp32-ulp onto the ESP32 as shown above |
| 41 | +2. Upload the `counter.py <examples/counter.py>`_ file to the ESP32 |
| 42 | +3. Run with ``import counter`` |
| 43 | + |
| 44 | +You can also try the `blink.py <examples/blink.py>`_ example, which shows how to |
| 45 | +let the ULP blink an LED. |
| 46 | + |
| 47 | +Look inside each example for a more detailed description. |
| 48 | + |
| 49 | + |
| 50 | +Support |
| 51 | +------- |
| 52 | + |
| 53 | +The following features are supported: |
| 54 | + |
| 55 | +* The entire `ESP32 ULP instruction set <https://esp-idf.readthedocs.io/en/latest/api-guides/ulp_instruction_set.html>`_ |
| 56 | +* Constants defined with ``.set`` |
| 57 | +* Constants defined with ``#define`` |
| 58 | +* Expressions in assembly code and constant definitions |
| 59 | +* RTC convenience macros (e.g. WRITE_RTC_REG) |
| 60 | +* Many ESP32 ULP code examples found on the web will work unmodified |
| 61 | + |
| 62 | +Not currently supported: |
| 63 | + |
| 64 | +* Assembler macros using ``.macro`` |
| 65 | +* Preprocessor macros using ``#define A(x,y) ...`` |
| 66 | +* Including files using ``#include`` |
| 67 | +* ESP32-S2 (not binary compatible with the ESP32) |
| 68 | + |
| 69 | + |
| 70 | +Requirements |
| 71 | +------------ |
| 72 | + |
| 73 | +The minimum supported version of MicroPython is v1.12. |
| 74 | + |
| 75 | +py-esp32-ulp has been tested on the Unix port of MicroPython and on real ESP32 |
| 76 | +devices with the chip type ESP32D0WDQ6 (revision 1) without SPIRAM. |
| 77 | + |
| 78 | + |
| 79 | +Advanced usage |
| 80 | +-------------- |
| 81 | + |
| 82 | +In real world applications, you might want to separate the assembly stage from |
| 83 | +the loading/running stage, to avoid having to assemble the code on every startup. |
| 84 | + |
| 85 | +The ``esp32_ulp.assemble_file`` function stores the assembled and linked binary |
| 86 | +into a file with a ``.ulp`` extension, which can later be loaded directly without |
| 87 | +assembling the source again. |
| 88 | + |
| 89 | +1. Create/upload an assembly source file and run the following to get a loadable |
| 90 | + ULP binary as a ``.ulp`` file: |
| 91 | + |
| 92 | + .. code-block:: python |
| 93 | +
|
| 94 | + import esp32_ulp |
| 95 | + esp32_ulp.assemble_file('code.S') # this results in code.ulp |
| 96 | +
|
| 97 | + Alternatively you can assemble the source on a PC with MicroPython, and transfer |
| 98 | + the resulting ULP binary to the ESP32. |
| 99 | + |
| 100 | + .. code-block:: python |
| 101 | +
|
| 102 | + git clone https://github.com/ThomasWaldmann/py-esp32-ulp |
| 103 | + cd py-esp32-ulp |
| 104 | + micropython -m esp32_ulp path/to/code.S # this results in path/to/code.ulp |
| 105 | + # now upload path/to/code.ulp to the ESP32 |
| 106 | +
|
| 107 | +2. The above prints out the offsets of all global symbols/labels. For the next step, |
| 108 | + you will need to note down the offset of the label, which represents the entry |
| 109 | + point to your code. |
| 110 | + |
| 111 | +3. Now load and run the resulting binary as follows: |
| 112 | + |
| 113 | + .. code-block:: python |
| 114 | +
|
| 115 | + from esp32 import ULP |
| 116 | +
|
| 117 | + ulp = ULP() |
| 118 | + with open('test.ulp', 'r') as f: |
| 119 | + # load the binary into RTC memory |
| 120 | + ulp.load_binary(0, f.read()) |
| 121 | +
|
| 122 | + # configure how often the ULP should wake up |
| 123 | + ulp.set_wakeup_period(0, 500000) # 500k usec == 0.5 sec |
| 124 | +
|
| 125 | + # start the ULP |
| 126 | + # assemble_file printed offsets in number of 32-bit words. |
| 127 | + # ulp.run() expects an offset in number of bytes. |
| 128 | + # Thus, multiply the offset to our entry point by 4. |
| 129 | + # e.g. for an offset of 2: |
| 130 | + # 2 words * 4 = 8 bytes |
| 131 | + ulp.run(2*4) # specify the offset of the entry point label |
| 132 | +
|
| 133 | +
|
| 134 | +Preprocessor |
| 135 | +------------ |
28 | 136 |
|
29 | 137 | There is a simple preprocessor that understands just enough to allow assembling
|
30 |
| -ULP source files containing convenience macros such as WRITE_RTC_REG. The |
31 |
| -preprocessor and how to use it is documented here: |
32 |
| -`Preprocessor support <docs/preprocess.rst>`_. |
| 138 | +ULP source files containing convenience macros such as WRITE_RTC_REG. This is |
| 139 | +especially useful for assembling ULP examples from Espressif or other ULP code |
| 140 | +found as part of Arduino/ESP-IDF projects. |
| 141 | + |
| 142 | +The preprocessor and how to use it is documented here: `Preprocessor support <docs/preprocess.rst>`_. |
33 | 143 |
|
34 |
| -The minimum supported version of MicroPython is v1.12. py-esp32-ulp has been |
35 |
| -tested with MicroPython v1.12 and v1.17. It has been tested on real ESP32 |
36 |
| -devices with the chip type ESP32D0WDQ6 (revision 1) without SPIRAM. It has |
37 |
| -also been tested on the Unix port. |
38 | 144 |
|
39 |
| -There might be some stuff missing, some bugs and other symptoms of beta |
40 |
| -software. Also, error and exception handling is rather rough yet. |
| 145 | +Testing |
| 146 | +------- |
41 | 147 |
|
42 |
| -Please be patient or contribute missing parts or fixes. |
| 148 | +There are unit tests and also compatibility tests that check whether the binary |
| 149 | +output is identical with what binutils-esp32ulp produces. |
43 | 150 |
|
44 |
| -See the issue tracker for known bugs and todo items. |
| 151 | +Consult the Github Actions `workflow definition file <.github/workflows/run_tests.yaml>`_ |
| 152 | +for how to run the different tests. |
45 | 153 |
|
46 | 154 |
|
47 | 155 | Links
|
48 | 156 | -----
|
49 | 157 |
|
50 |
| -We are NOT (fully) compatible with "as", but we try to be close for the stuff |
51 |
| -that is actually implemented: |
| 158 | +Espressif documentation: |
| 159 | + |
| 160 | +* `ESP32 ULP coprocessor instruction set <https://esp-idf.readthedocs.io/en/latest/api-guides/ulp_instruction_set.html>`_ |
| 161 | +* `ESP32 Technical Reference Manual <https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf>`_ |
| 162 | + |
| 163 | +GNU Assembler "as" documentation (we try to be compatible for all features that are implemented) |
52 | 164 |
|
53 |
| -https://sourceware.org/binutils/docs/as/index.html |
| 165 | +* `GNU Assembler manual <https://sourceware.org/binutils/docs/as/index.html>`_ |
54 | 166 |
|
55 |
| -Espressif docs: |
| 167 | +More ULP examples: |
56 | 168 |
|
57 |
| -https://esp-idf.readthedocs.io/en/latest/api-guides/ulp_instruction_set.html |
| 169 | +* https://github.com/espressif/esp-iot-solution/tree/master/examples/ulp_examples |
| 170 | +* https://github.com/duff2013/ulptool |
| 171 | +* https://github.com/joba-1/Blink-ULP/blob/master/main/ulp/ |
58 | 172 |
|
59 |
| -https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf |
60 | 173 |
|
61 |
| -Espressif ULP examples: |
| 174 | +License |
| 175 | +------- |
62 | 176 |
|
63 |
| -https://github.com/espressif/esp-iot-solution/tree/master/examples/ulp_examples |
| 177 | +This project is released under the `MIT License <LICENSE>`_. |
0 commit comments