martin.gano d0d7c53ee1 Tools: add Python 2 deprecation warning vor 5 Jahren
..
cmake 92ef27223d ulp: fix ULP assembler version detection for localized systems vor 5 Jahren
include e30cd361a8 global: rename esp32s2beta to esp32s2 vor 6 Jahren
ld 1518c410bc A switch between esp32 and esp32s2betta added to the ULP build process. vor 6 Jahren
test 3d0967a58a test: declare requirements and include dirs private vor 5 Jahren
CMakeLists.txt 9eccd7c082 components: use new component registration api vor 6 Jahren
Makefile.projbuild b38bc2f8f5 s2 support for make build removed. vor 6 Jahren
README.rst 9b5acea160 Add missing link to ulp header files and link to example following https://esp32.com/viewtopic.php?f=2&t=15562 vor 5 Jahren
component.mk cb649e452f remove executable permission from source files vor 7 Jahren
component_ulp_common.cmake bb639bb91d ulp: use quotes when specifying files for embedding ulp binaries vor 6 Jahren
component_ulp_common.mk 92ef27223d ulp: fix ULP assembler version detection for localized systems vor 5 Jahren
esp32ulp_mapgen.py d0d7c53ee1 Tools: add Python 2 deprecation warning vor 5 Jahren
project_include.cmake 07a71529de ulp: fix ulp external project args vor 5 Jahren
toolchain_ulp_version.mk 917889dfdf ulp: remove 20190801 version, update supported version for Make vor 6 Jahren
ulp.c e30cd361a8 global: rename esp32s2beta to esp32s2 vor 6 Jahren
ulp_macro.c 438d513a95 Merge branch 'master' into feature/esp32s2beta_merge vor 6 Jahren
ulp_private.h 2f56116db2 Cleanup of previous merge commit vor 6 Jahren

README.rst

Programming ULP coprocessor using C macros (legacy)
===================================================

In addition to the existing binutils port for the ESP32 ULP coprocessor, it is possible to generate programs for the ULP by embedding assembly-like macros into an ESP32 application. Here is an example how this can be done::

const ulp_insn_t program[] = {
I_MOVI(R3, 16), // R3 <- 16
I_LD(R0, R3, 0), // R0 <- RTC_SLOW_MEM[R3 + 0]
I_LD(R1, R3, 1), // R1 <- RTC_SLOW_MEM[R3 + 1]
I_ADDR(R2, R0, R1), // R2 <- R0 + R1
I_ST(R2, R3, 2), // R2 -> RTC_SLOW_MEM[R2 + 2]
I_HALT()
};
size_t load_addr = 0;
size_t size = sizeof(program)/sizeof(ulp_insn_t);
ulp_process_macros_and_load(load_addr, program, &size);
ulp_run(load_addr);

The ``program`` array is an array of ``ulp_insn_t``, i.e. ULP coprocessor instructions. Each ``I_XXX`` preprocessor define translates into a single 32-bit instruction. Arguments of these preprocessor defines can be register numbers (``R0 — R3``) and literal constants. See `ULP coprocessor instruction defines`_ section for descriptions of instructions and arguments they take.

.. note::

Because some of the instruction macros expand to inline function calls, defining such array in global scope will cause the compiler to produce an "initializer element is not constant" error. To fix this error, move the definition of instructions array into local scope.

Load and store instructions use addresses expressed in 32-bit words. Address 0 corresponds to the first word of ``RTC_SLOW_MEM`` (which is address 0x50000000 as seen by the main CPUs).

To generate branch instructions, special ``M_`` preprocessor defines are used. ``M_LABEL`` define can be used to define a branch target. Label identifier is a 16-bit integer. ``M_Bxxx`` defines can be used to generate branch instructions with target set to a particular label.

Implementation note: these ``M_`` preprocessor defines will be translated into two ``ulp_insn_t`` values: one is a token value which contains label number, and the other is the actual instruction. ``ulp_process_macros_and_load`` function resolves the label number to the address, modifies the branch instruction to use the correct address, and removes the the extra ``ulp_insn_t`` token which contains the label numer.

