diff --git a/components/ulp/Makefile.projbuild b/components/ulp/Makefile.projbuild index 026d64452..5bbf45453 100644 --- a/components/ulp/Makefile.projbuild +++ b/components/ulp/Makefile.projbuild @@ -1,8 +1,13 @@ +ifdef CONFIG_IDF_TARGET_ESP32S2BETA +ULP_BINUTILS_PREFIX ?= esp32s2ulp-elf- +else ULP_BINUTILS_PREFIX ?= esp32ulp-elf- +endif +# export ULP_AS := $(ULP_BINUTILS_PREFIX)as export ULP_LD := $(ULP_BINUTILS_PREFIX)ld export ULP_OBJCOPY := $(ULP_BINUTILS_PREFIX)objcopy export ULP_OBJDUMP := $(ULP_BINUTILS_PREFIX)objdump -export ULP_NM := $(ULP_BINUTILS_PREFIX)nm export ULP_LD_TEMPLATE := $(IDF_PATH)/components/ulp/ld/esp32.ulp.ld +export ULP_NM := $(ULP_BINUTILS_PREFIX)nm export ULP_MAP_GEN := $(IDF_PATH)/components/ulp/esp32ulp_mapgen.py diff --git a/components/ulp/cmake/toolchain-ulp.cmake b/components/ulp/cmake/toolchain-esp32-ulp.cmake similarity index 100% rename from components/ulp/cmake/toolchain-ulp.cmake rename to components/ulp/cmake/toolchain-esp32-ulp.cmake diff --git a/components/ulp/cmake/toolchain-esp32s2beta-ulp.cmake b/components/ulp/cmake/toolchain-esp32s2beta-ulp.cmake new file mode 100644 index 000000000..1c51fb0bb --- /dev/null +++ b/components/ulp/cmake/toolchain-esp32s2beta-ulp.cmake @@ -0,0 +1,15 @@ +# CMake toolchain file for ULP + +set(CMAKE_SYSTEM_NAME Generic) + +# Compiler is only used for preprocessing +set(CMAKE_C_COMPILER "xtensa-esp32s2-elf-gcc") + +set(CMAKE_ASM_COMPILER "esp32s2ulp-elf-as") +set(CMAKE_LINKER "esp32s2ulp-elf-ld") + +set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "${CMAKE_ASM${ASM_DIALECT}_COMPILER} \ + -o -c ") +set(CMAKE_EXE_LINKER_FLAGS "-A elf32-esp32s2ulp -nostdlib" CACHE STRING "ULP Linker Base Flags") +set(CMAKE_ASM_LINK_EXECUTABLE "${CMAKE_LINKER} \ + -o ") \ No newline at end of file diff --git a/components/ulp/include/esp32s2beta/ulp.h b/components/ulp/include/esp32s2beta/ulp.h index 58331cf52..c9d32bd1b 100644 --- a/components/ulp/include/esp32s2beta/ulp.h +++ b/components/ulp/include/esp32s2beta/ulp.h @@ -16,6 +16,7 @@ #include #include #include +#include "sdkconfig.h" #include "esp_err.h" #include "soc/soc.h" #include "ulp_common.h" @@ -76,15 +77,29 @@ extern "C" { #define ALU_SEL_MOV 4 /*!< Copy value (immediate to destination register or source register to destination register */ #define ALU_SEL_LSH 5 /*!< Shift left by given number of bits */ #define ALU_SEL_RSH 6 /*!< Shift right by given number of bits */ +#ifdef CONFIG_IDF_TARGET_ESP32S2BETA +#define ALU_SEL_INC 0 /*!< Stage_cnt = Stage_cnt + Imm */ +#define ALU_SEL_DEC 1 /*!< Stage_cnt = Stage_cnt - Imm */ +#define ALU_SEL_RST 2 /*!< Stage_cnt = 0 */ +#endif #define OPCODE_BRANCH 8 /*!< Branch instructions */ -#define SUB_OPCODE_BX 0 /*!< Branch to absolute PC (immediate or in register) */ #define BX_JUMP_TYPE_DIRECT 0 /*!< Unconditional jump */ #define BX_JUMP_TYPE_ZERO 1 /*!< Branch if last ALU result is zero */ #define BX_JUMP_TYPE_OVF 2 /*!< Branch if last ALU operation caused and overflow */ -#define SUB_OPCODE_B 1 /*!< Branch to a relative offset */ +#ifdef CONFIG_IDF_TARGET_ESP32 #define B_CMP_L 0 /*!< Branch if R0 is less than an immediate */ #define B_CMP_GE 1 /*!< Branch if R0 is greater than or equal to an immediate */ +#define SUB_OPCODE_BX 0 /*!< Branch to absolute PC (immediate or in register) */ +#define SUB_OPCODE_B 1 /*!< Branch to a relative offset */ +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA +#define B_CMP_L 1 /*!< Branch if R0 is less than an immediate */ +#define B_CMP_GE 2 /*!< Branch if R0 is greater than an immediate */ +#define B_CMP_EQ 4 /*!< Branch if R0 is equal to an immediate */ +#define SUB_OPCODE_BX 1 /*!< Branch to absolute PC (immediate or in register) */ +#define SUB_OPCODE_B 0 /*!< Branch to a relative offset base on R0 */ +#define SUB_OPCODE_B_STAGE 2 /*!< Branch to a relative offset base on stage reg */ +#endif #define OPCODE_END 9 /*!< Stop executing the program */ #define SUB_OPCODE_END 0 /*!< Stop executing the program and optionally wake up the chip */ @@ -99,6 +114,10 @@ extern "C" { #define OPCODE_MACRO 15 /*!< Not a real opcode. Used to identify labels and branches in the program */ #define SUB_OPCODE_MACRO_LABEL 0 /*!< Label macro */ #define SUB_OPCODE_MACRO_BRANCH 1 /*!< Branch macro */ + +#ifdef CONFIG_IDF_TARGET_ESP32S2BETA +#define OPCODE_SLEEP_WAIT 4 +#endif /**@}*/ /** @@ -123,6 +142,7 @@ union ulp_insn { uint32_t opcode : 4; /*!< Opcode (OPCODE_DELAY) */ } delay; /*!< Format of DELAY instruction */ +#ifdef CONFIG_IDF_TARGET_ESP32 struct { uint32_t dreg : 2; /*!< Register which contains data to store */ uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */ @@ -132,7 +152,24 @@ union ulp_insn { uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ST) */ uint32_t opcode : 4; /*!< Opcode (OPCODE_ST) */ } st; /*!< Format of ST instruction */ +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA + struct { + uint32_t dreg : 2; /*!< Data address register number */ + uint32_t sreg : 2; /*!< Base address register number */ + uint32_t data_label : 2; /*!< Data label */ + uint32_t upper : 1; /*!< High and low half-word Select 1: Write high half-word; 0 : write low half-word; */ + uint32_t write_way : 2; /*!< Write number Mode 0 : full word write; 1: with data_label; 3: without label; */ + uint32_t unused1 : 1; /*!< Unused */ + uint32_t offset : 11; /*!< When you select automatic storage, you need to configure the base address offset*/ + uint32_t unused2 : 4; /*!< Unused */ + uint32_t wr_auto : 1; /*!< Automatic storage selection enabled (burst mode)*/ + uint32_t offset_set : 1; /*!< Configure OFFSET enable */ + uint32_t manul_en : 1; /*!< Manual storage selection enabled */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_ST) */ + } st; /*!< Format of ST instruction */ +#endif +#ifdef CONFIG_IDF_TARGET_ESP32 struct { uint32_t dreg : 2; /*!< Register where the data should be loaded to */ uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */ @@ -141,12 +178,24 @@ union ulp_insn { uint32_t unused2 : 7; /*!< Unused */ uint32_t opcode : 4; /*!< Opcode (OPCODE_LD) */ } ld; /*!< Format of LD instruction */ +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA + struct { + uint32_t dreg : 2; /*!< Register where the data should be loaded to */ + uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */ + uint32_t unused1 : 6; /*!< Unused */ + uint32_t offset : 11; /*!< Offset to add to sreg */ + uint32_t unused2 : 6; /*!< Unused */ + uint32_t rd_upper: 1; + uint32_t opcode : 4; /*!< Opcode (OPCODE_LD) */ + } ld; /*!< Format of LD instruction */ +#endif struct { uint32_t unused : 28; /*!< Unused */ uint32_t opcode : 4; /*!< Opcode (OPCODE_HALT) */ } halt; /*!< Format of HALT instruction */ +#ifdef CONFIG_IDF_TARGET_ESP32 struct { uint32_t dreg : 2; /*!< Register which contains target PC, expressed in words (used if .reg == 1) */ uint32_t addr : 11; /*!< Target PC, expressed in words (used if .reg == 0) */ @@ -165,7 +214,29 @@ union ulp_insn { uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_B) */ uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */ } b; /*!< Format of BRANCH instruction (relative address) */ +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA + struct { + uint32_t dreg : 2; /*!< Register which contains target PC, expressed in words (used if .reg == 1) */ + uint32_t addr : 11; /*!< Target PC, expressed in words (used if .reg == 0) */ + uint32_t unused : 8; /*!< Unused */ + uint32_t reg : 1; /*!< Target PC in register (1) or immediate (0) */ + uint32_t type : 3; /*!< Jump condition (BX_JUMP_TYPE_xxx) */ + uint32_t unused1 : 1; /*!< Unused */ + uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_BX) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */ + } bx; /*!< Format of BRANCH instruction (absolute address) */ + struct { + uint32_t imm : 15; /*!< Immediate value to compare against */ + uint32_t cmp : 3; /*!< Comparison to perform: B_CMP_L or B_CMP_GE */ + uint32_t offset : 7; /*!< Absolute value of target PC offset w.r.t. current PC, expressed in words */ + uint32_t sign : 1; /*!< Sign of target PC offset: 0: positive, 1: negative */ + uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_B) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */ + } b; +#endif + +#ifdef CONFIG_IDF_TARGET_ESP32 struct { uint32_t dreg : 2; /*!< Destination register */ uint32_t sreg : 2; /*!< Register with operand A */ @@ -175,7 +246,20 @@ union ulp_insn { uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ALU_REG) */ uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */ } alu_reg; /*!< Format of ALU instruction (both sources are registers) */ +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA + struct { + uint32_t dreg : 2; /*!< Destination register */ + uint32_t sreg : 2; /*!< Register with operand A */ + uint32_t treg : 2; /*!< Register with operand B */ + uint32_t unused : 15; /*!< Unused */ + uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */ + uint32_t unused1 : 1; /*!< Unused */ + uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_ALU_REG) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */ + } alu_reg; /*!< Format of ALU instruction (both sources are registers) */ +#endif +#ifdef CONFIG_IDF_TARGET_ESP32 struct { uint32_t dreg : 2; /*!< Destination register */ uint32_t sreg : 2; /*!< Register with operand A */ @@ -185,6 +269,27 @@ union ulp_insn { uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */ uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */ } alu_imm; /*!< Format of ALU instruction (one source is an immediate) */ +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA + struct { + uint32_t dreg : 2; /*!< Destination register */ + uint32_t sreg : 2; /*!< Register with operand A */ + uint32_t imm : 16; /*!< Immediate value of operand B */ + uint32_t unused : 1; /*!< Unused */ + uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */ + uint32_t unused1 : 1; /*!< Unused */ + uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */ + } alu_imm; /*!< Format of ALU instruction (one source is an immediate) */ + struct { + uint32_t unused : 4; /*!< Unused */ + uint32_t imm : 16; /*!< Immediate value of operand B */ + uint32_t unused1 : 1; /*!< Unused */ + uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */ + uint32_t unused2 : 1; /*!< Unused */ + uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */ + } alu_cnt; /*!< Format of ALU instruction (one source is an immediate) */ +#endif struct { uint32_t addr : 8; /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */ @@ -203,7 +308,7 @@ union ulp_insn { uint32_t high : 5; /*!< High bit */ uint32_t opcode : 4; /*!< Opcode (OPCODE_WR_REG) */ } rd_reg; /*!< Format of RD_REG instruction */ - +#ifdef CONFIG_IDF_TARGET_ESP32 struct { uint32_t dreg : 2; /*!< Register where to store ADC result */ uint32_t mux : 4; /*!< Select SARADC pad (mux + 1) */ @@ -213,7 +318,17 @@ union ulp_insn { uint32_t unused2 : 4; /*!< Unused */ uint32_t opcode: 4; /*!< Opcode (OPCODE_ADC) */ } adc; /*!< Format of ADC instruction */ - +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA + struct { + uint32_t dreg : 2; /*!< Register where to store ADC result */ + uint32_t mux : 4; /*!< Select SARADC pad (mux + 1) */ + uint32_t sar_sel : 1; /*!< Select SARADC0 (0) or SARADC1 (1) */ + uint32_t hall_phase : 1; /*!< Unused */ + uint32_t xpd_hall : 1; /*!< Unused */ + uint32_t unused1 : 19; /*!< Unused */ + uint32_t opcode: 4; /*!< Opcode (OPCODE_ADC) */ + } adc; +#endif struct { uint32_t dreg : 2; /*!< Register where to store temperature measurement result */ uint32_t wait_delay: 14; /*!< Cycles to wait after measurement is done */ @@ -231,7 +346,7 @@ union ulp_insn { uint32_t rw : 1; /*!< Write (1) or read (0) */ uint32_t opcode : 4; /*!< Opcode (OPCODE_I2C) */ } i2c; /*!< Format of I2C instruction */ - +#ifdef CONFIG_IDF_TARGET_ESP32 struct { uint32_t wakeup : 1; /*!< Set to 1 to wake up chip */ uint32_t unused : 24; /*!< Unused */ @@ -245,7 +360,20 @@ union ulp_insn { uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_SLEEP) */ uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */ } sleep; /*!< Format of END instruction with sleep */ +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA + struct { + uint32_t wakeup : 1; /*!< Set to 1 to wake up chip */ + uint32_t unused : 25; /*!< Unused */ + uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_WAKEUP) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */ + } end; + struct { + uint32_t cycle_sel : 16; /*!< Select which one of SARADC_ULP_CP_SLEEP_CYCx_REG to get the sleep duration from */ + uint32_t unused : 12; /*!< Unused */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */ + } sleep; +#endif struct { uint32_t label : 16; /*!< Label number */ uint32_t unused : 8; /*!< Unused */ @@ -373,8 +501,13 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { * ULP program will continue running after this instruction. To stop * the currently running program, use I_HALT(). */ +#ifdef CONFIG_IDF_TARGET_ESP32 #define I_END() \ I_WR_REG_BIT(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN_S, 0) +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA +#define I_END() \ + I_WR_REG_BIT(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN_S, 0) +#endif /** * Select the time interval used to run ULP program. * @@ -390,12 +523,18 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { * By default, SENS_SLEEP_CYCLES_S0 register is used by the ULP * program timer. */ +#ifdef CONFIG_IDF_TARGET_ESP32 #define I_SLEEP_CYCLE_SEL(timer_idx) { .sleep = { \ .cycle_sel = timer_idx, \ .unused = 0, \ .sub_opcode = SUB_OPCODE_SLEEP, \ .opcode = OPCODE_END } } - +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA +#define I_SLEEP_CYCLE_SEL(timer_idx) { .sleep = { \ + .cycle_sel = timer_idx, \ + .unused = 0, \ + .opcode = OPCODE_SLEEP_WAIT } } +#endif /** * Perform temperature sensor measurement and store it into reg_dest. * @@ -414,6 +553,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { * adc_idx selects ADC (0 or 1). * pad_idx selects ADC pad (0 - 7). */ +#ifdef CONFIG_IDF_TARGET_ESP32 #define I_ADC(reg_dest, adc_idx, pad_idx) { .adc = {\ .dreg = reg_dest, \ .mux = pad_idx + 1, \ @@ -422,6 +562,16 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .cycles = 0, \ .unused2 = 0, \ .opcode = OPCODE_ADC } } +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA +#define I_ADC(reg_dest, adc_idx, pad_idx) { .adc = {\ + .dreg = reg_dest, \ + .mux = pad_idx + 1, \ + .sar_sel = adc_idx, \ + .hall_phase = 0, \ + .xpd_hall = 0, \ + .unused1 = 0, \ + .opcode = OPCODE_ADC } } +#endif /** * Store value from register reg_val into RTC memory. @@ -435,6 +585,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { * * RTC_SLOW_MEM[addr + offset_] = { 5'b0, insn_PC[10:0], val[15:0] } */ +#ifdef CONFIG_IDF_TARGET_ESP32 #define I_ST(reg_val, reg_addr, offset_) { .st = { \ .dreg = reg_val, \ .sreg = reg_addr, \ @@ -443,7 +594,138 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .unused2 = 0, \ .sub_opcode = SUB_OPCODE_ST, \ .opcode = OPCODE_ST } } +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA +/** + * burst Mode: write to consecutive address spaces. + * STW, STC instructions for the Class burst storage instructions for continuous address space write operation; + * Need to be used with the SET_OFFSET instruction, you first need to set the start address offset by SET_OFFSET, SREG is the base address, + * Where STW instruction WORD instruction, each execution time, address offset+1;STC for the half-word operation + * (First write high 16bit current address, the Second Write low 16bit current address), each performed twice, the address offset+1. + * Note: when using STC, you must write a word, that is, a burst operation instruction must be an even number. + */ +#define I_STO(offset_) { .st = { \ + .dreg = 0, \ + .sreg = 0, \ + .data_label = 0, \ + .upper = 0, \ + .write_way = 0, \ + .unused1 = 0, \ + .offset = offset_, \ + .unused2 = 0, \ + .wr_auto = 0, \ + .offset_set = 0, \ + .manul_en = 1, \ + .opcode = OPCODE_ST } } +#define I_STW(reg_val, reg_addr) { .st = { \ + .dreg = reg_val, \ + .sreg = reg_addr, \ + .data_label = 0, \ + .upper = 0, \ + .write_way = 0, \ + .unused1 = 0, \ + .offset = 0, \ + .unused2 = 0, \ + .wr_auto = 1, \ + .offset_set = 0, \ + .manul_en = 0, \ + .opcode = OPCODE_ST } } + +#define I_STC(reg_val, reg_addr) { .st = { \ + .dreg = reg_val, \ + .sreg = reg_addr, \ + .data_label = 0, \ + .upper = 0, \ + .write_way = 3, \ + .unused1 = 0, \ + .offset = 0, \ + .unused2 = 0, \ + .wr_auto = 1, \ + .offset_set = 0, \ + .manul_en = 0, \ + .opcode = OPCODE_ST } } +/** + * Single mode of operation: write to a single address space. + * + * Loads 16 LSBs from RTC memory word given by the sum of value in reg_addr and + * value of offset_. + */ +/* Mem [ Rsrc1 + offset ]{31:0} = {PC[10:0], 5�d0,Rdst[15:0]} */ +#define I_ST(reg_val, reg_addr, offset_) { .st = { \ + .dreg = reg_val, \ + .sreg = reg_addr, \ + .data_label = 0, \ + .upper = 0, \ + .write_way = 0, \ + .unused1 = 0, \ + .offset = offset_, \ + .unused2 = 0, \ + .wr_auto = 0, \ + .offset_set = 0, \ + .manul_en = 1, \ + .opcode = OPCODE_ST } } + +/* Mem [ Rsrc1 + offset ]{31:16} = {Rdst[15:0]} */ +#define I_STM32U(reg_val, reg_addr, offset_) { .st = { \ + .dreg = reg_val, \ + .sreg = reg_addr, \ + .data_label = 0, \ + .upper = 1, \ + .write_way = 3, \ + .unused1 = 0, \ + .offset = offset_, \ + .unused1 = 0, \ + .wr_auto = 0, \ + .offset_set = 0, \ + .manul_en = 1, \ + .opcode = OPCODE_ST } } + +/* Mem [ Rsrc1 + offset ]{15:0} = {Rdst[15:0]} */ +#define I_STM32L(reg_val, reg_addr, offset_) { .st = { \ + .dreg = reg_val, \ + .sreg = reg_addr, \ + .data_label = 0, \ + .upper = 0, \ + .write_way = 3, \ + .unused1 = 0, \ + .offset = offset_, \ + .unused2 = 0, \ + .wr_auto = 0, \ + .offset_set = 0, \ + .manul_en = 1, \ + .opcode = OPCODE_ST } } + +/* Mem [ Rsrc1 + offset ]{31:0} = {data_label[1:0],Rdst[13:0]} */ +#define I_STMLBU(reg_val, reg_addr, label, offset_) { .st = { \ + .dreg = reg_val, \ + .sreg = reg_addr, \ + .data_label = label, \ + .upper = 1, \ + .write_way = 1, \ + .unused1 = 0, \ + .offset = offset_, \ + .unused1 = 0, \ + .wr_auto = 0, \ + .offset_set = 0, \ + .manul_en = 1, \ + .opcode = OPCODE_ST } } + +/* Mem [ Rsrc1 + offset ]{15:0} = {data_label[1:0],Rdst[13:0]} */ +#define I_STMLBL(reg_val, reg_addr, label, offset_) { .st = { \ + .dreg = reg_val, \ + .sreg = reg_addr, \ + .data_label = label, \ + .upper = 0, \ + .write_way = 1, \ + .unused1 = 0, \ + .offset = offset_, \ + .unused2 = 0, \ + .wr_auto = 0, \ + .offset_set = 0, \ + .manul_en = 1, \ + .opcode = OPCODE_ST } } + +#endif /** * Load value from RTC memory into reg_dest register. @@ -451,6 +733,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { * Loads 16 LSBs from RTC memory word given by the sum of value in reg_addr and * value of offset_. */ +#ifdef CONFIG_IDF_TARGET_ESP32 #define I_LD(reg_dest, reg_addr, offset_) { .ld = { \ .dreg = reg_dest, \ .sreg = reg_addr, \ @@ -458,7 +741,16 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .offset = offset_, \ .unused2 = 0, \ .opcode = OPCODE_LD } } - +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA +#define I_LD(reg_dest, reg_addr, offset_) { .ld = { \ + .dreg = reg_dest, \ + .sreg = reg_addr, \ + .unused1 = 0, \ + .offset = offset_, \ + .unused2 = 0, \ + .rd_upper = 0, \ + .opcode = OPCODE_LD } } +#endif /** * Branch relative if R0 less than immediate value. @@ -474,6 +766,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .sub_opcode = SUB_OPCODE_B, \ .opcode = OPCODE_BRANCH } } +#ifdef CONFIG_IDF_TARGET_ESP32 /** * Branch relative if R0 greater or equal than immediate value. * @@ -487,7 +780,75 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .sign = (pc_offset >= 0) ? 0 : 1, \ .sub_opcode = SUB_OPCODE_B, \ .opcode = OPCODE_BRANCH } } +#endif +#ifdef CONFIG_IDF_TARGET_ESP32S2BETA + +/** + * Branch relative if R0 greater than immediate value. + * + * pc_offset is expressed in words, and can be from -127 to 127 + * imm_value is a 16-bit value to compare R0 against + */ +#define I_BG(pc_offset, imm_value) { .b = { \ + .imm = imm_value, \ + .cmp = B_CMP_GE, \ + .offset = abs(pc_offset), \ + .sign = (pc_offset >= 0) ? 0 : 1, \ + .sub_opcode = SUB_OPCODE_B, \ + .opcode = OPCODE_BRANCH } } + +/** + * Branch relative if R0 equal to immediate value. + * + * pc_offset is expressed in words, and can be from -127 to 127 + * imm_value is a 16-bit value to compare R0 against + */ +#define I_BE(pc_offset, imm_value) { .b = { \ + .imm = imm_value, \ + .cmp = B_CMP_EQ, \ + .offset = abs(pc_offset), \ + .sign = (pc_offset >= 0) ? 0 : 1, \ + .sub_opcode = SUB_OPCODE_B, \ + .opcode = OPCODE_BRANCH } } + +/* + * Branch to a relative offset base on stage reg + * If stage reg less imm_value, PC will jump pc_offset. + */ +#define I_BRLS(pc_offset, imm_value) { .b = { \ + .imm = imm_value, \ + .cmp = B_CMP_L, \ + .offset = abs(pc_offset), \ + .sign = (pc_offset >= 0) ? 0 : 1, \ + .sub_opcode = SUB_OPCODE_B_STAGE, \ + .opcode = OPCODE_BRANCH } } + +/* + * Branch to a relative offset base on stage reg + * If stage reg greater imm_value, PC will jump pc_offset. + */ +#define I_BRGS(pc_offset, imm_value) { .b = { \ + .imm = imm_value, \ + .cmp = B_CMP_GE, \ + .offset = abs(pc_offset), \ + .sign = (pc_offset >= 0) ? 0 : 1, \ + .sub_opcode = SUB_OPCODE_B_STAGE, \ + .opcode = OPCODE_BRANCH } } + +/* + * Branch to a relative offset base on stage reg + * If stage reg equal to imm_value, PC will jump pc_offset. + */ +#define I_BRES(pc_offset, imm_value) { .b = { \ + .imm = imm_value, \ + .cmp = B_CMP_EQ, \ + .offset = abs(pc_offset), \ + .sign = (pc_offset >= 0) ? 0 : 1, \ + .sub_opcode = SUB_OPCODE_B_STAGE, \ + .opcode = OPCODE_BRANCH } } + +#endif /** * Unconditional branch to absolute PC, address in register. * @@ -500,6 +861,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .unused = 0, \ .reg = 1, \ .type = BX_JUMP_TYPE_DIRECT, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_BX, \ .opcode = OPCODE_BRANCH } } @@ -514,6 +876,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .unused = 0, \ .reg = 0, \ .type = BX_JUMP_TYPE_DIRECT, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_BX, \ .opcode = OPCODE_BRANCH } } @@ -529,6 +892,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .unused = 0, \ .reg = 1, \ .type = BX_JUMP_TYPE_ZERO, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_BX, \ .opcode = OPCODE_BRANCH } } @@ -543,6 +907,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .unused = 0, \ .reg = 0, \ .type = BX_JUMP_TYPE_ZERO, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_BX, \ .opcode = OPCODE_BRANCH } } @@ -558,6 +923,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .unused = 0, \ .reg = 1, \ .type = BX_JUMP_TYPE_OVF, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_BX, \ .opcode = OPCODE_BRANCH } } @@ -572,6 +938,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .unused = 0, \ .reg = 0, \ .type = BX_JUMP_TYPE_OVF, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_BX, \ .opcode = OPCODE_BRANCH } } @@ -585,6 +952,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .treg = reg_src2, \ .unused = 0, \ .sel = ALU_SEL_ADD, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_REG, \ .opcode = OPCODE_ALU } } @@ -597,6 +965,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .treg = reg_src2, \ .unused = 0, \ .sel = ALU_SEL_SUB, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_REG, \ .opcode = OPCODE_ALU } } @@ -609,6 +978,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .treg = reg_src2, \ .unused = 0, \ .sel = ALU_SEL_AND, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_REG, \ .opcode = OPCODE_ALU } } @@ -621,6 +991,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .treg = reg_src2, \ .unused = 0, \ .sel = ALU_SEL_OR, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_REG, \ .opcode = OPCODE_ALU } } @@ -633,6 +1004,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .treg = 0, \ .unused = 0, \ .sel = ALU_SEL_MOV, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_REG, \ .opcode = OPCODE_ALU } } @@ -645,6 +1017,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .treg = reg_shift, \ .unused = 0, \ .sel = ALU_SEL_LSH, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_REG, \ .opcode = OPCODE_ALU } } @@ -658,6 +1031,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .treg = reg_shift, \ .unused = 0, \ .sel = ALU_SEL_RSH, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_REG, \ .opcode = OPCODE_ALU } } @@ -670,6 +1044,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .imm = imm_, \ .unused = 0, \ .sel = ALU_SEL_ADD, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_IMM, \ .opcode = OPCODE_ALU } } @@ -683,6 +1058,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .imm = imm_, \ .unused = 0, \ .sel = ALU_SEL_SUB, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_IMM, \ .opcode = OPCODE_ALU } } @@ -695,6 +1071,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .imm = imm_, \ .unused = 0, \ .sel = ALU_SEL_AND, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_IMM, \ .opcode = OPCODE_ALU } } @@ -707,6 +1084,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .imm = imm_, \ .unused = 0, \ .sel = ALU_SEL_OR, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_IMM, \ .opcode = OPCODE_ALU } } @@ -719,6 +1097,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .imm = imm_, \ .unused = 0, \ .sel = ALU_SEL_MOV, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_IMM, \ .opcode = OPCODE_ALU } } @@ -731,6 +1110,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .imm = imm_, \ .unused = 0, \ .sel = ALU_SEL_LSH, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_IMM, \ .opcode = OPCODE_ALU } } @@ -744,9 +1124,49 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) { .imm = imm_, \ .unused = 0, \ .sel = ALU_SEL_RSH, \ + .unused1 = 0, \ .sub_opcode = SUB_OPCODE_ALU_IMM, \ .opcode = OPCODE_ALU } } + +#ifdef CONFIG_IDF_TARGET_ESP32S2BETA +/** + * Increments the stage counter for the subscript of the cycle count, Stage_cnt = Stage_cnt + Imm + */ +#define I_SINC(imm_) { .alu_cnt = { \ + .unused = 0, \ + .imm = imm_, \ + .unused1 = 0, \ + .sel = ALU_SEL_INC, \ + .unused2 = 0, \ + .sub_opcode = SUB_OPCODE_ALU_CNT, \ + .opcode = OPCODE_ALU } } + +/** + * Decrements the stage counter for the subscript of the cycle count, Stage_cnt = Stage_cnt - Imm + */ +#define I_SDEC(imm_) { .alu_cnt = { \ + .unused = 0, \ + .imm = imm_, \ + .unused1 = 0, \ + .sel = ALU_SEL_DEC, \ + .unused2 = 0, \ + .sub_opcode = SUB_OPCODE_ALU_CNT, \ + .opcode = OPCODE_ALU } } + + /** + * Phase counter is reset for the cycle count subscript, Stage_cnt = 0 + */ +#define I_SRST() { .alu_cnt = { \ + .unused = 0, \ + .imm = 0, \ + .unused1 = 0, \ + .sel = ALU_SEL_RST, \ + .unused2 = 0, \ + .sub_opcode = SUB_OPCODE_ALU_CNT, \ + .opcode = OPCODE_ALU } } +#endif + /** * Define a label with number label_num. * diff --git a/components/ulp/ld/esp32.ulp.ld b/components/ulp/ld/esp32.ulp.ld index bd07c78cf..d3de12eb5 100644 --- a/components/ulp/ld/esp32.ulp.ld +++ b/components/ulp/ld/esp32.ulp.ld @@ -1,10 +1,16 @@ #include "sdkconfig.h" +#if CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM +#define LOCAL_ULP_COPROC_RESERVE_MEM CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM +#else +#define LOCAL_ULP_COPROC_RESERVE_MEM CONFIG_ESP32_ULP_COPROC_RESERVE_MEM +#endif + #define ULP_BIN_MAGIC 0x00706c75 #define HEADER_SIZE 12 MEMORY { - ram(RW) : ORIGIN = 0, LENGTH = CONFIG_ESP32_ULP_COPROC_RESERVE_MEM + ram(RW) : ORIGIN = 0, LENGTH = LOCAL_ULP_COPROC_RESERVE_MEM } SECTIONS diff --git a/components/ulp/project_include.cmake b/components/ulp/project_include.cmake index e33ea2d50..94afe208d 100644 --- a/components/ulp/project_include.cmake +++ b/components/ulp/project_include.cmake @@ -34,12 +34,19 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs) idf_build_get_property(python PYTHON) idf_build_get_property(extra_cmake_args EXTRA_CMAKE_ARGS) + if(IDF_TARGET STREQUAL "esp32") + set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-esp32-ulp.cmake) + endif() + if(IDF_TARGET STREQUAL "esp32s2beta") + set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-esp32s2beta-ulp.cmake) + endif() + externalproject_add(${app_name} SOURCE_DIR ${idf_path}/components/ulp/cmake BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${app_name} INSTALL_COMMAND "" CMAKE_ARGS -DCMAKE_GENERATOR=${CMAKE_GENERATOR} - -DCMAKE_TOOLCHAIN_FILE=${idf_path}/components/ulp/cmake/toolchain-ulp.cmake + -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FLAG} -DULP_S_SOURCES=${sources} -DULP_APP_NAME=${app_name} -DCOMPONENT_DIR=${COMPONENT_DIR} # Even though this resolves to a ';' separated list, this is fine. This must be special behavior diff --git a/components/ulp/toolchain_ulp_version.mk b/components/ulp/toolchain_ulp_version.mk index 1ca859c89..1627d1bcd 100644 --- a/components/ulp/toolchain_ulp_version.mk +++ b/components/ulp/toolchain_ulp_version.mk @@ -1 +1 @@ -SUPPORTED_ULP_ASSEMBLER_VERSION = 2.28.51.20170517 \ No newline at end of file +SUPPORTED_ULP_ASSEMBLER_VERSION = 2.28.51-esp-20190801 \ No newline at end of file diff --git a/components/ulp/ulp.c b/components/ulp/ulp.c index 34d853125..cc460bc25 100644 --- a/components/ulp/ulp.c +++ b/components/ulp/ulp.c @@ -65,6 +65,25 @@ esp_err_t ulp_run(uint32_t entry_point) SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_SLEEP_FOLW_8M); // enable ULP timer SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA + // disable ULP timer + CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); + // wait for at least 1 RTC_SLOW_CLK cycle + ets_delay_us(10); + // set entry point + REG_SET_FIELD(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_PC_INIT, entry_point); + + SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SEL); // Select ULP_TIMER trigger target for ULP. + CLEAR_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_DONE_FORCE); // Select the value for ULP_TIMER sleep. 1: REG_COCPU_DONE;0: ULP END value. + /* Set the number of cycles of ULP_TIMER sleep, the wait time required to start ULP */ + REG_SET_FIELD(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_TIMER_SLP_CYCLE, 100); + /* Clear interrupt COCPU status */ + REG_WRITE(RTC_CNTL_INT_CLR_REG, RTC_CNTL_COCPU_INT_CLR | RTC_CNTL_COCPU_TRAP_INT_CLR | RTC_CNTL_ULP_CP_INT_CLR); + // start ULP clock gate. + SET_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG ,RTC_CNTL_ULP_CP_CLK_FO); + // 1: start with timer. wait ULP_TIMER cnt timer. + CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_FORCE_START_TOP); // Select ULP_TIMER timer as COCPU trigger source + SET_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); // Software to turn on the ULP_TIMER timer #endif return ESP_OK; } @@ -131,6 +150,13 @@ esp_err_t ulp_set_wakeup_period(size_t period_index, uint32_t period_us) } REG_SET_FIELD(SENS_ULP_CP_SLEEP_CYC0_REG + period_index * sizeof(uint32_t), SENS_SLEEP_CYCLES_S0, (uint32_t) period_cycles); +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA + if (period_index > 4) { + return ESP_ERR_INVALID_ARG; + } + uint64_t period_us_64 = period_us; + uint64_t period_cycles = (period_us_64 * 1000) / 90; //COCPU sleep clock is 90KHZ. + REG_SET_FIELD(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_TIMER_SLP_CYCLE, period_cycles); #endif return ESP_OK; } diff --git a/examples/system/ulp/main/ulp/pulse_cnt.S b/examples/system/ulp/main/ulp/pulse_cnt.S index 774375e2a..55f21a0ba 100644 --- a/examples/system/ulp/main/ulp/pulse_cnt.S +++ b/examples/system/ulp/main/ulp/pulse_cnt.S @@ -75,7 +75,7 @@ entry: * Check which IO this is. */ move r0, r3 - jumpr read_io_high, 16, ge + jumps read_io_high, 16, ge /* Read the value of lower 16 RTC IOs into R0 */ READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S, 16) diff --git a/examples/system/ulp_adc/main/ulp_adc_example_main.c b/examples/system/ulp_adc/main/ulp_adc_example_main.c index c7be925ca..fdd314ef5 100644 --- a/examples/system/ulp_adc/main/ulp_adc_example_main.c +++ b/examples/system/ulp_adc/main/ulp_adc_example_main.c @@ -80,7 +80,9 @@ static void init_ulp_program(void) */ rtc_gpio_isolate(GPIO_NUM_12); rtc_gpio_isolate(GPIO_NUM_15); +#if CONFIG_IDF_TARGET_ESP32 esp_deep_sleep_disable_rom_logging(); // suppress boot messages +#endif } static void start_ulp_program(void) diff --git a/tools/test_idf_tools/test_idf_tools.py b/tools/test_idf_tools/test_idf_tools.py index a9573282b..a88702f84 100755 --- a/tools/test_idf_tools/test_idf_tools.py +++ b/tools/test_idf_tools/test_idf_tools.py @@ -73,7 +73,7 @@ class TestUsage(unittest.TestCase): output = output_stream.getvalue() xtensa_esp32_elf_version = 'esp-2019r2-8.2.0' - esp32ulp_version = '2.28.51.20170517' + esp32ulp_version = '2.28.51-esp-20190801' self.assertIn('* xtensa-esp32-elf:', output) self.assertIn('- %s (recommended)' % xtensa_esp32_elf_version, output) diff --git a/tools/tools.json b/tools/tools.json index 32c2a6e7a..79083a102 100644 --- a/tools/tools.json +++ b/tools/tools.json @@ -142,26 +142,71 @@ "versions": [ { "linux-amd64": { - "sha256": "c1bbcd65e1e30c7312a50344c8dbc70c2941580a79aa8f8abbce8e0e90c79566", - "size": 8246604, - "url": "https://dl.espressif.com/dl/binutils-esp32ulp-linux64-2.28.51-esp32ulp-20180809.tar.gz" + "sha256": "f036ef1907ee19c8705f7076ef8c2e3b6dd9ffff654d35c264e7036c14aa5230", + "size": 8249059, + "url": "https://github.com/espressif/binutils-esp32ulp/releases/download/v2.28.51-esp-20190801/binutils-esp32ulp-linux-amd64-2.28.51-esp-20190801.tar.gz" }, "macos": { - "sha256": "c92937d85cc9a90eb6c6099ce767ca021108c18c94e34bd7b1fa0cde168f94a0", - "size": 5726662, - "url": "https://dl.espressif.com/dl/binutils-esp32ulp-macos-2.28.51-esp32ulp-20180809.tar.gz" + "sha256": "04f812bf410ae6bef438c53ff4f4a33f34884d9072ae5815814b208ab408a9a4", + "size": 8871878, + "url": "https://github.com/espressif/binutils-esp32ulp/releases/download/v2.28.51-esp-20190801/binutils-esp32ulp-macos-2.28.51-esp-20190801.tar.gz" }, - "name": "2.28.51.20170517", + "name": "2.28.51-esp-20190801", "status": "recommended", "win32": { - "sha256": "92dc83e69e534c9f73d7b939088f2e84f757d2478483415d17fe9dd1c236f2fd", - "size": 12231559, - "url": "https://dl.espressif.com/dl/binutils-esp32ulp-win32-2.28.51-esp32ulp-20180809.zip" + "sha256": "44626cc2348686e9c57587142ca49cdab26fec742468942b8679f22b6661a7ec", + "size": 12232098, + "url": "https://github.com/espressif/binutils-esp32ulp/releases/download/v2.28.51-esp-20190801/binutils-esp32ulp-win32-2.28.51-esp-20190801.zip" }, "win64": { - "sha256": "92dc83e69e534c9f73d7b939088f2e84f757d2478483415d17fe9dd1c236f2fd", - "size": 12231559, - "url": "https://dl.espressif.com/dl/binutils-esp32ulp-win32-2.28.51-esp32ulp-20180809.zip" + "sha256": "44626cc2348686e9c57587142ca49cdab26fec742468942b8679f22b6661a7ec", + "size": 12232098, + "url": "https://github.com/espressif/binutils-esp32ulp/releases/download/v2.28.51-esp-20190801/binutils-esp32ulp-win32-2.28.51-esp-20190801.zip" + } + } + ] + }, + { + "description": "Toolchain for ESP32-S2 ULP coprocessor", + "export_paths": [ + [ + "esp32s2ulp-elf-binutils", + "bin" + ] + ], + "export_vars": {}, + "info_url": "https://github.com/espressif/binutils-esp32ulp", + "install": "always", + "license": "GPL-2.0-or-later", + "name": "esp32s2ulp-elf", + "version_cmd": [ + "esp32s2ulp-elf-as", + "--version" + ], + "version_regex": "\\(GNU Binutils\\)\\s+([0-9a-z\\.\\-]+)", + "versions": [ + { + "linux-amd64": { + "sha256": "0085852b0de25a2186c874a184385c1dde107414248ec6a726b48d6616da6274", + "size": 8253802, + "url": "https://github.com/espressif/binutils-esp32ulp/releases/download/v2.28.51-esp-20190801/binutils-esp32s2ulp-linux-amd64-2.28.51-esp-20190801.tar.gz" + }, + "macos": { + "sha256": "b180a5ed3b7b5aa4503f26e5bd562d8b0f4b55f24a2ca04942804fd88b4d91b5", + "size": 8877256, + "url": "https://github.com/espressif/binutils-esp32ulp/releases/download/v2.28.51-esp-20190801/binutils-esp32s2ulp-macos-2.28.51-esp-20190801.tar.gz" + }, + "name": "2.28.51-esp-20190801", + "status": "recommended", + "win32": { + "sha256": "dbd0f050273a95a82b3e506aba999c8e4d4b22c69e5f3f3efc712c8eb59355e2", + "size": 12238724, + "url": "https://github.com/espressif/binutils-esp32ulp/releases/download/v2.28.51-esp-20190801/binutils-esp32s2ulp-win32-2.28.51-esp-20190801.zip" + }, + "win64": { + "sha256": "dbd0f050273a95a82b3e506aba999c8e4d4b22c69e5f3f3efc712c8eb59355e2", + "size": 12238724, + "url": "https://github.com/espressif/binutils-esp32ulp/releases/download/v2.28.51-esp-20190801/binutils-esp32s2ulp-win32-2.28.51-esp-20190801.zip" } } ]