ulp.h 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  1. // Copyright 2016-2018 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #pragma once
  15. #include <stdint.h>
  16. #include <stddef.h>
  17. #include <stdlib.h>
  18. #include "esp_err.h"
  19. #include "soc/soc.h"
  20. #ifdef __cplusplus
  21. extern "C" {
  22. #endif
  23. #define ULP_FSM_PREPARE_SLEEP_CYCLES 2 /*!< Cycles spent by FSM preparing ULP for sleep */
  24. #define ULP_FSM_WAKEUP_SLEEP_CYCLES 2 /*!< Cycles spent by FSM waking up ULP from sleep */
  25. /**
  26. * @defgroup ulp_registers ULP coprocessor registers
  27. * @{
  28. */
  29. #define R0 0 /*!< general purpose register 0 */
  30. #define R1 1 /*!< general purpose register 1 */
  31. #define R2 2 /*!< general purpose register 2 */
  32. #define R3 3 /*!< general purpose register 3 */
  33. /**@}*/
  34. /** @defgroup ulp_opcodes ULP coprocessor opcodes, sub opcodes, and various modifiers/flags
  35. *
  36. * These definitions are not intended to be used directly.
  37. * They are used in definitions of instructions later on.
  38. *
  39. * @{
  40. */
  41. #define OPCODE_WR_REG 1 /*!< Instruction: write peripheral register (RTC_CNTL/RTC_IO/SARADC) */
  42. #define OPCODE_RD_REG 2 /*!< Instruction: read peripheral register (RTC_CNTL/RTC_IO/SARADC) */
  43. #define RD_REG_PERIPH_RTC_CNTL 0 /*!< Identifier of RTC_CNTL peripheral for RD_REG and WR_REG instructions */
  44. #define RD_REG_PERIPH_RTC_IO 1 /*!< Identifier of RTC_IO peripheral for RD_REG and WR_REG instructions */
  45. #define RD_REG_PERIPH_SENS 2 /*!< Identifier of SARADC peripheral for RD_REG and WR_REG instructions */
  46. #define RD_REG_PERIPH_RTC_I2C 3 /*!< Identifier of RTC_I2C peripheral for RD_REG and WR_REG instructions */
  47. #define OPCODE_I2C 3 /*!< Instruction: read/write I2C */
  48. #define SUB_OPCODE_I2C_RD 0 /*!< I2C read */
  49. #define SUB_OPCODE_I2C_WR 1 /*!< I2C write */
  50. #define OPCODE_DELAY 4 /*!< Instruction: delay (nop) for a given number of cycles */
  51. #define OPCODE_ADC 5 /*!< Instruction: SAR ADC measurement */
  52. #define OPCODE_ST 6 /*!< Instruction: store indirect to RTC memory */
  53. #define SUB_OPCODE_ST 4 /*!< Store 32 bits, 16 MSBs contain PC, 16 LSBs contain value from source register */
  54. #define OPCODE_ALU 7 /*!< Arithmetic instructions */
  55. #define SUB_OPCODE_ALU_REG 0 /*!< Arithmetic instruction, both source values are in register */
  56. #define SUB_OPCODE_ALU_IMM 1 /*!< Arithmetic instruction, one source value is an immediate */
  57. #define SUB_OPCODE_ALU_CNT 2 /*!< Arithmetic instruction, stage counter and an immediate */
  58. #define ALU_SEL_ADD 0 /*!< Addition */
  59. #define ALU_SEL_SUB 1 /*!< Subtraction */
  60. #define ALU_SEL_AND 2 /*!< Logical AND */
  61. #define ALU_SEL_OR 3 /*!< Logical OR */
  62. #define ALU_SEL_MOV 4 /*!< Copy value (immediate to destination register or source register to destination register */
  63. #define ALU_SEL_LSH 5 /*!< Shift left by given number of bits */
  64. #define ALU_SEL_RSH 6 /*!< Shift right by given number of bits */
  65. #define ALU_SEL_SINC 0 /*!< Increment the stage counter */
  66. #define ALU_SEL_SDEC 1 /*!< Decrement the stage counter */
  67. #define ALU_SEL_SRST 2 /*!< Reset the stage counter */
  68. #define OPCODE_BRANCH 8 /*!< Branch instructions */
  69. #define SUB_OPCODE_BX 0 /*!< Branch to absolute PC (immediate or in register) */
  70. #define SUB_OPCODE_BR 1 /*!< Branch to relative PC, conditional on R0 */
  71. #define SUB_OPCODE_BS 2 /*!< Branch to relative PC, conditional on the stage counter */
  72. #define BX_JUMP_TYPE_DIRECT 0 /*!< Unconditional jump */
  73. #define BX_JUMP_TYPE_ZERO 1 /*!< Branch if last ALU result is zero */
  74. #define BX_JUMP_TYPE_OVF 2 /*!< Branch if last ALU operation caused and overflow */
  75. #define SUB_OPCODE_B 1 /*!< Branch to a relative offset */
  76. #define B_CMP_L 0 /*!< Branch if R0 is less than an immediate */
  77. #define B_CMP_GE 1 /*!< Branch if R0 is greater than or equal to an immediate */
  78. #define JUMPS_LT 0 /*!< Branch if the stage counter < */
  79. #define JUMPS_GE 1 /*!< Branch if the stage counter >= */
  80. #define JUMPS_LE 2 /*!< Branch if the stage counter <= */
  81. #define OPCODE_END 9 /*!< Stop executing the program */
  82. #define SUB_OPCODE_END 0 /*!< Stop executing the program and optionally wake up the chip */
  83. #define SUB_OPCODE_SLEEP 1 /*!< Stop executing the program and run it again after selected interval */
  84. #define OPCODE_TSENS 10 /*!< Instruction: temperature sensor measurement */
  85. #define OPCODE_HALT 11 /*!< Halt the coprocessor */
  86. #define OPCODE_LD 13 /*!< Indirect load lower 16 bits from RTC memory */
  87. #define OPCODE_MACRO 15 /*!< Not a real opcode. Used to identify labels and branches in the program */
  88. #define SUB_OPCODE_MACRO_LABEL 0 /*!< Label macro */
  89. #define SUB_OPCODE_MACRO_BRANCH 1 /*!< Branch macro */
  90. #define SUB_OPCODE_MACRO_LABELPC 2 /*!< Label pointer macro */
  91. /**@}*/
  92. /**@{*/
  93. #define ESP_ERR_ULP_BASE 0x1200 /*!< Offset for ULP-related error codes */
  94. #define ESP_ERR_ULP_SIZE_TOO_BIG (ESP_ERR_ULP_BASE + 1) /*!< Program doesn't fit into RTC memory reserved for the ULP */
  95. #define ESP_ERR_ULP_INVALID_LOAD_ADDR (ESP_ERR_ULP_BASE + 2) /*!< Load address is outside of RTC memory reserved for the ULP */
  96. #define ESP_ERR_ULP_DUPLICATE_LABEL (ESP_ERR_ULP_BASE + 3) /*!< More than one label with the same number was defined */
  97. #define ESP_ERR_ULP_UNDEFINED_LABEL (ESP_ERR_ULP_BASE + 4) /*!< Branch instructions references an undefined label */
  98. #define ESP_ERR_ULP_BRANCH_OUT_OF_RANGE (ESP_ERR_ULP_BASE + 5) /*!< Branch target is out of range of B instruction (try replacing with BX) */
  99. /**@}*/
  100. /**
  101. * @brief Instruction format structure
  102. *
  103. * All ULP instructions are 32 bit long.
  104. * This union contains field layouts used by all of the supported instructions.
  105. * This union also includes a special "macro" instruction layout.
  106. * This is not a real instruction which can be executed by the CPU. It acts
  107. * as a token which is removed from the program by the
  108. * ulp_process_macros_and_load function.
  109. *
  110. * These structures are not intended to be used directly.
  111. * Preprocessor definitions provided below fill the fields of these structure with
  112. * the right arguments.
  113. */
  114. typedef union {
  115. struct {
  116. uint32_t cycles : 16; /*!< Number of cycles to sleep */
  117. uint32_t unused : 12; /*!< Unused */
  118. uint32_t opcode : 4; /*!< Opcode (OPCODE_DELAY) */
  119. } delay; /*!< Format of DELAY instruction */
  120. struct {
  121. uint32_t dreg : 2; /*!< Register which contains data to store */
  122. uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */
  123. uint32_t unused1 : 6; /*!< Unused */
  124. uint32_t offset : 11; /*!< Offset to add to sreg */
  125. uint32_t unused2 : 4; /*!< Unused */
  126. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ST) */
  127. uint32_t opcode : 4; /*!< Opcode (OPCODE_ST) */
  128. } st; /*!< Format of ST instruction */
  129. struct {
  130. uint32_t dreg : 2; /*!< Register where the data should be loaded to */
  131. uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */
  132. uint32_t unused1 : 6; /*!< Unused */
  133. uint32_t offset : 11; /*!< Offset to add to sreg */
  134. uint32_t unused2 : 7; /*!< Unused */
  135. uint32_t opcode : 4; /*!< Opcode (OPCODE_LD) */
  136. } ld; /*!< Format of LD instruction */
  137. struct {
  138. uint32_t unused : 28; /*!< Unused */
  139. uint32_t opcode : 4; /*!< Opcode (OPCODE_HALT) */
  140. } halt; /*!< Format of HALT instruction */
  141. struct {
  142. uint32_t dreg : 2; /*!< Register which contains target PC, expressed in words (used if .reg == 1) */
  143. uint32_t addr : 11; /*!< Target PC, expressed in words (used if .reg == 0) */
  144. uint32_t unused : 8; /*!< Unused */
  145. uint32_t reg : 1; /*!< Target PC in register (1) or immediate (0) */
  146. uint32_t type : 3; /*!< Jump condition (BX_JUMP_TYPE_xxx) */
  147. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_BX) */
  148. uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
  149. } bx; /*!< Format of BRANCH instruction (absolute address) */
  150. struct {
  151. uint32_t imm : 16; /*!< Immediate value to compare against */
  152. uint32_t cmp : 1; /*!< Comparison to perform: B_CMP_L or B_CMP_GE */
  153. uint32_t offset : 7; /*!< Absolute value of target PC offset w.r.t. current PC, expressed in words */
  154. uint32_t sign : 1; /*!< Sign of target PC offset: 0: positive, 1: negative */
  155. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_B) */
  156. uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
  157. } b; /*!< Format of BRANCH instruction (relative address, conditional on R0) */
  158. struct {
  159. uint32_t imm : 8; /*!< Immediate value to compare against */
  160. uint32_t unused : 7; /*!< Unused */
  161. uint32_t cmp : 2; /*!< Comparison to perform: JUMPS_LT, JUMPS_GE or JUMPS_LE */
  162. uint32_t offset : 7; /*!< Absolute value of target PC offset w.r.t. current PC, expressed in words */
  163. uint32_t sign : 1; /*!< Sign of target PC offset: 0: positive, 1: negative */
  164. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_BS) */
  165. uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
  166. } bs; /*!< Format of BRANCH instruction (relative address, conditional on the stage counter) */
  167. struct {
  168. uint32_t dreg : 2; /*!< Destination register */
  169. uint32_t sreg : 2; /*!< Register with operand A */
  170. uint32_t treg : 2; /*!< Register with operand B */
  171. uint32_t unused : 15; /*!< Unused */
  172. uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
  173. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ALU_REG) */
  174. uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
  175. } alu_reg; /*!< Format of ALU instruction (both sources are registers) */
  176. struct {
  177. uint32_t unused1 : 4; /*!< Unused */
  178. uint32_t imm : 8; /*!< Immediate value of operand */
  179. uint32_t unused2 : 9; /*!< Unused */
  180. uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_Sxxx */
  181. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ALU_CNT) */
  182. uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
  183. } alu_reg_s; /*!< Format of ALU instruction (stage counter and an immediate) */
  184. struct {
  185. uint32_t dreg : 2; /*!< Destination register */
  186. uint32_t sreg : 2; /*!< Register with operand A */
  187. uint32_t imm : 16; /*!< Immediate value of operand B */
  188. uint32_t unused : 1; /*!< Unused */
  189. uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
  190. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */
  191. uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
  192. } alu_imm; /*!< Format of ALU instruction (one source is an immediate) */
  193. struct {
  194. uint32_t addr : 8; /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */
  195. uint32_t periph_sel : 2; /*!< Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) */
  196. uint32_t data : 8; /*!< 8 bits of data to write */
  197. uint32_t low : 5; /*!< Low bit */
  198. uint32_t high : 5; /*!< High bit */
  199. uint32_t opcode : 4; /*!< Opcode (OPCODE_WR_REG) */
  200. } wr_reg; /*!< Format of WR_REG instruction */
  201. struct {
  202. uint32_t addr : 8; /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */
  203. uint32_t periph_sel : 2; /*!< Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) */
  204. uint32_t unused : 8; /*!< Unused */
  205. uint32_t low : 5; /*!< Low bit */
  206. uint32_t high : 5; /*!< High bit */
  207. uint32_t opcode : 4; /*!< Opcode (OPCODE_WR_REG) */
  208. } rd_reg; /*!< Format of RD_REG instruction */
  209. struct {
  210. uint32_t dreg : 2; /*!< Register where to store ADC result */
  211. uint32_t mux : 4; /*!< Select SARADC pad (mux + 1) */
  212. uint32_t sar_sel : 1; /*!< Select SARADC0 (0) or SARADC1 (1) */
  213. uint32_t unused1 : 1; /*!< Unused */
  214. uint32_t cycles : 16; /*!< TBD, cycles used for measurement */
  215. uint32_t unused2 : 4; /*!< Unused */
  216. uint32_t opcode: 4; /*!< Opcode (OPCODE_ADC) */
  217. } adc; /*!< Format of ADC instruction */
  218. struct {
  219. uint32_t dreg : 2; /*!< Register where to store temperature measurement result */
  220. uint32_t wait_delay: 14; /*!< Cycles to wait after measurement is done */
  221. uint32_t reserved: 12; /*!< Reserved, set to 0 */
  222. uint32_t opcode: 4; /*!< Opcode (OPCODE_TSENS) */
  223. } tsens; /*!< Format of TSENS instruction */
  224. struct {
  225. uint32_t i2c_addr : 8; /*!< I2C slave address */
  226. uint32_t data : 8; /*!< 8 bits of data for write operation */
  227. uint32_t low_bits : 3; /*!< low bit of range for write operation (lower bits are masked) */
  228. uint32_t high_bits : 3; /*!< high bit of range for write operation (higher bits are masked) */
  229. uint32_t i2c_sel : 4; /*!< index of slave address register [7:0] */
  230. uint32_t unused : 1; /*!< Unused */
  231. uint32_t rw : 1; /*!< Write (1) or read (0) */
  232. uint32_t opcode : 4; /*!< Opcode (OPCODE_I2C) */
  233. } i2c; /*!< Format of I2C instruction */
  234. struct {
  235. uint32_t wakeup : 1; /*!< Set to 1 to wake up chip */
  236. uint32_t unused : 24; /*!< Unused */
  237. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_WAKEUP) */
  238. uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */
  239. } end; /*!< Format of END instruction with wakeup */
  240. struct {
  241. uint32_t cycle_sel : 4; /*!< Select which one of SARADC_ULP_CP_SLEEP_CYCx_REG to get the sleep duration from */
  242. uint32_t unused : 21; /*!< Unused */
  243. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_SLEEP) */
  244. uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */
  245. } sleep; /*!< Format of END instruction with sleep */
  246. struct {
  247. uint32_t dreg : 2; /*!< Destination register (for SUB_OPCODE_MACRO_LABELPC) > */
  248. uint32_t label : 16; /*!< Label number */
  249. uint32_t unused : 6; /*!< Unused */
  250. uint32_t sub_opcode : 4; /*!< SUB_OPCODE_MACRO_LABEL or SUB_OPCODE_MACRO_BRANCH or SUB_OPCODE_MACRO_LABELPC */
  251. uint32_t opcode: 4; /*!< Opcode (OPCODE_MACRO) */
  252. } macro; /*!< Format of tokens used by MACROs */
  253. } ulp_insn_t;
  254. _Static_assert(sizeof(ulp_insn_t) == 4, "ULP coprocessor instruction size should be 4 bytes");
  255. /**
  256. * Delay (nop) for a given number of cycles
  257. */
  258. #define I_DELAY(cycles_) { .delay = {\
  259. .cycles = cycles_, \
  260. .unused = 0, \
  261. .opcode = OPCODE_DELAY } }
  262. /**
  263. * Halt the coprocessor.
  264. *
  265. * This instruction halts the coprocessor, but keeps ULP timer active.
  266. * As such, ULP program will be restarted again by timer.
  267. * To stop the program and prevent the timer from restarting the program,
  268. * use I_END(0) instruction.
  269. */
  270. #define I_HALT() { .halt = {\
  271. .unused = 0, \
  272. .opcode = OPCODE_HALT } }
  273. /**
  274. * Map SoC peripheral register to periph_sel field of RD_REG and WR_REG
  275. * instructions.
  276. *
  277. * @param reg peripheral register in RTC_CNTL_, RTC_IO_, SENS_, RTC_I2C peripherals.
  278. * @return periph_sel value for the peripheral to which this register belongs.
  279. */
  280. static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
  281. uint32_t ret = 3;
  282. if (reg < DR_REG_RTCCNTL_BASE) {
  283. assert(0 && "invalid register base");
  284. } else if (reg < DR_REG_RTCIO_BASE) {
  285. ret = RD_REG_PERIPH_RTC_CNTL;
  286. } else if (reg < DR_REG_SENS_BASE) {
  287. ret = RD_REG_PERIPH_RTC_IO;
  288. } else if (reg < DR_REG_RTC_I2C_BASE){
  289. ret = RD_REG_PERIPH_SENS;
  290. } else if (reg < DR_REG_IO_MUX_BASE){
  291. ret = RD_REG_PERIPH_RTC_I2C;
  292. } else {
  293. assert(0 && "invalid register base");
  294. }
  295. return ret;
  296. }
  297. /**
  298. * Write literal value to a peripheral register
  299. *
  300. * reg[high_bit : low_bit] = val
  301. * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
  302. */
  303. #define I_WR_REG(reg, low_bit, high_bit, val) {.wr_reg = {\
  304. .addr = (reg & 0xff) / sizeof(uint32_t), \
  305. .periph_sel = SOC_REG_TO_ULP_PERIPH_SEL(reg), \
  306. .data = val, \
  307. .low = low_bit, \
  308. .high = high_bit, \
  309. .opcode = OPCODE_WR_REG } }
  310. /**
  311. * Read from peripheral register into R0
  312. *
  313. * R0 = reg[high_bit : low_bit]
  314. * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
  315. */
  316. #define I_RD_REG(reg, low_bit, high_bit) {.rd_reg = {\
  317. .addr = (reg & 0xff) / sizeof(uint32_t), \
  318. .periph_sel = SOC_REG_TO_ULP_PERIPH_SEL(reg), \
  319. .unused = 0, \
  320. .low = low_bit, \
  321. .high = high_bit, \
  322. .opcode = OPCODE_RD_REG } }
  323. /**
  324. * Set or clear a bit in the peripheral register.
  325. *
  326. * Sets bit (1 << shift) of register reg to value val.
  327. * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
  328. */
  329. #define I_WR_REG_BIT(reg, shift, val) I_WR_REG(reg, shift, shift, val)
  330. /**
  331. * Wake the SoC from deep sleep.
  332. *
  333. * This instruction initiates wake up from deep sleep.
  334. * Use esp_deep_sleep_enable_ulp_wakeup to enable deep sleep wakeup
  335. * triggered by the ULP before going into deep sleep.
  336. * Note that ULP program will still keep running until the I_HALT
  337. * instruction, and it will still be restarted by timer at regular
  338. * intervals, even when the SoC is woken up.
  339. *
  340. * To stop the ULP program, use I_HALT instruction.
  341. *
  342. * To disable the timer which start ULP program, use I_END()
  343. * instruction. I_END instruction clears the
  344. * RTC_CNTL_ULP_CP_SLP_TIMER_EN_S bit of RTC_CNTL_STATE0_REG
  345. * register, which controls the ULP timer.
  346. */
  347. #define I_WAKE() { .end = { \
  348. .wakeup = 1, \
  349. .unused = 0, \
  350. .sub_opcode = SUB_OPCODE_END, \
  351. .opcode = OPCODE_END } }
  352. /**
  353. * Stop ULP program timer.
  354. *
  355. * This is a convenience macro which disables the ULP program timer.
  356. * Once this instruction is used, ULP program will not be restarted
  357. * anymore until ulp_run function is called.
  358. *
  359. * ULP program will continue running after this instruction. To stop
  360. * the currently running program, use I_HALT().
  361. */
  362. #define I_END() \
  363. I_WR_REG_BIT(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN_S, 0)
  364. /**
  365. * Select the time interval used to run ULP program.
  366. *
  367. * This instructions selects which of the SENS_SLEEP_CYCLES_Sx
  368. * registers' value is used by the ULP program timer.
  369. * When the ULP program stops at I_HALT instruction, ULP program
  370. * timer start counting. When the counter reaches the value of
  371. * the selected SENS_SLEEP_CYCLES_Sx register, ULP program
  372. * start running again from the start address (passed to the ulp_run
  373. * function).
  374. * There are 5 SENS_SLEEP_CYCLES_Sx registers, so 0 <= timer_idx < 5.
  375. *
  376. * By default, SENS_SLEEP_CYCLES_S0 register is used by the ULP
  377. * program timer.
  378. */
  379. #define I_SLEEP_CYCLE_SEL(timer_idx) { .sleep = { \
  380. .cycle_sel = timer_idx, \
  381. .unused = 0, \
  382. .sub_opcode = SUB_OPCODE_SLEEP, \
  383. .opcode = OPCODE_END } }
  384. /**
  385. * Perform temperature sensor measurement and store it into reg_dest.
  386. *
  387. * Delay can be set between 1 and ((1 << 14) - 1). Higher values give
  388. * higher measurement resolution.
  389. */
  390. #define I_TSENS(reg_dest, delay) { .tsens = { \
  391. .dreg = reg_dest, \
  392. .wait_delay = delay, \
  393. .reserved = 0, \
  394. .opcode = OPCODE_TSENS } }
  395. /**
  396. * Perform ADC measurement and store result in reg_dest.
  397. *
  398. * adc_idx selects ADC (0 or 1).
  399. * pad_idx selects ADC pad (0 - 7).
  400. */
  401. #define I_ADC(reg_dest, adc_idx, pad_idx) { .adc = {\
  402. .dreg = reg_dest, \
  403. .mux = pad_idx + 1, \
  404. .sar_sel = adc_idx, \
  405. .unused1 = 0, \
  406. .cycles = 0, \
  407. .unused2 = 0, \
  408. .opcode = OPCODE_ADC } }
  409. /**
  410. * Store value from register reg_val into RTC memory.
  411. *
  412. * The value is written to an offset calculated by adding value of
  413. * reg_addr register and offset_ field (this offset is expressed in 32-bit words).
  414. * 32 bits written to RTC memory are built as follows:
  415. * - bits [31:21] hold the PC of current instruction, expressed in 32-bit words
  416. * - bits [20:16] = 5'b1
  417. * - bits [15:0] are assigned the contents of reg_val
  418. *
  419. * RTC_SLOW_MEM[addr + offset_] = { 5'b0, insn_PC[10:0], val[15:0] }
  420. */
  421. #define I_ST(reg_val, reg_addr, offset_) { .st = { \
  422. .dreg = reg_val, \
  423. .sreg = reg_addr, \
  424. .unused1 = 0, \
  425. .offset = offset_, \
  426. .unused2 = 0, \
  427. .sub_opcode = SUB_OPCODE_ST, \
  428. .opcode = OPCODE_ST } }
  429. /**
  430. * Load value from RTC memory into reg_dest register.
  431. *
  432. * Loads 16 LSBs from RTC memory word given by the sum of value in reg_addr and
  433. * value of offset_.
  434. */
  435. #define I_LD(reg_dest, reg_addr, offset_) { .ld = { \
  436. .dreg = reg_dest, \
  437. .sreg = reg_addr, \
  438. .unused1 = 0, \
  439. .offset = offset_, \
  440. .unused2 = 0, \
  441. .opcode = OPCODE_LD } }
  442. /**
  443. * Branch relative if R0 less than immediate value.
  444. *
  445. * pc_offset is expressed in words, and can be from -127 to 127
  446. * imm_value is a 16-bit value to compare R0 against
  447. */
  448. #define I_BL(pc_offset, imm_value) { .b = { \
  449. .imm = imm_value, \
  450. .cmp = B_CMP_L, \
  451. .offset = abs(pc_offset), \
  452. .sign = (pc_offset >= 0) ? 0 : 1, \
  453. .sub_opcode = SUB_OPCODE_B, \
  454. .opcode = OPCODE_BRANCH } }
  455. /**
  456. * Branch relative if R0 greater or equal than immediate value.
  457. *
  458. * pc_offset is expressed in words, and can be from -127 to 127
  459. * imm_value is a 16-bit value to compare R0 against
  460. */
  461. #define I_BGE(pc_offset, imm_value) { .b = { \
  462. .imm = imm_value, \
  463. .cmp = B_CMP_GE, \
  464. .offset = abs(pc_offset), \
  465. .sign = (pc_offset >= 0) ? 0 : 1, \
  466. .sub_opcode = SUB_OPCODE_B, \
  467. .opcode = OPCODE_BRANCH } }
  468. /**
  469. * Unconditional branch to absolute PC, address in register.
  470. *
  471. * reg_pc is the register which contains address to jump to.
  472. * Address is expressed in 32-bit words.
  473. */
  474. #define I_BXR(reg_pc) { .bx = { \
  475. .dreg = reg_pc, \
  476. .addr = 0, \
  477. .unused = 0, \
  478. .reg = 1, \
  479. .type = BX_JUMP_TYPE_DIRECT, \
  480. .sub_opcode = SUB_OPCODE_BX, \
  481. .opcode = OPCODE_BRANCH } }
  482. /**
  483. * Unconditional branch to absolute PC, immediate address.
  484. *
  485. * Address imm_pc is expressed in 32-bit words.
  486. */
  487. #define I_BXI(imm_pc) { .bx = { \
  488. .dreg = 0, \
  489. .addr = imm_pc, \
  490. .unused = 0, \
  491. .reg = 0, \
  492. .type = BX_JUMP_TYPE_DIRECT, \
  493. .sub_opcode = SUB_OPCODE_BX, \
  494. .opcode = OPCODE_BRANCH } }
  495. /**
  496. * Branch to absolute PC if ALU result is zero, address in register.
  497. *
  498. * reg_pc is the register which contains address to jump to.
  499. * Address is expressed in 32-bit words.
  500. */
  501. #define I_BXZR(reg_pc) { .bx = { \
  502. .dreg = reg_pc, \
  503. .addr = 0, \
  504. .unused = 0, \
  505. .reg = 1, \
  506. .type = BX_JUMP_TYPE_ZERO, \
  507. .sub_opcode = SUB_OPCODE_BX, \
  508. .opcode = OPCODE_BRANCH } }
  509. /**
  510. * Branch to absolute PC if ALU result is zero, immediate address.
  511. *
  512. * Address imm_pc is expressed in 32-bit words.
  513. */
  514. #define I_BXZI(imm_pc) { .bx = { \
  515. .dreg = 0, \
  516. .addr = imm_pc, \
  517. .unused = 0, \
  518. .reg = 0, \
  519. .type = BX_JUMP_TYPE_ZERO, \
  520. .sub_opcode = SUB_OPCODE_BX, \
  521. .opcode = OPCODE_BRANCH } }
  522. /**
  523. * Branch to absolute PC if ALU overflow, address in register
  524. *
  525. * reg_pc is the register which contains address to jump to.
  526. * Address is expressed in 32-bit words.
  527. */
  528. #define I_BXFR(reg_pc) { .bx = { \
  529. .dreg = reg_pc, \
  530. .addr = 0, \
  531. .unused = 0, \
  532. .reg = 1, \
  533. .type = BX_JUMP_TYPE_OVF, \
  534. .sub_opcode = SUB_OPCODE_BX, \
  535. .opcode = OPCODE_BRANCH } }
  536. /**
  537. * Branch to absolute PC if ALU overflow, immediate address
  538. *
  539. * Address imm_pc is expressed in 32-bit words.
  540. */
  541. #define I_BXFI(imm_pc) { .bx = { \
  542. .dreg = 0, \
  543. .addr = imm_pc, \
  544. .unused = 0, \
  545. .reg = 0, \
  546. .type = BX_JUMP_TYPE_OVF, \
  547. .sub_opcode = SUB_OPCODE_BX, \
  548. .opcode = OPCODE_BRANCH } }
  549. /**
  550. * Addition: dest = src1 + src2
  551. */
  552. #define I_ADDR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
  553. .dreg = reg_dest, \
  554. .sreg = reg_src1, \
  555. .treg = reg_src2, \
  556. .unused = 0, \
  557. .sel = ALU_SEL_ADD, \
  558. .sub_opcode = SUB_OPCODE_ALU_REG, \
  559. .opcode = OPCODE_ALU } }
  560. /**
  561. * Subtraction: dest = src1 - src2
  562. */
  563. #define I_SUBR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
  564. .dreg = reg_dest, \
  565. .sreg = reg_src1, \
  566. .treg = reg_src2, \
  567. .unused = 0, \
  568. .sel = ALU_SEL_SUB, \
  569. .sub_opcode = SUB_OPCODE_ALU_REG, \
  570. .opcode = OPCODE_ALU } }
  571. /**
  572. * Logical AND: dest = src1 & src2
  573. */
  574. #define I_ANDR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
  575. .dreg = reg_dest, \
  576. .sreg = reg_src1, \
  577. .treg = reg_src2, \
  578. .unused = 0, \
  579. .sel = ALU_SEL_AND, \
  580. .sub_opcode = SUB_OPCODE_ALU_REG, \
  581. .opcode = OPCODE_ALU } }
  582. /**
  583. * Logical OR: dest = src1 | src2
  584. */
  585. #define I_ORR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
  586. .dreg = reg_dest, \
  587. .sreg = reg_src1, \
  588. .treg = reg_src2, \
  589. .unused = 0, \
  590. .sel = ALU_SEL_OR, \
  591. .sub_opcode = SUB_OPCODE_ALU_REG, \
  592. .opcode = OPCODE_ALU } }
  593. /**
  594. * Copy: dest = src
  595. */
  596. #define I_MOVR(reg_dest, reg_src) { .alu_reg = { \
  597. .dreg = reg_dest, \
  598. .sreg = reg_src, \
  599. .treg = 0, \
  600. .unused = 0, \
  601. .sel = ALU_SEL_MOV, \
  602. .sub_opcode = SUB_OPCODE_ALU_REG, \
  603. .opcode = OPCODE_ALU } }
  604. /**
  605. * Logical shift left: dest = src << shift
  606. */
  607. #define I_LSHR(reg_dest, reg_src, reg_shift) { .alu_reg = { \
  608. .dreg = reg_dest, \
  609. .sreg = reg_src, \
  610. .treg = reg_shift, \
  611. .unused = 0, \
  612. .sel = ALU_SEL_LSH, \
  613. .sub_opcode = SUB_OPCODE_ALU_REG, \
  614. .opcode = OPCODE_ALU } }
  615. /**
  616. * Logical shift right: dest = src >> shift
  617. */
  618. #define I_RSHR(reg_dest, reg_src, reg_shift) { .alu_reg = { \
  619. .dreg = reg_dest, \
  620. .sreg = reg_src, \
  621. .treg = reg_shift, \
  622. .unused = 0, \
  623. .sel = ALU_SEL_RSH, \
  624. .sub_opcode = SUB_OPCODE_ALU_REG, \
  625. .opcode = OPCODE_ALU } }
  626. /**
  627. * Add register and an immediate value: dest = src1 + imm
  628. */
  629. #define I_ADDI(reg_dest, reg_src, imm_) { .alu_imm = { \
  630. .dreg = reg_dest, \
  631. .sreg = reg_src, \
  632. .imm = imm_, \
  633. .unused = 0, \
  634. .sel = ALU_SEL_ADD, \
  635. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  636. .opcode = OPCODE_ALU } }
  637. /**
  638. * Subtract register and an immediate value: dest = src - imm
  639. */
  640. #define I_SUBI(reg_dest, reg_src, imm_) { .alu_imm = { \
  641. .dreg = reg_dest, \
  642. .sreg = reg_src, \
  643. .imm = imm_, \
  644. .unused = 0, \
  645. .sel = ALU_SEL_SUB, \
  646. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  647. .opcode = OPCODE_ALU } }
  648. /**
  649. * Logical AND register and an immediate value: dest = src & imm
  650. */
  651. #define I_ANDI(reg_dest, reg_src, imm_) { .alu_imm = { \
  652. .dreg = reg_dest, \
  653. .sreg = reg_src, \
  654. .imm = imm_, \
  655. .unused = 0, \
  656. .sel = ALU_SEL_AND, \
  657. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  658. .opcode = OPCODE_ALU } }
  659. /**
  660. * Logical OR register and an immediate value: dest = src | imm
  661. */
  662. #define I_ORI(reg_dest, reg_src, imm_) { .alu_imm = { \
  663. .dreg = reg_dest, \
  664. .sreg = reg_src, \
  665. .imm = imm_, \
  666. .unused = 0, \
  667. .sel = ALU_SEL_OR, \
  668. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  669. .opcode = OPCODE_ALU } }
  670. /**
  671. * Copy an immediate value into register: dest = imm
  672. */
  673. #define I_MOVI(reg_dest, imm_) { .alu_imm = { \
  674. .dreg = reg_dest, \
  675. .sreg = 0, \
  676. .imm = imm_, \
  677. .unused = 0, \
  678. .sel = ALU_SEL_MOV, \
  679. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  680. .opcode = OPCODE_ALU } }
  681. /**
  682. * Logical shift left register value by an immediate: dest = src << imm
  683. */
  684. #define I_LSHI(reg_dest, reg_src, imm_) { .alu_imm = { \
  685. .dreg = reg_dest, \
  686. .sreg = reg_src, \
  687. .imm = imm_, \
  688. .unused = 0, \
  689. .sel = ALU_SEL_LSH, \
  690. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  691. .opcode = OPCODE_ALU } }
  692. /**
  693. * Logical shift right register value by an immediate: dest = val >> imm
  694. */
  695. #define I_RSHI(reg_dest, reg_src, imm_) { .alu_imm = { \
  696. .dreg = reg_dest, \
  697. .sreg = reg_src, \
  698. .imm = imm_, \
  699. .unused = 0, \
  700. .sel = ALU_SEL_RSH, \
  701. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  702. .opcode = OPCODE_ALU } }
  703. /**
  704. * Define a label with number label_num.
  705. *
  706. * This is a macro which doesn't generate a real instruction.
  707. * The token generated by this macro is removed by ulp_process_macros_and_load
  708. * function. Label defined using this macro can be used in branch macros defined
  709. * below.
  710. */
  711. #define M_LABEL(label_num) { .macro = { \
  712. .dreg = 0, \
  713. .label = label_num, \
  714. .unused = 0, \
  715. .sub_opcode = SUB_OPCODE_MACRO_LABEL, \
  716. .opcode = OPCODE_MACRO } }
  717. /**
  718. * Token macro used by M_B and M_BX macros. Not to be used directly.
  719. */
  720. #define M_BRANCH(label_num) { .macro = { \
  721. .dreg = 0, \
  722. .label = label_num, \
  723. .unused = 0, \
  724. .sub_opcode = SUB_OPCODE_MACRO_BRANCH, \
  725. .opcode = OPCODE_MACRO } }
  726. /**
  727. * Token macro used by M_MOVL macro. Not to be used directly.
  728. */
  729. #define M_LABELPC(label_num) { .macro = { \
  730. .dreg = 0, \
  731. .label = label_num, \
  732. .unused = 0, \
  733. .sub_opcode = SUB_OPCODE_MACRO_LABELPC, \
  734. .opcode = OPCODE_MACRO } }
  735. /**
  736. * Macro: Move the program counter at the given label into the register.
  737. * This address can then be used with I_BXR, I_BXZR, I_BXFR, etc.
  738. *
  739. * This macro generates two ulp_insn_t values separated by a comma, and should
  740. * be used when defining contents of ulp_insn_t arrays. First value is not a
  741. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  742. * function.
  743. */
  744. #define M_MOVL(reg_dest, label_num) \
  745. M_LABELPC(label_num), \
  746. I_MOVI(reg_dest, 0)
  747. /**
  748. * Macro: branch to label label_num if R0 is less than immediate value.
  749. *
  750. * This macro generates two ulp_insn_t values separated by a comma, and should
  751. * be used when defining contents of ulp_insn_t arrays. First value is not a
  752. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  753. * function.
  754. */
  755. #define M_BL(label_num, imm_value) \
  756. M_BRANCH(label_num), \
  757. I_BL(0, imm_value)
  758. /**
  759. * Macro: branch to label label_num if R0 is greater or equal than immediate value
  760. *
  761. * This macro generates two ulp_insn_t values separated by a comma, and should
  762. * be used when defining contents of ulp_insn_t arrays. First value is not a
  763. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  764. * function.
  765. */
  766. #define M_BGE(label_num, imm_value) \
  767. M_BRANCH(label_num), \
  768. I_BGE(0, imm_value)
  769. /**
  770. * Macro: unconditional branch to label
  771. *
  772. * This macro generates two ulp_insn_t values separated by a comma, and should
  773. * be used when defining contents of ulp_insn_t arrays. First value is not a
  774. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  775. * function.
  776. */
  777. #define M_BX(label_num) \
  778. M_BRANCH(label_num), \
  779. I_BXI(0)
  780. /**
  781. * Macro: branch to label if ALU result is zero
  782. *
  783. * This macro generates two ulp_insn_t values separated by a comma, and should
  784. * be used when defining contents of ulp_insn_t arrays. First value is not a
  785. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  786. * function.
  787. */
  788. #define M_BXZ(label_num) \
  789. M_BRANCH(label_num), \
  790. I_BXZI(0)
  791. /**
  792. * Macro: branch to label if ALU overflow
  793. *
  794. * This macro generates two ulp_insn_t values separated by a comma, and should
  795. * be used when defining contents of ulp_insn_t arrays. First value is not a
  796. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  797. * function.
  798. */
  799. #define M_BXF(label_num) \
  800. M_BRANCH(label_num), \
  801. I_BXFI(0)
  802. /**
  803. * Increment the stage counter by immediate value
  804. */
  805. #define I_STAGE_INC(imm_) { .alu_reg_s = { \
  806. .unused1 = 0, \
  807. .imm = imm_, \
  808. .unused2 = 0, \
  809. .sel = ALU_SEL_SINC, \
  810. .sub_opcode = SUB_OPCODE_ALU_CNT, \
  811. .opcode = OPCODE_ALU } }
  812. /**
  813. * Decrement the stage counter by immediate value
  814. */
  815. #define I_STAGE_DEC(imm_) { .alu_reg_s = { \
  816. .unused1 = 0, \
  817. .imm = imm_, \
  818. .unused2 = 0, \
  819. .sel = ALU_SEL_SDEC, \
  820. .sub_opcode = SUB_OPCODE_ALU_CNT, \
  821. .opcode = OPCODE_ALU } }
  822. /**
  823. * Reset the stage counter
  824. */
  825. #define I_STAGE_RST() { .alu_reg_s = { \
  826. .unused1 = 0, \
  827. .imm = 0, \
  828. .unused2 = 0, \
  829. .sel = ALU_SEL_SRST, \
  830. .sub_opcode = SUB_OPCODE_ALU_CNT, \
  831. .opcode = OPCODE_ALU } }
  832. /**
  833. * Macro: branch to label if the stage counter is less than immediate value
  834. *
  835. * This macro generates two ulp_insn_t values separated by a comma, and should
  836. * be used when defining contents of ulp_insn_t arrays. First value is not a
  837. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  838. * function.
  839. */
  840. #define M_BSLT(label_num, imm_value) \
  841. M_BRANCH(label_num), \
  842. I_JUMPS(0, imm_value, JUMPS_LT)
  843. /**
  844. * Macro: branch to label if the stage counter is greater than or equal to immediate value
  845. *
  846. * This macro generates two ulp_insn_t values separated by a comma, and should
  847. * be used when defining contents of ulp_insn_t arrays. First value is not a
  848. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  849. * function.
  850. */
  851. #define M_BSGE(label_num, imm_value) \
  852. M_BRANCH(label_num), \
  853. I_JUMPS(0, imm_value, JUMPS_GE)
  854. /**
  855. * Macro: branch to label if the stage counter is less than or equal to immediate value
  856. *
  857. * This macro generates two ulp_insn_t values separated by a comma, and should
  858. * be used when defining contents of ulp_insn_t arrays. First value is not a
  859. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  860. * function.
  861. */
  862. #define M_BSLE(label_num, imm_value) \
  863. M_BRANCH(label_num), \
  864. I_JUMPS(0, imm_value, JUMPS_LE)
  865. /**
  866. * Macro: branch to label if the stage counter is equal to immediate value.
  867. * Implemented using two JUMPS instructions:
  868. * JUMPS next, imm_value, LT
  869. * JUMPS label_num, imm_value, LE
  870. *
  871. * This macro generates three ulp_insn_t values separated by commas, and should
  872. * be used when defining contents of ulp_insn_t arrays. Second value is not a
  873. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  874. * function.
  875. */
  876. #define M_BSEQ(label_num, imm_value) \
  877. I_JUMPS(2, imm_value, JUMPS_LT), \
  878. M_BRANCH(label_num), \
  879. I_JUMPS(0, imm_value, JUMPS_LE)
  880. /**
  881. * Macro: branch to label if the stage counter is greater than immediate value.
  882. * Implemented using two instructions:
  883. * JUMPS next, imm_value, LE
  884. * JUMPS label_num, imm_value, GE
  885. *
  886. * This macro generates three ulp_insn_t values separated by commas, and should
  887. * be used when defining contents of ulp_insn_t arrays. Second value is not a
  888. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  889. * function.
  890. */
  891. #define M_BSGT(label_num, imm_value) \
  892. I_JUMPS(2, imm_value, JUMPS_LE), \
  893. M_BRANCH(label_num), \
  894. I_JUMPS(0, imm_value, JUMPS_GE)
  895. /**
  896. * Branch relative if (stage counter [comp_type] [imm_value]) evaluates to true.
  897. *
  898. * pc_offset is expressed in words, and can be from -127 to 127
  899. * imm_value is an 8-bit value to compare the stage counter against
  900. * comp_type is the type of comparison to perform: JUMPS_LT (<), JUMPS_GE (>=) or JUMPS_LE (<=)
  901. */
  902. #define I_JUMPS(pc_offset, imm_value, comp_type) { .bs = { \
  903. .imm = imm_value, \
  904. .unused = 0, \
  905. .cmp = comp_type, \
  906. .offset = abs(pc_offset), \
  907. .sign = (pc_offset >= 0) ? 0 : 1, \
  908. .sub_opcode = SUB_OPCODE_BS, \
  909. .opcode = OPCODE_BRANCH } }
  910. /**
  911. * Perform an I2C transaction with a slave device.
  912. * I_I2C_READ and I_I2C_WRITE are provided for convenience, instead of using this directly.
  913. *
  914. * Slave address (in 7-bit format) has to be set in advance into SENS_I2C_SLAVE_ADDRx register field, where x == slave_sel.
  915. * For read operations, 8 bits of read result is stored into R0 register.
  916. * For write operations, val will be written to sub_addr at [high_bit:low_bit]. Bits outside of this range are masked.
  917. */
  918. #define I_I2C_RW(sub_addr, val, low_bit, high_bit, slave_sel, rw_bit) { .i2c = {\
  919. .i2c_addr = sub_addr, \
  920. .data = val, \
  921. .low_bits = low_bit, \
  922. .high_bits = high_bit, \
  923. .i2c_sel = slave_sel, \
  924. .unused = 0, \
  925. .rw = rw_bit, \
  926. .opcode = OPCODE_I2C } }
  927. /**
  928. * Read a byte from the sub address of an I2C slave, and store the result in R0.
  929. *
  930. * Slave address (in 7-bit format) has to be set in advance into SENS_I2C_SLAVE_ADDRx register field, where x == slave_sel.
  931. */
  932. #define I_I2C_READ(slave_sel, sub_addr) I_I2C_RW(sub_addr, 0, 0, 0, slave_sel, SUB_OPCODE_I2C_RD)
  933. /**
  934. * Write a byte to the sub address of an I2C slave.
  935. *
  936. * Slave address (in 7-bit format) has to be set in advance into SENS_I2C_SLAVE_ADDRx register field, where x == slave_sel.
  937. */
  938. #define I_I2C_WRITE(slave_sel, sub_addr, val) I_I2C_RW(sub_addr, val, 0, 7, slave_sel, SUB_OPCODE_I2C_WR)
  939. #define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */
  940. /**
  941. * @brief Resolve all macro references in a program and load it into RTC memory
  942. * @param load_addr address where the program should be loaded, expressed in 32-bit words
  943. * @param program ulp_insn_t array with the program
  944. * @param psize size of the program, expressed in 32-bit words
  945. * @return
  946. * - ESP_OK on success
  947. * - ESP_ERR_NO_MEM if auxiliary temporary structure can not be allocated
  948. * - one of ESP_ERR_ULP_xxx if program is not valid or can not be loaded
  949. */
  950. esp_err_t ulp_process_macros_and_load(uint32_t load_addr, const ulp_insn_t* program, size_t* psize);
  951. /**
  952. * @brief Load ULP program binary into RTC memory
  953. *
  954. * ULP program binary should have the following format (all values little-endian):
  955. *
  956. * 1. MAGIC, (value 0x00706c75, 4 bytes)
  957. * 2. TEXT_OFFSET, offset of .text section from binary start (2 bytes)
  958. * 3. TEXT_SIZE, size of .text section (2 bytes)
  959. * 4. DATA_SIZE, size of .data section (2 bytes)
  960. * 5. BSS_SIZE, size of .bss section (2 bytes)
  961. * 6. (TEXT_OFFSET - 12) bytes of arbitrary data (will not be loaded into RTC memory)
  962. * 7. .text section
  963. * 8. .data section
  964. *
  965. * Linker script in components/ulp/ld/esp32.ulp.ld produces ELF files which
  966. * correspond to this format. This linker script produces binaries with load_addr == 0.
  967. *
  968. * @param load_addr address where the program should be loaded, expressed in 32-bit words
  969. * @param program_binary pointer to program binary
  970. * @param program_size size of the program binary
  971. * @return
  972. * - ESP_OK on success
  973. * - ESP_ERR_INVALID_ARG if load_addr is out of range
  974. * - ESP_ERR_INVALID_SIZE if program_size doesn't match (TEXT_OFFSET + TEXT_SIZE + DATA_SIZE)
  975. * - ESP_ERR_NOT_SUPPORTED if the magic number is incorrect
  976. */
  977. esp_err_t ulp_load_binary(uint32_t load_addr, const uint8_t* program_binary, size_t program_size);
  978. /**
  979. * @brief Run the program loaded into RTC memory
  980. * @param entry_point entry point, expressed in 32-bit words
  981. * @return ESP_OK on success
  982. */
  983. esp_err_t ulp_run(uint32_t entry_point);
  984. /**
  985. * @brief Set one of ULP wakeup period values
  986. *
  987. * ULP coprocessor starts running the program when the wakeup timer counts up
  988. * to a given value (called period). There are 5 period values which can be
  989. * programmed into SENS_ULP_CP_SLEEP_CYCx_REG registers, x = 0..4.
  990. * By default, wakeup timer will use the period set into SENS_ULP_CP_SLEEP_CYC0_REG,
  991. * i.e. period number 0. ULP program code can use SLEEP instruction to select
  992. * which of the SENS_ULP_CP_SLEEP_CYCx_REG should be used for subsequent wakeups.
  993. *
  994. * However, please note that SLEEP instruction issued (from ULP program) while the system
  995. * is in deep sleep mode does not have effect, and sleep cycle count 0 is used.
  996. *
  997. * @param period_index wakeup period setting number (0 - 4)
  998. * @param period_us wakeup period, us
  999. * @note The ULP FSM requires two clock cycles to wakeup before being able to run the program.
  1000. * Then additional 16 cycles are reserved after wakeup waiting until the 8M clock is stable.
  1001. * The FSM also requires two more clock cycles to go to sleep after the program execution is halted.
  1002. * The minimum wakeup period that may be set up for the ULP
  1003. * is equal to the total number of cycles spent on the above internal tasks.
  1004. * For a default configuration of the ULP running at 150kHz it makes about 133us.
  1005. * @return
  1006. * - ESP_OK on success
  1007. * - ESP_ERR_INVALID_ARG if period_index is out of range
  1008. */
  1009. esp_err_t ulp_set_wakeup_period(size_t period_index, uint32_t period_us);
  1010. #ifdef __cplusplus
  1011. }
  1012. #endif