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
。
同様の考慮事項はLD
とST
命令に適用されます。次のコードを検討してください。
.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の値 >= しきい値の場合ジャンプ
サイクル¶
条件 LE、LT、GE :実行する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スレーブ内のアドレス
- High 、Low - 読み取るビットの範囲を宣言します。[High、Low]範囲外のビットはマスクされます
- 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ビット値
- High 、Low - 書き込むビット範囲を宣言します。[High、Low]範囲外のビットはマスクされます
- 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.h
、soc/rtc_io_reg.h
、soc/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)