ulp.h 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  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 "sdkconfig.h"
  19. #include "esp_err.h"
  20. #include "soc/soc.h"
  21. #include "ulp_common.h"
  22. #ifdef __cplusplus
  23. extern "C" {
  24. #endif
  25. #define ULP_FSM_PREPARE_SLEEP_CYCLES 2 /*!< Cycles spent by FSM preparing ULP for sleep */
  26. #define ULP_FSM_WAKEUP_SLEEP_CYCLES 2 /*!< Cycles spent by FSM waking up ULP from sleep */
  27. /**
  28. * @defgroup ulp_registers ULP coprocessor registers
  29. * @{
  30. */
  31. #define R0 0 /*!< general purpose register 0 */
  32. #define R1 1 /*!< general purpose register 1 */
  33. #define R2 2 /*!< general purpose register 2 */
  34. #define R3 3 /*!< general purpose register 3 */
  35. /**@}*/
  36. /** @defgroup ulp_opcodes ULP coprocessor opcodes, sub opcodes, and various modifiers/flags
  37. *
  38. * These definitions are not intended to be used directly.
  39. * They are used in definitions of instructions later on.
  40. *
  41. * @{
  42. */
  43. #define OPCODE_WR_REG 1 /*!< Instruction: write peripheral register (RTC_CNTL/RTC_IO/SARADC) (not implemented yet) */
  44. #define OPCODE_RD_REG 2 /*!< Instruction: read peripheral register (RTC_CNTL/RTC_IO/SARADC) (not implemented yet) */
  45. #define RD_REG_PERIPH_RTC_CNTL 0 /*!< Identifier of RTC_CNTL peripheral for RD_REG and WR_REG instructions */
  46. #define RD_REG_PERIPH_RTC_IO 1 /*!< Identifier of RTC_IO peripheral for RD_REG and WR_REG instructions */
  47. #define RD_REG_PERIPH_SENS 2 /*!< Identifier of SARADC peripheral for RD_REG and WR_REG instructions */
  48. #define RD_REG_PERIPH_RTC_I2C 3 /*!< Identifier of RTC_I2C peripheral for RD_REG and WR_REG instructions */
  49. #define OPCODE_I2C 3 /*!< Instruction: read/write I2C (not implemented yet) */
  50. #define OPCODE_DELAY 4 /*!< Instruction: delay (nop) for a given number of cycles */
  51. #define OPCODE_ADC 5 /*!< Instruction: SAR ADC measurement (not implemented yet) */
  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 between counter register and an immediate (not implemented yet)*/
  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. #ifdef CONFIG_IDF_TARGET_ESP32S2BETA
  66. #define ALU_SEL_INC 0 /*!< Stage_cnt = Stage_cnt + Imm */
  67. #define ALU_SEL_DEC 1 /*!< Stage_cnt = Stage_cnt - Imm */
  68. #define ALU_SEL_RST 2 /*!< Stage_cnt = 0 */
  69. #endif
  70. #define OPCODE_BRANCH 8 /*!< Branch instructions */
  71. #define BX_JUMP_TYPE_DIRECT 0 /*!< Unconditional jump */
  72. #define BX_JUMP_TYPE_ZERO 1 /*!< Branch if last ALU result is zero */
  73. #define BX_JUMP_TYPE_OVF 2 /*!< Branch if last ALU operation caused and overflow */
  74. #ifdef CONFIG_IDF_TARGET_ESP32
  75. #define B_CMP_L 0 /*!< Branch if R0 is less than an immediate */
  76. #define B_CMP_GE 1 /*!< Branch if R0 is greater than or equal to an immediate */
  77. #define SUB_OPCODE_BX 0 /*!< Branch to absolute PC (immediate or in register) */
  78. #define SUB_OPCODE_B 1 /*!< Branch to a relative offset */
  79. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  80. #define B_CMP_L 1 /*!< Branch if R0 is less than an immediate */
  81. #define B_CMP_GE 2 /*!< Branch if R0 is greater than an immediate */
  82. #define B_CMP_EQ 4 /*!< Branch if R0 is equal to an immediate */
  83. #define SUB_OPCODE_BX 1 /*!< Branch to absolute PC (immediate or in register) */
  84. #define SUB_OPCODE_B 0 /*!< Branch to a relative offset base on R0 */
  85. #define SUB_OPCODE_B_STAGE 2 /*!< Branch to a relative offset base on stage reg */
  86. #endif
  87. #define OPCODE_END 9 /*!< Stop executing the program */
  88. #define SUB_OPCODE_END 0 /*!< Stop executing the program and optionally wake up the chip */
  89. #define SUB_OPCODE_SLEEP 1 /*!< Stop executing the program and run it again after selected interval */
  90. #define OPCODE_TSENS 10 /*!< Instruction: temperature sensor measurement (not implemented yet) */
  91. #define OPCODE_HALT 11 /*!< Halt the coprocessor */
  92. #define OPCODE_LD 13 /*!< Indirect load lower 16 bits from RTC memory */
  93. #define OPCODE_MACRO 15 /*!< Not a real opcode. Used to identify labels and branches in the program */
  94. #define SUB_OPCODE_MACRO_LABEL 0 /*!< Label macro */
  95. #define SUB_OPCODE_MACRO_BRANCH 1 /*!< Branch macro */
  96. #ifdef CONFIG_IDF_TARGET_ESP32S2BETA
  97. #define OPCODE_SLEEP_WAIT 4
  98. #endif
  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. union ulp_insn {
  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. #ifdef CONFIG_IDF_TARGET_ESP32
  121. struct {
  122. uint32_t dreg : 2; /*!< Register which contains data to store */
  123. uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */
  124. uint32_t unused1 : 6; /*!< Unused */
  125. uint32_t offset : 11; /*!< Offset to add to sreg */
  126. uint32_t unused2 : 4; /*!< Unused */
  127. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ST) */
  128. uint32_t opcode : 4; /*!< Opcode (OPCODE_ST) */
  129. } st; /*!< Format of ST instruction */
  130. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  131. struct {
  132. uint32_t dreg : 2; /*!< Data address register number */
  133. uint32_t sreg : 2; /*!< Base address register number */
  134. uint32_t data_label : 2; /*!< Data label */
  135. uint32_t upper : 1; /*!< High and low half-word Select 1: Write high half-word; 0 : write low half-word; */
  136. uint32_t write_way : 2; /*!< Write number Mode 0 : full word write; 1: with data_label; 3: without label; */
  137. uint32_t unused1 : 1; /*!< Unused */
  138. uint32_t offset : 11; /*!< When you select automatic storage, you need to configure the base address offset*/
  139. uint32_t unused2 : 4; /*!< Unused */
  140. uint32_t wr_auto : 1; /*!< Automatic storage selection enabled (burst mode)*/
  141. uint32_t offset_set : 1; /*!< Configure OFFSET enable */
  142. uint32_t manul_en : 1; /*!< Manual storage selection enabled */
  143. uint32_t opcode : 4; /*!< Opcode (OPCODE_ST) */
  144. } st; /*!< Format of ST instruction */
  145. #endif
  146. #ifdef CONFIG_IDF_TARGET_ESP32
  147. struct {
  148. uint32_t dreg : 2; /*!< Register where the data should be loaded to */
  149. uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */
  150. uint32_t unused1 : 6; /*!< Unused */
  151. uint32_t offset : 11; /*!< Offset to add to sreg */
  152. uint32_t unused2 : 7; /*!< Unused */
  153. uint32_t opcode : 4; /*!< Opcode (OPCODE_LD) */
  154. } ld; /*!< Format of LD instruction */
  155. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  156. struct {
  157. uint32_t dreg : 2; /*!< Register where the data should be loaded to */
  158. uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */
  159. uint32_t unused1 : 6; /*!< Unused */
  160. uint32_t offset : 11; /*!< Offset to add to sreg */
  161. uint32_t unused2 : 6; /*!< Unused */
  162. uint32_t rd_upper: 1;
  163. uint32_t opcode : 4; /*!< Opcode (OPCODE_LD) */
  164. } ld; /*!< Format of LD instruction */
  165. #endif
  166. struct {
  167. uint32_t unused : 28; /*!< Unused */
  168. uint32_t opcode : 4; /*!< Opcode (OPCODE_HALT) */
  169. } halt; /*!< Format of HALT instruction */
  170. #ifdef CONFIG_IDF_TARGET_ESP32
  171. struct {
  172. uint32_t dreg : 2; /*!< Register which contains target PC, expressed in words (used if .reg == 1) */
  173. uint32_t addr : 11; /*!< Target PC, expressed in words (used if .reg == 0) */
  174. uint32_t unused : 8; /*!< Unused */
  175. uint32_t reg : 1; /*!< Target PC in register (1) or immediate (0) */
  176. uint32_t type : 3; /*!< Jump condition (BX_JUMP_TYPE_xxx) */
  177. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_BX) */
  178. uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
  179. } bx; /*!< Format of BRANCH instruction (absolute address) */
  180. struct {
  181. uint32_t imm : 16; /*!< Immediate value to compare against */
  182. uint32_t cmp : 1; /*!< Comparison to perform: B_CMP_L or B_CMP_GE */
  183. uint32_t offset : 7; /*!< Absolute value of target PC offset w.r.t. current PC, expressed in words */
  184. uint32_t sign : 1; /*!< Sign of target PC offset: 0: positive, 1: negative */
  185. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_B) */
  186. uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
  187. } b; /*!< Format of BRANCH instruction (relative address) */
  188. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  189. struct {
  190. uint32_t dreg : 2; /*!< Register which contains target PC, expressed in words (used if .reg == 1) */
  191. uint32_t addr : 11; /*!< Target PC, expressed in words (used if .reg == 0) */
  192. uint32_t unused : 8; /*!< Unused */
  193. uint32_t reg : 1; /*!< Target PC in register (1) or immediate (0) */
  194. uint32_t type : 3; /*!< Jump condition (BX_JUMP_TYPE_xxx) */
  195. uint32_t unused1 : 1; /*!< Unused */
  196. uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_BX) */
  197. uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
  198. } bx; /*!< Format of BRANCH instruction (absolute address) */
  199. struct {
  200. uint32_t imm : 15; /*!< Immediate value to compare against */
  201. uint32_t cmp : 3; /*!< Comparison to perform: B_CMP_L or B_CMP_GE */
  202. uint32_t offset : 7; /*!< Absolute value of target PC offset w.r.t. current PC, expressed in words */
  203. uint32_t sign : 1; /*!< Sign of target PC offset: 0: positive, 1: negative */
  204. uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_B) */
  205. uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
  206. } b;
  207. #endif
  208. #ifdef CONFIG_IDF_TARGET_ESP32
  209. struct {
  210. uint32_t dreg : 2; /*!< Destination register */
  211. uint32_t sreg : 2; /*!< Register with operand A */
  212. uint32_t treg : 2; /*!< Register with operand B */
  213. uint32_t unused : 15; /*!< Unused */
  214. uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
  215. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ALU_REG) */
  216. uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
  217. } alu_reg; /*!< Format of ALU instruction (both sources are registers) */
  218. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  219. struct {
  220. uint32_t dreg : 2; /*!< Destination register */
  221. uint32_t sreg : 2; /*!< Register with operand A */
  222. uint32_t treg : 2; /*!< Register with operand B */
  223. uint32_t unused : 15; /*!< Unused */
  224. uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
  225. uint32_t unused1 : 1; /*!< Unused */
  226. uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_ALU_REG) */
  227. uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
  228. } alu_reg; /*!< Format of ALU instruction (both sources are registers) */
  229. #endif
  230. #ifdef CONFIG_IDF_TARGET_ESP32
  231. struct {
  232. uint32_t dreg : 2; /*!< Destination register */
  233. uint32_t sreg : 2; /*!< Register with operand A */
  234. uint32_t imm : 16; /*!< Immediate value of operand B */
  235. uint32_t unused : 1; /*!< Unused */
  236. uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
  237. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */
  238. uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
  239. } alu_imm; /*!< Format of ALU instruction (one source is an immediate) */
  240. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  241. struct {
  242. uint32_t dreg : 2; /*!< Destination register */
  243. uint32_t sreg : 2; /*!< Register with operand A */
  244. uint32_t imm : 16; /*!< Immediate value of operand B */
  245. uint32_t unused : 1; /*!< Unused */
  246. uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
  247. uint32_t unused1 : 1; /*!< Unused */
  248. uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */
  249. uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
  250. } alu_imm; /*!< Format of ALU instruction (one source is an immediate) */
  251. struct {
  252. uint32_t unused : 4; /*!< Unused */
  253. uint32_t imm : 16; /*!< Immediate value of operand B */
  254. uint32_t unused1 : 1; /*!< Unused */
  255. uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
  256. uint32_t unused2 : 1; /*!< Unused */
  257. uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */
  258. uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
  259. } alu_cnt; /*!< Format of ALU instruction (one source is an immediate) */
  260. #endif
  261. struct {
  262. uint32_t addr : 8; /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */
  263. uint32_t periph_sel : 2; /*!< Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) */
  264. uint32_t data : 8; /*!< 8 bits of data to write */
  265. uint32_t low : 5; /*!< Low bit */
  266. uint32_t high : 5; /*!< High bit */
  267. uint32_t opcode : 4; /*!< Opcode (OPCODE_WR_REG) */
  268. } wr_reg; /*!< Format of WR_REG instruction */
  269. struct {
  270. uint32_t addr : 8; /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */
  271. uint32_t periph_sel : 2; /*!< Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) */
  272. uint32_t unused : 8; /*!< Unused */
  273. uint32_t low : 5; /*!< Low bit */
  274. uint32_t high : 5; /*!< High bit */
  275. uint32_t opcode : 4; /*!< Opcode (OPCODE_WR_REG) */
  276. } rd_reg; /*!< Format of RD_REG instruction */
  277. #ifdef CONFIG_IDF_TARGET_ESP32
  278. struct {
  279. uint32_t dreg : 2; /*!< Register where to store ADC result */
  280. uint32_t mux : 4; /*!< Select SARADC pad (mux + 1) */
  281. uint32_t sar_sel : 1; /*!< Select SARADC0 (0) or SARADC1 (1) */
  282. uint32_t unused1 : 1; /*!< Unused */
  283. uint32_t cycles : 16; /*!< TBD, cycles used for measurement */
  284. uint32_t unused2 : 4; /*!< Unused */
  285. uint32_t opcode: 4; /*!< Opcode (OPCODE_ADC) */
  286. } adc; /*!< Format of ADC instruction */
  287. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  288. struct {
  289. uint32_t dreg : 2; /*!< Register where to store ADC result */
  290. uint32_t mux : 4; /*!< Select SARADC pad (mux + 1) */
  291. uint32_t sar_sel : 1; /*!< Select SARADC0 (0) or SARADC1 (1) */
  292. uint32_t hall_phase : 1; /*!< Unused */
  293. uint32_t xpd_hall : 1; /*!< Unused */
  294. uint32_t unused1 : 19; /*!< Unused */
  295. uint32_t opcode: 4; /*!< Opcode (OPCODE_ADC) */
  296. } adc;
  297. #endif
  298. struct {
  299. uint32_t dreg : 2; /*!< Register where to store temperature measurement result */
  300. uint32_t wait_delay: 14; /*!< Cycles to wait after measurement is done */
  301. uint32_t reserved: 12; /*!< Reserved, set to 0 */
  302. uint32_t opcode: 4; /*!< Opcode (OPCODE_TSENS) */
  303. } tsens; /*!< Format of TSENS instruction */
  304. struct {
  305. uint32_t i2c_addr : 8; /*!< I2C slave address */
  306. uint32_t data : 8; /*!< Data to read or write */
  307. uint32_t low_bits : 3; /*!< TBD */
  308. uint32_t high_bits : 3; /*!< TBD */
  309. uint32_t i2c_sel : 4; /*!< TBD, select reg_i2c_slave_address[7:0] */
  310. uint32_t unused : 1; /*!< Unused */
  311. uint32_t rw : 1; /*!< Write (1) or read (0) */
  312. uint32_t opcode : 4; /*!< Opcode (OPCODE_I2C) */
  313. } i2c; /*!< Format of I2C instruction */
  314. #ifdef CONFIG_IDF_TARGET_ESP32
  315. struct {
  316. uint32_t wakeup : 1; /*!< Set to 1 to wake up chip */
  317. uint32_t unused : 24; /*!< Unused */
  318. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_WAKEUP) */
  319. uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */
  320. } end; /*!< Format of END instruction with wakeup */
  321. struct {
  322. uint32_t cycle_sel : 4; /*!< Select which one of SARADC_ULP_CP_SLEEP_CYCx_REG to get the sleep duration from */
  323. uint32_t unused : 21; /*!< Unused */
  324. uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_SLEEP) */
  325. uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */
  326. } sleep; /*!< Format of END instruction with sleep */
  327. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  328. struct {
  329. uint32_t wakeup : 1; /*!< Set to 1 to wake up chip */
  330. uint32_t unused : 25; /*!< Unused */
  331. uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_WAKEUP) */
  332. uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */
  333. } end;
  334. struct {
  335. uint32_t cycle_sel : 16; /*!< Select which one of SARADC_ULP_CP_SLEEP_CYCx_REG to get the sleep duration from */
  336. uint32_t unused : 12; /*!< Unused */
  337. uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */
  338. } sleep;
  339. #endif
  340. struct {
  341. uint32_t label : 16; /*!< Label number */
  342. uint32_t unused : 8; /*!< Unused */
  343. uint32_t sub_opcode : 4; /*!< SUB_OPCODE_MACRO_LABEL or SUB_OPCODE_MACRO_BRANCH */
  344. uint32_t opcode: 4; /*!< Opcode (OPCODE_MACRO) */
  345. } macro; /*!< Format of tokens used by LABEL and BRANCH macros */
  346. };
  347. typedef union ulp_insn ulp_insn_t;
  348. _Static_assert(sizeof(ulp_insn_t) == 4, "ULP coprocessor instruction size should be 4 bytes");
  349. /**
  350. * Delay (nop) for a given number of cycles
  351. */
  352. #define I_DELAY(cycles_) { .delay = {\
  353. .cycles = cycles_, \
  354. .unused = 0, \
  355. .opcode = OPCODE_DELAY } }
  356. /**
  357. * Halt the coprocessor.
  358. *
  359. * This instruction halts the coprocessor, but keeps ULP timer active.
  360. * As such, ULP program will be restarted again by timer.
  361. * To stop the program and prevent the timer from restarting the program,
  362. * use I_END(0) instruction.
  363. */
  364. #define I_HALT() { .halt = {\
  365. .unused = 0, \
  366. .opcode = OPCODE_HALT } }
  367. /**
  368. * Map SoC peripheral register to periph_sel field of RD_REG and WR_REG
  369. * instructions.
  370. *
  371. * @param reg peripheral register in RTC_CNTL_, RTC_IO_, SENS_, RTC_I2C peripherals.
  372. * @return periph_sel value for the peripheral to which this register belongs.
  373. */
  374. static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
  375. uint32_t ret = 3;
  376. if (reg < DR_REG_RTCCNTL_BASE) {
  377. assert(0 && "invalid register base");
  378. } else if (reg < DR_REG_RTCIO_BASE) {
  379. ret = RD_REG_PERIPH_RTC_CNTL;
  380. } else if (reg < DR_REG_SENS_BASE) {
  381. ret = RD_REG_PERIPH_RTC_IO;
  382. } else if (reg < DR_REG_RTC_I2C_BASE){
  383. ret = RD_REG_PERIPH_SENS;
  384. } else if (reg < DR_REG_IO_MUX_BASE){
  385. ret = RD_REG_PERIPH_RTC_I2C;
  386. } else {
  387. assert(0 && "invalid register base");
  388. }
  389. return ret;
  390. }
  391. /**
  392. * Write literal value to a peripheral register
  393. *
  394. * reg[high_bit : low_bit] = val
  395. * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
  396. */
  397. #define I_WR_REG(reg, low_bit, high_bit, val) {.wr_reg = {\
  398. .addr = (reg & 0xff) / sizeof(uint32_t), \
  399. .periph_sel = SOC_REG_TO_ULP_PERIPH_SEL(reg), \
  400. .data = val, \
  401. .low = low_bit, \
  402. .high = high_bit, \
  403. .opcode = OPCODE_WR_REG } }
  404. /**
  405. * Read from peripheral register into R0
  406. *
  407. * R0 = reg[high_bit : low_bit]
  408. * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
  409. */
  410. #define I_RD_REG(reg, low_bit, high_bit) {.rd_reg = {\
  411. .addr = (reg & 0xff) / sizeof(uint32_t), \
  412. .periph_sel = SOC_REG_TO_ULP_PERIPH_SEL(reg), \
  413. .unused = 0, \
  414. .low = low_bit, \
  415. .high = high_bit, \
  416. .opcode = OPCODE_RD_REG } }
  417. /**
  418. * Set or clear a bit in the peripheral register.
  419. *
  420. * Sets bit (1 << shift) of register reg to value val.
  421. * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
  422. */
  423. #define I_WR_REG_BIT(reg, shift, val) I_WR_REG(reg, shift, shift, val)
  424. /**
  425. * Wake the SoC from deep sleep.
  426. *
  427. * This instruction initiates wake up from deep sleep.
  428. * Use esp_deep_sleep_enable_ulp_wakeup to enable deep sleep wakeup
  429. * triggered by the ULP before going into deep sleep.
  430. * Note that ULP program will still keep running until the I_HALT
  431. * instruction, and it will still be restarted by timer at regular
  432. * intervals, even when the SoC is woken up.
  433. *
  434. * To stop the ULP program, use I_HALT instruction.
  435. *
  436. * To disable the timer which start ULP program, use I_END()
  437. * instruction. I_END instruction clears the
  438. * RTC_CNTL_ULP_CP_SLP_TIMER_EN_S bit of RTC_CNTL_STATE0_REG
  439. * register, which controls the ULP timer.
  440. */
  441. #define I_WAKE() { .end = { \
  442. .wakeup = 1, \
  443. .unused = 0, \
  444. .sub_opcode = SUB_OPCODE_END, \
  445. .opcode = OPCODE_END } }
  446. /**
  447. * Stop ULP program timer.
  448. *
  449. * This is a convenience macro which disables the ULP program timer.
  450. * Once this instruction is used, ULP program will not be restarted
  451. * anymore until ulp_run function is called.
  452. *
  453. * ULP program will continue running after this instruction. To stop
  454. * the currently running program, use I_HALT().
  455. */
  456. #ifdef CONFIG_IDF_TARGET_ESP32
  457. #define I_END() \
  458. I_WR_REG_BIT(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN_S, 0)
  459. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  460. #define I_END() \
  461. I_WR_REG_BIT(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN_S, 0)
  462. #endif
  463. /**
  464. * Select the time interval used to run ULP program.
  465. *
  466. * This instructions selects which of the SENS_SLEEP_CYCLES_Sx
  467. * registers' value is used by the ULP program timer.
  468. * When the ULP program stops at I_HALT instruction, ULP program
  469. * timer start counting. When the counter reaches the value of
  470. * the selected SENS_SLEEP_CYCLES_Sx register, ULP program
  471. * start running again from the start address (passed to the ulp_run
  472. * function).
  473. * There are 5 SENS_SLEEP_CYCLES_Sx registers, so 0 <= timer_idx < 5.
  474. *
  475. * By default, SENS_SLEEP_CYCLES_S0 register is used by the ULP
  476. * program timer.
  477. */
  478. #ifdef CONFIG_IDF_TARGET_ESP32
  479. #define I_SLEEP_CYCLE_SEL(timer_idx) { .sleep = { \
  480. .cycle_sel = timer_idx, \
  481. .unused = 0, \
  482. .sub_opcode = SUB_OPCODE_SLEEP, \
  483. .opcode = OPCODE_END } }
  484. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  485. #define I_SLEEP_CYCLE_SEL(timer_idx) { .sleep = { \
  486. .cycle_sel = timer_idx, \
  487. .unused = 0, \
  488. .opcode = OPCODE_SLEEP_WAIT } }
  489. #endif
  490. /**
  491. * Perform temperature sensor measurement and store it into reg_dest.
  492. *
  493. * Delay can be set between 1 and ((1 << 14) - 1). Higher values give
  494. * higher measurement resolution.
  495. */
  496. #define I_TSENS(reg_dest, delay) { .tsens = { \
  497. .dreg = reg_dest, \
  498. .wait_delay = delay, \
  499. .reserved = 0, \
  500. .opcode = OPCODE_TSENS } }
  501. /**
  502. * Perform ADC measurement and store result in reg_dest.
  503. *
  504. * adc_idx selects ADC (0 or 1).
  505. * pad_idx selects ADC pad (0 - 7).
  506. */
  507. #ifdef CONFIG_IDF_TARGET_ESP32
  508. #define I_ADC(reg_dest, adc_idx, pad_idx) { .adc = {\
  509. .dreg = reg_dest, \
  510. .mux = pad_idx + 1, \
  511. .sar_sel = adc_idx, \
  512. .unused1 = 0, \
  513. .cycles = 0, \
  514. .unused2 = 0, \
  515. .opcode = OPCODE_ADC } }
  516. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  517. #define I_ADC(reg_dest, adc_idx, pad_idx) { .adc = {\
  518. .dreg = reg_dest, \
  519. .mux = pad_idx + 1, \
  520. .sar_sel = adc_idx, \
  521. .hall_phase = 0, \
  522. .xpd_hall = 0, \
  523. .unused1 = 0, \
  524. .opcode = OPCODE_ADC } }
  525. #endif
  526. /**
  527. * Store value from register reg_val into RTC memory.
  528. *
  529. * The value is written to an offset calculated by adding value of
  530. * reg_addr register and offset_ field (this offset is expressed in 32-bit words).
  531. * 32 bits written to RTC memory are built as follows:
  532. * - bits [31:21] hold the PC of current instruction, expressed in 32-bit words
  533. * - bits [20:16] = 5'b1
  534. * - bits [15:0] are assigned the contents of reg_val
  535. *
  536. * RTC_SLOW_MEM[addr + offset_] = { 5'b0, insn_PC[10:0], val[15:0] }
  537. */
  538. #ifdef CONFIG_IDF_TARGET_ESP32
  539. #define I_ST(reg_val, reg_addr, offset_) { .st = { \
  540. .dreg = reg_val, \
  541. .sreg = reg_addr, \
  542. .unused1 = 0, \
  543. .offset = offset_, \
  544. .unused2 = 0, \
  545. .sub_opcode = SUB_OPCODE_ST, \
  546. .opcode = OPCODE_ST } }
  547. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  548. /**
  549. * burst Mode: write to consecutive address spaces.
  550. * STW, STC instructions for the Class burst storage instructions for continuous address space write operation;
  551. * Need to be used with the SET_OFFSET instruction, you first need to set the start address offset by SET_OFFSET, SREG is the base address,
  552. * Where STW instruction WORD instruction, each execution time, address offset+1;STC for the half-word operation
  553. * (First write high 16bit current address, the Second Write low 16bit current address), each performed twice, the address offset+1.
  554. * Note: when using STC, you must write a word, that is, a burst operation instruction must be an even number.
  555. */
  556. #define I_STO(offset_) { .st = { \
  557. .dreg = 0, \
  558. .sreg = 0, \
  559. .data_label = 0, \
  560. .upper = 0, \
  561. .write_way = 0, \
  562. .unused1 = 0, \
  563. .offset = offset_, \
  564. .unused2 = 0, \
  565. .wr_auto = 0, \
  566. .offset_set = 0, \
  567. .manul_en = 1, \
  568. .opcode = OPCODE_ST } }
  569. #define I_STW(reg_val, reg_addr) { .st = { \
  570. .dreg = reg_val, \
  571. .sreg = reg_addr, \
  572. .data_label = 0, \
  573. .upper = 0, \
  574. .write_way = 0, \
  575. .unused1 = 0, \
  576. .offset = 0, \
  577. .unused2 = 0, \
  578. .wr_auto = 1, \
  579. .offset_set = 0, \
  580. .manul_en = 0, \
  581. .opcode = OPCODE_ST } }
  582. #define I_STC(reg_val, reg_addr) { .st = { \
  583. .dreg = reg_val, \
  584. .sreg = reg_addr, \
  585. .data_label = 0, \
  586. .upper = 0, \
  587. .write_way = 3, \
  588. .unused1 = 0, \
  589. .offset = 0, \
  590. .unused2 = 0, \
  591. .wr_auto = 1, \
  592. .offset_set = 0, \
  593. .manul_en = 0, \
  594. .opcode = OPCODE_ST } }
  595. /**
  596. * Single mode of operation: write to a single address space.
  597. *
  598. * Loads 16 LSBs from RTC memory word given by the sum of value in reg_addr and
  599. * value of offset_.
  600. */
  601. /* Mem [ Rsrc1 + offset ]{31:0} = {PC[10:0], 5�d0,Rdst[15:0]} */
  602. #define I_ST(reg_val, reg_addr, offset_) { .st = { \
  603. .dreg = reg_val, \
  604. .sreg = reg_addr, \
  605. .data_label = 0, \
  606. .upper = 0, \
  607. .write_way = 0, \
  608. .unused1 = 0, \
  609. .offset = offset_, \
  610. .unused2 = 0, \
  611. .wr_auto = 0, \
  612. .offset_set = 0, \
  613. .manul_en = 1, \
  614. .opcode = OPCODE_ST } }
  615. /* Mem [ Rsrc1 + offset ]{31:16} = {Rdst[15:0]} */
  616. #define I_STM32U(reg_val, reg_addr, offset_) { .st = { \
  617. .dreg = reg_val, \
  618. .sreg = reg_addr, \
  619. .data_label = 0, \
  620. .upper = 1, \
  621. .write_way = 3, \
  622. .unused1 = 0, \
  623. .offset = offset_, \
  624. .unused1 = 0, \
  625. .wr_auto = 0, \
  626. .offset_set = 0, \
  627. .manul_en = 1, \
  628. .opcode = OPCODE_ST } }
  629. /* Mem [ Rsrc1 + offset ]{15:0} = {Rdst[15:0]} */
  630. #define I_STM32L(reg_val, reg_addr, offset_) { .st = { \
  631. .dreg = reg_val, \
  632. .sreg = reg_addr, \
  633. .data_label = 0, \
  634. .upper = 0, \
  635. .write_way = 3, \
  636. .unused1 = 0, \
  637. .offset = offset_, \
  638. .unused2 = 0, \
  639. .wr_auto = 0, \
  640. .offset_set = 0, \
  641. .manul_en = 1, \
  642. .opcode = OPCODE_ST } }
  643. /* Mem [ Rsrc1 + offset ]{31:0} = {data_label[1:0],Rdst[13:0]} */
  644. #define I_STMLBU(reg_val, reg_addr, label, offset_) { .st = { \
  645. .dreg = reg_val, \
  646. .sreg = reg_addr, \
  647. .data_label = label, \
  648. .upper = 1, \
  649. .write_way = 1, \
  650. .unused1 = 0, \
  651. .offset = offset_, \
  652. .unused1 = 0, \
  653. .wr_auto = 0, \
  654. .offset_set = 0, \
  655. .manul_en = 1, \
  656. .opcode = OPCODE_ST } }
  657. /* Mem [ Rsrc1 + offset ]{15:0} = {data_label[1:0],Rdst[13:0]} */
  658. #define I_STMLBL(reg_val, reg_addr, label, offset_) { .st = { \
  659. .dreg = reg_val, \
  660. .sreg = reg_addr, \
  661. .data_label = label, \
  662. .upper = 0, \
  663. .write_way = 1, \
  664. .unused1 = 0, \
  665. .offset = offset_, \
  666. .unused2 = 0, \
  667. .wr_auto = 0, \
  668. .offset_set = 0, \
  669. .manul_en = 1, \
  670. .opcode = OPCODE_ST } }
  671. #endif
  672. /**
  673. * Load value from RTC memory into reg_dest register.
  674. *
  675. * Loads 16 LSBs from RTC memory word given by the sum of value in reg_addr and
  676. * value of offset_.
  677. */
  678. #ifdef CONFIG_IDF_TARGET_ESP32
  679. #define I_LD(reg_dest, reg_addr, offset_) { .ld = { \
  680. .dreg = reg_dest, \
  681. .sreg = reg_addr, \
  682. .unused1 = 0, \
  683. .offset = offset_, \
  684. .unused2 = 0, \
  685. .opcode = OPCODE_LD } }
  686. #elif defined CONFIG_IDF_TARGET_ESP32S2BETA
  687. #define I_LD(reg_dest, reg_addr, offset_) { .ld = { \
  688. .dreg = reg_dest, \
  689. .sreg = reg_addr, \
  690. .unused1 = 0, \
  691. .offset = offset_, \
  692. .unused2 = 0, \
  693. .rd_upper = 0, \
  694. .opcode = OPCODE_LD } }
  695. #endif
  696. /**
  697. * Branch relative if R0 less than immediate value.
  698. *
  699. * pc_offset is expressed in words, and can be from -127 to 127
  700. * imm_value is a 16-bit value to compare R0 against
  701. */
  702. #define I_BL(pc_offset, imm_value) { .b = { \
  703. .imm = imm_value, \
  704. .cmp = B_CMP_L, \
  705. .offset = abs(pc_offset), \
  706. .sign = (pc_offset >= 0) ? 0 : 1, \
  707. .sub_opcode = SUB_OPCODE_B, \
  708. .opcode = OPCODE_BRANCH } }
  709. #ifdef CONFIG_IDF_TARGET_ESP32
  710. /**
  711. * Branch relative if R0 greater or equal than immediate value.
  712. *
  713. * pc_offset is expressed in words, and can be from -127 to 127
  714. * imm_value is a 16-bit value to compare R0 against
  715. */
  716. #define I_BGE(pc_offset, imm_value) { .b = { \
  717. .imm = imm_value, \
  718. .cmp = B_CMP_GE, \
  719. .offset = abs(pc_offset), \
  720. .sign = (pc_offset >= 0) ? 0 : 1, \
  721. .sub_opcode = SUB_OPCODE_B, \
  722. .opcode = OPCODE_BRANCH } }
  723. #endif
  724. #ifdef CONFIG_IDF_TARGET_ESP32S2BETA
  725. /**
  726. * Branch relative if R0 greater than immediate value.
  727. *
  728. * pc_offset is expressed in words, and can be from -127 to 127
  729. * imm_value is a 16-bit value to compare R0 against
  730. */
  731. #define I_BG(pc_offset, imm_value) { .b = { \
  732. .imm = imm_value, \
  733. .cmp = B_CMP_GE, \
  734. .offset = abs(pc_offset), \
  735. .sign = (pc_offset >= 0) ? 0 : 1, \
  736. .sub_opcode = SUB_OPCODE_B, \
  737. .opcode = OPCODE_BRANCH } }
  738. /**
  739. * Branch relative if R0 equal to immediate value.
  740. *
  741. * pc_offset is expressed in words, and can be from -127 to 127
  742. * imm_value is a 16-bit value to compare R0 against
  743. */
  744. #define I_BE(pc_offset, imm_value) { .b = { \
  745. .imm = imm_value, \
  746. .cmp = B_CMP_EQ, \
  747. .offset = abs(pc_offset), \
  748. .sign = (pc_offset >= 0) ? 0 : 1, \
  749. .sub_opcode = SUB_OPCODE_B, \
  750. .opcode = OPCODE_BRANCH } }
  751. /*
  752. * Branch to a relative offset base on stage reg
  753. * If stage reg less imm_value, PC will jump pc_offset.
  754. */
  755. #define I_BRLS(pc_offset, imm_value) { .b = { \
  756. .imm = imm_value, \
  757. .cmp = B_CMP_L, \
  758. .offset = abs(pc_offset), \
  759. .sign = (pc_offset >= 0) ? 0 : 1, \
  760. .sub_opcode = SUB_OPCODE_B_STAGE, \
  761. .opcode = OPCODE_BRANCH } }
  762. /*
  763. * Branch to a relative offset base on stage reg
  764. * If stage reg greater imm_value, PC will jump pc_offset.
  765. */
  766. #define I_BRGS(pc_offset, imm_value) { .b = { \
  767. .imm = imm_value, \
  768. .cmp = B_CMP_GE, \
  769. .offset = abs(pc_offset), \
  770. .sign = (pc_offset >= 0) ? 0 : 1, \
  771. .sub_opcode = SUB_OPCODE_B_STAGE, \
  772. .opcode = OPCODE_BRANCH } }
  773. /*
  774. * Branch to a relative offset base on stage reg
  775. * If stage reg equal to imm_value, PC will jump pc_offset.
  776. */
  777. #define I_BRES(pc_offset, imm_value) { .b = { \
  778. .imm = imm_value, \
  779. .cmp = B_CMP_EQ, \
  780. .offset = abs(pc_offset), \
  781. .sign = (pc_offset >= 0) ? 0 : 1, \
  782. .sub_opcode = SUB_OPCODE_B_STAGE, \
  783. .opcode = OPCODE_BRANCH } }
  784. #endif
  785. /**
  786. * Unconditional branch to absolute PC, address in register.
  787. *
  788. * reg_pc is the register which contains address to jump to.
  789. * Address is expressed in 32-bit words.
  790. */
  791. #define I_BXR(reg_pc) { .bx = { \
  792. .dreg = reg_pc, \
  793. .addr = 0, \
  794. .unused = 0, \
  795. .reg = 1, \
  796. .type = BX_JUMP_TYPE_DIRECT, \
  797. .unused1 = 0, \
  798. .sub_opcode = SUB_OPCODE_BX, \
  799. .opcode = OPCODE_BRANCH } }
  800. /**
  801. * Unconditional branch to absolute PC, immediate address.
  802. *
  803. * Address imm_pc is expressed in 32-bit words.
  804. */
  805. #define I_BXI(imm_pc) { .bx = { \
  806. .dreg = 0, \
  807. .addr = imm_pc, \
  808. .unused = 0, \
  809. .reg = 0, \
  810. .type = BX_JUMP_TYPE_DIRECT, \
  811. .unused1 = 0, \
  812. .sub_opcode = SUB_OPCODE_BX, \
  813. .opcode = OPCODE_BRANCH } }
  814. /**
  815. * Branch to absolute PC if ALU result is zero, address in register.
  816. *
  817. * reg_pc is the register which contains address to jump to.
  818. * Address is expressed in 32-bit words.
  819. */
  820. #define I_BXZR(reg_pc) { .bx = { \
  821. .dreg = reg_pc, \
  822. .addr = 0, \
  823. .unused = 0, \
  824. .reg = 1, \
  825. .type = BX_JUMP_TYPE_ZERO, \
  826. .unused1 = 0, \
  827. .sub_opcode = SUB_OPCODE_BX, \
  828. .opcode = OPCODE_BRANCH } }
  829. /**
  830. * Branch to absolute PC if ALU result is zero, immediate address.
  831. *
  832. * Address imm_pc is expressed in 32-bit words.
  833. */
  834. #define I_BXZI(imm_pc) { .bx = { \
  835. .dreg = 0, \
  836. .addr = imm_pc, \
  837. .unused = 0, \
  838. .reg = 0, \
  839. .type = BX_JUMP_TYPE_ZERO, \
  840. .unused1 = 0, \
  841. .sub_opcode = SUB_OPCODE_BX, \
  842. .opcode = OPCODE_BRANCH } }
  843. /**
  844. * Branch to absolute PC if ALU overflow, address in register
  845. *
  846. * reg_pc is the register which contains address to jump to.
  847. * Address is expressed in 32-bit words.
  848. */
  849. #define I_BXFR(reg_pc) { .bx = { \
  850. .dreg = reg_pc, \
  851. .addr = 0, \
  852. .unused = 0, \
  853. .reg = 1, \
  854. .type = BX_JUMP_TYPE_OVF, \
  855. .unused1 = 0, \
  856. .sub_opcode = SUB_OPCODE_BX, \
  857. .opcode = OPCODE_BRANCH } }
  858. /**
  859. * Branch to absolute PC if ALU overflow, immediate address
  860. *
  861. * Address imm_pc is expressed in 32-bit words.
  862. */
  863. #define I_BXFI(imm_pc) { .bx = { \
  864. .dreg = 0, \
  865. .addr = imm_pc, \
  866. .unused = 0, \
  867. .reg = 0, \
  868. .type = BX_JUMP_TYPE_OVF, \
  869. .unused1 = 0, \
  870. .sub_opcode = SUB_OPCODE_BX, \
  871. .opcode = OPCODE_BRANCH } }
  872. /**
  873. * Addition: dest = src1 + src2
  874. */
  875. #define I_ADDR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
  876. .dreg = reg_dest, \
  877. .sreg = reg_src1, \
  878. .treg = reg_src2, \
  879. .unused = 0, \
  880. .sel = ALU_SEL_ADD, \
  881. .unused1 = 0, \
  882. .sub_opcode = SUB_OPCODE_ALU_REG, \
  883. .opcode = OPCODE_ALU } }
  884. /**
  885. * Subtraction: dest = src1 - src2
  886. */
  887. #define I_SUBR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
  888. .dreg = reg_dest, \
  889. .sreg = reg_src1, \
  890. .treg = reg_src2, \
  891. .unused = 0, \
  892. .sel = ALU_SEL_SUB, \
  893. .unused1 = 0, \
  894. .sub_opcode = SUB_OPCODE_ALU_REG, \
  895. .opcode = OPCODE_ALU } }
  896. /**
  897. * Logical AND: dest = src1 & src2
  898. */
  899. #define I_ANDR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
  900. .dreg = reg_dest, \
  901. .sreg = reg_src1, \
  902. .treg = reg_src2, \
  903. .unused = 0, \
  904. .sel = ALU_SEL_AND, \
  905. .unused1 = 0, \
  906. .sub_opcode = SUB_OPCODE_ALU_REG, \
  907. .opcode = OPCODE_ALU } }
  908. /**
  909. * Logical OR: dest = src1 | src2
  910. */
  911. #define I_ORR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
  912. .dreg = reg_dest, \
  913. .sreg = reg_src1, \
  914. .treg = reg_src2, \
  915. .unused = 0, \
  916. .sel = ALU_SEL_OR, \
  917. .unused1 = 0, \
  918. .sub_opcode = SUB_OPCODE_ALU_REG, \
  919. .opcode = OPCODE_ALU } }
  920. /**
  921. * Copy: dest = src
  922. */
  923. #define I_MOVR(reg_dest, reg_src) { .alu_reg = { \
  924. .dreg = reg_dest, \
  925. .sreg = reg_src, \
  926. .treg = 0, \
  927. .unused = 0, \
  928. .sel = ALU_SEL_MOV, \
  929. .unused1 = 0, \
  930. .sub_opcode = SUB_OPCODE_ALU_REG, \
  931. .opcode = OPCODE_ALU } }
  932. /**
  933. * Logical shift left: dest = src << shift
  934. */
  935. #define I_LSHR(reg_dest, reg_src, reg_shift) { .alu_reg = { \
  936. .dreg = reg_dest, \
  937. .sreg = reg_src, \
  938. .treg = reg_shift, \
  939. .unused = 0, \
  940. .sel = ALU_SEL_LSH, \
  941. .unused1 = 0, \
  942. .sub_opcode = SUB_OPCODE_ALU_REG, \
  943. .opcode = OPCODE_ALU } }
  944. /**
  945. * Logical shift right: dest = src >> shift
  946. */
  947. #define I_RSHR(reg_dest, reg_src, reg_shift) { .alu_reg = { \
  948. .dreg = reg_dest, \
  949. .sreg = reg_src, \
  950. .treg = reg_shift, \
  951. .unused = 0, \
  952. .sel = ALU_SEL_RSH, \
  953. .unused1 = 0, \
  954. .sub_opcode = SUB_OPCODE_ALU_REG, \
  955. .opcode = OPCODE_ALU } }
  956. /**
  957. * Add register and an immediate value: dest = src1 + imm
  958. */
  959. #define I_ADDI(reg_dest, reg_src, imm_) { .alu_imm = { \
  960. .dreg = reg_dest, \
  961. .sreg = reg_src, \
  962. .imm = imm_, \
  963. .unused = 0, \
  964. .sel = ALU_SEL_ADD, \
  965. .unused1 = 0, \
  966. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  967. .opcode = OPCODE_ALU } }
  968. /**
  969. * Subtract register and an immediate value: dest = src - imm
  970. */
  971. #define I_SUBI(reg_dest, reg_src, imm_) { .alu_imm = { \
  972. .dreg = reg_dest, \
  973. .sreg = reg_src, \
  974. .imm = imm_, \
  975. .unused = 0, \
  976. .sel = ALU_SEL_SUB, \
  977. .unused1 = 0, \
  978. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  979. .opcode = OPCODE_ALU } }
  980. /**
  981. * Logical AND register and an immediate value: dest = src & imm
  982. */
  983. #define I_ANDI(reg_dest, reg_src, imm_) { .alu_imm = { \
  984. .dreg = reg_dest, \
  985. .sreg = reg_src, \
  986. .imm = imm_, \
  987. .unused = 0, \
  988. .sel = ALU_SEL_AND, \
  989. .unused1 = 0, \
  990. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  991. .opcode = OPCODE_ALU } }
  992. /**
  993. * Logical OR register and an immediate value: dest = src | imm
  994. */
  995. #define I_ORI(reg_dest, reg_src, imm_) { .alu_imm = { \
  996. .dreg = reg_dest, \
  997. .sreg = reg_src, \
  998. .imm = imm_, \
  999. .unused = 0, \
  1000. .sel = ALU_SEL_OR, \
  1001. .unused1 = 0, \
  1002. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  1003. .opcode = OPCODE_ALU } }
  1004. /**
  1005. * Copy an immediate value into register: dest = imm
  1006. */
  1007. #define I_MOVI(reg_dest, imm_) { .alu_imm = { \
  1008. .dreg = reg_dest, \
  1009. .sreg = 0, \
  1010. .imm = imm_, \
  1011. .unused = 0, \
  1012. .sel = ALU_SEL_MOV, \
  1013. .unused1 = 0, \
  1014. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  1015. .opcode = OPCODE_ALU } }
  1016. /**
  1017. * Logical shift left register value by an immediate: dest = src << imm
  1018. */
  1019. #define I_LSHI(reg_dest, reg_src, imm_) { .alu_imm = { \
  1020. .dreg = reg_dest, \
  1021. .sreg = reg_src, \
  1022. .imm = imm_, \
  1023. .unused = 0, \
  1024. .sel = ALU_SEL_LSH, \
  1025. .unused1 = 0, \
  1026. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  1027. .opcode = OPCODE_ALU } }
  1028. /**
  1029. * Logical shift right register value by an immediate: dest = val >> imm
  1030. */
  1031. #define I_RSHI(reg_dest, reg_src, imm_) { .alu_imm = { \
  1032. .dreg = reg_dest, \
  1033. .sreg = reg_src, \
  1034. .imm = imm_, \
  1035. .unused = 0, \
  1036. .sel = ALU_SEL_RSH, \
  1037. .unused1 = 0, \
  1038. .sub_opcode = SUB_OPCODE_ALU_IMM, \
  1039. .opcode = OPCODE_ALU } }
  1040. #ifdef CONFIG_IDF_TARGET_ESP32S2BETA
  1041. /**
  1042. * Increments the stage counter for the subscript of the cycle count, Stage_cnt = Stage_cnt + Imm
  1043. */
  1044. #define I_SINC(imm_) { .alu_cnt = { \
  1045. .unused = 0, \
  1046. .imm = imm_, \
  1047. .unused1 = 0, \
  1048. .sel = ALU_SEL_INC, \
  1049. .unused2 = 0, \
  1050. .sub_opcode = SUB_OPCODE_ALU_CNT, \
  1051. .opcode = OPCODE_ALU } }
  1052. /**
  1053. * Decrements the stage counter for the subscript of the cycle count, Stage_cnt = Stage_cnt - Imm
  1054. */
  1055. #define I_SDEC(imm_) { .alu_cnt = { \
  1056. .unused = 0, \
  1057. .imm = imm_, \
  1058. .unused1 = 0, \
  1059. .sel = ALU_SEL_DEC, \
  1060. .unused2 = 0, \
  1061. .sub_opcode = SUB_OPCODE_ALU_CNT, \
  1062. .opcode = OPCODE_ALU } }
  1063. /**
  1064. * Phase counter is reset for the cycle count subscript, Stage_cnt = 0
  1065. */
  1066. #define I_SRST() { .alu_cnt = { \
  1067. .unused = 0, \
  1068. .imm = 0, \
  1069. .unused1 = 0, \
  1070. .sel = ALU_SEL_RST, \
  1071. .unused2 = 0, \
  1072. .sub_opcode = SUB_OPCODE_ALU_CNT, \
  1073. .opcode = OPCODE_ALU } }
  1074. #endif
  1075. /**
  1076. * Define a label with number label_num.
  1077. *
  1078. * This is a macro which doesn't generate a real instruction.
  1079. * The token generated by this macro is removed by ulp_process_macros_and_load
  1080. * function. Label defined using this macro can be used in branch macros defined
  1081. * below.
  1082. */
  1083. #define M_LABEL(label_num) { .macro = { \
  1084. .label = label_num, \
  1085. .unused = 0, \
  1086. .sub_opcode = SUB_OPCODE_MACRO_LABEL, \
  1087. .opcode = OPCODE_MACRO } }
  1088. /**
  1089. * Token macro used by M_B and M_BX macros. Not to be used directly.
  1090. */
  1091. #define M_BRANCH(label_num) { .macro = { \
  1092. .label = label_num, \
  1093. .unused = 0, \
  1094. .sub_opcode = SUB_OPCODE_MACRO_BRANCH, \
  1095. .opcode = OPCODE_MACRO } }
  1096. /**
  1097. * Macro: branch to label label_num if R0 is less than immediate value.
  1098. *
  1099. * This macro generates two ulp_insn_t values separated by a comma, and should
  1100. * be used when defining contents of ulp_insn_t arrays. First value is not a
  1101. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  1102. * function.
  1103. */
  1104. #define M_BL(label_num, imm_value) \
  1105. M_BRANCH(label_num), \
  1106. I_BL(0, imm_value)
  1107. /**
  1108. * Macro: branch to label label_num if R0 is greater or equal than immediate value
  1109. *
  1110. * This macro generates two ulp_insn_t values separated by a comma, and should
  1111. * be used when defining contents of ulp_insn_t arrays. First value is not a
  1112. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  1113. * function.
  1114. */
  1115. #define M_BGE(label_num, imm_value) \
  1116. M_BRANCH(label_num), \
  1117. I_BGE(0, imm_value)
  1118. /**
  1119. * Macro: unconditional branch to label
  1120. *
  1121. * This macro generates two ulp_insn_t values separated by a comma, and should
  1122. * be used when defining contents of ulp_insn_t arrays. First value is not a
  1123. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  1124. * function.
  1125. */
  1126. #define M_BX(label_num) \
  1127. M_BRANCH(label_num), \
  1128. I_BXI(0)
  1129. /**
  1130. * Macro: branch to label if ALU result is zero
  1131. *
  1132. * This macro generates two ulp_insn_t values separated by a comma, and should
  1133. * be used when defining contents of ulp_insn_t arrays. First value is not a
  1134. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  1135. * function.
  1136. */
  1137. #define M_BXZ(label_num) \
  1138. M_BRANCH(label_num), \
  1139. I_BXZI(0)
  1140. /**
  1141. * Macro: branch to label if ALU overflow
  1142. *
  1143. * This macro generates two ulp_insn_t values separated by a comma, and should
  1144. * be used when defining contents of ulp_insn_t arrays. First value is not a
  1145. * real instruction; it is a token which is removed by ulp_process_macros_and_load
  1146. * function.
  1147. */
  1148. #define M_BXF(label_num) \
  1149. M_BRANCH(label_num), \
  1150. I_BXFI(0)
  1151. #define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */
  1152. #ifdef __cplusplus
  1153. }
  1154. #endif