Skip to content

ULPコプロセッサ命令セット

このドキュメントでは、ESP32 ULPコプロセッサーアセンブラーで使用される命令について詳しく説明します。

ULPコプロセッサには、R0、R1、R2、R3とラベル付けされた4つの16ビット汎用レジスタがあります。また、ループの実装に使用できる8ビットカウンターレジスタ(stage_cnt)もあります。 ステージカウントレジスタには、特別な指示を使用してアクセスします。

ULPコプロセッサは、8kバイトのRTC_SLOW_MEMメモリ領域にアクセスできます。メモリは32ビットワード単位でアドレス指定されます。RTC_CNTL、RTC_IO、およびSENS周辺機器の周辺機器レジスタにもアクセスできます。

すべての命令は32ビットです。ジャンプ命令、ALU命令、ペリフェラルレジスタ、メモリアクセス命令は1サイクルで実行されます。周辺機器(TSENS、ADC、I2C)で動作する命令は、周辺機器の動作に応じて、可変サイクル数を取ります。

命令の構文は大文字と小文字を区別しません。大文字と小文字を使用して、任意に混在させることができます。これは、レジスタ名と命令名の両方に当てはまります。

注意事項

アドレス指定に関する注意

引数としてレジスタを使用するESP32 ULPコプロセッサのJUMP、ST、LD命令(ジャンプアドレス、ストア/ロードベースアドレス)は、引数が32ビットワードで表現されることを想定しています。

次のプログラム例を考えてみましょう。

entry:
        NOP
        NOP
        NOP
        NOP
loop:
        MOVE R1, loop
        JUMP R1

このプログラムがアセンブルおよびリンクされると、loopラベルのアドレスは16(バイトで表現)に等しくなります。 ただし、JUMP 命令は、レジスタに格納されているアドレスが32ビットワードで表現されることを想定しています。 この一般的なユースケースを考慮して、アセンブラーは命令を生成するときにloopラベルのアドレスをバイトからワードに変換するMOVEにて、コード生成コードは次のコードと同等になります。

0000    NOP
0004    NOP
0008    NOP
000c    NOP
0010    MOVE R1, 4
0014    JUMP R1

もう1つのケースは、MOVE命令の引数がラベルではなく定数である場合です。この場合、アセンブラーは変換せずに値をそのまま使用します。

.set        val, 0x10
MOVE        R1, val

この場合、R1にロードされる値はになります0x10

同様の考慮事項はLDST命令に適用されます。次のコードを検討してください。

        .global array
array:  .long 0
        .long 0
        .long 0
        .long 0

        MOVE R1, array
        MOVE R2, 0x1234
        ST R2, R1, 0      // R2の値を最初の配列要素に書き込む
                          // 例) array[0]

        ST R2, R1, 4      // R2の値を2番目の配列要素に書き込む
                          // (4バイトオフセット), 例) array[1]

        ADD R1, R1, 2     // アドレスを2ワード(8バイト)インクリメント
        ST R2, R1, 0      // R2の値を3番目の配列要素に書き込む
                          // 例) array[2]

命令実行時間に関する注意

ULPコプロセッサはRTC_FAST_CLKからクロックを供給されます。RTC_FAST_CLKは通常、内部8MHz発振器から供給しています。 正確なULPクロック周波数を知る必要があるアプリケーションは、メインのXTALクロックに対してそれを確認できます。

#include "soc/rtc.h"

// XTALに対して8M/256クロックを較正し、8M/256クロック周期を取得
uint32_t rtc_8md256_period = rtc_clk_cal(RTC_CAL_8MD256, 100);
uint32_t rtc_fast_freq_hz = 1000000ULL * (1 << RTC_CLK_CAL_FRACT) * 256 / rtc_8md256_period;

ULPコプロセッサは、命令に応じて、各インストラクションをフェッチするために特定の数のクロックサイクルと、実行するために特定の数のサイクルを必要とします。 実行時間の詳細については、以下の各命令の説明を参照してください。

