esp32: Add support for the esp32's ULP.

The ULP is available as esp32.ULP().  See README.ulp.md for basic usage.
pull/1/head
Andreas Valder 2017-11-20 17:03:38 +01:00 committed by Damien George
parent d43c737756
commit 298c072433
6 changed files with 236 additions and 1 deletions

View File

@ -83,6 +83,7 @@ INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/lwip/posix
INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/include
INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include
INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include
INC_ESPCOMP += -I$(ESPCOMP)/ulp/include
INC_ESPCOMP += -I$(ESPCOMP)/vfs/include
INC_ESPCOMP += -I$(ESPCOMP)/newlib/platform_include
INC_ESPCOMP += -I$(ESPCOMP)/xtensa-debug-module/include
@ -148,6 +149,7 @@ SRC_C = \
network_lan.c \
modsocket.c \
modesp.c \
esp32_ulp.c \
modesp32.c \
moduhashlib.c \
espneopixel.c \
@ -417,6 +419,10 @@ ESPIDF_SPI_FLASH_O = $(addprefix $(ESPCOMP)/spi_flash/,\
flash_ops.o \
)
ESPIDF_ULP_O = $(addprefix $(ESPCOMP)/ulp/,\
ulp.o \
)
$(BUILD)/$(ESPCOMP)/lwip/%.o: CFLAGS += -Wno-address -Wno-unused-variable -Wno-unused-but-set-variable
ESPIDF_LWIP_O = $(addprefix $(ESPCOMP)/lwip/,\
api/pppapi.o \
@ -605,6 +611,7 @@ OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NGHTTP_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NVS_FLASH_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_OPENSSL_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SPI_FLASH_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ULP_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_WPA_SUPPLICANT_O))
################################################################################
# Main targets

View File

@ -0,0 +1,126 @@
# ULP
To compile binarys for the ulp you need the ulp toolkit. Download it from https://github.com/espressif/binutils-esp32ulp/wiki#downloads
Then extract it, then add ```esp32ulp-elf-binutils/bin``` to your PATH
## Example Makefile
```make
ULP_S_SOURCES := main.S
ULP_APP_NAME := test
ULP_LD_SCRIPT := esp32.ulp.ld
SRC_PATH := src
BUILD_PATH := build
include $(ESPIDF)/components/ulp/Makefile.projbuild
ULP_ELF := $(ULP_APP_NAME).elf
ULP_MAP := $(ULP_ELF:.elf=.map)
ULP_SYM := $(ULP_ELF:.elf=.sym)
ULP_BIN := $(ULP_ELF:.elf=.bin)
ULP_EXPORTS_LD := $(ULP_ELF:.elf=.ld)
ULP_EXPORTS_HEADER := $(ULP_ELF:.elf=.h)
ULP_OBJECTS := $(notdir $(ULP_S_SOURCES:.S=.ulp.o))
ULP_DEP := $(notdir $(ULP_S_SOURCES:.S=.ulp.d)) $(ULP_LD_SCRIPT:.ld=.d)
ULP_PREPROCESSED := $(notdir $(ULP_S_SOURCES:.S=.ulp.pS))
ULP_LISTINGS := $(notdir $(ULP_S_SOURCES:.S=.ulp.lst))
.PHONY: all clean
all: $(BUILD_PATH) $(BUILD_PATH)/$(ULP_BIN)
clean:
rm -rf $(BUILD_PATH)
$(BUILD_PATH):
mkdir $@
# Generate preprocessed linker file.
$(BUILD_PATH)/$(ULP_APP_NAME).ld: $(SRC_PATH)/$(ULP_LD_SCRIPT)
cpp -P $< -o $@
# Generate preprocessed assembly files.
# To inspect these preprocessed files, add a ".PRECIOUS: %.ulp.pS" rule.
$(BUILD_PATH)/%.ulp.pS: $(SRC_PATH)/%.S
cpp $< -o $@
# Compiled preprocessed files into object files.
$(BUILD_PATH)/%.ulp.o: $(BUILD_PATH)/%.ulp.pS
$(ULP_AS) -al=$(patsubst %.ulp.o,%.ulp.lst,$@) -o $@ $<
# Link object files and generate map file
$(BUILD_PATH)/$(ULP_ELF): $(BUILD_PATH)/$(ULP_OBJECTS) $(BUILD_PATH)/$(ULP_APP_NAME).ld
$(ULP_LD) -o $@ -A elf32-esp32ulp -Map=$(BUILD_PATH)/$(ULP_MAP) -T $(BUILD_PATH)/$(ULP_APP_NAME).ld $<
# Dump the list of global symbols in a convenient format.
$(ULP_SYM): $(ULP_ELF)
$(ULP_NM) -g -f posix $< > $@
# Dump the binary for inclusion into the project
$(BUILD_PATH)/$(ULP_BIN): $(BUILD_PATH)/$(ULP_ELF)
$(ULP_OBJCOPY) -O binary $< $@
```
## Example linker script for the ulp
```
#define ULP_BIN_MAGIC 0x00706c75
#define HEADER_SIZE 12
#define CONFIG_ULP_COPROC_RESERVE_MEM 4096
MEMORY
{
ram(RW) : ORIGIN = 0, LENGTH = CONFIG_ULP_COPROC_RESERVE_MEM
}
SECTIONS
{
.text : AT(HEADER_SIZE)
{
*(.text)
} >ram
.data :
{
. = ALIGN(4);
*(.data)
} >ram
.bss :
{
. = ALIGN(4);
*(.bss)
} >ram
.header : AT(0)
{
LONG(ULP_BIN_MAGIC)
SHORT(LOADADDR(.text))
SHORT(SIZEOF(.text))
SHORT(SIZEOF(.data))
SHORT(SIZEOF(.bss))
}
}
```
## Example ulp code
```asm
move R3, 99
move R0, 10
# mem[R0+0] = R3
st R3, R0, 0
HALT
```
## Example python code using the ulp
```python
import esp32
import time
u = esp32.ULP()
with open('test.bin', 'rb') as f:
b = f.read()
u.load_binary(0,b)
u.run(0)
```

