Merge branch 'bugfix/ulp_fixes_v3.0' into 'release/v3.0'

ULP fixes (backport v3.0)

See merge request idf/esp-idf!3002
This commit is contained in:
Angus Gratton 2018-08-22 13:37:16 +08:00
commit 132b439359
9 changed files with 1075 additions and 914 deletions

View file

@ -81,7 +81,7 @@ build: $(COMPONENT_BUILD_DIR)/$(ULP_EXPORTS_HEADER) \
$(ULP_EXP_DEP_OBJECTS) : $(ULP_EXPORTS_HEADER) $(ULP_SYM)
# Finally, set all the variables processed by the build system.
COMPONENT_EXTRA_CLEAN := $(ULP_OBJECTS) \
COMPONENT_EXTRA_CLEAN += $(ULP_OBJECTS) \
$(ULP_LD_SCRIPT) \
$(ULP_PREPROCESSED) \
$(ULP_ELF) $(ULP_BIN) \
@ -91,6 +91,6 @@ COMPONENT_EXTRA_CLEAN := $(ULP_OBJECTS) \
$(ULP_DEP) \
$(ULP_LISTINGS)
COMPONENT_EMBED_FILES := $(COMPONENT_BUILD_DIR)/$(ULP_BIN)
COMPONENT_ADD_LDFLAGS := -l$(COMPONENT_NAME) -T $(COMPONENT_BUILD_DIR)/$(ULP_EXPORTS_LD)
COMPONENT_EXTRA_INCLUDES := $(COMPONENT_BUILD_DIR)
COMPONENT_EMBED_FILES += $(COMPONENT_BUILD_DIR)/$(ULP_BIN)
COMPONENT_ADD_LDFLAGS += -l$(COMPONENT_NAME) -T $(COMPONENT_BUILD_DIR)/$(ULP_EXPORTS_LD)
COMPONENT_EXTRA_INCLUDES += $(COMPONENT_BUILD_DIR)

View file