命令フェッチ時間は次のとおりです。

  • 2クロックサイクル— ALUおよび分岐命令に続く命令用
  • 4クロックサイクル—その他の場合

RTCメモリとRTCレジスタにアクセスする場合、ULPコプロセッサの優先順位はメインCPUよりも低いことに注意してください。 これは、メインCPUがULPと同じメモリ領域にアクセスしている間、ULPコプロセッサーの実行が中断される可能性があることを意味します。

命令

NOP - 操作なし

構文

NOP

オペランド

無し

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

操作は実行されません。PCのみがインクリメントされます。

1:    NOP

ADD - レジスタを加算

構文

ADD Rdst, Rsrc1, Rsrc2
ADD Rdst, Rsrc1, imm

オペランド

  • Rdst - レジスタR[0..3]
  • Rsrc1 - レジスタR[0..3]
  • Rsrc2 - レジスタR[0..3]
  • Imm - 16ビット符号付き値

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

この命令は、ソースレジスタを別のソースレジスタまたは16ビットの符号付き値に追加し、結果をデスティネーションレジスタに保存します。

1:    ADD R1, R2, R3        // R1 = R2 + R3

2:    Add R1, R2, 0x1234    // R1 = R2 + 0x1234

3:    .set value1, 0x03     // 定数宣言 value1=0x03
      Add R1, R2, value1    // R1 = R2 + value1

4:    .global label         // ラベル宣言
      Add R1, R2, label     // R1 = R2 + label
        ...
      label: nop            // ラベル宣言

SUB - レジスタを減算

構文

SUB Rdst, Rsrc1, Rsrc2
SUB Rdst, Rsrc1, imm

オペランド

  • Rdst - レジスタR[0..3]
  • Rsrc1 - レジスタR[0..3]
  • Rsrc2 - レジスタR[0..3]
  • Imm - 16ビット符号付き値

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

この命令は、別のソースレジスタからソースレジスタを減算するか、ソースレジスタから16ビット符号付き値を減算し、結果をデスティネーションレジスタに格納します。

1:         SUB R1, R2, R3             // R1 = R2 - R3

2:         sub R1, R2, 0x1234         // R1 = R2 - 0x1234

3:         .set value1, 0x03          // 定数宣言 value1=0x03
           SUB R1, R2, value1         // R1 = R2 - value1

4:         .global label              // ラベル宣言
           SUB R1, R2, label          // R1 = R2 - label
             ....
  label:   nop                        // ラベル宣言

AND - 2つのオペランドの論理積

構文

AND Rdst, Rsrc1, Rsrc2
AND Rdst, Rsrc1, imm

オペランド

  • Rdst - レジスタR[0..3]
  • Rsrc1 - レジスタR[0..3]
  • Rsrc2 - レジスタR[0..3]
  • Imm - 16ビット符号付き値

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

この命令は、ソースレジスタと別のソースレジスタまたは16ビット符号付き値の論理ANDを実行し、結果をデスティネーションレジスタに保存します。

1:        AND R1, R2, R3          // R1 = R2 & R3

2:        AND R1, R2, 0x1234      // R1 = R2 & 0x1234

3:        .set value1, 0x03       // 定数宣言 value1=0x03
          AND R1, R2, value1      // R1 = R2 & value1

4:        .global label           // ラベル宣言
          AND R1, R2, label       // R1 = R2 & label
              ...
  label:  nop                     // ラベル宣言

OR - 2つのオペランドの論理和

構文

OR Rdst, Rsrc1, Rsrc2
OR Rdst, Rsrc1, imm

オペランド

  • Rdst - レジスタR[0..3]
  • Rsrc1 - レジスタR[0..3]
  • Rsrc2 - レジスタR[0..3]
  • Imm - 16ビット符号付き値

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

