1ESP32-S2 ULP coprocessor instruction set 2======================================== 3 4This document provides details about the instructions used by ESP32-S2 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 regiter 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 14 15Note about addressing 16--------------------- 17ESP32-S2 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. 18 19Consider the following example program:: 20 21 entry: 22 NOP 23 NOP 24 NOP 25 NOP 26 loop: 27 MOVE R1, loop 28 JUMP R1 29 30When 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:: 31 32 0000 NOP 33 0004 NOP 34 0008 NOP 35 000c NOP 36 0010 MOVE R1, 4 37 0014 JUMP R1 38 39The 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:: 40 41 .set val, 0x10 42 MOVE R1, val 43 44In this case, value loaded into R1 will be ``0x10``. 45 46Similar considerations apply to ``LD`` and ``ST`` instructions. Consider the following code:: 47 48 .global array 49 array: .long 0 50 .long 0 51 .long 0 52 .long 0 53 54 MOVE R1, array 55 MOVE R2, 0x1234 56 ST R2, R1, 0 // write value of R2 into the first array element, 57 // i.e. array[0] 58 59 ST R2, R1, 4 // write value of R2 into the second array element 60 // (4 byte offset), i.e. array[1] 61 62 ADD R1, R1, 2 // this increments address by 2 words (8 bytes) 63 ST R2, R1, 0 // write value of R2 into the third array element, 64 // i.e. array[2] 65 66 67Note about instruction execution time 68------------------------------------- 69 70ULP 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:: 71 72 #include "soc/rtc.h" 73 74 // calibrate 8M/256 clock against XTAL, get 8M/256 clock period 75 uint32_t rtc_8md256_period = rtc_clk_cal(RTC_CAL_8MD256, 100); 76 uint32_t rtc_fast_freq_hz = 1000000ULL * (1 << RTC_CLK_CAL_FRACT) * 256 / rtc_8md256_period; 77 78ULP 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. 79 80Instruction fetch time is: 81 82- 2 clock cycles — for instructions following ALU and branch instructions. 83- 4 clock cycles — in other cases. 84 85Note 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. 86 87 88Difference between ESP32 ULP and ESP32-S2 ULP Instruction sets 89-------------------------------------------------------------- 90 91Compare to the ESP32 ULP coprocessor, the ESP-S2 ULP coprocessor has extended instruction set. The ESP32-S2 ULP is not binary compatible with ESP32 ULP, 92but the assembled program that was written for the ESP32 ULP will also work on the ESP32-S2 ULP after rebuild. 93The list of the new instructions that was added to the ESP32-S2 ULP is: LDL, LDH, STO, ST32, STI32. 94The detailed description of these commands please see below. 95 96 97**NOP** - no operation 98---------------------- 99 100**Syntax** 101 **NOP** 102**Operands** 103 None 104**Cycles** 105 2 cycle to execute, 4 cycles to fetch next instruction 106**Description** 107 No operation is performed. Only the PC is incremented. 108 109**Example**:: 110 111 1: NOP 112 113 114**ADD** - Add to register 115------------------------- 116 117**Syntax** 118 **ADD** *Rdst, Rsrc1, Rsrc2* 119 120 **ADD** *Rdst, Rsrc1, imm* 121 122 123**Operands** 124 - *Rdst* - Register R[0..3] 125 - *Rsrc1* - Register R[0..3] 126 - *Rsrc2* - Register R[0..3] 127 - *Imm* - 16-bit signed value 128 129**Cycles** 130 2 cycles to execute, 4 cycles to fetch next instruction 131 132**Description** 133 The instruction adds source register to another source register or to a 16-bit signed value and stores result to the destination register. 134 135**Examples**:: 136 137 1: ADD R1, R2, R3 //R1 = R2 + R3 138 139 2: Add R1, R2, 0x1234 //R1 = R2 + 0x1234 140 141 3: .set value1, 0x03 //constant value1=0x03 142 Add R1, R2, value1 //R1 = R2 + value1 143 144 145 4: .global label //declaration of variable label 146 Add R1, R2, label //R1 = R2 + label 147 ... 148 label: nop //definition of variable label 149 150 151**SUB** - Subtract from register 152-------------------------------- 153 154**Syntax** 155 **SUB** *Rdst, Rsrc1, Rsrc2* 156 157 **SUB** *Rdst, Rsrc1, imm* 158 159**Operands** 160 - *Rdst* - Register R[0..3] 161 - *Rsrc1* - Register R[0..3] 162 - *Rsrc2* - Register R[0..3] 163 - *Imm* - 16-bit signed value 164 165**Cycles** 166 2 cycles to execute, 4 cycles to fetch next instruction 167 168**Description** 169 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. 170 171**Examples**:: 172 173 1: SUB R1, R2, R3 //R1 = R2 - R3 174 175 2: sub R1, R2, 0x1234 //R1 = R2 - 0x1234 176 177 3: .set value1, 0x03 //constant value1=0x03 178 SUB R1, R2, value1 //R1 = R2 - value1 179 4: .global label //declaration of variable label 180 SUB R1, R2, label //R1 = R2 - label 181 .... 182 label: nop //definition of variable label 183 184 185**AND** - Logical AND of two operands 186------------------------------------- 187 188**Syntax** 189 **AND** *Rdst, Rsrc1, Rsrc2* 190 191 **AND** *Rdst, Rsrc1, imm* 192 193**Operands** 194 - *Rdst* - Register R[0..3] 195 - *Rsrc1* - Register R[0..3] 196 - *Rsrc2* - Register R[0..3] 197 - *Imm* - 16-bit signed value 198 199**Cycles** 200 2 cycles to execute, 4 cycles to fetch next instruction 201 202**Description** 203 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. 204 205**Examples**:: 206 207 1: AND R1, R2, R3 //R1 = R2 & R3 208 209 2: AND R1, R2, 0x1234 //R1 = R2 & 0x1234 210 211 3: .set value1, 0x03 //constant value1=0x03 212 AND R1, R2, value1 //R1 = R2 & value1 213 214 4: .global label //declaration of variable label 215 AND R1, R2, label //R1 = R2 & label 216 ... 217 label: nop //definition of variable label 218 219 220**OR** - Logical OR of two operands 221----------------------------------- 222 223**Syntax** 224 **OR** *Rdst, Rsrc1, Rsrc2* 225 226 **OR** *Rdst, Rsrc1, imm* 227 228**Operands** 229 - *Rdst* - Register R[0..3] 230 - *Rsrc1* - Register R[0..3] 231 - *Rsrc2* - Register R[0..3] 232 - *Imm* - 16-bit signed value 233 234**Cycles** 235 2 cycles to execute, 4 cycles to fetch next instruction 236 237**Description** 238 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. 239 240**Examples**:: 241 242 1: OR R1, R2, R3 //R1 = R2 \| R3 243 244 2: OR R1, R2, 0x1234 //R1 = R2 \| 0x1234 245 246 3: .set value1, 0x03 //constant value1=0x03 247 OR R1, R2, value1 //R1 = R2 \| value1 248 249 4: .global label //declaration of variable label 250 OR R1, R2, label //R1 = R2 \|label 251 ... 252 label: nop //definition of variable label 253 254 255**LSH** - Logical Shift Left 256---------------------------- 257 258**Syntax** 259 **LSH** *Rdst, Rsrc1, Rsrc2* 260 261 **LSH** *Rdst, Rsrc1, imm* 262 263**Operands** 264 - *Rdst* - Register R[0..3] 265 - *Rsrc1* - Register R[0..3] 266 - *Rsrc2* - Register R[0..3] 267 - *Imm* - 16-bit signed value 268 269**Cycles** 270 2 cycles to execute, 4 cycles to fetch next instruction 271 272**Description** 273 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. 274 275**Examples**:: 276 277 1: LSH R1, R2, R3 //R1 = R2 << R3 278 279 2: LSH R1, R2, 0x03 //R1 = R2 << 0x03 280 281 3: .set value1, 0x03 //constant value1=0x03 282 LSH R1, R2, value1 //R1 = R2 << value1 283 284 4: .global label //declaration of variable label 285 LSH R1, R2, label //R1 = R2 << label 286 ... 287 label: nop //definition of variable label 288 289 290**RSH** - Logical Shift Right 291----------------------------- 292 293**Syntax** 294 **RSH** *Rdst, Rsrc1, Rsrc2* 295 296 **RSH** *Rdst, Rsrc1, imm* 297 298**Operands** 299 *Rdst* - Register R[0..3] 300 *Rsrc1* - Register R[0..3] 301 *Rsrc2* - Register R[0..3] 302 *Imm* - 16-bit signed value 303 304**Cycles** 305 2 cycles to execute, 4 cycles to fetch next instruction 306 307**Description** 308 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. 309 310**Examples**:: 311 312 1: RSH R1, R2, R3 //R1 = R2 >> R3 313 314 2: RSH R1, R2, 0x03 //R1 = R2 >> 0x03 315 316 3: .set value1, 0x03 //constant value1=0x03 317 RSH R1, R2, value1 //R1 = R2 >> value1 318 319 4: .global label //declaration of variable label 320 RSH R1, R2, label //R1 = R2 >> label 321 label: nop //definition of variable label 322 323 324**MOVE** – Move to register 325--------------------------- 326 327**Syntax** 328 **MOVE** *Rdst, Rsrc* 329 330 **MOVE** *Rdst, imm* 331 332**Operands** 333 - *Rdst* – Register R[0..3] 334 - *Rsrc* – Register R[0..3] 335 - *Imm* – 16-bit signed value 336 337**Cycles** 338 2 cycles to execute, 4 cycles to fetch next instruction 339 340**Description** 341 The instruction move to destination register value from source register or 16-bit signed value. 342 343 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 344 345 346**Examples**:: 347 348 1: MOVE R1, R2 //R1 = R2 349 350 2: MOVE R1, 0x03 //R1 = 0x03 351 352 3: .set value1, 0x03 //constant value1=0x03 353 MOVE R1, value1 //R1 = value1 354 355 4: .global label //declaration of label 356 MOVE R1, label //R1 = address_of(label) / 4 357 ... 358 label: nop //definition of label 359 360 361**STL**/**ST** – Store data to the low 16 bits of 32-bits memory 362---------------------------------------------------------------- 363 364**Syntax** 365 **ST** *Rsrc, Rdst, offset, Label* 366 **STL** *Rsrc, Rdst, offset, Label* 367 368**Operands** 369 - *Rsrc* – Register R[0..3], holds the 16-bit value to store 370 - *Rdst* – Register R[0..3], address of the destination, in 32-bit words 371 - *Offset* – 11-bit signed value, offset in bytes 372 - *Label* – 2-bit user defined unsigned value 373 374**Cycles** 375 4 cycles to execute, 4 cycles to fetch next instruction 376 377**Description** 378 The instruction stores the 16-bit value of Rsrc to the lower half-word of memory with address Rdst+offset:: 379 380 Mem[Rdst + offset / 4]{15:0} = {Rsrc[15:0]} 381 Mem[Rdst + offset / 4]{15:0} = {Label[1:0],Rsrc[13:0]} 382 383 The ST command introduced to make compatibility with previous versions of UPL core. 384 The application can use higher 16 bits to determine which instruction in the ULP program has written any particular word into memory. 385 386**Examples**:: 387 388 1: STL R1, R2, 0x12 //MEM[R2+0x12] = R1 389 390 2: .data //Data section definition 391 Addr1: .word 123 // Define label Addr1 16 bit 392 .set offs, 0x00 // Define constant offs 393 .text //Text section definition 394 MOVE R1, 1 // R1 = 1 395 MOVE R2, Addr1 // R2 = Addr1 396 STL R1, R2, offs // MEM[R2 + 0] = R1 397 // MEM[Addr1 + 0] will be 32'hxxxx0001 398 3: 399 MOVE R1, 1 // R1 = 1 400 STL R1, R2, 0x12,1 // MEM[R2+0x12] 0xxxxx4001 401 402 403**STH** – Store data to the high 16 bits of 32-bits memory 404---------------------------------------------------------- 405 406**Syntax** 407 **STH** *Rsrc, Rdst, offset, Label* 408 409**Operands** 410 - *Rsrc* – Register R[0..3], holds the 16-bit value to store 411 - *Rdst* – Register R[0..3], address of the destination, in 32-bit words 412 - *Offset* – 11-bit signed value, offset in bytes 413 - *Label* – 2-bit user defined unsigned value 414 415**Cycles** 416 4 cycles to execute, 4 cycles to fetch next instruction 417 418**Description** 419 The instruction stores the 16-bit value of Rsrc to the high half-word of memory with address Rdst+offset:: 420 421 Mem[Rdst + offset / 4]{31:16} = {Rsrc[15:0]} 422 Mem[Rdst + offset / 4]{31:16} = {Label[1:0],Rsrc[13:0]} 423 424**Examples**:: 425 426 1: STH R1, R2, 0x12 //MEM[R2+0x12][31:16] = R1 427 428 2: .data //Data section definition 429 Addr1: .word 123 // Define label Addr1 16 bit 430 .set offs, 0x00 // Define constant offs 431 .text //Text section definition 432 MOVE R1, 1 // R1 = 1 433 MOVE R2, Addr1 // R2 = Addr1 434 STH R1, R2, offs // MEM[R2 + 0] = R1 435 // MEM[Addr1 + 0] will be 32'h0001xxxx 436 3: 437 MOVE R1, 1 // R1 = 1 438 STH R1, R2, 0x12, 1 //MEM[R2+0x12] 0x4001xxxx 439 440 441**STO** – Set offset value for auto increment operation 442------------------------------------------------------- 443 444**Syntax** 445 **STO** *offset* 446 447**Operands** 448 - *Offset* – 11-bit signed value, offset in bytes 449 450**Cycles** 451 4 cycles to execute, 4 cycles to fetch next instruction 452 453**Description** 454 The instruction set 16-bit value to the offset register:: 455 456 offset = value/ 4 457 458**Examples**:: 459 460 1: STO 0x12 // Offset = 0x12/4 461 462 2: .data //Data section definition 463 Addr1: .word 123 // Define label Addr1 16 bit 464 .set offs, 0x00 // Define constant offs 465 .text //Text section definition 466 STO offs // Offset = 0x00 467 468 469**STI** – Store data to the 32-bits memory with auto increment of predefined offset address 470------------------------------------------------------------------------------------------- 471 472**Syntax** 473 **STI** *Rsrc, Rdst, Label* 474 475**Operands** 476 - *Rsrc* – Register R[0..3], holds the 16-bit value to store 477 - *Rdst* – Register R[0..3], address of the destination, in 32-bit words 478 - *Label* – 2-bit user defined unsigned value 479 480**Cycles** 481 4 cycles to execute, 4 cycles to fetch next instruction 482 483**Description** 484 The instruction stores the 16-bit value of Rsrc to the low and high half-word of memory with address Rdst+offset with 485 auto increment of offset:: 486 487 Mem[Rdst + offset / 4]{15:0/31:16} = {Rsrc[15:0]} 488 Mem[Rdst + offset / 4]{15:0/31:16} = {Label[1:0],Rsrc[13:0]} 489 490**Examples**:: 491 492 1: STO 0 // Set offset to 0 493 STI R1, R2, 0x12 //MEM[R2+0x12][15:0] = R1 494 STI R1, R2, 0x12 //MEM[R2+0x12][31:16] = R1 495 496 2: .data //Data section definition 497 Addr1: .word 123 // Define label Addr1 16 bit 498 .set offs, 0x00 // Define constant offs 499 .text //Text section definition 500 STO 0 // Set offset to 0 501 MOVE R1, 1 // R1 = 1 502 MOVE R2, Addr1 // R2 = Addr1 503 STI R1, R2 // MEM[R2 + 0] = R1 504 // MEM[Addr1 + 0] will be 32'hxxxx0001 505 STIx R1, R2 // MEM[R2 + 0] = R1 506 // MEM[Addr1 + 0] will be 32'h00010001 507 3: 508 STO 0 // Set offset to 0 509 MOVE R1, 1 // R1 = 1 510 STI R1, R2, 1 //MEM[R2+0x12] 0xxxxx4001 511 STI R1, R2, 1 //MEM[R2+0x12] 0x40014001 512 513 514**ST32** – Store 32-bits data to the 32-bits memory 515--------------------------------------------------- 516 517**Syntax** 518 **ST32** *Rsrc, Rdst, offset, Label* 519 520**Operands** 521 - *Rsrc* – Register R[0..3], holds the 16-bit value to store 522 - *Rdst* – Register R[0..3], address of the destination, in 32-bit words 523 - *Offset* – 11-bit signed value, offset in bytes 524 - *Label* – 2-bit user defined unsigned value 525 526**Cycles** 527 4 cycles to execute, 4 cycles to fetch next instruction 528 529**Description** 530 The instruction stores 11 bits of the PC value, label value and the 16-bit value of Rsrc to the 32-bits memory with address Rdst+offset:: 531 532 Mem[Rdst + offset / 4]{31:0} = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]} 533 534**Examples**:: 535 536 1: ST32 R1, R2, 0x12, 0 //MEM[R2+0x12][31:0] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]} 537 538 2: .data //Data section definition 539 Addr1: .word 123 // Define label Addr1 16 bit 540 .set offs, 0x00 // Define constant offs 541 .text //Text section definition 542 MOVE R1, 1 // R1 = 1 543 MOVE R2, Addr1 // R2 = Addr1 544 ST32 R1, R2, offs,1// MEM[R2 + 0] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]} 545 // MEM[Addr1 + 0] will be 32'h00010001 546 547 548**STI32** – Store 32-bits data to the 32-bits memory with auto increment of adress offset 549----------------------------------------------------------------------------------------- 550 551**Syntax** 552 **STI32** *Rsrc, Rdst, Label* 553 554**Operands** 555 - *Rsrc* – Register R[0..3], holds the 16-bit value to store 556 - *Rdst* – Register R[0..3], address of the destination, in 32-bit words 557 - *Label* – 2-bit user defined unsigned value 558 559**Cycles** 560 4 cycles to execute, 4 cycles to fetch next instruction 561 562**Description** 563 The instruction stores 11 bits of the PC value, label value and the 16-bit value of Rsrc to the 32-bits memory with address Rdst+offset:: 564 565 Mem[Rdst + offset / 4]{31:0} = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]} 566 567 Where offset value set by STO instruction 568 569**Examples**:: 570 571 1: STO 0x12 572 STI32 R1, R2, 0 //MEM[R2+0x12][31:0] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]} 573 STI32 R1, R2, 0 //MEM[R2+0x13][31:0] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]} 574 575 2: .data //Data section definition 576 Addr1: .word 123 // Define label Addr1 16 bit 577 .set offs, 0x00 // Define constant offs 578 .text //Text section definition 579 MOVE R1, 1 // R1 = 1 580 MOVE R2, Addr1 // R2 = Addr1 581 STO offs 582 STI32 R1, R2, 1// MEM[R2 + 0] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]} 583 // MEM[Addr1 + 0] will be 32'h00010001 584 ST32 R1, R2, 1// MEM[R2 + 1] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]} 585 // MEM[Addr1 + 1] will be 32'h00010001 586 587 588**LDL**/**LD** – Load data from low part of the 32-bits memory 589-------------------------------------------------------------- 590 591**Syntax** 592 **LD** *Rdst, Rsrc, offset* 593 **LDL** *Rdst, Rsrc, offset* 594 595**Operands** 596 *Rdst* – Register R[0..3], destination 597 598 *Rsrc* – Register R[0..3], holds address of destination, in 32-bit words 599 600 *Offset* – 13-bit signed value, offset in bytes 601 602**Cycles** 603 4 cycles to execute, 4 cycles to fetch next instruction 604 605**Description** 606 The instruction loads lower 16-bit half-word from memory with address Rsrc+offset into the destination register Rdst:: 607 608 Rdst[15:0] = Mem[Rsrc + offset / 4][15:0] 609 610 The LD command do the same as LDL, and included for compatibility with previous versions of ULP core. 611 612**Examples**:: 613 614 1: LDL R1, R2, 0x12 //R1 = MEM[R2+0x12] 615 616 2: .data //Data section definition 617 Addr1: .word 123 // Define label Addr1 16 bit 618 .set offs, 0x00 // Define constant offs 619 .text //Text section definition 620 MOVE R1, 1 // R1 = 1 621 MOVE R2, Addr1 // R2 = Addr1 / 4 (address of label is converted into words) 622 LDL R1, R2, offs // R1 = MEM[R2 + 0] 623 // R1 will be 123 624 625 626**LDH** – Load data from high part of the 32-bits memory 627-------------------------------------------------------- 628 629**Syntax** 630 **LDH** *Rdst, Rsrc, offset* 631 632**Operands** 633 *Rdst* – Register R[0..3], destination 634 635 *Rsrc* – Register R[0..3], holds address of destination, in 32-bit words 636 637 *Offset* – 13-bit signed value, offset in bytes 638 639**Cycles** 640 4 cycles to execute, 4 cycles to fetch next instruction 641 642**Description** 643 The instruction loads higher 16-bit half-word from memory with address Rsrc+offset into the destination register Rdst:: 644 645 Rdst[15:0] = Mem[Rsrc + offset / 4][15:0] 646 647 The LD command do the same as LDL, and included for compatibility with previous versions of ULP core. 648 649**Examples**:: 650 651 1: LDH R1, R2, 0x12 //R1 = MEM[R2+0x12] 652 653 2: .data //Data section definition 654 Addr1: .word 0x12345678 // Define label Addr1 16 bit 655 .set offs, 0x00 // Define constant offs 656 .text //Text section definition 657 MOVE R1, 1 // R1 = 1 658 MOVE R2, Addr1 // R2 = Addr1 / 4 (address of label is converted into words) 659 LDH R1, R2, offs // R1 = MEM[R2 + 0] 660 // R1 will be 0x1234 661 662 663**JUMP** – Jump to an absolute address 664-------------------------------------- 665 666**Syntax** 667 **JUMP** *Rdst* 668 669 **JUMP** *ImmAddr* 670 671 **JUMP** *Rdst, Condition* 672 673 **JUMP** *ImmAddr, Condition* 674 675 676**Operands** 677 - *Rdst* – Register R[0..3] containing address to jump to (expressed in 32-bit words) 678 679 - *ImmAddr* – 13 bits address (expressed in bytes), aligned to 4 bytes 680 681 - *Condition*: 682 - EQ – jump if last ALU operation result was zero 683 - OV – jump if last ALU has set overflow flag 684 685**Cycles** 686 2 cycles to execute, 2 cycles to fetch next instruction 687 688**Description** 689 The instruction makes jump to the specified address. Jump can be either unconditional or based on an ALU flag. 690 691**Examples**:: 692 693 1: JUMP R1 // Jump to address in R1 (address in R1 is in 32-bit words) 694 695 2: JUMP 0x120, EQ // Jump to address 0x120 (in bytes) if ALU result is zero 696 697 3: JUMP label // Jump to label 698 ... 699 label: nop // Definition of label 700 701 4: .global label // Declaration of global label 702 703 MOVE R1, label // R1 = label (value loaded into R1 is in words) 704 JUMP R1 // Jump to label 705 ... 706 label: nop // Definition of label 707 708 709 710**JUMPR** – Jump to a relative offset (condition based on R0) 711------------------------------------------------------------- 712 713**Syntax** 714 **JUMPR** *Step, Threshold, Condition* 715 716**Operands** 717 - *Step* – relative shift from current position, in bytes 718 - *Threshold* – threshold value for branch condition 719 - *Condition*: 720 - *EQ* (equal) – jump if value in R0 == threshold 721 - *LT* (less than) – jump if value in R0 < threshold 722 - *LE* (less or equal) – jump if value in R0 <= threshold 723 - *GT* (greater than) – jump if value in R0 > threshold 724 - *GE* (greater or equal) – jump if value in R0 >= threshold 725 726**Cycles** 727 Conditions *EQ*, *GT* and *LT*: 2 cycles to execute, 2 cycles to fetch next instruction 728 729 Conditions *LE* and *GE* are implemented in the assembler using two **JUMPR** instructions:: 730 731 // JUMPR target, threshold, LE is implemented as: 732 733 JUMPR target, threshold, EQ 734 JUMPR target, threshold, LT 735 736 // JUMPR target, threshold, GE is implemented as: 737 738 JUMPR target, threshold, EQ 739 JUMPR target, threshold, GT 740 741 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. 742 743**Description** 744 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. 745 746**Examples**:: 747 748 1:pos: JUMPR 16, 20, GE // Jump to address (position + 16 bytes) if value in R0 >= 20 749 750 2: // Down counting loop using R0 register 751 MOVE R0, 16 // load 16 into R0 752 label: SUB R0, R0, 1 // R0-- 753 NOP // do something 754 JUMPR label, 1, GE // jump to label if R0 >= 1 755 756 757 758**JUMPS** – Jump to a relative address (condition based on stage count) 759----------------------------------------------------------------------- 760 761**Syntax** 762 **JUMPS** *Step, Threshold, Condition* 763 764**Operands** 765 - *Step* – relative shift from current position, in bytes 766 - *Threshold* – threshold value for branch condition 767 - *Condition*: 768 - *EQ* (equal) – jump if value in stage_cnt == threshold 769 - *LT* (less than) – jump if value in stage_cnt < threshold 770 - *LE* (less or equal) - jump if value in stage_cnt <= threshold 771 - *GT* (greater than) – jump if value in stage_cnt > threshold 772 - *GE* (greater or equal) — jump if value in stage_cnt >= threshold 773 774**Cycles** 775 2 cycles to execute, 2 cycles to fetch next instruction:: 776 777 // JUMPS target, threshold, EQ is implemented as: 778 779 JUMPS next, threshold, LT 780 JUMPS target, threshold, LE 781 next: 782 783 // JUMPS target, threshold, GT is implemented as: 784 785 JUMPS next, threshold, LE 786 JUMPS target, threshold, GE 787 next: 788 789 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. 790 791 792**Description** 793 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. 794 795**Examples**:: 796 797 1:pos: JUMPS 16, 20, EQ // Jump to (position + 16 bytes) if stage_cnt == 20 798 799 2: // Up counting loop using stage count register 800 STAGE_RST // set stage_cnt to 0 801 label: STAGE_INC 1 // stage_cnt++ 802 NOP // do something 803 JUMPS label, 16, LT // jump to label if stage_cnt < 16 804 805 806 807**STAGE_RST** – Reset stage count register 808------------------------------------------ 809**Syntax** 810 **STAGE_RST** 811 812**Operands** 813 No operands 814 815**Description** 816 The instruction sets the stage count register to 0 817 818**Cycles** 819 2 cycles to execute, 4 cycles to fetch next instruction 820 821**Examples**:: 822 823 1: STAGE_RST // Reset stage count register 824 825 826 827**STAGE_INC** – Increment stage count register 828---------------------------------------------- 829 830**Syntax** 831 **STAGE_INC** *Value* 832 833**Operands** 834 - *Value* – 8 bits value 835 836**Cycles** 837 2 cycles to execute, 4 cycles to fetch next instruction 838 839**Description** 840 The instruction increments stage count register by given value. 841 842**Examples**:: 843 844 1: STAGE_INC 10 // stage_cnt += 10 845 846 2: // Up counting loop example: 847 STAGE_RST // set stage_cnt to 0 848 label: STAGE_INC 1 // stage_cnt++ 849 NOP // do something 850 JUMPS label, 16, LT // jump to label if stage_cnt < 16 851 852 853**STAGE_DEC** – Decrement stage count register 854---------------------------------------------- 855 856**Syntax** 857 **STAGE_DEC** *Value* 858 859**Operands** 860 - *Value* – 8 bits value 861 862**Cycles** 863 2 cycles to execute, 4 cycles to fetch next instruction 864 865**Description** 866 The instruction decrements stage count register by given value. 867 868**Examples**:: 869 870 1: STAGE_DEC 10 // stage_cnt -= 10; 871 872 2: // Down counting loop exaple 873 STAGE_RST // set stage_cnt to 0 874 STAGE_INC 16 // increment stage_cnt to 16 875 label: STAGE_DEC 1 // stage_cnt--; 876 NOP // do something 877 JUMPS label, 0, GT // jump to label if stage_cnt > 0 878 879 880**HALT** – End the program 881-------------------------- 882 883**Syntax** 884 **HALT** 885 886**Operands** 887 No operands 888 889**Cycles** 890 2 cycles to execute 891 892**Description** 893 The instruction halts the ULP coprocessor and restarts ULP wakeup timer, if it is enabled. 894 895**Examples**:: 896 897 1: HALT // Halt the coprocessor 898 899 900 901**WAKE** – Wake up the chip 902--------------------------- 903 904**Syntax** 905 **WAKE** 906 907**Operands** 908 No operands 909 910**Cycles** 911 2 cycles to execute, 4 cycles to fetch next instruction 912 913**Description** 914 The instruction sends an interrupt from ULP to RTC controller. 915 916 - If the SoC is in deep sleep mode, and ULP wakeup is enabled, this causes the SoC to wake up. 917 918 - 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. 919 920 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). 921 922**Examples**:: 923 924 1: is_rdy_for_wakeup: // Read RTC_CNTL_RDY_FOR_WAKEUP bit 925 READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP) 926 AND r0, r0, 1 927 JUMP is_rdy_for_wakeup, eq // Retry until the bit is set 928 WAKE // Trigger wake up 929 REG_WR 0x006, 24, 24, 0 // Stop ULP timer (clear RTC_CNTL_ULP_CP_SLP_TIMER_EN) 930 HALT // Stop the ULP program 931 // After these instructions, SoC will wake up, 932 // and ULP will not run again until started by the main program. 933 934 935 936**WAIT** – wait some number of cycles 937------------------------------------- 938 939**Syntax** 940 **WAIT** *Cycles* 941 942**Operands** 943 - *Cycles* – number of cycles for wait 944 945**Cycles** 946 2 + *Cycles* cycles to execute, 4 cycles to fetch next instruction 947 948**Description** 949 The instruction delays for given number of cycles. 950 951**Examples**:: 952 953 1: WAIT 10 // Do nothing for 10 cycles 954 955 2: .set wait_cnt, 10 // Set a constant 956 WAIT wait_cnt // wait for 10 cycles 957 958 959**TSENS** – do measurement with temperature sensor 960-------------------------------------------------- 961 962**Syntax** 963 - **TSENS** *Rdst, Wait_Delay* 964 965**Operands** 966 - *Rdst* – Destination Register R[0..3], result will be stored to this register 967 - *Wait_Delay* – number of cycles used to perform the measurement 968 969**Cycles** 970 2 + *Wait_Delay* + 3 * TSENS_CLK to execute, 4 cycles to fetch next instruction 971 972**Description** 973 The instruction performs measurement using TSENS and stores the result into a general purpose register. 974 975**Examples**:: 976 977 1: TSENS R1, 1000 // Measure temperature sensor for 1000 cycles, 978 // and store result to R1 979 980 981**ADC** – do measurement with ADC 982--------------------------------- 983 984**Syntax** 985 - **ADC** *Rdst, Sar_sel, Mux* 986 987 - **ADC** *Rdst, Sar_sel, Mux, 0* — deprecated form 988 989**Operands** 990 - *Rdst* – Destination Register R[0..3], result will be stored to this register 991 - *Sar_sel* – Select ADC: 0 = SARADC1, 1 = SARADC2 992 - *Mux* - selected PAD, SARADC Pad[Mux-1] is enabled. If the user passes Mux value 1, then ADC pad 0 gets used. 993 994**Cycles** 995 ``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 996 997**Description** 998 The instruction makes measurements from ADC. 999 1000**Examples**:: 1001 1002 1: ADC R1, 0, 1 // Measure value using ADC1 pad 2 and store result into R1 1003 1004 1005**REG_RD** – read from peripheral register 1006------------------------------------------ 1007 1008**Syntax** 1009 **REG_RD** *Addr, High, Low* 1010 1011**Operands** 1012 - *Addr* – Register address, in 32-bit words 1013 - *High* – Register end bit number 1014 - *Low* – Register start bit number 1015 1016**Cycles** 1017 4 cycles to execute, 4 cycles to fetch next instruction 1018 1019**Description** 1020 The instruction reads up to 16 bits from a peripheral register into a general purpose register: ``R0 = REG[Addr][High:Low]``. 1021 1022 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 PeriBUS1 as follows:: 1023 1024 addr_ulp = (addr_peribus1 - DR_REG_RTCCNTL_BASE) / 4 1025 1026**Examples**:: 1027 1028 1: REG_RD 0x120, 7, 4 // load 4 bits: R0 = {12'b0, REG[0x120][7:4]} 1029 1030 1031**REG_WR** – write to peripheral register 1032----------------------------------------- 1033 1034**Syntax** 1035 **REG_WR** *Addr, High, Low, Data* 1036 1037**Operands** 1038 - *Addr* – Register address, in 32-bit words. 1039 - *High* – Register end bit number 1040 - *Low* – Register start bit number 1041 - *Data* – Value to write, 8 bits 1042 1043**Cycles** 1044 8 cycles to execute, 4 cycles to fetch next instruction 1045 1046**Description** 1047 The instruction writes up to 8 bits from an immediate data value into a peripheral register: ``REG[Addr][High:Low] = data``. 1048 1049 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 PeriBUS1 as follows:: 1050 1051 addr_ulp = (addr_peribus1 - DR_REG_RTCCNTL_BASE) / 4 1052 1053**Examples**:: 1054 1055 1: REG_WR 0x120, 7, 0, 0x10 // set 8 bits: REG[0x120][7:0] = 0x10 1056 1057 1058Convenience macros for peripheral registers access 1059-------------------------------------------------- 1060 1061ULP source files are passed through C preprocessor before the assembler. This allows certain macros to be used to facilitate access to peripheral registers. 1062 1063Some existing macros are defined in ``soc/soc_ulp.h`` header file. These macros allow access to the fields of peripheral registers by their names. 1064Peripheral 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``. 1065 1066READ_RTC_REG(rtc_reg, low_bit, bit_width) 1067 Read up to 16 bits from rtc_reg[low_bit + bit_width - 1 : low_bit] into R0. For example:: 1068 1069 #include "soc/soc_ulp.h" 1070 #include "soc/rtc_cntl_reg.h" 1071 1072 /* Read 16 lower bits of RTC_CNTL_TIME0_REG into R0 */ 1073 READ_RTC_REG(RTC_CNTL_TIME0_REG, 0, 16) 1074 1075READ_RTC_FIELD(rtc_reg, field) 1076 Read from a field in rtc_reg into R0, up to 16 bits. For example:: 1077 1078 #include "soc/soc_ulp.h" 1079 #include "soc/sens_reg.h" 1080 1081 /* Read 8-bit SENS_TSENS_OUT field of SENS_SAR_SLAVE_ADDR3_REG into R0 */ 1082 READ_RTC_FIELD(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT) 1083 1084WRITE_RTC_REG(rtc_reg, low_bit, bit_width, value) 1085 Write immediate value into rtc_reg[low_bit + bit_width - 1 : low_bit], bit_width <= 8. For example:: 1086 1087 #include "soc/soc_ulp.h" 1088 #include "soc/rtc_io_reg.h" 1089 1090 /* Set BIT(2) of RTC_GPIO_OUT_DATA_W1TS field in RTC_GPIO_OUT_W1TS_REG */ 1091 WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S + 2, 1, 1) 1092 1093WRITE_RTC_FIELD(rtc_reg, field, value) 1094 Write immediate value into a field in rtc_reg, up to 8 bits. For example:: 1095 1096 #include "soc/soc_ulp.h" 1097 #include "soc/rtc_cntl_reg.h" 1098 1099 /* Set RTC_CNTL_ULP_CP_SLP_TIMER_EN field of RTC_CNTL_STATE0_REG to 0 */ 1100 WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0) 1101