Here is an example of using labels and branches::

const ulp_insn_t program[] = {
I_MOVI(R0, 34), // R0 <- 34
M_LABEL(1), // label_1
I_MOVI(R1, 32), // R1 <- 32
I_LD(R1, R1, 0), // R1 <- RTC_SLOW_MEM[R1]
I_MOVI(R2, 33), // R2 <- 33
I_LD(R2, R2, 0), // R2 <- RTC_SLOW_MEM[R2]
I_SUBR(R3, R1, R2), // R3 <- R1 - R2
I_ST(R3, R0, 0), // R3 -> RTC_SLOW_MEM[R0 + 0]
I_ADDI(R0, R0, 1), // R0++
M_BL(1, 64), // if (R0 < 64) goto label_1
I_HALT(),
};
RTC_SLOW_MEM[32] = 42;
RTC_SLOW_MEM[33] = 18;
size_t load_addr = 0;
size_t size = sizeof(program)/sizeof(ulp_insn_t);
ulp_process_macros_and_load(load_addr, program, &size);
ulp_run(load_addr);


Application Example
-------------------

Demonstration of entering into deep sleep mode and waking up using several wake up sources: :example:`system/deep_sleep`.


API Reference
-------------

Header File
^^^^^^^^^^^

.. list::

:esp32: - :component_file:`ulp/include/esp32/ulp.h`
:esp32s2: - :component_file:`ulp/include/esp32s2/ulp.h`

Functions
^^^^^^^^^

.. doxygenfunction:: ulp_process_macros_and_load
.. doxygenfunction:: ulp_run

Error codes
^^^^^^^^^^^

.. doxygendefine:: ESP_ERR_ULP_BASE
.. doxygendefine:: ESP_ERR_ULP_SIZE_TOO_BIG
.. doxygendefine:: ESP_ERR_ULP_INVALID_LOAD_ADDR
.. doxygendefine:: ESP_ERR_ULP_DUPLICATE_LABEL
.. doxygendefine:: ESP_ERR_ULP_UNDEFINED_LABEL
.. doxygendefine:: ESP_ERR_ULP_BRANCH_OUT_OF_RANGE

ULP coprocessor registers
^^^^^^^^^^^^^^^^^^^^^^^^^

ULP co-processor has 4 16-bit general purpose registers. All registers have same functionality, with one exception. R0 register is used by some of the compare-and-branch instructions as a source register.

These definitions can be used for all instructions which require a register.

.. doxygengroup:: ulp_registers
:content-only:

ULP coprocessor instruction defines
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. doxygendefine:: I_DELAY
.. doxygendefine:: I_HALT
.. doxygendefine:: I_END
.. doxygendefine:: I_ST
.. doxygendefine:: I_LD
.. doxygendefine:: I_WR_REG
.. doxygendefine:: I_RD_REG
.. doxygendefine:: I_BL
.. doxygendefine:: I_BGE
.. doxygendefine:: I_BXR
.. doxygendefine:: I_BXI
.. doxygendefine:: I_BXZR
.. doxygendefine:: I_BXZI
.. doxygendefine:: I_BXFR
.. doxygendefine:: I_BXFI
.. doxygendefine:: I_ADDR
.. doxygendefine:: I_SUBR
.. doxygendefine:: I_ANDR
.. doxygendefine:: I_ORR
.. doxygendefine:: I_MOVR
.. doxygendefine:: I_LSHR
.. doxygendefine:: I_RSHR
.. doxygendefine:: I_ADDI
.. doxygendefine:: I_SUBI
.. doxygendefine:: I_ANDI
.. doxygendefine:: I_ORI
.. doxygendefine:: I_MOVI
.. doxygendefine:: I_LSHI
.. doxygendefine:: I_RSHI
.. doxygendefine:: M_LABEL
.. doxygendefine:: M_BL
.. doxygendefine:: M_BGE
.. doxygendefine:: M_BX
.. doxygendefine:: M_BXZ
.. doxygendefine:: M_BXF

Defines
^^^^^^^

.. doxygendefine:: RTC_SLOW_MEM