この命令は、ソースレジスタと別のソースレジスタまたは16ビット符号付き値の論理ORを実行し、結果をデスティネーションレジスタに保存します。

1:       OR R1, R2, R3           // R1 = R2 | R3

2:       OR R1, R2, 0x1234       // R1 = R2 | 0x1234

3:       .set value1, 0x03       // 定数宣言 value1=0x03
         OR R1, R2, value1       // R1 = R2 | value1

4:       .global label           // ラベル宣言
         OR R1, R2, label        // R1 = R2 | label
         ...
  label: nop                     // ラベル宣言

LSH - 論理左シフト

構文

LSH Rdst, Rsrc1, Rsrc2
LSH Rdst, Rsrc1, imm

オペランド

  • Rdst - レジスタR[0..3]
  • Rsrc1 - レジスタR[0..3]
  • Rsrc2 - レジスタR[0..3]
  • Imm - 16ビット符号付き値

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

この命令は、ソースレジスタの左への論理シフトを行って、別のソースレジスタからのビット数または16ビットの符号付き値に変換し、結果をデスティネーションレジスタに保存します。

1:       LSH R1, R2, R3            // R1 = R2 << R3

2:       LSH R1, R2, 0x03          // R1 = R2 << 0x03

3:       .set value1, 0x03         // 定数宣言 value1=0x03
         LSH R1, R2, value1        // R1 = R2 << value1

4:       .global label             // ラベル宣言
         LSH R1, R2, label         // R1 = R2 << label
         ...
  label: nop                       // ラベル宣言

RSH - 論理右シフト

構文

RSH Rdst, Rsrc1, Rsrc2
RSH Rdst, Rsrc1, imm

オペランド

  • RDST - レジスタR[0..3]
  • Rsrc1 - レジスタR[0..3]
  • Rsrc2 - レジスタR[0..3]
  • imm - 16ビット符号付き値

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

この命令は、ソースレジスタの右に別のソースレジスタのビット数または16ビットの符号付き値に論理シフトし、結果をデスティネーションレジスタに保存します。

1:        RSH R1, R2, R3              // R1 = R2 >> R3

2:        RSH R1, R2, 0x03            // R1 = R2 >> 0x03

3:        .set value1, 0x03           // 定数宣言 value1=0x03
          RSH R1, R2, value1          // R1 = R2 >> value1

4:        .global label               // ラベル宣言
          RSH R1, R2, label           // R1 = R2 >> label
  label:  nop                         // ラベル宣言

MOVE - レジスタに移動

構文

MOVE Rdst, Rsrc
MOVE Rdst, imm

オペランド

  • Rdst - レジスタR[0..3]
  • Rsrc - レジスタR[0..3]
  • Imm - 16ビット符号付き値

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

命令は、ソースレジスタまたは16ビット符号付き値からデスティネーションレジスタ値に移動します。

ラベルがイミディエートとしてそのまま使用する場合、ラベルのアドレスはバイトからワードに変換されることに注意してください。 これは、LD、ST、およびJUMP命令は、アドレスレジスタ値がバイトではなくワードで表現されることを想定しているためです。

1:        MOVE       R1, R2            // R1 = R2

2:        MOVE       R1, 0x03          // R1 = 0x03

3:        .set       value1, 0x03      // 定数宣言 value1=0x03
          MOVE       R1, value1        // R1 = value1

4:        .global    label             // ラベル宣言
          MOVE       R1, label         // R1 = address_of(label) / 4
          ...
  label:  nop                          // ラベル宣言

ST - データをメモリに保存する

構文

ST Rsrc, Rdst, offset

オペランド

  • Rsrc - レジスタR [0..3]、保存する16ビット値を保持
  • Rdst - レジスタR [0..3]、宛先のアドレス、32ビットワード
  • offset - 10ビットの符号付き値、バイト単位のオフセット

サイクル

実行するのに4サイクル、次の命令をフェッチするのに4サイクル。