View File

@ -0,0 +1,97 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 "Andreas Valder" <andreas.valder@serioese.gmbh>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "esp32/ulp.h"
#include "esp_err.h"
typedef struct _esp32_ulp_obj_t {
mp_obj_base_t base;
} esp32_ulp_obj_t;
const mp_obj_type_t esp32_ulp_type;
// singleton ULP object
STATIC const esp32_ulp_obj_t esp32_ulp_obj = {{&esp32_ulp_type}};
STATIC mp_obj_t esp32_ulp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
// return constant object
return (mp_obj_t)&esp32_ulp_obj;
}
STATIC mp_obj_t esp32_ulp_set_wakeup_period(mp_obj_t self_in, mp_obj_t period_index_in, mp_obj_t period_us_in) {
mp_uint_t period_index = mp_obj_get_int(period_index_in);
mp_uint_t period_us = mp_obj_get_int(period_us_in);
int _errno = ulp_set_wakeup_period(period_index, period_us);
if (_errno != ESP_OK) {
mp_raise_OSError(_errno);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_ulp_set_wakeup_period_obj, esp32_ulp_set_wakeup_period);
STATIC mp_obj_t esp32_ulp_load_binary(mp_obj_t self_in, mp_obj_t load_addr_in, mp_obj_t program_binary_in) {
mp_uint_t load_addr = mp_obj_get_int(load_addr_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(program_binary_in, &bufinfo, MP_BUFFER_READ);
int _errno = ulp_load_binary(load_addr, bufinfo.buf, bufinfo.len/sizeof(uint32_t));
if (_errno != ESP_OK) {
mp_raise_OSError(_errno);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_ulp_load_binary_obj, esp32_ulp_load_binary);
STATIC mp_obj_t esp32_ulp_run(mp_obj_t self_in, mp_obj_t entry_point_in) {
mp_uint_t entry_point = mp_obj_get_int(entry_point_in);
int _errno = ulp_run(entry_point/sizeof(uint32_t));
if (_errno != ESP_OK) {
mp_raise_OSError(_errno);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_ulp_run_obj, esp32_ulp_run);
STATIC const mp_rom_map_elem_t esp32_ulp_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_set_wakeup_period), MP_ROM_PTR(&esp32_ulp_set_wakeup_period_obj) },
{ MP_ROM_QSTR(MP_QSTR_load_binary), MP_ROM_PTR(&esp32_ulp_load_binary_obj) },
{ MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&esp32_ulp_run_obj) },
{ MP_ROM_QSTR(MP_QSTR_RESERVE_MEM), MP_ROM_INT(CONFIG_ULP_COPROC_RESERVE_MEM) },
};
STATIC MP_DEFINE_CONST_DICT(esp32_ulp_locals_dict, esp32_ulp_locals_dict_table);
const mp_obj_type_t esp32_ulp_type = {
{ &mp_type_type },
.name = MP_QSTR_ULP,
.make_new = esp32_ulp_make_new,
.locals_dict = (mp_obj_t)&esp32_ulp_locals_dict,
};

View File

@ -126,6 +126,9 @@ STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_touch), (mp_obj_t)&esp32_wake_on_touch_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_ext0), (mp_obj_t)&esp32_wake_on_ext0_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_ext1), (mp_obj_t)&esp32_wake_on_ext1_obj },
{ MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&esp32_ulp_type) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WAKEUP_ALL_LOW), mp_const_false },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WAKEUP_ANY_HIGH), mp_const_true },
};

View File

@ -26,4 +26,6 @@
#define RTC_LAST_EXT_PIN 39
#define RTC_IS_VALID_EXT_PIN(pin_id) ((1ll << (pin_id)) & RTC_VALID_EXT_PINS)
extern const mp_obj_type_t esp32_ulp_type;
#endif // MICROPY_INCLUDED_ESP32_MODESP32_H

View File

@ -5,7 +5,7 @@
#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0
#define CONFIG_BT_RESERVE_DRAM 0x0
#define CONFIG_ULP_COPROC_RESERVE_MEM 0
#define CONFIG_ULP_COPROC_RESERVE_MEM 2040
#define CONFIG_PHY_DATA_OFFSET 0xf000
#define CONFIG_APP_OFFSET 0x10000