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