mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
62 lines
3.1 KiB
ReStructuredText
62 lines
3.1 KiB
ReStructuredText
使用 C 语言宏编程 ULP FSM 协处理器(遗留)
|
|
===========================================
|
|
|
|
:link_to_translation:`en:[English]`
|
|
|
|
想要为 ULP FSM 协处理器生成程序,除了用 {IDF_TARGET_NAME} ULP 协处理器目前的 binutils 端口外,还可以将类似汇编的宏嵌入到 {IDF_TARGET_NAME} 应用程序中。以下是一个示例::
|
|
|
|
const ulp_insn_t program[] = {
|
|
I_MOVI(R3, 16), // R3 <- 16
|
|
I_LD(R0, R3, 0), // R0 <- RTC_SLOW_MEM[R3 + 0]
|
|
I_LD(R1, R3, 1), // R1 <- RTC_SLOW_MEM[R3 + 1]
|
|
I_ADDR(R2, R0, R1), // R2 <- R0 + R1
|
|
I_ST(R2, R3, 2), // R2 -> RTC_SLOW_MEM[R2 + 2]
|
|
I_HALT()
|
|
};
|
|
size_t load_addr = 0;
|
|
size_t size = sizeof(program)/sizeof(ulp_insn_t);
|
|
ulp_process_macros_and_load(load_addr, program, &size);
|
|
ulp_run(load_addr);
|
|
|
|
``program`` 数组是一个 ``ulp_insn_t`` 数组,即 ULP 协处理器指令。每个 ``I_XXX`` 预处理宏都会转换为单个 32 位指令。这些预处理宏的参数可以是寄存器号 (``R0 — R3``) 和字面常量。有关指令及其参数的详细信息,请参阅本指南末尾的 API 参考部分。
|
|
|
|
.. note::
|
|
|
|
由于一些宏指令会展开为内联函数调用,将这样的数组定义为全局数组会导致编译器报错:"initializer element is not constant"。要修复此错误,请定义指令数组为局部数组。
|
|
|
|
.. note::
|
|
|
|
加载指令 (LD)、存储指令 (ST) 和移动指令 (MOV) 均使用 **32 位字地址**。地址 0 对应 ``RTC_SLOW_MEM`` 的第一个字。
|
|
这与汇编代码中相同指令的地址参数处理方式不同。详情请参阅 :ref:`ulp-fsm-addressing`。
|
|
|
|
要生成分支指令,使用特殊的 ``M_`` 预处理宏定义。 ``M_LABEL`` 宏定义可用于定义分支目标。标签标识符是一个 16 位整数。 ``M_Bxxx`` 宏定义可用于生成目标设置为特定标签的分支指令。
|
|
|
|
实现注意事项:这些 ``M_`` 预处理宏将被转换为两个 ulp_insn_t 值:一个是包含标签号的令牌值,另一个是实际指令。 ``ulp_process_macros_and_load`` 函数将标签号解析为地址,修改分支指令以使用正确的地址,并移除包含标签号的额外 ``ulp_insn_t`` 令牌。
|
|
|
|
以下是使用标签和分支的示例::
|
|
|
|
const ulp_insn_t program[] = {
|
|
I_MOVI(R0, 34), // R0 <- 34
|
|
M_LABEL(1), // label_1
|
|
I_MOVI(R1, 32), // R1 <- 32
|
|
I_LD(R1, R1, 0), // R1 <- RTC_SLOW_MEM[R1]
|
|
I_MOVI(R2, 33), // R2 <- 33
|
|
I_LD(R2, R2, 0), // R2 <- RTC_SLOW_MEM[R2]
|
|
I_SUBR(R3, R1, R2), // R3 <- R1 - R2
|
|
I_ST(R3, R0, 0), // R3 -> RTC_SLOW_MEM[R0 + 0]
|
|
I_ADDI(R0, R0, 1), // R0++
|
|
M_BL(1, 64), // if (R0 < 64) goto label_1
|
|
I_HALT(),
|
|
};
|
|
RTC_SLOW_MEM[32] = 42;
|
|
RTC_SLOW_MEM[33] = 18;
|
|
size_t load_addr = 0;
|
|
size_t size = sizeof(program)/sizeof(ulp_insn_t);
|
|
ulp_process_macros_and_load(load_addr, program, &size);
|
|
ulp_run(load_addr);
|
|
|
|
API 参考
|
|
--------
|
|
|
|
.. include-build-file:: inc/ulp.inc
|