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