@ -17,6 +17,7 @@
#include <stddef.h>
#include <stdlib.h>
#include "esp_err.h"
#include "soc/soc.h"
#ifdef __cplusplus
extern "C" {
@ -857,7 +858,7 @@ esp_err_t ulp_process_macros_and_load(uint32_t load_addr, const ulp_insn_t* prog
* 3. TEXT_SIZE, size of .text section (2 bytes)
* 4. DATA_SIZE, size of .data section (2 bytes)
* 5. BSS_SIZE, size of .bss section (2 bytes)
* 6. (TEXT_OFFSET - 16) bytes of arbitrary data (will not be loaded into RTC memory)
* 6. (TEXT_OFFSET - 12) bytes of arbitrary data (will not be loaded into RTC memory)
* 7. .text section
* 8. .data section
*

View file

@ -1 +1,11 @@
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
ULP_APP_NAME = ulp_test
ULP_S_SOURCES = $(addprefix $(COMPONENT_PATH)/ulp/, \
test_jumps.S \
)
ULP_EXP_DEP_OBJECTS := test_ulp_as.o
include $(IDF_PATH)/components/ulp/component_ulp_common.mk
COMPONENT_ADD_LDFLAGS += -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

View file

@ -0,0 +1,25 @@
#include <unistd.h>
#include "unity.h"
#include "soc/rtc_cntl_reg.h"
#include "esp32/ulp.h"
#include "ulp_test.h"
extern const uint8_t ulp_test_bin_start[] asm("_binary_ulp_test_bin_start");
extern const uint8_t ulp_test_bin_end[] asm("_binary_ulp_test_bin_end");
TEST_CASE("jumps condition", "[ulp]")
{
esp_err_t err = ulp_load_binary(0, ulp_test_bin_start,
(ulp_test_bin_end - ulp_test_bin_start) / sizeof(uint32_t));
TEST_ESP_OK(err);
REG_CLR_BIT(RTC_CNTL_INT_RAW_REG, RTC_CNTL_ULP_CP_INT_RAW);
TEST_ESP_OK(ulp_run(&ulp_test_jumps - RTC_SLOW_MEM));
usleep(10000);
TEST_ASSERT_NOT_EQUAL(0, REG_GET_BIT(RTC_CNTL_INT_RAW_REG, RTC_CNTL_ULP_CP_INT_RAW));
TEST_ASSERT_EQUAL(0, ulp_jumps_fail & UINT16_MAX);
TEST_ASSERT_EQUAL(1, ulp_jumps_pass & UINT16_MAX);
}

View file

@ -0,0 +1,101 @@
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/soc_ulp.h"
.bss
.global jumps_pass
jumps_pass:
.long 0
.global jumps_fail
jumps_fail:
.long 0
.text
.global test_jumps
test_jumps:
/* tests for LT (less than) condition */
stage_rst /* cnt = 0 */
jumps test_fail, 0, LT /* 0 < 0: false, should not jump */
jumps 1f, 1, LT /* 0 < 1: true, should jump */
jump test_fail
1:
stage_inc 2 /* cnt = 2 */
jumps 1f, 3, LT /* 2 < 1: true */
jump test_fail
1:
jumps test_fail, 1, LT /* 2 < 1: false */
jumps test_fail, 2, LT /* 2 < 2: false */
/* tests for LE (less or equal) condition */
stage_rst /* cnt = 0 */
jumps 1f, 0, LE /* 0 <= 0: true */
jump test_fail
1:
jumps 1f, 1, LE /* 0 <= 1: true */
jump test_fail
1:
stage_inc 2 /* cnt = 2 */
jumps test_fail, 1, LE /* 2 <= 1: false */
/* tests for EQ (equal) condition */
stage_rst /* cnt = 0 */
jumps 1f, 0, EQ /* 0 = 0: true */
jump test_fail
1:
jumps test_fail, 1, EQ /* 0 = 1: false */
stage_inc 1 /* cnt = 1 */
jumps test_fail, 0, EQ /* 1 = 0: false */
jumps test_fail, 2, EQ /* 1 = 2: false */
jumps 1f, 1, EQ /* 1 = 1: true */
1:
/* tests for GE (greater or equal) condition */
stage_rst /* cnt = 0 */
jumps 1f, 0, GE /* 0 >= 0: true */
jump test_fail
1:
jumps test_fail, 1, GE /* 0 >= 1: false */
stage_inc 1 /* cnt = 1 */
jumps 1f, 0, GE /* 1 >= 0: true */
jump test_fail
1:
jumps 1f, 1, GE /* 1 >= 1: true */
jump test_fail
1:
jumps test_fail, 2, GE /* 1 >= 2: false */
/* tests for GT (greater than) condition */
stage_rst /* cnt = 0 */
jumps test_fail, 0, GT /* 0 > 0: false */
jumps test_fail, 1, GE /* 0 > 1: false */
stage_inc 1 /* cnt = 1 */
jumps 1f, 0, GT /* 1 > 0: true */
jump test_fail
1:
jumps test_fail, 1, GT /* 1 > 1: false */
jumps test_fail, 2, GT /* 1 > 2: false */
jump test_pass
test_fail:
move r0, jumps_fail
move r1, 1
st r1, r0, 0
jump done
test_pass:
move r0, jumps_pass
move r1, 1
st r1, r0, 0
jump done
.global done
done:
wake
halt

View file

@ -15,8 +15,8 @@ Installing the toolchain
ULP coprocessor code is written in assembly and compiled using the `binutils-esp32ulp toolchain`_.
1. Download the toolchain using the links listed on this page:
https://github.com/espressif/binutils-esp32ulp/wiki#downloads
1. Download pre-built binaries of the latest toolchain release from:
https://github.com/espressif/binutils-esp32ulp/releases.
2. Extract the toolchain into a directory, and add the path to the ``bin/`` directory of the toolchain to the ``PATH`` environment variable.
@ -134,7 +134,7 @@ Each ULP program is embedded into the ESP-IDF application as a binary blob. Appl
Once the program is loaded into RTC memory, application can start it, passing the address of the entry point to ``ulp_run`` function::
ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t)) );
ESP_ERROR_CHECK( ulp_run(&ulp_entry - RTC_SLOW_MEM) );
.. doxygenfunction:: ulp_run

78
docs/api-guides/ulp_instruction_set.rst Executable file → Normal file
View file

