diff --git a/bin/exception_decoder.py b/bin/exception_decoder.py index 8ef66b9bb..ec94ce20e 100755 --- a/bin/exception_decoder.py +++ b/bin/exception_decoder.py @@ -11,19 +11,22 @@ Meshtastic notes: * version that's checked into meshtastic repo is based on: https://github.com/me21/EspArduinoExceptionDecoder which adds in ESP32 Backtrace decoding. * this also updates the defaults to use ESP32, instead of ESP8266 and defaults to the built firmware.bin +* also updated the toolchain name, which will be set according to the platform To use, copy the "Backtrace: 0x...." line to a file, e.g., backtrace.txt, then run: $ bin/exception_decoder.py backtrace.txt +For a platform other than ESP32, use the -p option, e.g.: +$ bin/exception_decoder.py -p ESP32S3 backtrace.txt +To specify a specific .elf file, use the -e option, e.g.: +$ bin/exception_decoder.py -e firmware.elf backtrace.txt """ import argparse +import os import re import subprocess -from collections import namedtuple - import sys - -import os +from collections import namedtuple EXCEPTIONS = [ "Illegal instruction", @@ -55,24 +58,39 @@ EXCEPTIONS = [ "LoadStorePrivilege: A load or store referenced a virtual address at a ring level less than CRING", "reserved", "LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads", - "StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores" + "StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores", ] PLATFORMS = { - "ESP8266": "lx106", - "ESP32": "esp32" + "ESP8266": "xtensa-lx106", + "ESP32": "xtensa-esp32", + "ESP32S3": "xtensa-esp32s3", + "ESP32C3": "riscv32-esp", +} +TOOLS = { + "ESP8266": "xtensa", + "ESP32": "xtensa-esp32", + "ESP32S3": "xtensa-esp32s3", + "ESP32C3": "riscv32-esp", } -BACKTRACE_REGEX = re.compile(r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b") +BACKTRACE_REGEX = re.compile( + r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b" +) EXCEPTION_REGEX = re.compile("^Exception \\((?P[0-9]*)\\):$") -COUNTER_REGEX = re.compile('^epc1=(?P0x[0-9a-f]+) epc2=(?P0x[0-9a-f]+) epc3=(?P0x[0-9a-f]+) ' - 'excvaddr=(?P0x[0-9a-f]+) depc=(?P0x[0-9a-f]+)$') +COUNTER_REGEX = re.compile( + "^epc1=(?P0x[0-9a-f]+) epc2=(?P0x[0-9a-f]+) epc3=(?P0x[0-9a-f]+) " + "excvaddr=(?P0x[0-9a-f]+) depc=(?P0x[0-9a-f]+)$" +) CTX_REGEX = re.compile("^ctx: (?P.+)$") -POINTER_REGEX = re.compile('^sp: (?P[0-9a-f]+) end: (?P[0-9a-f]+) offset: (?P[0-9a-f]+)$') -STACK_BEGIN = '>>>stack>>>' -STACK_END = '<<[0-9a-f]+) end: (?P[0-9a-f]+) offset: (?P[0-9a-f]+)$" +) +STACK_BEGIN = ">>>stack>>>" +STACK_END = "<<[0-9a-f]+):\W+(?P[0-9a-f]+) (?P[0-9a-f]+) (?P[0-9a-f]+) (?P[0-9a-f]+)(\W.*)?$') + "^(?P[0-9a-f]+):\W+(?P[0-9a-f]+) (?P[0-9a-f]+) (?P[0-9a-f]+) (?P[0-9a-f]+)(\W.*)?$" +) StackLine = namedtuple("StackLine", ["offset", "content"]) @@ -96,15 +114,18 @@ class ExceptionDataParser(object): self.stack = [] def _parse_backtrace(self, line): - if line.startswith('Backtrace:'): - self.stack = [StackLine(offset=0, content=(addr,)) for addr in BACKTRACE_REGEX.findall(line)] + if line.startswith("Backtrace:"): + self.stack = [ + StackLine(offset=0, content=(addr,)) + for addr in BACKTRACE_REGEX.findall(line) + ] return None return self._parse_backtrace def _parse_exception(self, line): match = EXCEPTION_REGEX.match(line) if match is not None: - self.exception = int(match.group('exc')) + self.exception = int(match.group("exc")) return self._parse_counters return self._parse_exception @@ -144,14 +165,22 @@ class ExceptionDataParser(object): if line != STACK_END: match = STACK_REGEX.match(line) if match is not None: - self.stack.append(StackLine(offset=match.group("off"), - content=(match.group("c1"), match.group("c2"), match.group("c3"), - match.group("c4")))) + self.stack.append( + StackLine( + offset=match.group("off"), + content=( + match.group("c1"), + match.group("c2"), + match.group("c3"), + match.group("c4"), + ), + ) + ) return self._parse_stack_line return None def parse_file(self, file, platform, stack_only=False): - if platform == 'ESP32': + if platform != "ESP8266": func = self._parse_backtrace else: func = self._parse_exception @@ -175,7 +204,9 @@ class AddressResolver(object): self._address_map = {} def _lookup(self, addresses): - cmd = [self._tool, "-aipfC", "-e", self._elf] + [addr for addr in addresses if addr is not None] + cmd = [self._tool, "-aipfC", "-e", self._elf] + [ + addr for addr in addresses if addr is not None + ] if sys.version_info[0] < 3: output = subprocess.check_output(cmd) @@ -190,19 +221,27 @@ class AddressResolver(object): match = line_regex.match(line) if match is None: - if last is not None and line.startswith('(inlined by)'): - line = line [12:].strip() - self._address_map[last] += ("\n \-> inlined by: " + line) + if last is not None and line.startswith("(inlined by)"): + line = line[12:].strip() + self._address_map[last] += "\n \-> inlined by: " + line continue - if match.group("result") == '?? ??:0': + if match.group("result") == "?? ??:0": continue self._address_map[match.group("addr")] = match.group("result") last = match.group("addr") def fill(self, parser): - addresses = [parser.epc1, parser.epc2, parser.epc3, parser.excvaddr, parser.sp, parser.end, parser.offset] + addresses = [ + parser.epc1, + parser.epc2, + parser.epc3, + parser.excvaddr, + parser.sp, + parser.end, + parser.offset, + ] for line in parser.stack: addresses.extend(line.content) @@ -257,8 +296,10 @@ def print_stack(lines, resolver): def print_result(parser, resolver, platform, full=True, stack_only=False): - if platform == 'ESP8266' and not stack_only: - print('Exception: {} ({})'.format(parser.exception, EXCEPTIONS[parser.exception])) + if platform == "ESP8266" and not stack_only: + print( + "Exception: {} ({})".format(parser.exception, EXCEPTIONS[parser.exception]) + ) print("") print_addr("epc1", parser.epc1, resolver) @@ -285,15 +326,33 @@ def print_result(parser, resolver, platform, full=True, stack_only=False): def parse_args(): parser = argparse.ArgumentParser(description="decode ESP Stacktraces.") - parser.add_argument("-p", "--platform", help="The platform to decode from", choices=PLATFORMS.keys(), - default="ESP32") - parser.add_argument("-t", "--tool", help="Path to the xtensa toolchain", - default="~/.platformio/packages/toolchain-xtensa32/") - parser.add_argument("-e", "--elf", help="path to elf file", - default=".pio/build/esp32/firmware.elf") - parser.add_argument("-f", "--full", help="Print full stack dump", action="store_true") - parser.add_argument("-s", "--stack_only", help="Decode only a stractrace", action="store_true") - parser.add_argument("file", help="The file to read the exception data from ('-' for STDIN)", default="-") + parser.add_argument( + "-p", + "--platform", + help="The platform to decode from", + choices=PLATFORMS.keys(), + default="ESP32", + ) + parser.add_argument( + "-t", + "--tool", + help="Path to the toolchain (without specific platform)", + default="~/.platformio/packages/toolchain-", + ) + parser.add_argument( + "-e", "--elf", help="path to elf file", default=".pio/build/tbeam/firmware.elf" + ) + parser.add_argument( + "-f", "--full", help="Print full stack dump", action="store_true" + ) + parser.add_argument( + "-s", "--stack_only", help="Decode only a stractrace", action="store_true" + ) + parser.add_argument( + "file", + help="The file to read the exception data from ('-' for STDIN)", + default="-", + ) return parser.parse_args() @@ -309,10 +368,12 @@ if __name__ == "__main__": sys.exit(1) file = open(args.file, "r") - addr2line = os.path.join(os.path.abspath(os.path.expanduser(args.tool)), - "bin/xtensa-" + PLATFORMS[args.platform] + "-elf-addr2line") - if os.name == 'nt': - addr2line += '.exe' + addr2line = os.path.join( + os.path.abspath(os.path.expanduser(args.tool + TOOLS[args.platform])), + "bin/" + PLATFORMS[args.platform] + "-elf-addr2line", + ) + if os.name == "nt": + addr2line += ".exe" if not os.path.exists(addr2line): print("ERROR: addr2line not found (" + addr2line + ")") diff --git a/src/ButtonThread.h b/src/ButtonThread.h index 5f68aa5b6..7138d3b6a 100644 --- a/src/ButtonThread.h +++ b/src/ButtonThread.h @@ -138,6 +138,7 @@ class ButtonThread : public concurrency::OSThread #ifdef BUTTON_PIN if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) != moduleConfig.canned_message.inputbroker_pin_press) || + !(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) || !moduleConfig.canned_message.enabled) { powerFSM.trigger(EVENT_PRESS); } @@ -232,4 +233,4 @@ class ButtonThread : public concurrency::OSThread } }; -} // namespace concurrency +} // namespace concurrency \ No newline at end of file diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index 3b97dd723..eb716ac03 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -7,9 +7,9 @@ #include "main.h" #include -// #ifdef HELTEC_WIRELESS_PAPER -// SPIClass *hspi = NULL; -// #endif +#ifdef HELTEC_WIRELESS_PAPER +SPIClass *hspi = NULL; +#endif #define COLORED GxEPD_BLACK #define UNCOLORED GxEPD_WHITE @@ -47,7 +47,7 @@ #elif defined(HELTEC_WIRELESS_PAPER) // #define TECHO_DISPLAY_MODEL GxEPD2_213_T5D -#define TECHO_DISPLAY_MODEL GxEPD2_213_BN +#define TECHO_DISPLAY_MODEL GxEPD2_213_FC1 #endif GxEPD2_BW *adafruitDisplay; @@ -71,7 +71,7 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY // setGeometry(GEOMETRY_RAWMODE, 200, 200); #elif defined(HELTEC_WIRELESS_PAPER) - // setGeometry(GEOMETRY_RAWMODE, 212, 104); + // GxEPD2_213_BN - 2.13 inch b/w 250x122 setGeometry(GEOMETRY_RAWMODE, 250, 122); #elif defined(MAKERPYTHON) // GxEPD2_290_T5D @@ -119,7 +119,6 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit) // tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK); for (uint32_t y = 0; y < displayHeight; y++) { for (uint32_t x = 0; x < displayWidth; x++) { - // get src pixel in the page based ordering the OLED lib uses FIXME, super inefficient auto b = buffer[x + (y / 8) * displayWidth]; auto isset = b & (1 << (y & 7)); @@ -148,7 +147,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit) #elif defined(PCA10059) || defined(M5_COREINK) adafruitDisplay->nextPage(); - +#elif defined(HELTEC_WIRELESS_PAPER) + adafruitDisplay->nextPage(); #elif defined(PRIVATE_HW) || defined(my) adafruitDisplay->nextPage(); @@ -231,13 +231,16 @@ bool EInkDisplay::connect() } #elif defined(HELTEC_WIRELESS_PAPER) { - auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY); + hspi = new SPIClass(HSPI); + hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS + delay(100); + pinMode(Vext, OUTPUT); + digitalWrite(Vext, LOW); + delay(100); + auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi); adafruitDisplay = new GxEPD2_BW(*lowLevel); - // hspi = new SPIClass(HSPI); - // hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS - adafruitDisplay->init(115200, true, 10, false, SPI, SPISettings(6000000, MSBFIRST, SPI_MODE0)); + adafruitDisplay->init(); adafruitDisplay->setRotation(3); - adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight); } #elif defined(PCA10059) { diff --git a/variants/heltec_wireless_paper/pins_arduino.h b/variants/heltec_wireless_paper/pins_arduino.h new file mode 100644 index 000000000..66d091691 --- /dev/null +++ b/variants/heltec_wireless_paper/pins_arduino.h @@ -0,0 +1,78 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define WIFI_Kit_32 true +#define DISPLAY_HEIGHT 64 +#define DISPLAY_WIDTH 128 + +#define EXTERNAL_NUM_INTERRUPTS 16 +#define NUM_DIGITAL_PINS 40 +#define NUM_ANALOG_INPUTS 16 + +#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1) +#define digitalPinToInterrupt(p) (((p) < 40) ? (p) : -1) +#define digitalPinHasPWM(p) (p < 34) + +static const uint8_t LED_BUILTIN = 35; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN + +static const uint8_t KEY_BUILTIN = 0; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 41; +static const uint8_t SCL = 42; + +static const uint8_t SS = 8; +static const uint8_t MOSI = 10; +static const uint8_t MISO = 11; +static const uint8_t SCK = 9; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +static const uint8_t Vext = 45; +static const uint8_t LED = 18; + +static const uint8_t RST_LoRa = 12; +static const uint8_t BUSY_LoRa = 13; +static const uint8_t DIO0 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/heltec_wireless_paper/platformio.ini b/variants/heltec_wireless_paper/platformio.ini index 0bc7f14d1..dd93b52cb 100644 --- a/variants/heltec_wireless_paper/platformio.ini +++ b/variants/heltec_wireless_paper/platformio.ini @@ -5,4 +5,7 @@ build_flags = ${esp32s3_base.build_flags} -D HELTEC_WIRELESS_PAPER -I variants/heltec_wireless_paper lib_deps = ${esp32s3_base.lib_deps} - zinggjm/GxEPD2@^1.5.2 + https://github.com/ixt/GxEPD2#39f325b677713eb04dfcc83b8e402e77523fb8bf + adafruit/Adafruit BusIO@^1.13.2 + lewisxhe/PCF8563_Library@^1.0.1 +upload_speed = 115200 \ No newline at end of file diff --git a/variants/heltec_wireless_paper/variant.h b/variants/heltec_wireless_paper/variant.h index 88c5faaa1..4daf9a655 100644 --- a/variants/heltec_wireless_paper/variant.h +++ b/variants/heltec_wireless_paper/variant.h @@ -15,7 +15,16 @@ #define PIN_EINK_SCLK 3 #define PIN_EINK_MOSI 2 -#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost +/* + * SPI interfaces + */ +#define SPI_INTERFACES_COUNT 2 + +#define PIN_SPI_MISO 10 // MISO P0.17 +#define PIN_SPI_MOSI 11 // MOSI P0.15 +#define PIN_SPI_SCK 9 // SCK P0.13 + +#define VEXT_ENABLE 45 // active low, powers the oled display and the lora antenna boost #define BUTTON_PIN 0 #define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage