From 7b02eae9e6b886fc5abb832a35086a88df79c90e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 16 Dec 2016 20:01:15 +0800 Subject: [PATCH] ulp: add RD_REG, WR_REG, END instruction --- components/ulp/README.rst | 3 ++ components/ulp/include/esp32/ulp.h | 65 ++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/components/ulp/README.rst b/components/ulp/README.rst index 14c67d710..875a01ef8 100644 --- a/components/ulp/README.rst +++ b/components/ulp/README.rst @@ -83,8 +83,11 @@ ULP coprocessor instruction defines .. doxygendefine:: I_DELAY .. doxygendefine:: I_HALT +.. doxygendefine:: I_END .. doxygendefine:: I_ST .. doxygendefine:: I_LD +.. doxygendefine:: I_WR_REG +.. doxygendefine:: I_RD_REG .. doxygendefine:: I_BL .. doxygendefine:: I_BGE .. doxygendefine:: I_BXR diff --git a/components/ulp/include/esp32/ulp.h b/components/ulp/include/esp32/ulp.h index c23d9cf9d..18ad41ca6 100644 --- a/components/ulp/include/esp32/ulp.h +++ b/components/ulp/include/esp32/ulp.h @@ -47,6 +47,10 @@ extern "C" { #define OPCODE_RD_REG 2 /*!< Instruction: read peripheral register (RTC_CNTL/RTC_IO/SARADC) (not implemented yet) */ +#define RD_REG_PERIPH_RTC_CNTL 0 /*!< Identifier of RTC_CNTL peripheral for RD_REG and WR_REG instructions */ +#define RD_REG_PERIPH_RTC_IO 1 /*!< Identifier of RTC_IO peripheral for RD_REG and WR_REG instructions */ +#define RD_REG_PERIPH_SARADC 2 /*!< Identifier of SARADC peripheral for RD_REG and WR_REG instructions */ + #define OPCODE_I2C 3 /*!< Instruction: read/write I2C (not implemented yet) */ #define OPCODE_DELAY 4 /*!< Instruction: delay (nop) for a given number of cycles */ @@ -191,8 +195,8 @@ typedef union { uint32_t addr : 8; /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */ uint32_t periph_sel : 2; /*!< Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) */ uint32_t data : 8; /*!< 8 bits of data to write */ - uint32_t high : 5; /*!< High bit */ uint32_t low : 5; /*!< Low bit */ + uint32_t high : 5; /*!< High bit */ uint32_t opcode : 4; /*!< Opcode (OPCODE_WR_REG) */ } wr_reg; /*!< Format of WR_REG instruction */ @@ -200,10 +204,10 @@ typedef union { uint32_t addr : 8; /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */ uint32_t periph_sel : 2; /*!< Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) */ uint32_t unused : 8; /*!< Unused */ - uint32_t high : 5; /*!< High bit */ uint32_t low : 5; /*!< Low bit */ + uint32_t high : 5; /*!< High bit */ uint32_t opcode : 4; /*!< Opcode (OPCODE_WR_REG) */ - } rd_reg; /*!< Format of WR_REG instruction */ + } rd_reg; /*!< Format of RD_REG instruction */ struct { uint32_t dreg : 2; /*!< Register where to store ADC result */ @@ -256,6 +260,8 @@ typedef union { } ulp_insn_t; +_Static_assert(sizeof(ulp_insn_t) == 4, "ULP coprocessor instruction size should be 4 bytes"); + /** * Delay (nop) for a given number of cycles */ @@ -272,6 +278,59 @@ typedef union { .opcode = OPCODE_HALT } } +static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { + uint32_t ret = 3; + if (reg < DR_REG_RTCCNTL_BASE) { + assert(0 && "invalid register base"); + } else if (reg < DR_REG_RTCIO_BASE) { + ret = 0; + } else if (reg < DR_REG_SENS_BASE) { + ret = 1; + } else if (reg < DR_REG_RTCMEM0_BASE){ + ret = 2; + } else { + assert(0 && "invalid register base"); + } + return ret; +} + +/** + * Write literal value to a peripheral register + * + * reg[high_bit : low_bit] = val + */ +#define I_WR_REG(reg, low_bit, high_bit, val) {.wr_reg = {\ + .addr = reg & 0xff, \ + .periph_sel = SOC_REG_TO_ULP_PERIPH_SEL(reg), \ + .data = val, \ + .low = low_bit, \ + .high = high_bit, \ + .opcode = OPCODE_WR_REG } } + +/** + * Read from peripheral register into R0 + * + * R0 = reg[high_bit : low_bit] + */ +#define I_RD_REG(reg, low_bit, high_bit, val) {.wr_reg = {\ + .addr = reg & 0xff, \ + .periph_sel = SOC_REG_TO_ULP_PERIPH_SEL(reg), \ + .unused = 0, \ + .low = low_bit, \ + .high = high_bit, \ + .opcode = OPCODE_RD_REG } } + +/** + * End program. + * + * If wake == 1, wake up main CPU. + */ +#define I_END(wake) { .end = { \ + .wakeup = wake, \ + .unused = 0, \ + .sub_opcode = SUB_OPCODE_END, \ + .opcode = OPCODE_END } } + /** * Store value from register reg_val into RTC memory. *