1ESP32 ULP coprocessor instruction set
2=====================================
3
4This document provides details about the instructions used by {IDF_TARGET_NAME} ULP coprocessor assembler.
5
6ULP coprocessor has 4 16-bit general purpose registers, labeled R0, R1, R2, R3. It also has an 8-bit counter register (stage_cnt) which can be used to implement loops. Stage count register is accessed using special instructions.
7
8ULP coprocessor can access 8k bytes of RTC_SLOW_MEM memory region. Memory is addressed in 32-bit word units. It can also access peripheral registers in RTC_CNTL, RTC_IO, and SENS peripherals.
9
10All instructions are 32-bit. Jump instructions, ALU instructions, peripheral register and memory access instructions are executed in 1 cycle. Instructions which work with peripherals (TSENS, ADC, I2C) take variable number of cycles, depending on peripheral operation.
11
12The instruction syntax is case insensitive. Upper and lower case letters can be used and intermixed arbitrarily. This is true both for register names and instruction names.
13
14Note about addressing
15---------------------
16{IDF_TARGET_NAME} ULP coprocessor's JUMP, ST, LD instructions which take register as an argument (jump address, store/load base address) expect the argument to be expressed in 32-bit words.
17
18Consider the following example program::
19
20  entry:
21          NOP
22          NOP
23          NOP
24          NOP
25  loop:
26          MOVE R1, loop
27          JUMP R1
28
29When this program is assembled and linked, address of label ``loop`` will be equal to 16 (expressed in bytes). However `JUMP` instruction expects the address stored in register to be expressed in 32-bit words. To account for this common use case, assembler will convert the address of label `loop` from bytes to words, when generating ``MOVE`` instruction, so the code generated code will be equivalent to::
30
31  0000    NOP
32  0004    NOP
33  0008    NOP
34  000c    NOP
35  0010    MOVE R1, 4
36  0014    JUMP R1
37
38The other case is when the argument of ``MOVE`` instruction is not a label but a constant. In this case assembler will use the value as is, without any conversion::
39
40          .set        val, 0x10
41          MOVE        R1, val
42
43In this case, value loaded into R1 will be ``0x10``.
44
45Similar considerations apply to ``LD`` and ``ST`` instructions. Consider the following code::
46
47          .global array
48  array:  .long 0
49          .long 0
50          .long 0
51          .long 0
52
53          MOVE R1, array
54          MOVE R2, 0x1234
55          ST R2, R1, 0      // write value of R2 into the first array element,
56                            // i.e. array[0]
57
58          ST R2, R1, 4      // write value of R2 into the second array element
59                            // (4 byte offset), i.e. array[1]
60
61          ADD R1, R1, 2     // this increments address by 2 words (8 bytes)
62          ST R2, R1, 0      // write value of R2 into the third array element,
63                            // i.e. array[2]
64
65Note about instruction execution time
66-------------------------------------
67
68ULP coprocessor is clocked from RTC_FAST_CLK, which is normally derived from the internal 8MHz oscillator. Applications which need to know exact ULP clock frequency can calibrate it against the main XTAL clock::
69
70    #include "soc/rtc.h"
71
72    // calibrate 8M/256 clock against XTAL, get 8M/256 clock period
73    uint32_t rtc_8md256_period = rtc_clk_cal(RTC_CAL_8MD256, 100);
74    uint32_t rtc_fast_freq_hz = 1000000ULL * (1 << RTC_CLK_CAL_FRACT) * 256 / rtc_8md256_period;
75
76ULP coprocessor needs certain number of clock cycles to fetch each instruction, plus certain number of cycles to execute it, depending on the instruction. See description of each instruction below for details on the execution time.
77
78Instruction fetch time is:
79
80- 2 clock cycles — for instructions following ALU and branch instructions.
81- 4 clock cycles — in other cases.
82
83Note that when accessing RTC memories and RTC registers, ULP coprocessor has lower priority than the main CPUs. This means that ULP coprocessor execution may be suspended while the main CPUs access same memory region as the ULP.
84
85
86**NOP** - no operation
87----------------------
88
89**Syntax**
90  **NOP**
91**Operands**
92  None
93**Cycles**
94  2 cycle to execute, 4 cycles to fetch next instruction
95**Description**
96  No operation is performed. Only the PC is incremented.
97
98**Example**::
99
100  1:    NOP
101
102
103**ADD** - Add to register
104-------------------------
105
106**Syntax**
107    **ADD**      *Rdst, Rsrc1, Rsrc2*
108
109    **ADD**      *Rdst, Rsrc1, imm*
110
111
112**Operands**
113  - *Rdst* - Register R[0..3]
114  - *Rsrc1* - Register R[0..3]
115  - *Rsrc2* - Register R[0..3]
116  - *Imm* - 16-bit signed value
117
118**Cycles**
119  2 cycles to execute, 4 cycles to fetch next instruction
120
121**Description**
122  The instruction adds source register to another source register or to a 16-bit signed value and stores result to the destination register.
123
124**Examples**::
125
126  1:    ADD R1, R2, R3        //R1 = R2 + R3
127
128  2:    Add R1, R2, 0x1234    //R1 = R2 + 0x1234
129
130  3:    .set value1, 0x03     //constant value1=0x03
131        Add R1, R2, value1    //R1 = R2 + value1
132
133
134  4:    .global label         //declaration of variable label
135        Add R1, R2, label     //R1 = R2 + label
136          ...
137        label: nop            //definition of variable label
138
139
140**SUB** - Subtract from register
141--------------------------------
142
143**Syntax**
144  **SUB** *Rdst, Rsrc1, Rsrc2*
145
146  **SUB** *Rdst, Rsrc1, imm*
147
148**Operands**
149  - *Rdst*  - Register R[0..3]
150  - *Rsrc1* - Register R[0..3]
151  - *Rsrc2* - Register R[0..3]
152  - *Imm*   - 16-bit signed value
153
154**Cycles**
155  2 cycles to execute, 4 cycles to fetch next instruction
156
157**Description**
158  The instruction subtracts the source register from another source register or subtracts 16-bit signed value from a source register, and stores result to the destination register.
159
160**Examples**::
161
162  1:         SUB R1, R2, R3             //R1 = R2 - R3
163
164  2:         sub R1, R2, 0x1234         //R1 = R2 - 0x1234
165
166  3:         .set value1, 0x03          //constant value1=0x03
167             SUB R1, R2, value1         //R1 = R2 - value1
168  4:         .global label              //declaration of variable label
169             SUB R1, R2, label          //R1 = R2 - label
170               ....
171    label:   nop                        //definition of variable label
172
173
174**AND** - Logical AND of two operands
175-------------------------------------
176
177**Syntax**
178    **AND** *Rdst, Rsrc1, Rsrc2*
179
180    **AND** *Rdst, Rsrc1, imm*
181
182**Operands**
183  - *Rdst* - Register R[0..3]
184  - *Rsrc1* - Register R[0..3]
185  - *Rsrc2* - Register R[0..3]
186  - *Imm* - 16-bit signed value
187
188**Cycles**
189  2 cycles to execute, 4 cycles to fetch next instruction
190
191**Description**
192  The instruction does logical AND of a source register and another source register or 16-bit signed value and stores result to the destination register.
193
194**Examples**::
195
196  1:        AND R1, R2, R3          //R1 = R2 & R3
197
198  2:        AND R1, R2, 0x1234      //R1 = R2 & 0x1234
199
200  3:        .set value1, 0x03       //constant value1=0x03
201            AND R1, R2, value1      //R1 = R2 & value1
202
203  4:        .global label           //declaration of variable label
204            AND R1, R2, label       //R1 = R2 & label
205                ...
206    label:  nop                     //definition of variable label
207
208
209**OR** - Logical OR of two operands
210-----------------------------------
211
212**Syntax**
213  **OR** *Rdst, Rsrc1, Rsrc2*
214
215  **OR** *Rdst, Rsrc1, imm*
216
217**Operands**
218  - *Rdst* - Register R[0..3]
219  - *Rsrc1* - Register R[0..3]
220  - *Rsrc2* - Register R[0..3]
221  - *Imm* - 16-bit signed value
222
223**Cycles**
224  2 cycles to execute, 4 cycles to fetch next instruction
225
226**Description**
227  The instruction does logical OR of a source register and another source register or 16-bit signed value and stores result to the destination register.
228
229**Examples**::
230
231  1:       OR R1, R2, R3           //R1 = R2 \| R3
232
233  2:       OR R1, R2, 0x1234       //R1 = R2 \| 0x1234
234
235  3:       .set value1, 0x03       //constant value1=0x03
236           OR R1, R2, value1       //R1 = R2 \| value1
237
238  4:       .global label           //declaration of variable label
239           OR R1, R2, label        //R1 = R2 \|label
240           ...
241    label: nop                     //definition of variable label
242
243
244
245**LSH** - Logical Shift Left
246----------------------------
247
248**Syntax**
249  **LSH** *Rdst, Rsrc1, Rsrc2*
250
251  **LSH** *Rdst, Rsrc1, imm*
252
253**Operands**
254  - *Rdst* - Register R[0..3]
255  - *Rsrc1* - Register R[0..3]
256  - *Rsrc2* - Register R[0..3]
257  - *Imm* - 16-bit signed value
258
259**Cycles**
260  2 cycles to execute, 4 cycles to fetch next instruction
261
262**Description**
263   The instruction does logical shift to left of source register to number of bits from another source register or 16-bit signed value and store result to the destination register.
264
265**Examples**::
266
267  1:       LSH R1, R2, R3            //R1 = R2 << R3
268
269  2:       LSH R1, R2, 0x03          //R1 = R2 << 0x03
270
271  3:       .set value1, 0x03         //constant value1=0x03
272           LSH R1, R2, value1        //R1 = R2 << value1
273
274  4:       .global label             //declaration of variable label
275           LSH R1, R2, label         //R1 = R2 << label
276           ...
277    label:  nop                       //definition of variable label
278
279
280**RSH** - Logical Shift Right
281-----------------------------
282
283**Syntax**
284   **RSH** *Rdst, Rsrc1, Rsrc2*
285
286   **RSH** *Rdst, Rsrc1, imm*
287
288**Operands**
289  *Rdst* - Register R[0..3]
290  *Rsrc1* - Register R[0..3]
291  *Rsrc2* - Register R[0..3]
292  *Imm* - 16-bit signed value
293
294**Cycles**
295  2 cycles to execute, 4 cycles to fetch next instruction
296
297**Description**
298  The instruction does logical shift to right of source register to number of bits from another source register or 16-bit signed value and store result to the destination register.
299
300**Examples**::
301
302  1:        RSH R1, R2, R3              //R1 = R2 >> R3
303
304  2:        RSH R1, R2, 0x03            //R1 = R2 >> 0x03
305
306  3:        .set value1, 0x03           //constant value1=0x03
307            RSH R1, R2, value1          //R1 = R2 >> value1
308
309  4:        .global label               //declaration of variable label
310            RSH R1, R2, label           //R1 = R2 >> label
311    label:  nop                         //definition of variable label
312
313
314
315**MOVE** – Move to register
316---------------------------
317
318**Syntax**
319  **MOVE**     *Rdst, Rsrc*
320
321  **MOVE**     *Rdst, imm*
322
323**Operands**
324  - *Rdst* – Register R[0..3]
325  - *Rsrc* – Register R[0..3]
326  - *Imm*  – 16-bit signed value
327
328**Cycles**
329  2 cycles to execute, 4 cycles to fetch next instruction
330
331**Description**
332   The instruction move to destination register value from source register or 16-bit signed value.
333
334   Note that when a label is used as an immediate, the address of the label will be converted from bytes to words. This is because LD, ST, and JUMP instructions expect the address register value to be expressed in words rather than bytes. To avoid using an extra instruction
335
336
337**Examples**::
338
339  1:        MOVE       R1, R2            //R1 = R2
340
341  2:        MOVE       R1, 0x03          //R1 = 0x03
342
343  3:        .set       value1, 0x03      //constant value1=0x03
344            MOVE       R1, value1        //R1 = value1
345
346  4:        .global     label            //declaration of label
347            MOVE        R1, label        //R1 = address_of(label) / 4
348            ...
349    label:  nop                          //definition of label
350
351
352**ST** – Store data to the memory
353---------------------------------
354
355**Syntax**
356  **ST**     *Rsrc, Rdst, offset*
357
358**Operands**
359  - *Rsrc* – Register R[0..3], holds the 16-bit value to store
360  - *Rdst* – Register R[0..3], address of the destination, in 32-bit words
361  - *Offset* – 13-bit signed value, offset in bytes
362
363**Cycles**
364  4 cycles to execute, 4 cycles to fetch next instruction
365
366**Description**
367  The instruction stores the 16-bit value of Rsrc to the lower half-word of memory with address Rdst+offset. The upper half-word is written with the current program counter (PC) (expressed in words, shifted left by 5 bits) OR'd with Rdst (0..3)::
368
369    Mem[Rdst + offset / 4]{31:0} = {PC[10:0], 3'b0, Rdst, Rsrc[15:0]}
370
371  The application can use higher 16 bits to determine which instruction in the ULP program has written any particular word into memory.
372
373**Examples**::
374
375  1:        ST  R1, R2, 0x12        //MEM[R2+0x12] = R1
376
377  2:        .data                   //Data section definition
378    Addr1:  .word     123           // Define label Addr1 16 bit
379            .set      offs, 0x00    // Define constant offs
380            .text                   //Text section definition
381            MOVE      R1, 1         // R1 = 1
382            MOVE      R2, Addr1     // R2 = Addr1
383            ST        R1, R2, offs  // MEM[R2 +  0] = R1
384                                    // MEM[Addr1 + 0] will be 32'h600001
385
386
387**LD** – Load data from the memory
388----------------------------------
389
390**Syntax**
391   **LD**      *Rdst, Rsrc, offset*
392
393**Operands**
394   *Rdst*  – Register R[0..3], destination
395
396   *Rsrc* – Register R[0..3], holds address of destination, in 32-bit words
397
398   *Offset* – 13-bit signed value, offset in bytes
399
400**Cycles**
401  4 cycles to execute, 4 cycles to fetch next instruction
402
403**Description**
404   The instruction loads lower 16-bit half-word from memory with address Rsrc+offset into the destination register Rdst::
405
406     Rdst[15:0] = Mem[Rsrc + offset / 4][15:0]
407
408**Examples**::
409
410  1:        LD  R1, R2, 0x12            //R1 = MEM[R2+0x12]
411
412  2:        .data                       //Data section definition
413    Addr1:  .word     123               // Define label Addr1 16 bit
414            .set      offs, 0x00        // Define constant offs
415            .text                       //Text section definition
416            MOVE      R1, 1             // R1 = 1
417            MOVE      R2, Addr1         // R2 = Addr1 / 4 (address of label is converted into words)
418            LD        R1, R2, offs      // R1 = MEM[R2 +  0]
419                                        // R1 will be 123
420
421
422
423
424**JUMP** – Jump to an absolute address
425--------------------------------------
426
427**Syntax**
428  **JUMP**        *Rdst*
429
430  **JUMP**        *ImmAddr*
431
432  **JUMP**        *Rdst, Condition*
433
434  **JUMP**        *ImmAddr, Condition*
435
436
437**Operands**
438  - *Rdst* – Register R[0..3] containing address to jump to (expressed in 32-bit words)
439
440  - *ImmAddr* – 13 bits address (expressed in bytes), aligned to 4 bytes
441
442  - *Condition*:
443     - EQ – jump if last ALU operation result was zero
444     - OV – jump if last ALU has set overflow flag
445
446**Cycles**
447  2 cycles to execute, 2 cycles to fetch next instruction
448
449**Description**
450  The instruction makes jump to the specified address. Jump can be either unconditional or based on an ALU flag.
451
452**Examples**::
453
454  1:        JUMP       R1            // Jump to address in R1 (address in R1 is in 32-bit words)
455
456  2:        JUMP       0x120, EQ     // Jump to address 0x120 (in bytes) if ALU result is zero
457
458  3:        JUMP       label         // Jump to label
459            ...
460    label:  nop                      // Definition of label
461
462  4:        .global    label         // Declaration of global label
463
464            MOVE       R1, label     // R1 = label (value loaded into R1 is in words)
465            JUMP       R1            // Jump to label
466            ...
467    label:  nop                      // Definition of label
468
469
470
471**JUMPR** – Jump to a relative offset (condition based on R0)
472-------------------------------------------------------------
473
474**Syntax**
475   **JUMPR**        *Step, Threshold, Condition*
476
477**Operands**
478   - *Step*          – relative shift from current position, in bytes
479   - *Threshold*     – threshold value for branch condition
480   - *Condition*:
481      - *EQ* (equal) – jump if value in R0 == threshold
482      - *LT* (less than) – jump if value in R0 < threshold
483      - *LE* (less or equal) – jump if value in R0 <= threshold
484      - *GT* (greater than) – jump if value in R0 > threshold
485      - *GE* (greater or equal) – jump if value in R0 >= threshold
486
487
488**Cycles**
489  Conditions *LT*, *GE*, *LE* and *GT*: 2 cycles to execute, 2 cycles to fetch next instruction
490
491  Conditions *LE* and *GT* are implemented in the assembler using one **JUMPR** instructions::
492
493    // JUMPR target, threshold, GT is implemented as:
494
495             JUMPR target, threshold+1, GE
496
497    // JUMPR target, threshold, LE is implemented as:
498
499             JUMPR target, threshold + 1, LT
500
501  Conditions *EQ* is implemented in the assembler using two **JUMPR** instructions::
502
503    // JUMPR target, threshold, EQ is implemented as:
504
505             JUMPR next, threshold + 1, GE
506             JUMPR target, threshold, GE
507    next:
508
509  Therefore the execution time will depend on the branches taken: either 2 cycles to execute + 2 cycles to fetch, or 4 cycles to execute + 4 cycles to fetch.
510
511**Description**
512   The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of R0 register value and the threshold value.
513
514**Examples**::
515
516  1:pos:    JUMPR       16, 20, GE   // Jump to address (position + 16 bytes) if value in R0 >= 20
517
518  2:        // Down counting loop using R0 register
519            MOVE        R0, 16       // load 16 into R0
520    label:  SUB         R0, R0, 1    // R0--
521            NOP                      // do something
522            JUMPR       label, 1, GE // jump to label if R0 >= 1
523
524
525
526**JUMPS** – Jump to a relative address (condition based on stage count)
527-----------------------------------------------------------------------
528
529**Syntax**
530   **JUMPS**        *Step, Threshold, Condition*
531
532**Operands**
533   - *Step*       – relative shift from current position, in bytes
534   - *Threshold*  – threshold value for branch condition
535   - *Condition*:
536       - *EQ* (equal) – jump if value in stage_cnt == threshold
537       - *LT* (less than) –  jump if value in stage_cnt < threshold
538       - *LE* (less or equal) - jump if value in stage_cnt <= threshold
539       - *GT* (greater than) –  jump if value in stage_cnt > threshold
540       - *GE* (greater or equal) — jump if value in stage_cnt >= threshold
541
542**Cycles**
543  Conditions *LE*, *LT*, *GE*: 2 cycles to execute, 2 cycles to fetch next instruction
544
545  Conditions *EQ*, *GT* are implemented in the assembler using two **JUMPS** instructions::
546
547    // JUMPS target, threshold, EQ is implemented as:
548
549             JUMPS next, threshold, LT
550             JUMPS target, threshold, LE
551    next:
552
553    // JUMPS target, threshold, GT is implemented as:
554
555             JUMPS next, threshold, LE
556             JUMPS target, threshold, GE
557    next:
558
559  Therefore the execution time will depend on the branches taken: either 2 cycles to execute + 2 cycles to fetch, or 4 cycles to execute + 4 cycles to fetch.
560
561
562**Description**
563    The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of count register value and threshold value.
564
565**Examples**::
566
567   1:pos:    JUMPS     16, 20, EQ     // Jump to (position + 16 bytes) if stage_cnt == 20
568
569   2:        // Up counting loop using stage count register
570             STAGE_RST                  // set stage_cnt to 0
571     label:  STAGE_INC  1               // stage_cnt++
572             NOP                        // do something
573             JUMPS       label, 16, LT  // jump to label if stage_cnt < 16
574
575
576
577**STAGE_RST** – Reset stage count register
578------------------------------------------
579**Syntax**
580     **STAGE_RST**
581
582**Operands**
583   No operands
584
585**Description**
586   The instruction sets the stage count register to 0
587
588**Cycles**
589  2 cycles to execute, 4 cycles to fetch next instruction
590
591**Examples**::
592
593   1:       STAGE_RST      // Reset stage count register
594
595
596
597**STAGE_INC** – Increment stage count register
598----------------------------------------------
599
600**Syntax**
601  **STAGE_INC**      *Value*
602
603**Operands**
604   - *Value* – 8 bits value
605
606**Cycles**
607  2 cycles to execute, 4 cycles to fetch next instruction
608
609**Description**
610   The instruction increments stage count register by given value.
611
612**Examples**::
613
614  1:        STAGE_INC      10          // stage_cnt += 10
615
616  2:        // Up counting loop example:
617            STAGE_RST                  // set stage_cnt to 0
618    label:  STAGE_INC  1               // stage_cnt++
619            NOP                        // do something
620            JUMPS      label, 16, LT   // jump to label if stage_cnt < 16
621
622
623**STAGE_DEC** – Decrement stage count register
624----------------------------------------------
625
626**Syntax**
627  **STAGE_DEC**      *Value*
628
629**Operands**
630   - *Value* – 8 bits value
631
632**Cycles**
633  2 cycles to execute, 4 cycles to fetch next instruction
634
635**Description**
636   The instruction decrements stage count register by given value.
637
638**Examples**::
639
640  1:        STAGE_DEC      10        // stage_cnt -= 10;
641
642  2:        // Down counting loop example
643            STAGE_RST                // set stage_cnt to 0
644            STAGE_INC  16            // increment stage_cnt to 16
645    label:  STAGE_DEC  1             // stage_cnt--;
646            NOP                      // do something
647            JUMPS      label, 0, GT  // jump to label if stage_cnt > 0
648
649
650**HALT** – End the program
651--------------------------
652
653**Syntax**
654  **HALT**
655
656**Operands**
657  No operands
658
659**Cycles**
660  2 cycles to execute
661
662**Description**
663   The instruction halts the ULP coprocessor and restarts ULP wakeup timer, if it is enabled.
664
665**Examples**::
666
667  1:       HALT      // Halt the coprocessor
668
669
670
671**WAKE** – Wake up the chip
672---------------------------
673
674**Syntax**
675   **WAKE**
676
677**Operands**
678  No operands
679
680**Cycles**
681  2 cycles to execute, 4 cycles to fetch next instruction
682
683**Description**
684  The instruction sends an interrupt from ULP to RTC controller.
685
686  - If the SoC is in deep sleep mode, and ULP wakeup is enabled, this causes the SoC to wake up.
687
688  - If the SoC is not in deep sleep mode, and ULP interrupt bit (RTC_CNTL_ULP_CP_INT_ENA) is set in RTC_CNTL_INT_ENA_REG register, RTC interrupt will be triggered.
689
690  Note that before using WAKE instruction, ULP program may needs to wait until RTC controller is ready to wake up the main CPU. This is indicated using RTC_CNTL_RDY_FOR_WAKEUP bit of RTC_CNTL_LOW_POWER_ST_REG register. If WAKE instruction is executed while RTC_CNTL_RDY_FOR_WAKEUP is zero, it has no effect (wake up does not occur).
691
692**Examples**::
693
694  1: is_rdy_for_wakeup:                   // Read RTC_CNTL_RDY_FOR_WAKEUP bit
695            READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
696            AND r0, r0, 1
697            JUMP is_rdy_for_wakeup, eq    // Retry until the bit is set
698            WAKE                          // Trigger wake up
699            REG_WR 0x006, 24, 24, 0       // Stop ULP timer (clear RTC_CNTL_ULP_CP_SLP_TIMER_EN)
700            HALT                          // Stop the ULP program
701            // After these instructions, SoC will wake up,
702            // and ULP will not run again until started by the main program.
703
704
705
706**SLEEP** – set ULP wakeup timer period
707---------------------------------------
708
709**Syntax**
710  **SLEEP**   *sleep_reg*
711
712**Operands**
713   - *sleep_reg* – 0..4, selects one of ``SENS_ULP_CP_SLEEP_CYCx_REG`` registers.
714
715**Cycles**
716  2 cycles to execute, 4 cycles to fetch next instruction
717
718**Description**
719   The instruction selects which of the ``SENS_ULP_CP_SLEEP_CYCx_REG`` (x = 0..4) register values is to be used by the ULP wakeup timer as wakeup period. By default, the value from ``SENS_ULP_CP_SLEEP_CYC0_REG`` is used.
720
721**Examples**::
722
723  1:        SLEEP     1         // Use period set in SENS_ULP_CP_SLEEP_CYC1_REG
724
725  2:        .set sleep_reg, 4   // Set constant
726            SLEEP  sleep_reg    // Use period set in SENS_ULP_CP_SLEEP_CYC4_REG
727
728
729**WAIT** – wait some number of cycles
730-------------------------------------
731
732**Syntax**
733   **WAIT**   *Cycles*
734
735**Operands**
736   - *Cycles* – number of cycles for wait
737
738**Cycles**
739  2 + *Cycles* cycles to execute, 4 cycles to fetch next instruction
740
741**Description**
742   The instruction delays for given number of cycles.
743
744**Examples**::
745
746  1:        WAIT     10         // Do nothing for 10 cycles
747
748  2:        .set  wait_cnt, 10  // Set a constant
749            WAIT  wait_cnt      // wait for 10 cycles
750
751
752
753
754**TSENS** – do measurement with temperature sensor
755--------------------------------------------------
756
757**Syntax**
758   - **TSENS**   *Rdst, Wait_Delay*
759
760**Operands**
761  - *Rdst* – Destination Register R[0..3], result will be stored to this register
762  - *Wait_Delay* – number of cycles used to perform the measurement
763
764**Cycles**
765  2 + *Wait_Delay* + 3 * TSENS_CLK to execute, 4 cycles to fetch next instruction
766
767**Description**
768   The instruction performs measurement using TSENS and stores the result into a general purpose register.
769
770**Examples**::
771
772  1:        TSENS     R1, 1000     // Measure temperature sensor for 1000 cycles,
773                                   // and store result to R1
774
775
776
777
778**ADC** – do measurement with ADC
779---------------------------------
780
781**Syntax**
782  - **ADC**   *Rdst, Sar_sel, Mux*
783
784  - **ADC**   *Rdst, Sar_sel, Mux, 0* — deprecated form
785
786**Operands**
787  - *Rdst* – Destination Register R[0..3], result will be stored to this register
788  - *Sar_sel* – Select ADC: 0 = SARADC1, 1 = SARADC2
789  - *Mux*  - Enable ADC channel. Channel number is [Mux-1]. If the user passes Mux value 1, then ADC channel 0 gets used.
790
791**Cycles**
792  ``23 + max(1, SAR_AMP_WAIT1) + max(1, SAR_AMP_WAIT2) + max(1, SAR_AMP_WAIT3) + SARx_SAMPLE_CYCLE + SARx_SAMPLE_BIT`` cycles to execute, 4 cycles to fetch next instruction
793
794**Description**
795  The instruction makes measurements from ADC.
796
797**Examples**::
798
799   1:        ADC      R1, 0, 1      // Measure value using ADC1 channel 0 and store result into R1
800
801**I2C_RD** - read single byte from I2C slave
802----------------------------------------------
803
804**Syntax**
805  - **I2C_RD**   *Sub_addr, High, Low, Slave_sel*
806
807**Operands**
808  - *Sub_addr* – Address within the I2C slave to read.
809  - *High*, *Low* — Define range of bits to read. Bits outside of [High, Low] range are masked.
810  - *Slave_sel*  -  Index of I2C slave address to use.
811
812**Cycles**
813  Execution time mostly depends on I2C communication time. 4 cycles to fetch next instruction.
814
815**Description**
816  ``I2C_RD`` instruction reads one byte from I2C slave with index ``Slave_sel``. Slave address (in 7-bit format) has to be set in advance into `SENS_I2C_SLAVE_ADDRx` register field, where ``x == Slave_sel``.
817  8 bits of read result is stored into `R0` register.
818
819**Examples**::
820
821   1:        I2C_RD      0x10, 7, 0, 0      // Read byte from sub-address 0x10 of slave with address set in SENS_I2C_SLAVE_ADDR0
822
823
824**I2C_WR** - write single byte to I2C slave
825----------------------------------------------
826
827**Syntax**
828  - **I2C_WR**   *Sub_addr, Value, High, Low, Slave_sel*
829
830**Operands**
831  - *Sub_addr* – Address within the I2C slave to write.
832  - *Value* – 8-bit value to be written.
833  - *High*, *Low* — Define range of bits to write. Bits outside of [High, Low] range are masked.
834  - *Slave_sel*  -  Index of I2C slave address to use.
835
836**Cycles**
837  Execution time mostly depends on I2C communication time. 4 cycles to fetch next instruction.
838
839**Description**
840  ``I2C_WR`` instruction writes one byte to I2C slave with index ``Slave_sel``. Slave address (in 7-bit format) has to be set in advance into `SENS_I2C_SLAVE_ADDRx` register field, where ``x == Slave_sel``.
841
842**Examples**::
843
844   1:        I2C_WR      0x20, 0x33, 7, 0, 1      // Write byte 0x33 to sub-address 0x20 of slave with address set in SENS_I2C_SLAVE_ADDR1.
845
846
847**REG_RD** – read from peripheral register
848------------------------------------------
849
850**Syntax**
851   **REG_RD**   *Addr, High, Low*
852
853**Operands**
854  - *Addr* – Register address, in 32-bit words
855  - *High* – Register end bit number
856  - *Low* – Register start bit number
857
858**Cycles**
859  4 cycles to execute, 4 cycles to fetch next instruction
860
861**Description**
862  The instruction reads up to 16 bits from a peripheral register into a general purpose register: ``R0 = REG[Addr][High:Low]``.
863
864  This instruction can access registers in RTC_CNTL, RTC_IO, SENS, and RTC_I2C peripherals. Address of the the register, as seen from the ULP, can be calculated from the address of the same register on the DPORT bus as follows::
865
866    addr_ulp = (addr_dport - DR_REG_RTCCNTL_BASE) / 4
867
868**Examples**::
869
870  1:        REG_RD      0x120, 7, 4     // load 4 bits: R0 = {12'b0, REG[0x120][7:4]}
871
872
873**REG_WR** – write to peripheral register
874-----------------------------------------
875
876**Syntax**
877  **REG_WR**   *Addr, High, Low, Data*
878
879**Operands**
880  - *Addr* – Register address, in 32-bit words.
881  - *High* – Register end bit number
882  - *Low* – Register start bit number
883  - *Data* – Value to write, 8 bits
884
885**Cycles**
886  8 cycles to execute, 4 cycles to fetch next instruction
887
888**Description**
889  The instruction writes up to 8 bits from an immediate data value into a peripheral register: ``REG[Addr][High:Low] = data``.
890
891  This instruction can access registers in RTC_CNTL, RTC_IO, SENS, and RTC_I2C peripherals. Address of the the register, as seen from the ULP, can be calculated from the address of the same register on the DPORT bus as follows::
892
893    addr_ulp = (addr_dport - DR_REG_RTCCNTL_BASE) / 4
894
895**Examples**::
896
897   1:        REG_WR      0x120, 7, 0, 0x10   // set 8 bits: REG[0x120][7:0] = 0x10
898
899Convenience macros for peripheral registers access
900--------------------------------------------------
901
902ULP source files are passed through C preprocessor before the assembler. This allows certain macros to be used to facilitate access to peripheral registers.
903
904Some existing macros are defined in ``soc/soc_ulp.h`` header file. These macros allow access to the fields of peripheral registers by their names.
905Peripheral registers names which can be used with these macros are the ones defined in ``soc/rtc_cntl_reg.h``, ``soc/rtc_io_reg.h``, ``soc/sens_reg.h``, and ``soc/rtc_i2c_reg.h``.
906
907READ_RTC_REG(rtc_reg, low_bit, bit_width)
908  Read up to 16 bits from rtc_reg[low_bit + bit_width - 1 : low_bit] into R0. For example::
909
910    #include "soc/soc_ulp.h"
911    #include "soc/rtc_cntl_reg.h"
912
913    /* Read 16 lower bits of RTC_CNTL_TIME0_REG into R0 */
914    READ_RTC_REG(RTC_CNTL_TIME0_REG, 0, 16)
915
916READ_RTC_FIELD(rtc_reg, field)
917  Read from a field in rtc_reg into R0, up to 16 bits. For example::
918
919    #include "soc/soc_ulp.h"
920    #include "soc/sens_reg.h"
921
922    /* Read 8-bit SENS_TSENS_OUT field of SENS_SAR_SLAVE_ADDR3_REG into R0 */
923    READ_RTC_FIELD(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT)
924
925WRITE_RTC_REG(rtc_reg, low_bit, bit_width, value)
926  Write immediate value into rtc_reg[low_bit + bit_width - 1 : low_bit], bit_width <= 8. For example::
927
928    #include "soc/soc_ulp.h"
929    #include "soc/rtc_io_reg.h"
930
931    /* Set BIT(2) of RTC_GPIO_OUT_DATA_W1TS field in RTC_GPIO_OUT_W1TS_REG */
932    WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S + 2, 1, 1)
933
934
935WRITE_RTC_FIELD(rtc_reg, field, value)
936  Write immediate value into a field in rtc_reg, up to 8 bits. For example::
937
938    #include "soc/soc_ulp.h"
939    #include "soc/rtc_cntl_reg.h"
940
941    /* Set RTC_CNTL_ULP_CP_SLP_TIMER_EN field of RTC_CNTL_STATE0_REG to 0 */
942    WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
943
944
945
946
947
948
949