@ -73,7 +73,12 @@ ULP coprocessor is clocked from RTC_FAST_CLK, which is normally derived from the
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 coprocessor needs 2 clock cycle to fetch each instuction (fetching is not pipelined), plus certain number of cycles to execute, depending on the instruction. See description of each instruction for details on the execution time.
ULP coprocessor needs certain number of clock cycles to fetch each instuction, plus certain number of cycles to execute it, depending on the instruction. See description of each instruction below for details on the execution time.
Instruction fetch time is:
- 2 clock cycles — for instructions following ALU and branch instructions.
- 4 clock cycles — in other cases.
Note that when accessing RTC memories and RTC registers, ULP coprocessor has lower priority than the main CPUs. This means that ULP coprocessor execution may be suspended while the main CPUs access same memory region as the ULP.
@ -86,7 +91,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
**Operands**
None
**Cycles**
2 (fetch) + 1 (execute)
2 cycle to execute, 4 cycles to fetch next instruction
**Description**
No operation is performed. Only the PC is incremented.
@ -111,7 +116,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Imm* - 16-bit signed value
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction adds source register to another source register or to a 16-bit signed value and stores result to the destination register.
@ -147,7 +152,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Imm* - 16-bit signed value
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction subtracts the source register from another source register or subtracts 16-bit signed value from a source register, and stores result to the destination register.
@ -181,7 +186,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Imm* - 16-bit signed value
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction does logical AND of a source register and another source register or 16-bit signed value and stores result to the destination register.
@ -216,7 +221,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Imm* - 16-bit signed value
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction does logical OR of a source register and another source register or 16-bit signed value and stores result to the destination register.
@ -252,7 +257,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Imm* - 16-bit signed value
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction does logical shift to left of source register to number of bits from another source register or 16-bit signed value and store result to the destination register.
@ -287,7 +292,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
*Imm* - 16-bit signed value
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction does logical shift to right of source register to number of bits from another source register or 16-bit signed value and store result to the destination register.
@ -321,7 +326,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Imm* 16-bit signed value
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction move to destination register value from source register or 16-bit signed value.
@ -356,7 +361,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Offset* 10-bit signed value, offset in bytes
**Cycles**
2 (fetch) + 4 (execute)
4 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction stores the 16-bit value of Rsrc to the lower half-word of memory with address Rdst+offset. The upper half-word is written with the current program counter (PC), expressed in words, shifted left by 5 bits::
@ -393,7 +398,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
*Offset* 10-bit signed value, offset in bytes
**Cycles**
2 (fetch) + 4 (execute)
4 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction loads lower 16-bit half-word from memory with address Rsrc+offset into the destination register Rdst::
@ -439,7 +444,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- OV jump if last ALU has set overflow flag
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 2 cycles to fetch next instruction
**Description**
The instruction makes jump to the specified address. Jump can be either unconditional or based on an ALU flag.
@ -478,7 +483,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *LT* (less than) jump if value in R0 < threshold
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 2 cycles to fetch next instruction
**Description**
The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of R0 register value and the threshold value.
@ -507,10 +512,29 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Condition*:
- *EQ* (equal) jump if value in stage_cnt == threshold
- *LT* (less than) jump if value in stage_cnt < threshold
- *LE* (less or equal) - jump if value in stage_cnt <= threshold
- *GT* (greater than) jump if value in stage_cnt > threshold
- *GE* (greater or equal) — jump if value in stage_cnt >= threshold
**Cycles**
2 (fetch) + 2 (execute)
Conditions *LE*, *LT*, *GE*: 2 cycles to execute, 2 cycles to fetch next instruction
Conditions *EQ*, *GT* are implemented in the assembler using two **JUMPS** instructions::
// JUMPS target, threshold, EQ is implemented as:
JUMPS next, threshold, LT
JUMPS target, threshold, LE
next:
// JUMPS target, threshold, GT is implemented as:
JUMPS next, threshold, LE
JUMPS target, threshold, GE
next:
Therefore the execution time will depend on the branches taken: either 2 cycles to execute + 2 cycles to fetch, or 4 cycles to execute + 4 cycles to fetch.
**Description**
The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of count register value and threshold value.
@ -539,7 +563,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
The instruction sets the stage count register to 0
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Examples**::
@ -557,7 +581,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Value* 8 bits value
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction increments stage count register by given value.
@ -583,7 +607,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Value* 8 bits value
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction decrements stage count register by given value.
@ -610,7 +634,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
No operands
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute
**Description**
The instruction halts the ULP coprocessor and restarts ULP wakeup timer, if it is enabled.
@ -631,7 +655,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
No operands
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction sends an interrupt from ULP to RTC controller.
@ -666,7 +690,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *sleep_reg* 0..4, selects one of ``SENS_ULP_CP_SLEEP_CYCx_REG`` registers.
**Cycles**
2 (fetch) + 2 (execute)
2 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction selects which of the ``SENS_ULP_CP_SLEEP_CYCx_REG`` (x = 0..4) register values is to be used by the ULP wakeup timer as wakeup period. By default, the value from ``SENS_ULP_CP_SLEEP_CYC0_REG`` is used.
@ -689,7 +713,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Cycles* number of cycles for wait
**Cycles**
2 (fetch) + *Cycles* (execute)
2 + *Cycles* cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction delays for given number of cycles.
@ -715,7 +739,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Wait_Delay* number of cycles used to perform the measurement
**Cycles**
2 (fetch) + *Wait_Delay* + 3 * TSENS_CLK
2 + *Wait_Delay* + 3 * TSENS_CLK to execute, 4 cycles to fetch next instruction
**Description**
The instruction performs measurement using TSENS and stores the result into a general purpose register.
@ -742,7 +766,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Mux* - selected PAD, SARADC Pad[Mux+1] is enabled
**Cycles**
2 (fetch) + 21 + max(1, SAR_AMP_WAIT1) + max(1, SAR_AMP_WAIT2) + max(1, SAR_AMP_WAIT3) + SARx_SAMPLE_CYCLE + SARx_SAMPLE_BIT
``23 + max(1, SAR_AMP_WAIT1) + max(1, SAR_AMP_WAIT2) + max(1, SAR_AMP_WAIT3) + SARx_SAMPLE_CYCLE + SARx_SAMPLE_BIT`` cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction makes measurements from ADC.
@ -763,7 +787,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Slave_sel* - Index of I2C slave address to use.
**Cycles**
2 (fetch) + I2C communication time
Execution time mostly depends on I2C communication time. 4 cycles to fetch next instruction.
**Description**
``I2C_RD`` instruction reads one byte from I2C slave with index ``Slave_sel``. Slave address (in 7-bit format) has to be set in advance into `SENS_I2C_SLAVE_ADDRx` register field, where ``x == Slave_sel``.
@ -787,7 +811,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Slave_sel* - Index of I2C slave address to use.
**Cycles**
2 (fetch) + I2C communication time
Execution time mostly depends on I2C communication time. 4 cycles to fetch next instruction.
**Description**
``I2C_WR`` instruction writes one byte to I2C slave with index ``Slave_sel``. Slave address (in 7-bit format) has to be set in advance into `SENS_I2C_SLAVE_ADDRx` register field, where ``x == Slave_sel``.
@ -809,7 +833,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Low* Low part of R0
**Cycles**
2 (fetch) + 6 (execute)
4 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction reads up to 16 bits from a peripheral register into a general purpose register: ``R0 = REG[Addr][High:Low]``.
@ -837,7 +861,7 @@ Note that when accessing RTC memories and RTC registers, ULP coprocessor has low
- *Data* value to write, 8 bits
**Cycles**
2 (fetch) + 10 (execute)
8 cycles to execute, 4 cycles to fetch next instruction
**Description**
The instruction writes up to 8 bits from a general purpose register into a peripheral register. ``REG[Addr][High:Low] = data``

View file

@ -80,7 +80,7 @@ static void init_ulp_program()
REG_SET_FIELD(SENS_ULP_CP_SLEEP_CYC0_REG, SENS_SLEEP_CYCLES_S0, 3095);
/* Start the program */
err = ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t));
err = ulp_run(&ulp_entry - RTC_SLOW_MEM);
ESP_ERROR_CHECK(err);
}

View file

@ -87,6 +87,6 @@ static void start_ulp_program()
ulp_sample_counter = 0;
/* Start the program */
esp_err_t err = ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t));
esp_err_t err = ulp_run(&ulp_entry - RTC_SLOW_MEM);
ESP_ERROR_CHECK(err);
}