README.rst 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. Programming ULP coprocessor using C macros
  2. ==========================================
  3. 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::
  4. const ulp_insn_t program[] = {
  5. I_MOVI(R3, 16), // R3 <- 16
  6. I_LD(R0, R3, 0), // R0 <- RTC_SLOW_MEM[R3 + 0]
  7. I_LD(R1, R3, 1), // R1 <- RTC_SLOW_MEM[R3 + 1]
  8. I_ADDR(R2, R0, R1), // R2 <- R0 + R1
  9. I_ST(R2, R3, 2), // R2 -> RTC_SLOW_MEM[R2 + 2]
  10. I_HALT()
  11. };
  12. size_t load_addr = 0;
  13. size_t size = sizeof(program)/sizeof(ulp_insn_t);
  14. ulp_process_macros_and_load(load_addr, program, &size);
  15. ulp_run(load_addr);
  16. 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.
  17. 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).
  18. 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.
  19. 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.
  20. Here is an example of using labels and branches::
  21. const ulp_insn_t program[] = {
  22. I_MOVI(R0, 34), // R0 <- 34
  23. M_LABEL(1), // label_1
  24. I_MOVI(R1, 32), // R1 <- 32
  25. I_LD(R1, R1, 0), // R1 <- RTC_SLOW_MEM[R1]
  26. I_MOVI(R2, 33), // R2 <- 33
  27. I_LD(R2, R2, 0), // R2 <- RTC_SLOW_MEM[R2]
  28. I_SUBR(R3, R1, R2), // R3 <- R1 - R2
  29. I_ST(R3, R0, 0), // R3 -> RTC_SLOW_MEM[R0 + 0]
  30. I_ADDI(R0, R0, 1), // R0++
  31. M_BL(1, 64), // if (R0 < 64) goto label_1
  32. I_HALT(),
  33. };
  34. RTC_SLOW_MEM[32] = 42;
  35. RTC_SLOW_MEM[33] = 18;
  36. size_t load_addr = 0;
  37. size_t size = sizeof(program)/sizeof(ulp_insn_t);
  38. ulp_process_macros_and_load(load_addr, program, &size);
  39. ulp_run(load_addr);
  40. Functions
  41. ^^^^^^^^^
  42. .. doxygenfunction:: ulp_process_macros_and_load
  43. .. doxygenfunction:: ulp_run
  44. Error codes
  45. ^^^^^^^^^^^
  46. .. doxygendefine:: ESP_ERR_ULP_BASE
  47. .. doxygendefine:: ESP_ERR_ULP_SIZE_TOO_BIG
  48. .. doxygendefine:: ESP_ERR_ULP_INVALID_LOAD_ADDR
  49. .. doxygendefine:: ESP_ERR_ULP_DUPLICATE_LABEL
  50. .. doxygendefine:: ESP_ERR_ULP_UNDEFINED_LABEL
  51. .. doxygendefine:: ESP_ERR_ULP_BRANCH_OUT_OF_RANGE
  52. ULP coprocessor registers
  53. ^^^^^^^^^^^^^^^^^^^^^^^^^
  54. 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.
  55. These definitions can be used for all instructions which require a register.
  56. .. doxygengroup:: ulp_registers
  57. :content-only:
  58. ULP coprocessor instruction defines
  59. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  60. .. doxygendefine:: I_DELAY
  61. .. doxygendefine:: I_HALT
  62. .. doxygendefine:: I_END
  63. .. doxygendefine:: I_ST
  64. .. doxygendefine:: I_LD
  65. .. doxygendefine:: I_WR_REG
  66. .. doxygendefine:: I_RD_REG
  67. .. doxygendefine:: I_BL
  68. .. doxygendefine:: I_BGE
  69. .. doxygendefine:: I_BXR
  70. .. doxygendefine:: I_BXI
  71. .. doxygendefine:: I_BXZR
  72. .. doxygendefine:: I_BXZI
  73. .. doxygendefine:: I_BXFR
  74. .. doxygendefine:: I_BXFI
  75. .. doxygendefine:: I_ADDR
  76. .. doxygendefine:: I_SUBR
  77. .. doxygendefine:: I_ANDR
  78. .. doxygendefine:: I_ORR
  79. .. doxygendefine:: I_MOVR
  80. .. doxygendefine:: I_LSHR
  81. .. doxygendefine:: I_RSHR
  82. .. doxygendefine:: I_ADDI
  83. .. doxygendefine:: I_SUBI
  84. .. doxygendefine:: I_ANDI
  85. .. doxygendefine:: I_ORI
  86. .. doxygendefine:: I_MOVI
  87. .. doxygendefine:: I_LSHI
  88. .. doxygendefine:: I_RSHI
  89. .. doxygendefine:: M_LABEL
  90. .. doxygendefine:: M_BL
  91. .. doxygendefine:: M_BGE
  92. .. doxygendefine:: M_BX
  93. .. doxygendefine:: M_BXZ
  94. .. doxygendefine:: M_BXF
  95. Defines
  96. ^^^^^^^
  97. .. doxygendefine:: RTC_SLOW_MEM