From 828d63d51ec8651b6a22335460f8ee1273721c89 Mon Sep 17 00:00:00 2001 From: ubIQio Date: Thu, 13 Sep 2018 14:17:54 +0100 Subject: [PATCH 1/5] add ULP support with uPython assembler --- .gitignore | 1 + .../internalfs_image/image/ulp_count.py | 47 + .../components/micropython/component.mk | 1 + .../micropython/esp32/machine_ulp.c | 100 ++ .../micropython/esp32/machine_ulp.h | 30 + .../micropython/esp32/machine_ulp.h.gch | Bin 0 -> 177572 bytes .../components/micropython/esp32/modmachine.c | 2 + .../components/micropython/esp32/modmachine.h | 1 + .../esp32/modules/esp32_ulp/__init__.py | 0 .../esp32/modules/esp32_ulp/__main__.py | 36 + .../esp32/modules/esp32_ulp/assemble.py | 283 ++++++ .../esp32/modules/esp32_ulp/link.py | 26 + .../esp32/modules/esp32_ulp/nocomment.py | 119 +++ .../esp32/modules/esp32_ulp/opcodes.py | 647 ++++++++++++ .../esp32/modules/esp32_ulp/soc.py | 59 ++ .../esp32/modules/esp32_ulp/util.py | 11 + .../components/micropython/esp32/ulp.h | 917 ++++++++++++++++++ .../esp32/sdkconfig => sdkconfig.ulp} | 48 +- 18 files changed, 2313 insertions(+), 15 deletions(-) create mode 100644 MicroPython_BUILD/components/internalfs_image/image/ulp_count.py create mode 100644 MicroPython_BUILD/components/micropython/esp32/machine_ulp.c create mode 100644 MicroPython_BUILD/components/micropython/esp32/machine_ulp.h create mode 100644 MicroPython_BUILD/components/micropython/esp32/machine_ulp.h.gch create mode 100644 MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/__init__.py create mode 100644 MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/__main__.py create mode 100644 MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/assemble.py create mode 100644 MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/link.py create mode 100644 MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/nocomment.py create mode 100644 MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/opcodes.py create mode 100644 MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/soc.py create mode 100644 MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/util.py create mode 100644 MicroPython_BUILD/components/micropython/esp32/ulp.h rename MicroPython_BUILD/{firmware/esp32/sdkconfig => sdkconfig.ulp} (94%) diff --git a/.gitignore b/.gitignore index 7c759ade..ae14062a 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,4 @@ xtensa-esp32-elf/ xtensa-esp32-elf_psram/ backup.sh +.DS_Store diff --git a/MicroPython_BUILD/components/internalfs_image/image/ulp_count.py b/MicroPython_BUILD/components/internalfs_image/image/ulp_count.py new file mode 100644 index 00000000..fd4d5dd8 --- /dev/null +++ b/MicroPython_BUILD/components/internalfs_image/image/ulp_count.py @@ -0,0 +1,47 @@ +""" +Very basic example showing data exchange main CPU <--> ULP coprocessor. + +To show that the ULP is doing something, it just increments the value . +It does that once per ulp timer wakeup (and then the ULP halts until it gets +waked up via the timer again). + +The timer is set to a rather long period, so you can watch the data value +incrementing (see loop at the end). +""" + +from machine import ULP +from machine import mem32 +import utime +import machine + +from esp32_ulp.__main__ import src_to_binary + +source = """\ +data: .long 0 + +entry: move r3, data # load address of data into r3 + ld r2, r3, 0 # load data contents ([r3+0]) into r2 + add r2, r2, 1 # increment r2 + st r2, r3, 0 # store r2 contents into data ([r3+0]) + halt # halt ULP co-processor (until next wake-up) +""" + + +print ("Wake Reason:",machine.wake_reason()) +binary = src_to_binary(source) + +load_addr, entry_addr = 0, 4 + +ULP_MEM_BASE = 0x50000000 +ULP_DATA_MASK = 0xffff # ULP data is only in lower 16 bits + +ulp = ULP() +ulp.set_wakeup_period(0, 1000000) # use timer0, wakeup after 1s +ulp.load_binary(load_addr, binary) + +mem32[ULP_MEM_BASE + load_addr] = 0x1000 +ulp.run(entry_addr) + +while True: + print(hex(mem32[ULP_MEM_BASE + load_addr] & ULP_DATA_MASK)) + utime.sleep(1) diff --git a/MicroPython_BUILD/components/micropython/component.mk b/MicroPython_BUILD/components/micropython/component.mk index faae2b63..ded71916 100644 --- a/MicroPython_BUILD/components/micropython/component.mk +++ b/MicroPython_BUILD/components/micropython/component.mk @@ -181,6 +181,7 @@ SRC_C = $(addprefix esp32/,\ modymodem.c \ machine_hw_i2c.c \ machine_neopixel.c \ + machine_ulp.c \ machine_dht.c \ machine_ow.c \ ) diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_ulp.c b/MicroPython_BUILD/components/micropython/esp32/machine_ulp.c new file mode 100644 index 00000000..06d79c29 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/machine_ulp.c @@ -0,0 +1,100 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 "Eric Poulsen" + * + * 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 "machine_ulp.h" + +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mperrno.h" + +#include "ulp.h" +#include "esp_err.h" + +typedef struct _machine_ulp_obj_t { + mp_obj_base_t base; +} machine_ulp_obj_t; + +const mp_obj_type_t machine_ulp_type; + +// singleton ULP object +STATIC const machine_ulp_obj_t machine_ulp_obj = {{&machine_ulp_type}}; + +STATIC mp_obj_t machine_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)&machine_ulp_obj; +} + +STATIC mp_obj_t machine_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(machine_ulp_set_wakeup_period_obj, machine_ulp_set_wakeup_period); + +STATIC mp_obj_t machine_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(machine_ulp_load_binary_obj, machine_ulp_load_binary); + +STATIC mp_obj_t machine_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(machine_ulp_run_obj, machine_ulp_run); + +STATIC const mp_map_elem_t machine_ulp_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_set_wakeup_period), (mp_obj_t)&machine_ulp_set_wakeup_period_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_load_binary), (mp_obj_t)&machine_ulp_load_binary_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_run), (mp_obj_t)&machine_ulp_run_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_COPROC_RESERVE_MEM), MP_ROM_INT(CONFIG_ULP_COPROC_RESERVE_MEM) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_ulp_locals_dict, machine_ulp_locals_dict_table); + +const mp_obj_type_t machine_ulp_type = { + { &mp_type_type }, + .name = MP_QSTR_ULP, + .make_new = machine_ulp_make_new, + .locals_dict = (mp_obj_t)&machine_ulp_locals_dict, +}; diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_ulp.h b/MicroPython_BUILD/components/micropython/esp32/machine_ulp.h new file mode 100644 index 00000000..5ff0c924 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/machine_ulp.h @@ -0,0 +1,30 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 "Eric Poulsen" + * + * 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. + */ + +#ifndef MICROPY_INCLUDED_ESP32_MACINE_ULP_H +#define MICROPY_INCLUDED_ESP32_MACINE_ULP_H + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_ulp.h.gch b/MicroPython_BUILD/components/micropython/esp32/machine_ulp.h.gch new file mode 100644 index 0000000000000000000000000000000000000000..a0a5e2f309f53041778df5a2a83b86f811f5d66f GIT binary patch literal 177572 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 SO8<_Dhia!gA``8$ru`rN&n!Fu literal 0 HcmV?d00001 diff --git a/MicroPython_BUILD/components/micropython/esp32/modmachine.c b/MicroPython_BUILD/components/micropython/esp32/modmachine.c index 1aeed635..15c0244b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modmachine.c +++ b/MicroPython_BUILD/components/micropython/esp32/modmachine.c @@ -64,6 +64,7 @@ #include "extmod/machine_pulse.h" #include "extmod/vfs_native.h" #include "modmachine.h" +#include "machine_ulp.h" #include "mpsleep.h" #include "machine_rtc.h" #include "uart.h" @@ -1013,6 +1014,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&machine_ulp_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hw_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, diff --git a/MicroPython_BUILD/components/micropython/esp32/modmachine.h b/MicroPython_BUILD/components/micropython/esp32/modmachine.h index d1928b4d..9f38ce6e 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modmachine.h +++ b/MicroPython_BUILD/components/micropython/esp32/modmachine.h @@ -115,6 +115,7 @@ extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_touchpad_type; extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t machine_dac_type; +extern const mp_obj_type_t machine_ulp_type; extern const mp_obj_type_t machine_pwm_type; extern const mp_obj_type_t machine_hw_spi_type; extern const mp_obj_type_t machine_hw_i2c_type; diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/__init__.py b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/__main__.py b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/__main__.py new file mode 100644 index 00000000..584a3dd7 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/__main__.py @@ -0,0 +1,36 @@ +import sys + +from .util import garbage_collect + +from .assemble import Assembler +from .link import make_binary +garbage_collect('after import') + + +def src_to_binary(src): + assembler = Assembler() + assembler.assemble(src) + garbage_collect('before symbols export') + addrs_syms = assembler.symbols.export() + for addr, sym in addrs_syms: + print('%04d %s' % (addr, sym)) + + text, data, bss_len = assembler.fetch() + return make_binary(text, data, bss_len) + + +def main(fn): + with open(fn) as f: + src = f.read() + + binary = src_to_binary(src) + + if fn.endswith('.s') or fn.endswith('.S'): + fn = fn[:-2] + with open(fn + '.ulp', 'wb') as f: + f.write(binary) + + +if __name__ == '__main__': + main(sys.argv[1]) + diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/assemble.py b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/assemble.py new file mode 100644 index 00000000..d0b1ff2c --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/assemble.py @@ -0,0 +1,283 @@ +""" +ESP32 ULP Co-Processor Assembler +""" + +from . import opcodes +from .nocomment import remove_comments +from .util import garbage_collect + +TEXT, DATA, BSS = 'text', 'data', 'bss' + +REL, ABS = 0, 1 + + +class SymbolTable: + def __init__(self, symbols, bases): + self._symbols = symbols + self._bases = bases + self._pass = None + + def set_pass(self, _pass): + self._pass = _pass + + def set_bases(self, bases): + self._bases = bases + + def set_from(self, from_section, from_offset): + self._from_section, self._from_offset = from_section, from_offset + + def get_from(self): + return self._from_section, self._from_offset + + def set_sym(self, symbol, stype, section, value): + entry = (stype, section, value) + if symbol in self._symbols and entry != self._symbols[symbol]: + raise Exception('redefining symbol %s with different value %r -> %r.' % (label, self._symbols[symbol], entry)) + self._symbols[symbol] = entry + + def has_sym(self, symbol): + return symbol in self._symbols + + def get_sym(self, symbol): + try: + entry = self._symbols[symbol] + except KeyError: + if self._pass == 1: + entry = (REL, TEXT, 0) # for a dummy, this is good enough + else: + raise + return entry + + def dump(self): + for symbol, entry in self._symbols.items(): + print(symbol, entry) + + def export(self): + addrs_syms = [(self.resolve_absolute(entry), symbol) for symbol, entry in self._symbols.items()] + return sorted(addrs_syms) + + def to_abs_addr(self, section, offset): + try: + base = self._bases[section] + except KeyError: + if self._pass == 1: + base = 0 # for a dummy this is good enough + else: + raise + return base + offset + + def resolve_absolute(self, symbol): + if isinstance(symbol, str): + stype, section, value = self.get_sym(symbol) + elif isinstance(symbol, tuple): + stype, section, value = symbol + else: + raise TypeError + if stype == REL: + return self.to_abs_addr(section, value) + if stype == ABS: + return value + raise TypeError(stype) + + def resolve_relative(self, symbol): + if isinstance(symbol, str): + sym_type, sym_section, sym_value = self.get_sym(symbol) + elif isinstance(symbol, tuple): + sym_type, sym_section, sym_value = symbol + else: + raise TypeError + if sym_type == REL: + sym_addr = self.to_abs_addr(sym_section, sym_value) + elif sym_type == ABS: + sym_addr = sym_value + from_addr = self.to_abs_addr(self._from_section, self._from_offset) + return sym_addr - from_addr + + +class Assembler: + + def __init__(self, symbols=None, bases=None): + self.symbols = SymbolTable(symbols or {}, bases or {}) + opcodes.symbols = self.symbols # XXX dirty hack + + def init(self, a_pass): + self.a_pass = a_pass + self.symbols.set_pass(a_pass) + self.sections = dict(text=[], data=[]) + self.offsets = dict(text=0, data=0, bss=0) + self.section = TEXT + + def parse_line(self, line): + """ + parse one line of assembler into label, opcode, args. + comments already have been removed by pre-processing. + + a line looks like (label, opcode, args, comment are all optional): + + label: opcode arg1, arg2, ... + """ + if not line: + return + has_label = line[0] not in '\t ' + if has_label: + label_line = line.split(None, 1) + if len(label_line) == 2: + label, line = label_line + else: # 1 + label, line = label_line[0], None + label = label.rstrip(':') + else: + label, line = None, line.lstrip() + if line is None: + opcode, args = None, () + else: + opcode_args = line.split(None, 1) + if len(opcode_args) == 2: + opcode, args = opcode_args + args = tuple(arg.strip() for arg in args.split(',')) + else: # 1 + opcode, args = opcode_args[0], () + return label, opcode, args + + + def parse(self, lines): + parsed = [self.parse_line(line) for line in lines] + return [p for p in parsed if p is not None] + + + def append_section(self, value, expected_section=None): + s = self.section + if expected_section is not None and s is not expected_section: + raise TypeError('only allowed in %s section' % expected_section) + if s is BSS: + # just increase BSS size by value + self.offsets[s] += value + else: + self.sections[s].append(value) + self.offsets[s] += len(value) + + def finalize_sections(self): + # make sure all sections have a bytelength dividable by 4, + # thus having all sections aligned at 32bit-word boundaries. + for s in list(self.sections.keys()) + [BSS, ]: + offs = self.offsets[s] + mod = offs % 4 + if mod: + fill = int(0).to_bytes(4 - mod, 'little') + self.offsets[s] += len(fill) + if s is not BSS: + self.sections[s].append(fill) + + def compute_bases(self): + bases = {} + addr = 0 + # lay out sections in this order: + for s in [TEXT, DATA, BSS]: # TODO: more flexibility for custom sections + bases[s] = addr + addr += self.offsets[s] // 4 # 32bit word addresses + return bases + + def dump(self): + print("Symbols:") + self.symbols.dump() + print("%s section:" % TEXT) + for t in self.sections[TEXT]: + print("%08x" % int.from_bytes(t, 'little')) + print("size: %d" % self.offsets[TEXT]) + print("%s section:" % DATA) + for d in self.sections[DATA]: + print("%08x" % int.from_bytes(d, 'little')) + print("size: %d" % self.offsets[DATA]) + print("%s section:" % BSS) + print("size: %d" % self.offsets[BSS]) + + def fetch(self): + def get_bytes(section): + return b''.join(self.sections[section]) + + return get_bytes(TEXT), get_bytes(DATA), self.offsets[BSS] + + def d_text(self): + self.section = TEXT + + def d_data(self): + self.section = DATA + + def d_bss(self): + self.section = BSS + + def fill(self, section, amount, fill_byte): + if fill_byte is not None and section is BSS: + raise ValueError('fill in bss section not allowed') + if section is TEXT: # TODO: text section should be filled with NOPs + raise ValueError('fill/skip/align in text section not supported') + fill = int(fill_byte or 0).to_bytes(1, 'little') * amount + self.offsets[section] += len(fill) + if section is not BSS: + self.sections[section].append(fill) + + def d_skip(self, amount, fill=None): + amount = int(amount) + self.fill(self.section, amount, fill) + + d_space = d_skip + + def d_align(self, align=4, fill=None): + align = int(align) + offs = self.offsets[self.section] + mod = offs % align + if mod: + amount = align - mod + self.fill(self.section, amount, fill) + + def d_set(self, symbol, expr): + value = int(expr) # TODO: support more than just integers + self.symbols.set_sym(symbol, ABS, None, value) + + def append_data(self, wordlen, args): + data = [int(arg).to_bytes(wordlen, 'little') for arg in args] + self.append_section(b''.join(data)) + + def d_byte(self, *args): + self.append_data(1, args) + + def d_word(self, *args): + self.append_data(2, args) + + def d_long(self, *args): + self.append_data(4, args) + + def assembler_pass(self, lines): + for label, opcode, args in self.parse(lines): + self.symbols.set_from(self.section, self.offsets[self.section] // 4) + if label is not None: + self.symbols.set_sym(label, REL, *self.symbols.get_from()) + if opcode is not None: + if opcode[0] == '.': + # assembler directive + func = getattr(self, 'd_' + opcode[1:]) + if func is not None: + result = func(*args) + if result is not None: + self.append_section(result) + continue + else: + # machine instruction + func = getattr(opcodes, 'i_' + opcode, None) + if func is not None: + instruction = func(*args) + self.append_section(instruction.to_bytes(4, 'little'), TEXT) + continue + raise Exception('Unknown opcode or directive: %s' % opcode) + self.finalize_sections() + + def assemble(self, text): + lines = remove_comments(text) + self.init(1) # pass 1 is only to get the symbol table right + self.assembler_pass(lines) + self.symbols.set_bases(self.compute_bases()) + garbage_collect('before pass2') + self.init(2) # now we know all symbols and bases, do the real assembler pass, pass 2 + self.assembler_pass(lines) + garbage_collect('after pass2') + diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/link.py b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/link.py new file mode 100644 index 00000000..fd9332bb --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/link.py @@ -0,0 +1,26 @@ +from uctypes import struct, addressof, LITTLE_ENDIAN, UINT16, UINT32 + + +def make_binary(text, data, bss_size): + if not isinstance(text, bytes): + raise TypeError('text section must be binary bytes') + if not isinstance(data, bytes): + raise TypeError('data section must be binary bytes') + binary_header_struct_def = dict( + magic = 0 | UINT32, + text_offset = 4 | UINT16, + text_size = 6 | UINT16, + data_size = 8 | UINT16, + bss_size = 10 | UINT16, + ) + header = bytearray(12) + h = struct(addressof(header), binary_header_struct_def, LITTLE_ENDIAN) + # https://github.com/espressif/esp-idf/blob/master/components/ulp/ld/esp32.ulp.ld + # ULP program binary should have the following format (all values little-endian): + h.magic = 0x00706c75 # (4 bytes) + h.text_offset = 12 # offset of .text section from binary start (2 bytes) + h.text_size = len(text) # size of .text section (2 bytes) + h.data_size = len(data) # size of .data section (2 bytes) + h.bss_size = bss_size # size of .bss section (2 bytes) + return bytes(header) + text + data + diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/nocomment.py b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/nocomment.py new file mode 100644 index 00000000..2ac9e8d7 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/nocomment.py @@ -0,0 +1,119 @@ +def remove_comments(s): + """ + Remove comments of these styles: + + CHASH: # comment python style, up to: EOL + CSLASHSLASH: // comment C style, up to: EOL + CSLASHSTAR: /* comment C style (single/multi line), up to: */ + + Strings can be like 'strings' or "strings". + Any comment-starting chars within strings are not considered. + Escaping of (string-end) chars via backslash in strings is considered. + + Also, leading and trailing whitespace is removed (after comment removal). + Indented lines are re-indented afterwards with a single tab char. + + Line numbers stay as in input file because empty lines are kept. + + s: string with comments (can include newlines) + returns: list of text lines + """ + # note: micropython's ure module was not capable enough to process this: + # missing methods, re modes, recursion limit exceeded, ... + # simpler hacks also didn't seem powerful enough to address all the + # corner cases of CSLASHSTAR vs. *STR, so this state machine came to life: + SRC, CHASH, CSLASHSLASH, CSLASHSTAR, DSTR, SSTR = range(6) # states + + line = [] # collect chars of one line + lines = [] # collect result lines + + def finish_line(): + # assemble a line from characters, try to get rid of trailing and + # most of leading whitespace (keep/put one tab for indented lines). + nonlocal line + line = ''.join(line) + is_indented = line.startswith(' ') or line.startswith('\t') + line = line.strip() + if line and is_indented: + line = '\t' + line + lines.append(line) + line = [] + + state = SRC + i = 0 + length = len(s) + while i < length: + c = s[i] + cn = s[i + 1] if i + 1 < length else '\0' + if state == SRC: + if c == '#': # starting to-EOL comment + state = CHASH + i += 1 + elif c == '/': + if cn == '/': # starting to-EOL comment + state = CSLASHSLASH + i += 2 + elif cn == '*': # starting a /* comment + state = CSLASHSTAR + i += 2 + else: + i += 1 + line.append(c) + elif c == '"': + state = DSTR + i += 1 + line.append(c) + elif c == "'": + state = SSTR + i += 1 + line.append(c) + elif c == '\n': + i += 1 + finish_line() + else: + i += 1 + line.append(c) + elif state == CHASH or state == CSLASHSLASH: + if c != '\n': # comment runs until EOL + i += 1 + else: + state = SRC + i += 1 + finish_line() + elif state == CSLASHSTAR: + if c == '*' and cn == '/': # ending a comment */ + state = SRC + i += 2 + elif c == '\n': + i += 1 + finish_line() + else: + i += 1 + elif state == DSTR and c == '"' or state == SSTR and c == "'": # string end + state = SRC + i += 1 + line.append(c) + elif state == DSTR or state == SSTR: + i += 1 + line.append(c) + if c == '\\': # escaping backslash + i += 1 # do not look at char after the backslash + line.append(cn) + else: + raise Exception("state: %d c: %s cn: %s" % (state, c, cn)) + if line: + # no final \n triggered processing these chars yet, do it now + finish_line() + return lines + + +if __name__ == '__main__': + import sys + filename = sys.argv[1] + with open(filename, "r") as f: + text = f.read() + lines = remove_comments(text) + with open(filename + ".nocomments", "w") as f: + for line in lines: + f.write(line + '\n') + diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/opcodes.py b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/opcodes.py new file mode 100644 index 00000000..4e2ca042 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/opcodes.py @@ -0,0 +1,647 @@ +""" +ESP32 ULP Co-Processor Instructions +""" + +from ucollections import namedtuple +from uctypes import struct, addressof, LITTLE_ENDIAN, UINT32, BFUINT32, BF_POS, BF_LEN + +from .soc import * + +# XXX dirty hack: use a global for the symbol table +symbols = None + +# Opcodes, Sub-Opcodes, Modes, ... + +OPCODE_WR_REG = 1 +OPCODE_RD_REG = 2 + +RD_REG_PERIPH_RTC_CNTL = 0 +RD_REG_PERIPH_RTC_IO = 1 +RD_REG_PERIPH_SENS = 2 +RD_REG_PERIPH_RTC_I2C = 3 + +OPCODE_I2C = 3 + +OPCODE_DELAY = 4 + +OPCODE_ADC = 5 + +OPCODE_ST = 6 +SUB_OPCODE_ST = 4 + +OPCODE_ALU = 7 +SUB_OPCODE_ALU_REG = 0 +SUB_OPCODE_ALU_IMM = 1 +ALU_SEL_ADD = 0 +ALU_SEL_SUB = 1 +ALU_SEL_AND = 2 +ALU_SEL_OR = 3 +ALU_SEL_MOV = 4 +ALU_SEL_LSH = 5 +ALU_SEL_RSH = 6 +SUB_OPCODE_ALU_CNT = 2 +ALU_SEL_INC = 0 +ALU_SEL_DEC = 1 +ALU_SEL_RST = 2 + +OPCODE_BRANCH = 8 +SUB_OPCODE_BX = 0 +BX_JUMP_TYPE_DIRECT = 0 +BX_JUMP_TYPE_ZERO = 1 +BX_JUMP_TYPE_OVF = 2 +SUB_OPCODE_B = 1 +B_CMP_L = 0 +B_CMP_GE = 1 +SUB_OPCODE_BC = 2 +BC_CMP_LT = 0 +BC_CMP_GT = 1 +BC_CMP_EQ = 2 + +OPCODE_END = 9 +SUB_OPCODE_END = 0 +SUB_OPCODE_SLEEP = 1 + +OPCODE_TSENS = 10 + +OPCODE_HALT = 11 + +OPCODE_LD = 13 + + +def make_ins_struct_def(layout): + lines = layout.strip().splitlines() + pos = 0 # bitfield definitions start from lsb + struct_def = {} + for line in lines: + bitfield = line.split('#', 1)[0] # get rid of comment + name, width = bitfield.split(':', 1) + name = name.strip() + width = int(width.strip()) + struct_def[name] = BFUINT32 | pos << BF_POS | width << BF_LEN + pos += width + if pos != 32: + raise ValueError('make_ins: bit field widths must sum up to 32. [%s]' % layout) + struct_def['all'] = UINT32 + return struct_def + + +def make_ins(layout): + """ + transform textual instruction layout description into a ready-to-use uctypes struct + """ + struct_def = make_ins_struct_def(layout) + instruction = bytearray(4) + return struct(addressof(instruction), struct_def, LITTLE_ENDIAN) + + +# instruction structure definitions + +_wr_reg = make_ins(""" + addr : 8 # Address within either RTC_CNTL, RTC_IO, or SARADC + periph_sel : 2 # Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) + data : 8 # 8 bits of data to write + low : 5 # Low bit + high : 5 # High bit + opcode : 4 # Opcode (OPCODE_WR_REG) +""") + + +_rd_reg = make_ins(""" + addr : 8 # Address within either RTC_CNTL, RTC_IO, or SARADC + periph_sel : 2 # Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) + unused : 8 # Unused + low : 5 # Low bit + high : 5 # High bit + opcode : 4 # Opcode (OPCODE_WR_REG) +""") + + +_i2c = make_ins(""" + sub_addr : 8 # address within I2C slave + data : 8 # Data to write (not used for read) + low : 3 # low bit + high : 3 # high bit + i2c_sel : 4 # select i2c slave via SENS_I2C_SLAVE_ADDRx + unused : 1 # Unused + rw : 1 # Write (1) or read (0) + opcode : 4 # Opcode (OPCODE_I2C) +""") + + +_delay = make_ins(""" + cycles : 16 # Number of cycles to sleep + unused : 12 # Unused + opcode : 4 # Opcode (OPCODE_DELAY) +""") + + +_tsens = make_ins(""" + dreg : 2 # Register where to store TSENS result + delay : 14 # Number of cycles needed to obtain a measurement + unused : 12 # Unused + opcode : 4 # Opcode (OPCODE_TSENS) +""") + + +_adc = make_ins(""" + dreg : 2 # Register where to store ADC result + mux : 4 # Select SARADC pad (mux + 1) + sar_sel : 1 # Select SARADC0 (0) or SARADC1 (1) + unused1 : 1 # Unused + cycles : 16 # TBD, cycles used for measurement + unused2 : 4 # Unused + opcode: 4 # Opcode (OPCODE_ADC) +""") + + +_st = make_ins(""" + sreg : 2 # Register which contains data to store + dreg : 2 # Register which contains address in RTC memory (expressed in words) + unused1 : 6 # Unused + offset : 11 # Offset to add to dreg + unused2 : 4 # Unused + sub_opcode : 3 # Sub opcode (SUB_OPCODE_ST) + opcode : 4 # Opcode (OPCODE_ST) +""") + + +_alu_reg = make_ins(""" + dreg : 2 # Destination register + sreg : 2 # Register with operand A + treg : 2 # Register with operand B + unused : 15 # Unused + sel : 4 # Operation to perform, one of ALU_SEL_xxx + sub_opcode : 3 # Sub opcode (SUB_OPCODE_ALU_REG) + opcode : 4 # Opcode (OPCODE_ALU) +""") + + +_alu_imm = make_ins(""" + dreg : 2 # Destination register + sreg : 2 # Register with operand A + imm : 16 # Immediate value of operand B + unused : 1 # Unused + sel : 4 # Operation to perform, one of ALU_SEL_xxx + sub_opcode : 3 # Sub opcode (SUB_OPCODE_ALU_IMM) + opcode : 4 # Opcode (OPCODE_ALU) +""") + + +_alu_cnt = make_ins(""" + unused1 : 4 # Unused + imm : 8 # Immediate value (to inc / dec stage counter) + unused2 : 9 # Unused + sel : 4 # Operation to perform, one of ALU_SEL_xxx + sub_opcode : 3 # Sub opcode (SUB_OPCODE_ALU_CNT) + opcode : 4 # Opcode (OPCODE_ALU) +""") + + +_bx = make_ins(""" + dreg : 2 # Register which contains target PC, expressed in words (used if .reg == 1) + addr : 11 # Target PC, expressed in words (used if .reg == 0) + unused : 8 # Unused + reg : 1 # Target PC in register (1) or immediate (0) + type : 3 # Jump condition (BX_JUMP_TYPE_xxx) + sub_opcode : 3 # Sub opcode (SUB_OPCODE_BX) + opcode : 4 # Opcode (OPCODE_BRANCH) +""") + + +_b = make_ins(""" + imm : 16 # Immediate value to compare against + cmp : 1 # Comparison to perform: B_CMP_L or B_CMP_GE + offset : 7 # Absolute value of target PC offset w.r.t. current PC, expressed in words + sign : 1 # Sign of target PC offset: 0: positive, 1: negative + sub_opcode : 3 # Sub opcode (SUB_OPCODE_B) + opcode : 4 # Opcode (OPCODE_BRANCH) +""") + + +_bc = make_ins(""" + imm : 8 # Immediate value to compare against + unused : 7 # Unused + cmp : 2 # Comparison to perform: BC_CMP_LT, GT or EQ + offset : 7 # Absolute value of target PC offset w.r.t. current PC, expressed in words + sign : 1 # Sign of target PC offset: 0: positive, 1: negative + sub_opcode : 3 # Sub opcode (SUB_OPCODE_BC) + opcode : 4 # Opcode (OPCODE_BRANCH) +""") + + +_end = make_ins(""" + wakeup : 1 # Set to 1 to wake up chip + unused : 24 # Unused + sub_opcode : 3 # Sub opcode (SUB_OPCODE_END) + opcode : 4 # Opcode (OPCODE_END) +""") + + +_sleep = make_ins(""" + cycle_sel : 4 # Select which one of SARADC_ULP_CP_SLEEP_CYCx_REG to get the sleep duration from + unused : 21 # Unused + sub_opcode : 3 # Sub opcode (SUB_OPCODE_SLEEP) + opcode : 4 # Opcode (OPCODE_END) +""") + + +_halt = make_ins(""" + unused : 28 # Unused + opcode : 4 # Opcode (OPCODE_HALT) +""") + + +_ld = make_ins(""" + dreg : 2 # Register where the data should be loaded to + sreg : 2 # Register which contains address in RTC memory (expressed in words) + unused1 : 6 # Unused + offset : 11 # Offset to add to sreg + unused2 : 7 # Unused + opcode : 4 # Opcode (OPCODE_LD) +""") + + +# assembler opcode definitions + +REG, IMM, COND, SYM = 0, 1, 2, 3 +ARG = namedtuple('ARG', ('type', 'value', 'raw')) + + +def arg_qualify(arg): + """ + look at arg and qualify its type: + REG(ister), IMM(ediate) value + + then convert arg into a int value, e.g. 'R1' -> 1 or '0x20' -> 32. + + return result as ARG namedtuple + """ + arg_lower = arg.lower() + if len(arg) == 2: + if arg_lower[0] == 'r' and arg[1] in '0123456789': + reg = int(arg[1]) + if 0 <= reg <= 3: + return ARG(REG, reg, arg) + raise ValueError('arg_qualify: valid registers are r0, r1, r2, r3. Given: %s' % arg) + if arg_lower in ['--', 'eq', 'ov', 'lt', 'gt', 'ge']: + return ARG(COND, arg_lower, arg) + try: + return ARG(IMM, int(arg), arg) + except ValueError: + pass + entry = symbols.get_sym(arg) + return ARG(SYM, entry, arg) + + +def get_reg(arg): + if isinstance(arg, str): + arg = arg_qualify(arg) + if arg.type == REG: + return arg.value + raise TypeError('wanted: register, got: %s' % arg.raw) + + +def get_imm(arg): + if isinstance(arg, str): + arg = arg_qualify(arg) + if arg.type == IMM: + return arg.value + if arg.type == SYM: + return symbols.resolve_absolute(arg.value) + raise TypeError('wanted: immediate, got: %s' % arg.raw) + + +get_abs = get_imm + + +def get_rel(arg): + if isinstance(arg, str): + arg = arg_qualify(arg) + if arg.type == IMM: + return arg.value + if arg.type == SYM: + return symbols.resolve_relative(arg.value) + raise TypeError('wanted: immediate, got: %s' % arg.raw) + + +def get_cond(arg): + if isinstance(arg, str): + arg = arg_qualify(arg) + if arg.type == COND: + return arg.value + raise TypeError('wanted: condition, got: %s' % arg.raw) + + +def _soc_reg_to_ulp_periph_sel(reg): + # Map SoC peripheral register to periph_sel field of RD_REG and WR_REG instructions. + ret = 3 + if reg < DR_REG_RTCCNTL_BASE: + raise ValueError("invalid register base") + elif reg < DR_REG_RTCIO_BASE: + ret = RD_REG_PERIPH_RTC_CNTL + elif reg < DR_REG_SENS_BASE: + ret = RD_REG_PERIPH_RTC_IO + elif reg < DR_REG_RTC_I2C_BASE: + ret = RD_REG_PERIPH_SENS + elif reg < DR_REG_IO_MUX_BASE: + ret = RD_REG_PERIPH_RTC_I2C + else: + raise ValueError("invalid register base") + return ret + + +def i_reg_wr(reg, high_bit, low_bit, val): + reg = get_imm(reg) + _wr_reg.addr = (reg & 0xff) >> 2 + _wr_reg.periph_sel = _soc_reg_to_ulp_periph_sel(reg) + _wr_reg.data = get_imm(val) + _wr_reg.low = get_imm(low_bit) + _wr_reg.high = get_imm(high_bit) + _wr_reg.opcode = OPCODE_WR_REG + return _wr_reg.all + + +def i_reg_rd(reg, high_bit, low_bit): + reg = get_imm(reg) + _rd_reg.addr = (reg & 0xff) >> 2 + _rd_reg.periph_sel = _soc_reg_to_ulp_periph_sel(reg) + _rd_reg.unused = 0 + _rd_reg.low = get_imm(low_bit) + _rd_reg.high = get_imm(high_bit) + _rd_reg.opcode = OPCODE_RD_REG + return _rd_reg.all + + +def i_i2c_rd(sub_addr, high_bit, low_bit, slave_sel): + _i2c.sub_addr = get_imm(sub_addr) + _i2c.data = 0 + _i2c.low = get_imm(low_bit) + _i2c.high = get_imm(high_bit) + _i2c.i2c_sel = get_imm(slave_sel) + _i2c.unused = 0 + _i2c.rw = 0 + _i2c.opcode = OPCODE_I2C + return _i2c.all + + +def i_i2c_wr(sub_addr, value, high_bit, low_bit, slave_sel): + _i2c.sub_addr = get_imm(sub_addr) + _i2c.data = get_imm(value) + _i2c.low = get_imm(low_bit) + _i2c.high = get_imm(high_bit) + _i2c.i2c_sel = get_imm(slave_sel) + _i2c.unused = 0 + _i2c.rw = 1 + _i2c.opcode = OPCODE_I2C + return _i2c.all + + +def i_nop(): + _delay.cycles = 0 + _delay.unused = 0 + _delay.opcode = OPCODE_DELAY + return _delay.all + + +def i_wait(cycles): + _delay.cycles = get_imm(cycles) + _delay.unused = 0 + _delay.opcode = OPCODE_DELAY + return _delay.all + + +def i_tsens(reg_dest, delay): + _tsens.dreg = get_reg(reg_dest) + _tsens.delay = get_imm(delay) + _tsens.unused = 0 + _tsens.opcode = OPCODE_TSENS + return _tsens.all + + +def i_adc(reg_dest, adc_idx, mux): + _adc.dreg = get_reg(reg_dest) + _adc.mux = get_imm(mux) + _adc.sar_sel = get_imm(adc_idx) + _adc.unused1 = 0 + _adc.cycles = 0 + _adc.unused2 = 0 + _adc.opcode = OPCODE_ADC + return _adc.all + + +def i_st(reg_val, reg_addr, offset): + _st.dreg = get_reg(reg_addr) + _st.sreg = get_reg(reg_val) + _st.unused1 = 0 + _st.offset = get_imm(offset) // 4 + _st.unused2 = 0 + _st.sub_opcode = SUB_OPCODE_ST + _st.opcode = OPCODE_ST + return _st.all + + +def i_halt(): + _halt.unused = 0 + _halt.opcode = OPCODE_HALT + return _halt.all + + +def i_ld(reg_dest, reg_addr, offset): + _ld.dreg = get_reg(reg_dest) + _ld.sreg = get_reg(reg_addr) + _ld.unused1 = 0 + _ld.offset = get_imm(offset) // 4 + _ld.unused2 = 0 + _ld.opcode = OPCODE_LD + return _ld.all + + +def i_move(reg_dest, reg_imm_src): + # this is the only ALU instruction with 2 args: move r0, r1 + dest = get_reg(reg_dest) + src = arg_qualify(reg_imm_src) + if src.type == REG: + _alu_reg.dreg = dest + _alu_reg.sreg = src.value + _alu_reg.treg = 1 # XXX undocumented, this is the value binutils-esp32 uses + _alu_reg.unused = 0 + _alu_reg.sel = ALU_SEL_MOV + _alu_reg.sub_opcode = SUB_OPCODE_ALU_REG + _alu_reg.opcode = OPCODE_ALU + return _alu_reg.all + if src.type == IMM or src.type == SYM: + _alu_imm.dreg = dest + _alu_imm.sreg = 0 + _alu_imm.imm = get_abs(src) + _alu_imm.unused = 0 + _alu_imm.sel = ALU_SEL_MOV + _alu_imm.sub_opcode = SUB_OPCODE_ALU_IMM + _alu_imm.opcode = OPCODE_ALU + return _alu_imm.all + raise TypeError('unsupported operand: %s' % src.raw) + + +def _alu3(reg_dest, reg_src1, reg_imm_src2, alu_sel): + """ + ALU instructions with 3 args, like e.g. add r1, r2, r3 + """ + dest = get_reg(reg_dest) + src1 = get_reg(reg_src1) + src2 = arg_qualify(reg_imm_src2) + if src2.type == REG: + _alu_reg.dreg = dest + _alu_reg.sreg = src1 + _alu_reg.treg = src2.value + _alu_reg.unused = 0 + _alu_reg.sel = alu_sel + _alu_reg.sub_opcode = SUB_OPCODE_ALU_REG + _alu_reg.opcode = OPCODE_ALU + return _alu_reg.all + if src2.type == IMM or src2.type == SYM: + _alu_imm.dreg = dest + _alu_imm.sreg = src1 + _alu_imm.imm = get_abs(src2) + _alu_imm.unused = 0 + _alu_imm.sel = alu_sel + _alu_imm.sub_opcode = SUB_OPCODE_ALU_IMM + _alu_imm.opcode = OPCODE_ALU + return _alu_imm.all + raise TypeError('unsupported operand: %s' % src2.raw) + + +def i_add(reg_dest, reg_src1, reg_imm_src2): + return _alu3(reg_dest, reg_src1, reg_imm_src2, ALU_SEL_ADD) + + +def i_sub(reg_dest, reg_src1, reg_imm_src2): + return _alu3(reg_dest, reg_src1, reg_imm_src2, ALU_SEL_SUB) + + +def i_and(reg_dest, reg_src1, reg_imm_src2): + return _alu3(reg_dest, reg_src1, reg_imm_src2, ALU_SEL_AND) + + +def i_or(reg_dest, reg_src1, reg_imm_src2): + return _alu3(reg_dest, reg_src1, reg_imm_src2, ALU_SEL_OR) + + +def i_lsh(reg_dest, reg_src1, reg_imm_src2): + return _alu3(reg_dest, reg_src1, reg_imm_src2, ALU_SEL_LSH) + + +def i_rsh(reg_dest, reg_src1, reg_imm_src2): + return _alu3(reg_dest, reg_src1, reg_imm_src2, ALU_SEL_RSH) + + +def _alu_stage(imm, alu_sel): + """ + Stage counter instructions with 1 arg: stage_inc / stage_dec + """ + imm = get_imm(imm) + _alu_cnt.unused1 = 0 + _alu_cnt.imm = imm + _alu_cnt.unused2 = 0 + _alu_cnt.sel = alu_sel + _alu_cnt.sub_opcode = SUB_OPCODE_ALU_CNT + _alu_cnt.opcode = OPCODE_ALU + return _alu_cnt.all + + +def i_stage_inc(imm): + return _alu_stage(imm, ALU_SEL_INC) + + +def i_stage_dec(imm): + return _alu_stage(imm, ALU_SEL_DEC) + + +def i_stage_rst(): + return _alu_stage('0', ALU_SEL_RST) + + +def i_wake(): + _end.wakeup = 1 + _end.unused = 0 + _end.sub_opcode = SUB_OPCODE_END + _end.opcode = OPCODE_END + return _end.all + + +def i_sleep(timer_idx): + _sleep.cycle_sel = get_imm(timer_idx) + _sleep.unused = 0 + _sleep.sub_opcode = SUB_OPCODE_SLEEP + _sleep.opcode = OPCODE_END + return _sleep.all + + +def i_jump(target, condition='--'): + target = arg_qualify(target) + condition = get_cond(condition) + if condition == 'eq': + jump_type = BX_JUMP_TYPE_ZERO + elif condition == 'ov': + jump_type = BX_JUMP_TYPE_OVF + elif condition == '--': # means unconditional + jump_type = BX_JUMP_TYPE_DIRECT + else: + raise ValueError("invalid flags condition") + if target.type == IMM or target.type == SYM: + _bx.dreg = 0 + _bx.addr = get_abs(target) + _bx.unused = 0 + _bx.reg = 0 + _bx.type = jump_type + _bx.sub_opcode = SUB_OPCODE_BX + _bx.opcode = OPCODE_BRANCH + return _bx.all + if target.type == REG: + _bx.dreg = target.value + _bx.addr = 0 + _bx.unused = 0 + _bx.reg = 1 + _bx.type = jump_type + _bx.sub_opcode = SUB_OPCODE_BX + _bx.opcode = OPCODE_BRANCH + return _bx.all + raise TypeError('unsupported operand: %s' % target.raw) + + +def i_jumpr(offset, threshold, condition): + offset = get_rel(offset) + threshold = get_imm(threshold) + condition = get_cond(condition) + if condition == 'lt': + cmp_op = B_CMP_L + elif condition == 'ge': + cmp_op = B_CMP_GE + else: + raise ValueError("invalid comparison condition") + _b.imm = threshold + _b.cmp = cmp_op + _b.offset = abs(offset) + _b.sign = 0 if offset >= 0 else 1 + _b.sub_opcode = SUB_OPCODE_B + _b.opcode = OPCODE_BRANCH + return _b.all + + +def i_jumps(offset, threshold, condition): + offset = get_rel(offset) + threshold = get_imm(threshold) + condition = get_cond(condition) + if condition == 'lt': + cmp_op = BC_CMP_LT + elif condition == 'gt': + cmp_op = BC_CMP_GT + elif condition == 'eq': + cmp_op = BC_CMP_EQ + else: + raise ValueError("invalid comparison condition") + _bc.imm = threshold + _bc.cmp = cmp_op + _bc.offset = abs(offset) + _bc.sign = 0 if offset >= 0 else 1 + _bc.sub_opcode = SUB_OPCODE_BC + _bc.opcode = OPCODE_BRANCH + return _bc.all diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/soc.py b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/soc.py new file mode 100644 index 00000000..c6072e6c --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/soc.py @@ -0,0 +1,59 @@ +""" +Address / Register definitions for the ESP32 SoC +""" + +DR_REG_DPORT_BASE = 0x3ff00000 +DR_REG_AES_BASE = 0x3ff01000 +DR_REG_RSA_BASE = 0x3ff02000 +DR_REG_SHA_BASE = 0x3ff03000 +DR_REG_FLASH_MMU_TABLE_PRO = 0x3ff10000 +DR_REG_FLASH_MMU_TABLE_APP = 0x3ff12000 +DR_REG_DPORT_END = 0x3ff13FFC +DR_REG_UART_BASE = 0x3ff40000 +DR_REG_SPI1_BASE = 0x3ff42000 +DR_REG_SPI0_BASE = 0x3ff43000 +DR_REG_GPIO_BASE = 0x3ff44000 +DR_REG_GPIO_SD_BASE = 0x3ff44f00 +DR_REG_FE2_BASE = 0x3ff45000 +DR_REG_FE_BASE = 0x3ff46000 +DR_REG_FRC_TIMER_BASE = 0x3ff47000 +DR_REG_RTCCNTL_BASE = 0x3ff48000 +DR_REG_RTCIO_BASE = 0x3ff48400 +DR_REG_SENS_BASE = 0x3ff48800 +DR_REG_RTC_I2C_BASE = 0x3ff48C00 +DR_REG_IO_MUX_BASE = 0x3ff49000 +DR_REG_HINF_BASE = 0x3ff4B000 +DR_REG_UHCI1_BASE = 0x3ff4C000 +DR_REG_I2S_BASE = 0x3ff4F000 +DR_REG_UART1_BASE = 0x3ff50000 +DR_REG_BT_BASE = 0x3ff51000 +DR_REG_I2C_EXT_BASE = 0x3ff53000 +DR_REG_UHCI0_BASE = 0x3ff54000 +DR_REG_SLCHOST_BASE = 0x3ff55000 +DR_REG_RMT_BASE = 0x3ff56000 +DR_REG_PCNT_BASE = 0x3ff57000 +DR_REG_SLC_BASE = 0x3ff58000 +DR_REG_LEDC_BASE = 0x3ff59000 +DR_REG_EFUSE_BASE = 0x3ff5A000 +DR_REG_SPI_ENCRYPT_BASE = 0x3ff5B000 +DR_REG_NRX_BASE = 0x3ff5CC00 +DR_REG_BB_BASE = 0x3ff5D000 +DR_REG_PWM_BASE = 0x3ff5E000 +DR_REG_TIMERGROUP0_BASE = 0x3ff5F000 +DR_REG_TIMERGROUP1_BASE = 0x3ff60000 +DR_REG_RTCMEM0_BASE = 0x3ff61000 +DR_REG_RTCMEM1_BASE = 0x3ff62000 +DR_REG_RTCMEM2_BASE = 0x3ff63000 +DR_REG_SPI2_BASE = 0x3ff64000 +DR_REG_SPI3_BASE = 0x3ff65000 +DR_REG_SYSCON_BASE = 0x3ff66000 +DR_REG_APB_CTRL_BASE = 0x3ff66000 +DR_REG_I2C1_EXT_BASE = 0x3ff67000 +DR_REG_SDMMC_BASE = 0x3ff68000 +DR_REG_EMAC_BASE = 0x3ff69000 +DR_REG_PWM1_BASE = 0x3ff6C000 +DR_REG_I2S1_BASE = 0x3ff6D000 +DR_REG_UART2_BASE = 0x3ff6E000 +DR_REG_PWM2_BASE = 0x3ff6F000 +DR_REG_PWM3_BASE = 0x3ff70000 + diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/util.py b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/util.py new file mode 100644 index 00000000..c1844147 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/util.py @@ -0,0 +1,11 @@ +DEBUG = False + +import gc + + +def garbage_collect(msg, verbose=DEBUG): + free_before = gc.mem_free() + gc.collect() + free_after = gc.mem_free() + if verbose: + print("%s: %d --gc--> %d bytes free" % (msg, free_before, free_after)) diff --git a/MicroPython_BUILD/components/micropython/esp32/ulp.h b/MicroPython_BUILD/components/micropython/esp32/ulp.h new file mode 100644 index 00000000..6960ac97 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/ulp.h @@ -0,0 +1,917 @@ +// Copyright 2016-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#include +#include +#include "esp_err.h" +#include "soc/soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ULP_FSM_PREPARE_SLEEP_CYCLES 2 /*!< Cycles spent by FSM preparing ULP for sleep */ +#define ULP_FSM_WAKEUP_SLEEP_CYCLES 2 /*!< Cycles spent by FSM waking up ULP from sleep */ + +/** + * @defgroup ulp_registers ULP coprocessor registers + * @{ + */ + + +#define R0 0 /*!< general purpose register 0 */ +#define R1 1 /*!< general purpose register 1 */ +#define R2 2 /*!< general purpose register 2 */ +#define R3 3 /*!< general purpose register 3 */ +/**@}*/ + +/** @defgroup ulp_opcodes ULP coprocessor opcodes, sub opcodes, and various modifiers/flags + * + * These definitions are not intended to be used directly. + * They are used in definitions of instructions later on. + * + * @{ + */ + +#define OPCODE_WR_REG 1 /*!< Instruction: write peripheral register (RTC_CNTL/RTC_IO/SARADC) (not implemented yet) */ + +#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_SENS 2 /*!< Identifier of SARADC peripheral for RD_REG and WR_REG instructions */ +#define RD_REG_PERIPH_RTC_I2C 3 /*!< Identifier of RTC_I2C 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 */ + +#define OPCODE_ADC 5 /*!< Instruction: SAR ADC measurement (not implemented yet) */ + +#define OPCODE_ST 6 /*!< Instruction: store indirect to RTC memory */ +#define SUB_OPCODE_ST 4 /*!< Store 32 bits, 16 MSBs contain PC, 16 LSBs contain value from source register */ + +#define OPCODE_ALU 7 /*!< Arithmetic instructions */ +#define SUB_OPCODE_ALU_REG 0 /*!< Arithmetic instruction, both source values are in register */ +#define SUB_OPCODE_ALU_IMM 1 /*!< Arithmetic instruction, one source value is an immediate */ +#define SUB_OPCODE_ALU_CNT 2 /*!< Arithmetic instruction between counter register and an immediate (not implemented yet)*/ +#define ALU_SEL_ADD 0 /*!< Addition */ +#define ALU_SEL_SUB 1 /*!< Subtraction */ +#define ALU_SEL_AND 2 /*!< Logical AND */ +#define ALU_SEL_OR 3 /*!< Logical OR */ +#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 */ + +#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 */ +#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 OPCODE_END 9 /*!< Stop executing the program */ +#define SUB_OPCODE_END 0 /*!< Stop executing the program and optionally wake up the chip */ +#define SUB_OPCODE_SLEEP 1 /*!< Stop executing the program and run it again after selected interval */ + +#define OPCODE_TSENS 10 /*!< Instruction: temperature sensor measurement (not implemented yet) */ + +#define OPCODE_HALT 11 /*!< Halt the coprocessor */ + +#define OPCODE_LD 13 /*!< Indirect load lower 16 bits from RTC memory */ + +#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 */ +/**@}*/ + +/**@{*/ +#define ESP_ERR_ULP_BASE 0x1200 /*!< Offset for ULP-related error codes */ +#define ESP_ERR_ULP_SIZE_TOO_BIG (ESP_ERR_ULP_BASE + 1) /*!< Program doesn't fit into RTC memory reserved for the ULP */ +#define ESP_ERR_ULP_INVALID_LOAD_ADDR (ESP_ERR_ULP_BASE + 2) /*!< Load address is outside of RTC memory reserved for the ULP */ +#define ESP_ERR_ULP_DUPLICATE_LABEL (ESP_ERR_ULP_BASE + 3) /*!< More than one label with the same number was defined */ +#define ESP_ERR_ULP_UNDEFINED_LABEL (ESP_ERR_ULP_BASE + 4) /*!< Branch instructions references an undefined label */ +#define ESP_ERR_ULP_BRANCH_OUT_OF_RANGE (ESP_ERR_ULP_BASE + 5) /*!< Branch target is out of range of B instruction (try replacing with BX) */ +/**@}*/ + + +/** + * @brief Instruction format structure + * + * All ULP instructions are 32 bit long. + * This union contains field layouts used by all of the supported instructions. + * This union also includes a special "macro" instruction layout. + * This is not a real instruction which can be executed by the CPU. It acts + * as a token which is removed from the program by the + * ulp_process_macros_and_load function. + * + * These structures are not intended to be used directly. + * Preprocessor definitions provided below fill the fields of these structure with + * the right arguments. + */ +typedef union { + + struct { + uint32_t cycles : 16; /*!< Number of cycles to sleep */ + uint32_t unused : 12; /*!< Unused */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_DELAY) */ + } delay; /*!< Format of DELAY instruction */ + + 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) */ + uint32_t unused1 : 6; /*!< Unused */ + uint32_t offset : 11; /*!< Offset to add to sreg */ + uint32_t unused2 : 4; /*!< Unused */ + uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ST) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_ST) */ + } st; /*!< Format of ST instruction */ + + 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 : 7; /*!< Unused */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_LD) */ + } ld; /*!< Format of LD instruction */ + + struct { + uint32_t unused : 28; /*!< Unused */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_HALT) */ + } halt; /*!< Format of HALT instruction */ + + 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 sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_BX) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */ + } bx; /*!< Format of BRANCH instruction (absolute address) */ + + struct { + uint32_t imm : 16; /*!< Immediate value to compare against */ + uint32_t cmp : 1; /*!< 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 : 3; /*!< Sub opcode (SUB_OPCODE_B) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */ + } b; /*!< Format of BRANCH instruction (relative address) */ + + 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 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) */ + + 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 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) */ + + struct { + 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 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 */ + + struct { + 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 low : 5; /*!< Low bit */ + uint32_t high : 5; /*!< High bit */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_WR_REG) */ + } rd_reg; /*!< Format of RD_REG instruction */ + + 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 unused1 : 1; /*!< Unused */ + uint32_t cycles : 16; /*!< TBD, cycles used for measurement */ + uint32_t unused2 : 4; /*!< Unused */ + uint32_t opcode: 4; /*!< Opcode (OPCODE_ADC) */ + } adc; /*!< Format of ADC instruction */ + + struct { + uint32_t dreg : 2; /*!< Register where to store temperature measurement result */ + uint32_t wait_delay: 14; /*!< Cycles to wait after measurement is done */ + uint32_t reserved: 12; /*!< Reserved, set to 0 */ + uint32_t opcode: 4; /*!< Opcode (OPCODE_TSENS) */ + } tsens; /*!< Format of TSENS instruction */ + + struct { + uint32_t i2c_addr : 8; /*!< I2C slave address */ + uint32_t data : 8; /*!< Data to read or write */ + uint32_t low_bits : 3; /*!< TBD */ + uint32_t high_bits : 3; /*!< TBD */ + uint32_t i2c_sel : 4; /*!< TBD, select reg_i2c_slave_address[7:0] */ + uint32_t unused : 1; /*!< Unused */ + uint32_t rw : 1; /*!< Write (1) or read (0) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_I2C) */ + } i2c; /*!< Format of I2C instruction */ + + struct { + uint32_t wakeup : 1; /*!< Set to 1 to wake up chip */ + uint32_t unused : 24; /*!< Unused */ + uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_WAKEUP) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */ + } end; /*!< Format of END instruction with wakeup */ + + struct { + uint32_t cycle_sel : 4; /*!< Select which one of SARADC_ULP_CP_SLEEP_CYCx_REG to get the sleep duration from */ + uint32_t unused : 21; /*!< Unused */ + uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_SLEEP) */ + uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */ + } sleep; /*!< Format of END instruction with sleep */ + + struct { + uint32_t label : 16; /*!< Label number */ + uint32_t unused : 8; /*!< Unused */ + uint32_t sub_opcode : 4; /*!< SUB_OPCODE_MACRO_LABEL or SUB_OPCODE_MACRO_BRANCH */ + uint32_t opcode: 4; /*!< Opcode (OPCODE_MACRO) */ + } macro; /*!< Format of tokens used by LABEL and BRANCH macros */ + +} 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 + */ +#define I_DELAY(cycles_) { .delay = {\ + .cycles = cycles_, \ + .unused = 0, \ + .opcode = OPCODE_DELAY } } + +/** + * Halt the coprocessor. + * + * This instruction halts the coprocessor, but keeps ULP timer active. + * As such, ULP program will be restarted again by timer. + * To stop the program and prevent the timer from restarting the program, + * use I_END(0) instruction. + */ +#define I_HALT() { .halt = {\ + .unused = 0, \ + .opcode = OPCODE_HALT } } + +/** + * Map SoC peripheral register to periph_sel field of RD_REG and WR_REG + * instructions. + * + * @param reg peripheral register in RTC_CNTL_, RTC_IO_, SENS_, RTC_I2C peripherals. + * @return periph_sel value for the peripheral to which this register belongs. + */ +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 = RD_REG_PERIPH_RTC_CNTL; + } else if (reg < DR_REG_SENS_BASE) { + ret = RD_REG_PERIPH_RTC_IO; + } else if (reg < DR_REG_RTC_I2C_BASE){ + ret = RD_REG_PERIPH_SENS; + } else if (reg < DR_REG_IO_MUX_BASE){ + ret = RD_REG_PERIPH_RTC_I2C; + } else { + assert(0 && "invalid register base"); + } + return ret; +} + +/** + * Write literal value to a peripheral register + * + * reg[high_bit : low_bit] = val + * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers. + */ +#define I_WR_REG(reg, low_bit, high_bit, val) {.wr_reg = {\ + .addr = (reg & 0xff) / sizeof(uint32_t), \ + .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] + * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers. + */ +#define I_RD_REG(reg, low_bit, high_bit) {.rd_reg = {\ + .addr = (reg & 0xff) / sizeof(uint32_t), \ + .periph_sel = SOC_REG_TO_ULP_PERIPH_SEL(reg), \ + .unused = 0, \ + .low = low_bit, \ + .high = high_bit, \ + .opcode = OPCODE_RD_REG } } + +/** + * Set or clear a bit in the peripheral register. + * + * Sets bit (1 << shift) of register reg to value val. + * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers. + */ +#define I_WR_REG_BIT(reg, shift, val) I_WR_REG(reg, shift, shift, val) + +/** + * Wake the SoC from deep sleep. + * + * This instruction initiates wake up from deep sleep. + * Use esp_deep_sleep_enable_ulp_wakeup to enable deep sleep wakeup + * triggered by the ULP before going into deep sleep. + * Note that ULP program will still keep running until the I_HALT + * instruction, and it will still be restarted by timer at regular + * intervals, even when the SoC is woken up. + * + * To stop the ULP program, use I_HALT instruction. + * + * To disable the timer which start ULP program, use I_END() + * instruction. I_END instruction clears the + * RTC_CNTL_ULP_CP_SLP_TIMER_EN_S bit of RTC_CNTL_STATE0_REG + * register, which controls the ULP timer. + */ +#define I_WAKE() { .end = { \ + .wakeup = 1, \ + .unused = 0, \ + .sub_opcode = SUB_OPCODE_END, \ + .opcode = OPCODE_END } } + +/** + * Stop ULP program timer. + * + * This is a convenience macro which disables the ULP program timer. + * Once this instruction is used, ULP program will not be restarted + * anymore until ulp_run function is called. + * + * ULP program will continue running after this instruction. To stop + * the currently running program, use I_HALT(). + */ +#define I_END() \ + I_WR_REG_BIT(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN_S, 0) +/** + * Select the time interval used to run ULP program. + * + * This instructions selects which of the SENS_SLEEP_CYCLES_Sx + * registers' value is used by the ULP program timer. + * When the ULP program stops at I_HALT instruction, ULP program + * timer start counting. When the counter reaches the value of + * the selected SENS_SLEEP_CYCLES_Sx register, ULP program + * start running again from the start address (passed to the ulp_run + * function). + * There are 5 SENS_SLEEP_CYCLES_Sx registers, so 0 <= timer_idx < 5. + * + * By default, SENS_SLEEP_CYCLES_S0 register is used by the ULP + * program timer. + */ +#define I_SLEEP_CYCLE_SEL(timer_idx) { .sleep = { \ + .cycle_sel = timer_idx, \ + .unused = 0, \ + .sub_opcode = SUB_OPCODE_SLEEP, \ + .opcode = OPCODE_END } } + +/** + * Perform temperature sensor measurement and store it into reg_dest. + * + * Delay can be set between 1 and ((1 << 14) - 1). Higher values give + * higher measurement resolution. + */ +#define I_TSENS(reg_dest, delay) { .tsens = { \ + .dreg = reg_dest, \ + .wait_delay = delay, \ + .reserved = 0, \ + .opcode = OPCODE_TSENS } } + +/** + * Perform ADC measurement and store result in reg_dest. + * + * adc_idx selects ADC (0 or 1). + * pad_idx selects ADC pad (0 - 7). + */ +#define I_ADC(reg_dest, adc_idx, pad_idx) { .adc = {\ + .dreg = reg_dest, \ + .mux = pad_idx + 1, \ + .sar_sel = adc_idx, \ + .unused1 = 0, \ + .cycles = 0, \ + .unused2 = 0, \ + .opcode = OPCODE_ADC } } + +/** + * Store value from register reg_val into RTC memory. + * + * The value is written to an offset calculated by adding value of + * reg_addr register and offset_ field (this offset is expressed in 32-bit words). + * 32 bits written to RTC memory are built as follows: + * - bits [31:21] hold the PC of current instruction, expressed in 32-bit words + * - bits [20:16] = 5'b1 + * - bits [15:0] are assigned the contents of reg_val + * + * RTC_SLOW_MEM[addr + offset_] = { 5'b0, insn_PC[10:0], val[15:0] } + */ +#define I_ST(reg_val, reg_addr, offset_) { .st = { \ + .dreg = reg_val, \ + .sreg = reg_addr, \ + .unused1 = 0, \ + .offset = offset_, \ + .unused2 = 0, \ + .sub_opcode = SUB_OPCODE_ST, \ + .opcode = OPCODE_ST } } + + +/** + * Load value from RTC memory into reg_dest register. + * + * Loads 16 LSBs from RTC memory word given by the sum of value in reg_addr and + * value of offset_. + */ +#define I_LD(reg_dest, reg_addr, offset_) { .ld = { \ + .dreg = reg_dest, \ + .sreg = reg_addr, \ + .unused1 = 0, \ + .offset = offset_, \ + .unused2 = 0, \ + .opcode = OPCODE_LD } } + + +/** + * Branch relative if R0 less 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_BL(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, \ + .opcode = OPCODE_BRANCH } } + +/** + * Branch relative if R0 greater or equal 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_BGE(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 } } + +/** + * Unconditional branch to absolute PC, address in register. + * + * reg_pc is the register which contains address to jump to. + * Address is expressed in 32-bit words. + */ +#define I_BXR(reg_pc) { .bx = { \ + .dreg = reg_pc, \ + .addr = 0, \ + .unused = 0, \ + .reg = 1, \ + .type = BX_JUMP_TYPE_DIRECT, \ + .sub_opcode = SUB_OPCODE_BX, \ + .opcode = OPCODE_BRANCH } } + +/** + * Unconditional branch to absolute PC, immediate address. + * + * Address imm_pc is expressed in 32-bit words. + */ +#define I_BXI(imm_pc) { .bx = { \ + .dreg = 0, \ + .addr = imm_pc, \ + .unused = 0, \ + .reg = 0, \ + .type = BX_JUMP_TYPE_DIRECT, \ + .sub_opcode = SUB_OPCODE_BX, \ + .opcode = OPCODE_BRANCH } } + +/** + * Branch to absolute PC if ALU result is zero, address in register. + * + * reg_pc is the register which contains address to jump to. + * Address is expressed in 32-bit words. + */ +#define I_BXZR(reg_pc) { .bx = { \ + .dreg = reg_pc, \ + .addr = 0, \ + .unused = 0, \ + .reg = 1, \ + .type = BX_JUMP_TYPE_ZERO, \ + .sub_opcode = SUB_OPCODE_BX, \ + .opcode = OPCODE_BRANCH } } + +/** + * Branch to absolute PC if ALU result is zero, immediate address. + * + * Address imm_pc is expressed in 32-bit words. + */ +#define I_BXZI(imm_pc) { .bx = { \ + .dreg = 0, \ + .addr = imm_pc, \ + .unused = 0, \ + .reg = 0, \ + .type = BX_JUMP_TYPE_ZERO, \ + .sub_opcode = SUB_OPCODE_BX, \ + .opcode = OPCODE_BRANCH } } + +/** + * Branch to absolute PC if ALU overflow, address in register + * + * reg_pc is the register which contains address to jump to. + * Address is expressed in 32-bit words. + */ +#define I_BXFR(reg_pc) { .bx = { \ + .dreg = reg_pc, \ + .addr = 0, \ + .unused = 0, \ + .reg = 1, \ + .type = BX_JUMP_TYPE_OVF, \ + .sub_opcode = SUB_OPCODE_BX, \ + .opcode = OPCODE_BRANCH } } + +/** + * Branch to absolute PC if ALU overflow, immediate address + * + * Address imm_pc is expressed in 32-bit words. + */ +#define I_BXFI(imm_pc) { .bx = { \ + .dreg = 0, \ + .addr = imm_pc, \ + .unused = 0, \ + .reg = 0, \ + .type = BX_JUMP_TYPE_OVF, \ + .sub_opcode = SUB_OPCODE_BX, \ + .opcode = OPCODE_BRANCH } } + + +/** + * Addition: dest = src1 + src2 + */ +#define I_ADDR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \ + .dreg = reg_dest, \ + .sreg = reg_src1, \ + .treg = reg_src2, \ + .unused = 0, \ + .sel = ALU_SEL_ADD, \ + .sub_opcode = SUB_OPCODE_ALU_REG, \ + .opcode = OPCODE_ALU } } + +/** + * Subtraction: dest = src1 - src2 + */ +#define I_SUBR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \ + .dreg = reg_dest, \ + .sreg = reg_src1, \ + .treg = reg_src2, \ + .unused = 0, \ + .sel = ALU_SEL_SUB, \ + .sub_opcode = SUB_OPCODE_ALU_REG, \ + .opcode = OPCODE_ALU } } + +/** + * Logical AND: dest = src1 & src2 + */ +#define I_ANDR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \ + .dreg = reg_dest, \ + .sreg = reg_src1, \ + .treg = reg_src2, \ + .unused = 0, \ + .sel = ALU_SEL_AND, \ + .sub_opcode = SUB_OPCODE_ALU_REG, \ + .opcode = OPCODE_ALU } } + +/** + * Logical OR: dest = src1 | src2 + */ +#define I_ORR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \ + .dreg = reg_dest, \ + .sreg = reg_src1, \ + .treg = reg_src2, \ + .unused = 0, \ + .sel = ALU_SEL_OR, \ + .sub_opcode = SUB_OPCODE_ALU_REG, \ + .opcode = OPCODE_ALU } } + +/** + * Copy: dest = src + */ +#define I_MOVR(reg_dest, reg_src) { .alu_reg = { \ + .dreg = reg_dest, \ + .sreg = reg_src, \ + .treg = 0, \ + .unused = 0, \ + .sel = ALU_SEL_MOV, \ + .sub_opcode = SUB_OPCODE_ALU_REG, \ + .opcode = OPCODE_ALU } } + +/** + * Logical shift left: dest = src << shift + */ +#define I_LSHR(reg_dest, reg_src, reg_shift) { .alu_reg = { \ + .dreg = reg_dest, \ + .sreg = reg_src, \ + .treg = reg_shift, \ + .unused = 0, \ + .sel = ALU_SEL_LSH, \ + .sub_opcode = SUB_OPCODE_ALU_REG, \ + .opcode = OPCODE_ALU } } + + +/** + * Logical shift right: dest = src >> shift + */ +#define I_RSHR(reg_dest, reg_src, reg_shift) { .alu_reg = { \ + .dreg = reg_dest, \ + .sreg = reg_src, \ + .treg = reg_shift, \ + .unused = 0, \ + .sel = ALU_SEL_RSH, \ + .sub_opcode = SUB_OPCODE_ALU_REG, \ + .opcode = OPCODE_ALU } } + +/** + * Add register and an immediate value: dest = src1 + imm + */ +#define I_ADDI(reg_dest, reg_src, imm_) { .alu_imm = { \ + .dreg = reg_dest, \ + .sreg = reg_src, \ + .imm = imm_, \ + .unused = 0, \ + .sel = ALU_SEL_ADD, \ + .sub_opcode = SUB_OPCODE_ALU_IMM, \ + .opcode = OPCODE_ALU } } + + +/** + * Subtract register and an immediate value: dest = src - imm + */ +#define I_SUBI(reg_dest, reg_src, imm_) { .alu_imm = { \ + .dreg = reg_dest, \ + .sreg = reg_src, \ + .imm = imm_, \ + .unused = 0, \ + .sel = ALU_SEL_SUB, \ + .sub_opcode = SUB_OPCODE_ALU_IMM, \ + .opcode = OPCODE_ALU } } + +/** + * Logical AND register and an immediate value: dest = src & imm + */ +#define I_ANDI(reg_dest, reg_src, imm_) { .alu_imm = { \ + .dreg = reg_dest, \ + .sreg = reg_src, \ + .imm = imm_, \ + .unused = 0, \ + .sel = ALU_SEL_AND, \ + .sub_opcode = SUB_OPCODE_ALU_IMM, \ + .opcode = OPCODE_ALU } } + +/** + * Logical OR register and an immediate value: dest = src | imm + */ +#define I_ORI(reg_dest, reg_src, imm_) { .alu_imm = { \ + .dreg = reg_dest, \ + .sreg = reg_src, \ + .imm = imm_, \ + .unused = 0, \ + .sel = ALU_SEL_OR, \ + .sub_opcode = SUB_OPCODE_ALU_IMM, \ + .opcode = OPCODE_ALU } } + +/** + * Copy an immediate value into register: dest = imm + */ +#define I_MOVI(reg_dest, imm_) { .alu_imm = { \ + .dreg = reg_dest, \ + .sreg = 0, \ + .imm = imm_, \ + .unused = 0, \ + .sel = ALU_SEL_MOV, \ + .sub_opcode = SUB_OPCODE_ALU_IMM, \ + .opcode = OPCODE_ALU } } + +/** + * Logical shift left register value by an immediate: dest = src << imm + */ +#define I_LSHI(reg_dest, reg_src, imm_) { .alu_imm = { \ + .dreg = reg_dest, \ + .sreg = reg_src, \ + .imm = imm_, \ + .unused = 0, \ + .sel = ALU_SEL_LSH, \ + .sub_opcode = SUB_OPCODE_ALU_IMM, \ + .opcode = OPCODE_ALU } } + + +/** + * Logical shift right register value by an immediate: dest = val >> imm + */ +#define I_RSHI(reg_dest, reg_src, imm_) { .alu_imm = { \ + .dreg = reg_dest, \ + .sreg = reg_src, \ + .imm = imm_, \ + .unused = 0, \ + .sel = ALU_SEL_RSH, \ + .sub_opcode = SUB_OPCODE_ALU_IMM, \ + .opcode = OPCODE_ALU } } + +/** + * Define a label with number label_num. + * + * This is a macro which doesn't generate a real instruction. + * The token generated by this macro is removed by ulp_process_macros_and_load + * function. Label defined using this macro can be used in branch macros defined + * below. + */ +#define M_LABEL(label_num) { .macro = { \ + .label = label_num, \ + .unused = 0, \ + .sub_opcode = SUB_OPCODE_MACRO_LABEL, \ + .opcode = OPCODE_MACRO } } + +/** + * Token macro used by M_B and M_BX macros. Not to be used directly. + */ +#define M_BRANCH(label_num) { .macro = { \ + .label = label_num, \ + .unused = 0, \ + .sub_opcode = SUB_OPCODE_MACRO_BRANCH, \ + .opcode = OPCODE_MACRO } } + +/** + * Macro: branch to label label_num if R0 is less than immediate value. + * + * This macro generates two ulp_insn_t values separated by a comma, and should + * be used when defining contents of ulp_insn_t arrays. First value is not a + * real instruction; it is a token which is removed by ulp_process_macros_and_load + * function. + */ +#define M_BL(label_num, imm_value) \ + M_BRANCH(label_num), \ + I_BL(0, imm_value) + +/** + * Macro: branch to label label_num if R0 is greater or equal than immediate value + * + * This macro generates two ulp_insn_t values separated by a comma, and should + * be used when defining contents of ulp_insn_t arrays. First value is not a + * real instruction; it is a token which is removed by ulp_process_macros_and_load + * function. + */ +#define M_BGE(label_num, imm_value) \ + M_BRANCH(label_num), \ + I_BGE(0, imm_value) + +/** + * Macro: unconditional branch to label + * + * This macro generates two ulp_insn_t values separated by a comma, and should + * be used when defining contents of ulp_insn_t arrays. First value is not a + * real instruction; it is a token which is removed by ulp_process_macros_and_load + * function. + */ +#define M_BX(label_num) \ + M_BRANCH(label_num), \ + I_BXI(0) + +/** + * Macro: branch to label if ALU result is zero + * + * This macro generates two ulp_insn_t values separated by a comma, and should + * be used when defining contents of ulp_insn_t arrays. First value is not a + * real instruction; it is a token which is removed by ulp_process_macros_and_load + * function. + */ +#define M_BXZ(label_num) \ + M_BRANCH(label_num), \ + I_BXZI(0) + +/** + * Macro: branch to label if ALU overflow + * + * This macro generates two ulp_insn_t values separated by a comma, and should + * be used when defining contents of ulp_insn_t arrays. First value is not a + * real instruction; it is a token which is removed by ulp_process_macros_and_load + * function. + */ +#define M_BXF(label_num) \ + M_BRANCH(label_num), \ + I_BXFI(0) + + + +#define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */ + +/** + * @brief Resolve all macro references in a program and load it into RTC memory + * @param load_addr address where the program should be loaded, expressed in 32-bit words + * @param program ulp_insn_t array with the program + * @param psize size of the program, expressed in 32-bit words + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM if auxiliary temporary structure can not be allocated + * - one of ESP_ERR_ULP_xxx if program is not valid or can not be loaded + */ +esp_err_t ulp_process_macros_and_load(uint32_t load_addr, const ulp_insn_t* program, size_t* psize); + +/** + * @brief Load ULP program binary into RTC memory + * + * ULP program binary should have the following format (all values little-endian): + * + * 1. MAGIC, (value 0x00706c75, 4 bytes) + * 2. TEXT_OFFSET, offset of .text section from binary start (2 bytes) + * 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 - 12) bytes of arbitrary data (will not be loaded into RTC memory) + * 7. .text section + * 8. .data section + * + * Linker script in components/ulp/ld/esp32.ulp.ld produces ELF files which + * correspond to this format. This linker script produces binaries with load_addr == 0. + * + * @param load_addr address where the program should be loaded, expressed in 32-bit words + * @param program_binary pointer to program binary + * @param program_size size of the program binary + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if load_addr is out of range + * - ESP_ERR_INVALID_SIZE if program_size doesn't match (TEXT_OFFSET + TEXT_SIZE + DATA_SIZE) + * - ESP_ERR_NOT_SUPPORTED if the magic number is incorrect + */ +esp_err_t ulp_load_binary(uint32_t load_addr, const uint8_t* program_binary, size_t program_size); + +/** + * @brief Run the program loaded into RTC memory + * @param entry_point entry point, expressed in 32-bit words + * @return ESP_OK on success + */ +esp_err_t ulp_run(uint32_t entry_point); + +/** + * @brief Set one of ULP wakeup period values + * + * ULP coprocessor starts running the program when the wakeup timer counts up + * to a given value (called period). There are 5 period values which can be + * programmed into SENS_ULP_CP_SLEEP_CYCx_REG registers, x = 0..4. + * By default, wakeup timer will use the period set into SENS_ULP_CP_SLEEP_CYC0_REG, + * i.e. period number 0. ULP program code can use SLEEP instruction to select + * which of the SENS_ULP_CP_SLEEP_CYCx_REG should be used for subsequent wakeups. + * + * @param period_index wakeup period setting number (0 - 4) + * @param period_us wakeup period, us + * @note The ULP FSM requires two clock cycles to wakeup before being able to run the program. + * Then additional 16 cycles are reserved after wakeup waiting until the 8M clock is stable. + * The FSM also requires two more clock cycles to go to sleep after the program execution is halted. + * The minimum wakeup period that may be set up for the ULP + * is equal to the total number of cycles spent on the above internal tasks. + * For a default configuration of the ULP running at 150kHz it makes about 133us. + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if period_index is out of range + */ +esp_err_t ulp_set_wakeup_period(size_t period_index, uint32_t period_us); + +#ifdef __cplusplus +} +#endif diff --git a/MicroPython_BUILD/firmware/esp32/sdkconfig b/MicroPython_BUILD/sdkconfig.ulp similarity index 94% rename from MicroPython_BUILD/firmware/esp32/sdkconfig rename to MicroPython_BUILD/sdkconfig.ulp index f886b154..53320f49 100644 --- a/MicroPython_BUILD/firmware/esp32/sdkconfig +++ b/MicroPython_BUILD/sdkconfig.ulp @@ -34,7 +34,7 @@ CONFIG_FLASH_ENCRYPTION_ENABLED= # # Serial flasher config # -CONFIG_ESPTOOLPY_PORT="/dev/ttyUSB0" +CONFIG_ESPTOOLPY_PORT="/dev/tty.SLAB_USBtoUART" CONFIG_ESPTOOLPY_BAUD_115200B= CONFIG_ESPTOOLPY_BAUD_230400B= CONFIG_ESPTOOLPY_BAUD_921600B=y @@ -108,7 +108,7 @@ CONFIG_MICROPY_RX_BUFFER_SIZE=1080 CONFIG_MICROPY_USE_BOTH_CORES= CONFIG_MICROPY_TASK_PRIORITY=5 CONFIG_MICROPY_STACK_SIZE=20 -CONFIG_MICROPY_HEAP_SIZE=80 +CONFIG_MICROPY_HEAP_SIZE=3072 CONFIG_MICROPY_THREAD_MAX_THREADS=4 CONFIG_MICROPY_THREAD_STACK_SIZE=4 CONFIG_MICROPY_USE_TELNET=y @@ -131,20 +131,23 @@ CONFIG_MICROPY_FTPSERVER_BUFFER_SIZE=1024 # Modules # CONFIG_MICROPY_PY_FRAMEBUF=y -CONFIG_MICROPY_PY_USE_BTREE= -CONFIG_MICROPY_USE_WEBSOCKETS= +CONFIG_MICROPY_PY_USE_BTREE=y +CONFIG_MICROPY_USE_WEBSOCKETS=y CONFIG_MICROPY_USE_DISPLAY=y CONFIG_MICROPY_USE_TFT=y CONFIG_MICROPY_USE_EPD= CONFIG_MICROPY_USE_EVE= -CONFIG_MICROPY_USE_GSM= +CONFIG_MICROPY_USE_GSM=y CONFIG_MICROPY_USE_GPS=y CONFIG_MICROPY_GPS_SERVICE_STACK=3072 CONFIG_MICROPY_USE_ETHERNET= CONFIG_MICROPY_USE_MDNS=y CONFIG_MICROPY_USE_REQUESTS=y -CONFIG_MICROPY_USE_CURL= -CONFIG_MICROPY_USE_SSH= +CONFIG_MICROPY_USE_CURL=y +CONFIG_MICROPY_CURL_MAX_WRITE_SIZE=8192 +CONFIG_MICROPY_USE_CURL_TLS=y +CONFIG_MICROPY_USE_CURLFTP=y +CONFIG_MICROPY_USE_SSH=y CONFIG_MICROPY_USE_MQTT=y # @@ -251,7 +254,22 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_80= CONFIG_ESP32_DEFAULT_CPU_FREQ_160= CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 -CONFIG_SPIRAM_SUPPORT= +CONFIG_SPIRAM_SUPPORT=y + +# +# SPI RAM config +# +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND=y +CONFIG_SPIRAM_USE_MEMMAP= +CONFIG_SPIRAM_USE_CAPS_ALLOC=y +CONFIG_SPIRAM_USE_MALLOC= +CONFIG_SPIRAM_TYPE_ESPPSRAM32=y +CONFIG_SPIRAM_SIZE=4194304 +CONFIG_SPIRAM_SPEED_40M=y +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_CACHE_WORKAROUND=y +CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST=y CONFIG_MEMMAP_TRACEMEM= CONFIG_MEMMAP_TRACEMEM_TWOBANKS= CONFIG_ESP32_TRAX= @@ -280,8 +298,8 @@ CONFIG_CONSOLE_UART_CUSTOM= CONFIG_CONSOLE_UART_NONE= CONFIG_CONSOLE_UART_NUM=0 CONFIG_CONSOLE_UART_BAUDRATE=115200 -CONFIG_ULP_COPROC_ENABLED= -CONFIG_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_RESERVE_MEM=1024 CONFIG_ESP32_PANIC_PRINT_HALT=y CONFIG_ESP32_PANIC_PRINT_REBOOT= CONFIG_ESP32_PANIC_SILENT_REBOOT= @@ -329,10 +347,10 @@ CONFIG_ESP_ERR_TO_NAME_LOOKUP=y # CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=8 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16 -CONFIG_ESP32_WIFI_STATIC_TX_BUFFER= -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y -CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER= +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 CONFIG_ESP32_WIFI_CSI_ENABLED= CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 @@ -540,7 +558,7 @@ CONFIG_LWIP_MAX_RAW_PCBS=16 # # mbedTLS # -CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=8192 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 CONFIG_MBEDTLS_DEBUG= CONFIG_MBEDTLS_HARDWARE_AES=y CONFIG_MBEDTLS_HARDWARE_MPI= From a0d4509dc861daa0d47d1932bd982616aedaec71 Mon Sep 17 00:00:00 2001 From: ubIQio Date: Thu, 13 Sep 2018 19:28:44 +0100 Subject: [PATCH 2/5] remove .gch files --- .gitignore | 3 ++- .../micropython/esp32/machine_ulp.h.gch | Bin 177572 -> 0 bytes 2 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 MicroPython_BUILD/components/micropython/esp32/machine_ulp.h.gch diff --git a/.gitignore b/.gitignore index ae14062a..8af9c4f3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ *.dis #*.exe -# Packages +# Packages ############ # Logs and Databases @@ -53,3 +53,4 @@ xtensa-esp32-elf_psram/ backup.sh .DS_Store +*.gch diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_ulp.h.gch b/MicroPython_BUILD/components/micropython/esp32/machine_ulp.h.gch deleted file mode 100644 index a0a5e2f309f53041778df5a2a83b86f811f5d66f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 177572 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 SO8<_Dhia!gA``8$ru`rN&n!Fu From 5bc2dec76a6d8c46489547d321185a3d04c05bf1 Mon Sep 17 00:00:00 2001 From: ubIQio Date: Sun, 16 Sep 2018 21:21:17 +0100 Subject: [PATCH 3/5] Add pulse counter example --- .../internalfs_image/image/pulse_count.py | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 MicroPython_BUILD/components/internalfs_image/image/pulse_count.py diff --git a/MicroPython_BUILD/components/internalfs_image/image/pulse_count.py b/MicroPython_BUILD/components/internalfs_image/image/pulse_count.py new file mode 100644 index 00000000..0191bc57 --- /dev/null +++ b/MicroPython_BUILD/components/internalfs_image/image/pulse_count.py @@ -0,0 +1,169 @@ + + + +""" +================================================================================ + +Pulse Counter using ESP32 ULP processor + + Uses ULP to count pulses on GPIO4 (which is TOUCH0/RTCIO10 in RTC domain) + +================================================================================ + +Includes debouncer taken from code as popularised by Kenneth A. Kuhn. + +This is an algorithm that debounces or removes random or spurious +transitions of a digital signal read as an input by a computer. This is +particularly applicable when the input is from a mechanical contact. + +The algorithm uses integration as opposed to edge logic +(differentiation), which makes it very robust in the presence of noise. + +An integrator is used to perform a time hysteresis so that the signal must +persistently be in a logical state (0 or 1) in order for the output to change +to that state. Random transitions of the input will not affect the output +except in the rare case where statistical clustering is longer than the +specified integration time. + +The following example illustrates how this algorithm works. "real signal" +represents the real intended signal with no noise. "corrupted" has significant +random transitions added to the real signal. "integrator" represents the +integration which is constrained to be between 0 and 3. "output" only makes a +transition when the integrator reaches either 0 or 3. + +Note that the output signal lags the input signal by the integration time but +is free of spurious transitions. + +real signal 0000111111110000000111111100000000011111111110000000000111111100000 + +corrupted 0100111011011001000011011010001001011100101111000100010111011100010 +integrator 0100123233233212100012123232101001012321212333210100010123233321010 +output 0000001111111111100000001111100000000111111111110000000001111111000 + + +-------------------------------------------------------------------------------- + +""" + +from machine import mem32 +import utime +import machine + +from esp32_ulp.__main__ import src_to_binary + +source = """\ +pulse_count: .long 0 # 16 bit count of pulses returned to main processor +debounce: .long 0 # maximum saturation value of integrator, from main +last_state: .long 0 # internal record of last debounced state of pin +integrator: .long 0 + + + .set RTC_GPIO_IN_REG, 0x3ff48424 # = DR_REG_RTCIO_BASEĀ + 0x24 + + /* Step 1: Update the integrator based on the input signal. Note that the + integrator follows the input, decreasing or increasing towards the limits as + determined by the input state (0 or 1). */ + +entry: move r3, integrator # get integrator address + reg_rd RTC_GPIO_IN_REG, 14, 24 # get all 16 ULP GPIOs into r0 + and r0, r0, 1 # isolate TOUCH0/RTCIO10/GPIO4 + jump pin_low, eq # if pin high + ld r0, r3, 0 # get integrator value + jumpr done, debounce, ge # if integrator < debounce max count + add r0, r0, 1 # integrator +=1 + st r0, r3, 0 + jump chk_state + +pin_low: + ld r0, r3, 0 # get integrator value + jumpr chk_state, 1, lt # if integrator >= 1 + sub r0, r0, 1 # integrator -=1 + st r0, r3, 0 + + /* Step 2: Update the output state based on the integrator. Note that the + output will only change state if the integrator has reached a limit, either + 0 or MAXIMUM. */ + +chk_state: + move r2, last_state # get last qualified state of pin + ld r0, r2, 0 + jumpr chk_debounce, 1, lt # if previous state = 0 + ld r0, r3, 0 # and + jumpr done, 1, ge # integrator < 1 + move r0, 0 # falling edge qualified + st r0, r2, 0 # so update last_state=0 + move r3, pulse_count + ld r1, r3, 0 # and increment pulse count + add r1, r1, 1 + st r1, r3, 0 + halt # halt 'til next wakeup + +chk_debounce: # previous state was low + ld r0, r3, 0 # get integrator value + jumpr done, debounce, lt # if integrator >= debounce max + move r0,1 + st r0, r2, 0 # update last_state=1 + +done: + halt # halt 'til next wakeup +""" + + + +ULP_MEM_BASE = 0x50000000 +ULP_DATA_MASK = 0xffff # ULP data is only in lower 16 bits + +ULP_VARS = 4 # number of 32-bit vars used by ULP program + +load_addr = 0 +entry_addr = ULP_MEM_BASE + (ULP_VARS * 4) # entry address is offset by length of vars + +ulp_pulse_count = ULP_MEM_BASE + 0 +ulp_debounce = ULP_MEM_BASE + 4 + + +machine.Pin(4, machine.Pin.IN, machine.Pin.PULL_UP) +pin21 = machine.Pin(21, machine.Pin.OUT) + + +print ("\nLoading ULP...\n") + +binary = src_to_binary(source) + +ulp = machine.ULP() +ulp.set_wakeup_period(0, 100) # use timer0, wakeup after ~100us +ulp.load_binary(load_addr, binary) + + +if machine.nvs_getint('pulse_count_nv') == None: + machine.nvs_setint('pulse_count_nv', 0) + +init_count = machine.nvs_getint('pulse_count_nv') + +pulse_count = init_count # init pulse counts +pulse_gen_count = init_count +mem32[ulp_pulse_count] = init_count + +mem32[ulp_debounce] = 3 # 3 sample debounce + +ulp.run(entry_addr) + + +print ("\n\nPulse Count Test: \n----------------- \n") + +while True: + pulse_countL = mem32[ulp_pulse_count] & ULP_DATA_MASK + if (pulse_count & 0xffff) > pulse_countL: + pulse_count += 0x10000 + pulse_count = (pulse_count & ~0xffff) + pulse_countL + machine.nvs_setint('pulse_count_nv', pulse_count) + + print('Pulses Out:', pulse_gen_count) + print('Pulses In :', pulse_count, '\n') + + for t in range (500): + pin21.value(1) + utime.sleep_ms(1) + pin21.value(0) + pulse_gen_count += 1 + utime.sleep_ms(1) From f75482ae00b4e4de41d2f36890c1e22580280952 Mon Sep 17 00:00:00 2001 From: ubIQio Date: Mon, 17 Sep 2018 07:32:34 +0100 Subject: [PATCH 4/5] typo --- .../internalfs_image/image/pulse_count.py | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/MicroPython_BUILD/components/internalfs_image/image/pulse_count.py b/MicroPython_BUILD/components/internalfs_image/image/pulse_count.py index 0191bc57..5687e822 100644 --- a/MicroPython_BUILD/components/internalfs_image/image/pulse_count.py +++ b/MicroPython_BUILD/components/internalfs_image/image/pulse_count.py @@ -87,25 +87,27 @@ chk_state: move r2, last_state # get last qualified state of pin ld r0, r2, 0 - jumpr chk_debounce, 1, lt # if previous state = 0 + jumpr chk_debounce, 1, lt # if previous state was high ld r0, r3, 0 # and jumpr done, 1, ge # integrator < 1 move r0, 0 # falling edge qualified st r0, r2, 0 # so update last_state=0 - move r3, pulse_count - ld r1, r3, 0 # and increment pulse count - add r1, r1, 1 - st r1, r3, 0 - halt # halt 'til next wakeup + jump inc_pulse_count # update count on falling edge chk_debounce: # previous state was low ld r0, r3, 0 # get integrator value jumpr done, debounce, lt # if integrator >= debounce max - move r0,1 + move r0,1 # rising edge qualified st r0, r2, 0 # update last_state=1 + jump done # halt 'til next wakeup + +inc_pulse_count: # increment pulse count + move r3, pulse_count + ld r1, r3, 0 + add r1, r1, 1 + st r1, r3, 0 +done: halt # halt 'til next wakeup -done: - halt # halt 'til next wakeup """ From ac881e3b0734db76b5763cfdc1bfb7f45dc76cbb Mon Sep 17 00:00:00 2001 From: ubIQio Date: Mon, 17 Sep 2018 07:39:11 +0100 Subject: [PATCH 5/5] move examples into examples... --- .../internalfs_image/image/{ => examples}/pulse_count.py | 0 .../components/internalfs_image/image/{ => examples}/ulp_count.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename MicroPython_BUILD/components/internalfs_image/image/{ => examples}/pulse_count.py (100%) rename MicroPython_BUILD/components/internalfs_image/image/{ => examples}/ulp_count.py (100%) diff --git a/MicroPython_BUILD/components/internalfs_image/image/pulse_count.py b/MicroPython_BUILD/components/internalfs_image/image/examples/pulse_count.py similarity index 100% rename from MicroPython_BUILD/components/internalfs_image/image/pulse_count.py rename to MicroPython_BUILD/components/internalfs_image/image/examples/pulse_count.py diff --git a/MicroPython_BUILD/components/internalfs_image/image/ulp_count.py b/MicroPython_BUILD/components/internalfs_image/image/examples/ulp_count.py similarity index 100% rename from MicroPython_BUILD/components/internalfs_image/image/ulp_count.py rename to MicroPython_BUILD/components/internalfs_image/image/examples/ulp_count.py