説明

命令は、アドレスRdst + offsetでRsrcの16ビット値をメモリの下位ハーフワードに保存します。 上位ハーフワードは、現在のプログラムカウンター(PC)で書き込まれ、ワードで表され、5ビット左にシフトされます。

Mem[Rdst + offset / 4]{31:0} = {PC[10:0], 5'b0, Rsrc[15:0]}

アプリケーションは、上位16ビットを使用して、ULPプログラムのどの命令が特定のワードをメモリに書き込んだかを判断できます。

1:        ST  R1, R2, 0x12        // MEM[R2+0x12] = R1

2:        .data                   // データセクション宣言
  Addr1:  .word     123           // 16ビットのラベルAddr1宣言
          .set      offs, 0x00    // 定数offs宣言
          .text                   // テキストセクション宣言
          MOVE      R1, 1         // R1 = 1
          MOVE      R2, Addr1     // R2 = Addr1
          ST        R1, R2, offs  // MEM[R2 +  0] = R1
                                  // MEM[Addr1 + 0] = 32'h600001

LD - メモリからデータをロードする

構文

LD Rdst, Rsrc, offset

オペランド

  • Rdst - レジスタR[0..3]、宛先
  • Rsrc - レジスタR[0..3]、宛先のアドレスを32ビットワードで保持
  • offset - 10ビットの符号付き値、バイト単位のオフセット

サイクル

実行するのに4サイクル、次の命令をフェッチするのに4サイクル。

説明

この命令は、アドレスRsrc + offsetのメモリから下位16ビットのハーフワードをデスティネーションレジスタRdstにロードします。

Rdst[15:0] = Mem[Rsrc + offset / 4][15:0]

1:        LD  R1, R2, 0x12            // R1 = MEM[R2+0x12]

2:        .data                       // データセクション宣言
  Addr1:  .word     123               // 16ビットのラベルAddr1宣言
          .set      offs, 0x00        // 定数offs宣言
          .text                       // テキストセクション宣言
          MOVE      R1, 1             // R1 = 1
          MOVE      R2, Addr1         // R2 = Addr1 / 4 (ラベルのアドレスはワードに変換されます)
          LD        R1, R2, offs      // R1 = MEM[R2 +  0]
                                      // R1 = 123

JUMP - 絶対アドレスにジャンプする

構文

JUMP Rdst
JUMP ImmAddr
JUMP Rdst, 条件
JUMP ImmAddr, 条件

オペランド

  • Rdst - ジャンプ先のアドレスを含むレジスタR[0..3] (32ビットワードで表現)
  • ImmAddr - 4バイトにアラインされた13ビットアドレス(バイトで表現)
  • 条件
    • EQ - 最後のALU操作結果がゼロの場合ジャンプ
    • OV - 最後のALUがオーバーフローフラグを設定した場合にジャンプ

サイクル

実行するのに2サイクル、次の命令をフェッチするのに2サイクル。

説明

命令は、指定されたアドレスにジャンプします。ジャンプは、無条件またはALUフラグに基づくことができます。

1:        JUMP       R1            // R1のアドレスにジャンプします(R1のアドレスは32ビットワードです)

2:        JUMP       0x120, EQ     // ALU結果がゼロの場合、アドレス0x120(バイト単位)にジャンプします

3:        JUMP       label         // ラベルにジャンプ
          ...
  label:  nop                      // ラベル宣言

4:        .global    label         // グローバルラベル宣言

          MOVE       R1, label     // R1 = ラベル(R1にロードされる値はワード単位)
          JUMP       R1            // ラベルにジャンプ
          ...
  label:  nop                      // ラベル宣言

JUMPR - 相対オフセットへのジャンプ(R0に基づく条件)

構文

JUMPR ステップ, しきい値, 条件

オペランド

  • ステップ - 現在位置からの相対シフト(バイト単位)
  • しきい値 - 分岐条件のしきい値
  • 条件
    • GE (以上) - R0の値がしきい値以上の場合にジャンプ
    • LT (より小さい)- R0の値 < しきい値の場合ジャンプ

サイクル

実行するのに2サイクル、次の命令をフェッチするのに2サイクル。

説明

条件が真の場合、命令は相対アドレスにジャンプします。条件は、R0レジスタ値としきい値の比較の結果です。

1:pos:    JUMPR       16, 20, GE   // R0 >= 20の時に、アドレスにジャンプ(位置+16バイト)

2:        // R0レジスタを使用したダウンカウントループ
          MOVE        R0, 16       // R0に16をセット
  label:  SUB         R0, R0, 1    // R0--
          NOP                      // 何かをする
          JUMPR       label, 1, GE // R0 >= 1の時にラベルにジャンプする

JUMPS - 相対アドレスへのジャンプ(ステージカウントに基づく条件)

構文

JUMPS _ステップ_, _しきい値_, _条件_

オペランド

  • ステップ - 現在位置からの相対シフト(バイト単位)
  • しきい値 - 分岐条件のしきい値
  • 条件
    • EQ (等しい) - stage_cntの値 == しきい値の場合ジャンプ
    • LT (より小さい)- stage_cntの値 < しきい値の場合ジャンプ
    • LE (以下) - stage_cntの値 <= しきい値の場合ジャンプ
    • GT (より大きい)- stage_cntの値 > しきい値の場合ジャンプ
    • GE (以上) - stage_cntの値 >= しきい値の場合ジャンプ

サイクル

条件 LELTGE :実行する2サイクル、次の命令をフェッチする2サイクル

条件 EQ、_GT_は、2つのJUMPS命令を使用してアセンブラーに実装されます。

// JUMPSターゲット、しきい値、EQは次のように実装されます。

         JUMPS next, threshold, LT
         JUMPS target, threshold, LE
next:

// JUMPSターゲット、しきい値、GTは次のように実装されます。

         JUMPS next, threshold, LE
         JUMPS target, threshold, GE
next:

したがって、実行時間は、実行する2サイクル+フェッチする2サイクル、実行する4サイクル+フェッチする4サイクルのいずれかになります。

説明

条件が真の場合、命令は相対アドレスにジャンプします。条件は、カウントレジスタ値としきい値の比較の結果です。

1:pos:    JUMPS     16, 20, EQ       // stage_cnt == 20の場合、(位置+ 16バイト)にジャンプします

2:        // ステージカウントレジスタを使用したアップカウントループ
          STAGE_RST                  // stage_cnt = 0
  label:  STAGE_INC 1                // stage_cnt++
          NOP                        // 何かをする
          JUMPS     label, 16, LT    // stage_cnt < 16の時にラベルにジャンプする

STAGE_RST - ステージカウントレジスタのリセット

構文

STAGE_RST

オペランド

オペランドなし

説明

この命令は、ステージカウントレジスタを0に設定します。

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル

1:       STAGE_RST      // リセットステージカウントレジスタ

STAGE_INC - インクリメントステージカウントレジスタ

構文

STAGE_INC _Value_

オペランド

  • Value - 8ビット値

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

命令は、指定された値でステージカウントレジスタをインクリメントします。

1:        STAGE_INC      10          // stage_cnt += 10

2:        // カウントループの例:
          STAGE_RST                  // stage_cnt = 0
  label:  STAGE_INC  1               // stage_cnt++
          NOP                        // 何かをする
          JUMPS      label, 16, LT   // stage_cnt < 16の時にラベルにジャンプする

STAGE_DEC - ステージカウントレジスタをデクリメントする

構文

STAGE_DEC _Value_

オペランド

  • Value - 8ビット値

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

命令は、指定された値でステージカウントレジスタをデクリメントします。

1:        STAGE_DEC      10        // stage_cnt -= 10;

2:        // ダウンカウントループの例
          STAGE_RST                // stage_cnt = 0
          STAGE_INC  16            // stage_cnt += 16
  label:  STAGE_DEC  1             // stage_cnt--;
          NOP                      // 何かをする
          JUMPS      label, 0, GT  // stage_cnt > 0の時にラベルにジャンプする

HALT - プログラムを終了する

構文

HALT

オペランド

オペランドなし

サイクル

実行する2サイクル。

説明

命令は、ULPコプロセッサーを停止し、ULPウェイクアップタイマーが有効になっている場合は再起動します。

1:       HALT      // コプロセッサーを停止します

WAKE - チップを起動する

構文

WAKE

オペランド

オペランドなし

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

命令は、ULPからRTCコントローラーに割り込みを送信します。

  • SoCがディープスリープモードにあり、ULPウェイクアップが有効になっている場合、SoCがウェイクアップします。
  • SoCがディープスリープモードになっておらず、RTC_CNTL_INT_ENA_REGレジスタでULP割り込みビット(RTC_CNTL_ULP_CP_INT_ENA)が設定されている場合、RTC割り込みがトリガーされます。

WAKE命令を使用する前に、ULPプログラムはRTCコントローラーがメインCPUをウェイクアップする準備ができるまで待機する必要があることに注意してください。 これは、RTC_CNTL_LOW_POWER_ST_REGレジスタのRTC_CNTL_RDY_FOR_WAKEUPビットを使用して示されます。 RTC_CNTL_RDY_FOR_WAKEUPがゼロの間にWAKE命令が実行された場合、効果はありません(ウェイクアップは発生しません)。

1: is_rdy_for_wakeup:                   // RTC_CNTL_RDY_FOR_WAKEUPビットを読み取る
          READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
          AND r0, r0, 1
          JUMP is_rdy_for_wakeup, eq    // ビットが設定されるまでリトライする
          WAKE                          // トリガーウェイクアップ
          REG_WR 0x006, 24, 24, 0       // ULPタイマーを停止(RTC_CNTL_ULP_CP_SLP_TIMER_ENをクリア)
          HALT                          // ULPプログラムを停止します
          // これらの指示の後、SoCが起動し、
          // また、メインプログラムによって開始されるまで、ULPは再度実行されません。

SLEEP - ULPウェイクアップタイマー期間の設定

構文

SLEEP _sleep_reg_

オペランド

  • sleep_reg - 0..4、SENS_ULP_CP_SLEEP_CYCx_REG レジスタの1つを選択します。

サイクル

実行するのに2サイクル、次の命令をフェッチするのに4サイクル。

説明

この命令は、SENS_ULP_CP_SLEEP_CYCx_REG(x = 0..4)レジスタ値のどれをウェイクアップ期間としてULPウェイクアップタイマーが使用するかを選択します。 デフォルトでは、からの値 SENS_ULP_CP_SLEEP_CYC0_REGが使用されます。

1:        SLEEP     1         // SENS_ULP_CP_SLEEP_CYC1_REGで設定された期間を使用

2:        .set sleep_reg, 4   // 定数宣言
          SLEEP  sleep_reg    // SENS_ULP_CP_SLEEP_CYC4_REGで設定された期間を使用

WAIT - いくつかのサイクルを待つ

構文

WAIT _Cycles_

オペランド

  • Cycles - 待機のサイクル数

サイクル

実行するのに2 + Cycles サイクル、次の命令をフェッチするのに4サイクル。

説明

命令は、指定されたサイクル数だけ遅延します。

1:        WAIT     10         // 10サイクルの間何もしません

2:        .set  wait_cnt, 10  // 定数宣言
          WAIT  wait_cnt      // 10サイクルの間何もしません

TSENS - 温度センサーで測定を行う

構文

TSENS Rdst, Wait_Delay

オペランド

  • Rdst - デスティネーションレジスタR[0..3]、結果はこのレジスタに保存されます
  • Wait_Delay - 測定の実行に使用されるサイクル数

サイクル

実行するのに2 + Wait_Delay + 3 * TSENS_CLK サイクル、次の命令をフェッチするために4サイクル。

説明

この命令は、TSENSを使用して測定を実行し、結果を汎用レジスタに保存します。

1:        TSENS     R1, 1000     // 温度センサーを1000サイクル測定し、
                                 // 結果をR1に保存します

ADC - ADCで測定を行う

構文

ADC Rdst, Sar_sel, Mux
ADC Rdst, Sar_sel, Mux, 0 — deprecated form

オペランド

  • Rdst - デスティネーションレジスタR[0..3]、結果はこのレジスタに保存されます
  • Sar_sel - ADCの選択:0 = SARADC1、1 = SARADC2
  • Mux - 選択されたパッド、SARADC Pad[Mux+ 1]は有効

サイクル

実行するのに23 + max(1, SAR_AMP_WAIT1) + max(1, SAR_AMP_WAIT2) + max(1, SAR_AMP_WAIT3) + SARx_SAMPLE_CYCLE + SARx_SAMPLE_BIT サイクル、次の命令をフェッチするための4サイクル。

説明

この命令はADCから測定を行います。

1:        ADC      R1, 0, 1      // ADC1パッド2を使用して値を測定し、結果をR1に保存する

I2C_RD - I2Cスレーブからシングルバイトを読み取る

構文

I2C_RD Sub_addr, High, Low, Slave_sel

オペランド

  • Sub_addr - 読み取るI2Cスレーブ内のアドレス
  • HighLow - 読み取るビットの範囲を宣言します。[HighLow]範囲外のビットはマスクされます
  • Slave_sel - 使用するI2Cスレーブアドレスのインデックス

サイクル

実行時間は主にI2C通信時間に依存します。次の命令をフェッチするための4サイクル。

説明

I2C_RD 命令は、Slave_selを使用してI2Cスレーブから1バイトを読み取ります。 スレーブアドレス(7ビット形式)は、 SENS_I2C_SLAVE_ADDRx レジスタフィールドに事前に設定する必要があります。 読み出し結果の8ビットがR0レジスタに格納されます。 x == Slave_sel

1:        I2C_RD      0x10, 7, 0, 0      // SENS_I2C_SLAVE_ADDR0にアドレスが設定されたスレーブのサブアドレス0x10からバイトを読み取ります

I2C_WR - I2Cスレーブにシングルバイトを書き込む

構文

I2C_WR Sub_addr, Value, High, Low, Slave_sel

オペランド

  • Sub_addr - 書き込むI2Cスレーブ内のアドレス
  • Value - 書き込まれる8ビット値
  • HighLow - 書き込むビット範囲を宣言します。[HighLow]範囲外のビットはマスクされます
  • Slave_sel - 使用するI2Cスレーブアドレスのインデックス

サイクル

実行時間は主にI2C通信時間に依存します。次の命令をフェッチするための4サイクル。

説明

I2C_WR 命令は、Slave_selを使用してI2Cスレーブに1バイトを書き込みます。 スレーブアドレス(7ビット形式)は、SENS_I2C_SLAVE_ADDRx レジスタフィールドに事前に設定する必要があります。 x == Slave_sel

1:        I2C_WR      0x20, 0x33, 7, 0, 1      // SENS_I2C_SLAVE_ADDR1にアドレスが設定されたスレーブのサブアドレス0x20にバイト0x33を書き込みます

REG_RD - 周辺レジスタからの読み取り

構文

REG_RD Addr, High, Low

オペランド

  • Addr - 32ビットワードのレジスタアドレス
  • High - R0の高部分
  • Low - R0の低部分

サイクル

実行するのに4サイクル、次の命令をフェッチするのに4サイクル。

説明

この命令は、ペリフェラルレジスタから汎用レジスタに最大16ビットを読み込みます。 R0 = REG[Addr][High:Low]

この命令は、RTC_CNTL、RTC_IO、SENS、およびRTC_I2Cペリフェラルのレジスタにアクセスできます。 ULPから見たレジスタのアドレスは、次のようにDPORTバス上の同じレジスタのアドレスから計算できます。

addr_ulp = (addr_dport - DR_REG_RTCCNTL_BASE) / 4

1:        REG_RD      0x120, 2, 0     // 4ビット読み込み: R0 = {12'b0, REG[0x120][7:4]}

REG_WR - 周辺レジスタへの書き込み

構文

REG_WR Addr, High, Low, Data

オペランド

  • Addr - 32ビットワードのレジスタアドレス。
  • High - R0の高部分
  • Low - R0の低部分
  • Data - 書き込む値、8ビット

サイクル

実行するのに8サイクル、次の命令をフェッチするのに4サイクル。

説明

この命令は、汎用レジスタから周辺レジスタに最大8ビットを書き込みます。REG[Addr][High:Low] = data

この命令は、RTC_CNTL、RTC_IO、SENS、およびRTC_I2Cペリフェラルのレジスタにアクセスできます。 ULPから見たレジスタのアドレスは、次のようにDPORTバス上の同じレジスタのアドレスから計算できます。

addr_ulp = (addr_dport - DR_REG_RTCCNTL_BASE) / 4

1:        REG_WR      0x120, 7, 0, 0x10   // 8ビットセット: REG[0x120][7:0] = 0x10

周辺レジスタアクセス用の便利なマクロ

ULPソースファイルは、アセンブラの前にCプリプロセッサを介して渡されます。 これにより、特定のマクロを使用して周辺レジスタへのアクセスを容易にすることができます。

一部の既存のマクロは、soc/soc_ulp.h ヘッダーファイルで宣言されています。 これらのマクロを使用すると、周辺レジスタのフィールドに名前でアクセスできます。 これらのマクロを使用することができペリフェラルレジスタ名はものがで規定されているsoc/rtc_cntl_reg.hsoc/rtc_io_reg.hsoc/sens_reg.h、と soc/rtc_i2c_reg.h

READ_RTC_REG(rtc_reg, low_bit, bit_width)

rtc_reg [low_bit + bit_width-1:low_bit]からR0に最大16ビットを読み込みます。例えば:

#include "soc/soc_ulp.h"
#include "soc/rtc_cntl_reg.h"

/* RTC_CNTL_TIME0_REGの下位16ビットをR0に読み込む */
READ_RTC_REG(RTC_CNTL_TIME0_REG, 0, 16)

READ_RTC_FIELD(rtc_reg, field)

rtc_regのfieldから最大16ビットのR0に読み取ります。例えば:

#include "soc/soc_ulp.h"
#include "soc/sens_reg.h"

/* SENS_SAR_SLAVE_ADDR3_REGの8ビットSENS_TSENS_OUTフィールドをR0に読み込む */
READ_RTC_FIELD(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT)

WRITE_RTC_REG(rtc_reg, low_bit, bit_width, value)

valueをrtc_reg [low_bit + bit_width-1:low_bit]、bit_width <= 8に書き込みます。例:

#include "soc/soc_ulp.h"
#include "soc/rtc_io_reg.h"

/* RTC_GPIO_OUT_W1TS_REGのRTC_GPIO_OUT_DATA_W1TSフィールドのBIT(2)を設定します */
WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S + 2, 1, 1)

WRITE_RTC_FIELD(rtc_reg, field, value)

rtc_regのfieldに最大8ビットのvalueを書き込みます。例えば:

#include "soc/soc_ulp.h"
#include "soc/rtc_cntl_reg.h"

/* RTC_CNTL_STATE0_REGのRTC_CNTL_ULP_CP_SLP_TIMER_ENフィールドを0に設定します */
WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)

リファレンス