Merge branch 'meshtastic:master' into master

This commit is contained in:
Mictronics 2024-01-10 09:41:18 +01:00 committed by GitHub
commit 8f8829f6e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 212 additions and 57 deletions

View File

@ -11,19 +11,22 @@ Meshtastic notes:
* version that's checked into meshtastic repo is based on: https://github.com/me21/EspArduinoExceptionDecoder * version that's checked into meshtastic repo is based on: https://github.com/me21/EspArduinoExceptionDecoder
which adds in ESP32 Backtrace decoding. which adds in ESP32 Backtrace decoding.
* this also updates the defaults to use ESP32, instead of ESP8266 and defaults to the built firmware.bin * 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: To use, copy the "Backtrace: 0x...." line to a file, e.g., backtrace.txt, then run:
$ bin/exception_decoder.py backtrace.txt $ 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 argparse
import os
import re import re
import subprocess import subprocess
from collections import namedtuple
import sys import sys
from collections import namedtuple
import os
EXCEPTIONS = [ EXCEPTIONS = [
"Illegal instruction", "Illegal instruction",
@ -55,24 +58,39 @@ EXCEPTIONS = [
"LoadStorePrivilege: A load or store referenced a virtual address at a ring level less than CRING", "LoadStorePrivilege: A load or store referenced a virtual address at a ring level less than CRING",
"reserved", "reserved",
"LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads", "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 = { PLATFORMS = {
"ESP8266": "lx106", "ESP8266": "xtensa-lx106",
"ESP32": "esp32" "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<exc>[0-9]*)\\):$") EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$")
COUNTER_REGEX = re.compile('^epc1=(?P<epc1>0x[0-9a-f]+) epc2=(?P<epc2>0x[0-9a-f]+) epc3=(?P<epc3>0x[0-9a-f]+) ' COUNTER_REGEX = re.compile(
'excvaddr=(?P<excvaddr>0x[0-9a-f]+) depc=(?P<depc>0x[0-9a-f]+)$') "^epc1=(?P<epc1>0x[0-9a-f]+) epc2=(?P<epc2>0x[0-9a-f]+) epc3=(?P<epc3>0x[0-9a-f]+) "
"excvaddr=(?P<excvaddr>0x[0-9a-f]+) depc=(?P<depc>0x[0-9a-f]+)$"
)
CTX_REGEX = re.compile("^ctx: (?P<ctx>.+)$") CTX_REGEX = re.compile("^ctx: (?P<ctx>.+)$")
POINTER_REGEX = re.compile('^sp: (?P<sp>[0-9a-f]+) end: (?P<end>[0-9a-f]+) offset: (?P<offset>[0-9a-f]+)$') POINTER_REGEX = re.compile(
STACK_BEGIN = '>>>stack>>>' "^sp: (?P<sp>[0-9a-f]+) end: (?P<end>[0-9a-f]+) offset: (?P<offset>[0-9a-f]+)$"
STACK_END = '<<<stack<<<' )
STACK_BEGIN = ">>>stack>>>"
STACK_END = "<<<stack<<<"
STACK_REGEX = re.compile( STACK_REGEX = re.compile(
'^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$') "^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$"
)
StackLine = namedtuple("StackLine", ["offset", "content"]) StackLine = namedtuple("StackLine", ["offset", "content"])
@ -96,15 +114,18 @@ class ExceptionDataParser(object):
self.stack = [] self.stack = []
def _parse_backtrace(self, line): def _parse_backtrace(self, line):
if line.startswith('Backtrace:'): if line.startswith("Backtrace:"):
self.stack = [StackLine(offset=0, content=(addr,)) for addr in BACKTRACE_REGEX.findall(line)] self.stack = [
StackLine(offset=0, content=(addr,))
for addr in BACKTRACE_REGEX.findall(line)
]
return None return None
return self._parse_backtrace return self._parse_backtrace
def _parse_exception(self, line): def _parse_exception(self, line):
match = EXCEPTION_REGEX.match(line) match = EXCEPTION_REGEX.match(line)
if match is not None: if match is not None:
self.exception = int(match.group('exc')) self.exception = int(match.group("exc"))
return self._parse_counters return self._parse_counters
return self._parse_exception return self._parse_exception
@ -144,14 +165,22 @@ class ExceptionDataParser(object):
if line != STACK_END: if line != STACK_END:
match = STACK_REGEX.match(line) match = STACK_REGEX.match(line)
if match is not None: if match is not None:
self.stack.append(StackLine(offset=match.group("off"), self.stack.append(
content=(match.group("c1"), match.group("c2"), match.group("c3"), StackLine(
match.group("c4")))) offset=match.group("off"),
content=(
match.group("c1"),
match.group("c2"),
match.group("c3"),
match.group("c4"),
),
)
)
return self._parse_stack_line return self._parse_stack_line
return None return None
def parse_file(self, file, platform, stack_only=False): def parse_file(self, file, platform, stack_only=False):
if platform == 'ESP32': if platform != "ESP8266":
func = self._parse_backtrace func = self._parse_backtrace
else: else:
func = self._parse_exception func = self._parse_exception
@ -175,7 +204,9 @@ class AddressResolver(object):
self._address_map = {} self._address_map = {}
def _lookup(self, addresses): 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: if sys.version_info[0] < 3:
output = subprocess.check_output(cmd) output = subprocess.check_output(cmd)
@ -190,19 +221,27 @@ class AddressResolver(object):
match = line_regex.match(line) match = line_regex.match(line)
if match is None: if match is None:
if last is not None and line.startswith('(inlined by)'): if last is not None and line.startswith("(inlined by)"):
line = line[12:].strip() line = line[12:].strip()
self._address_map[last] += ("\n \-> inlined by: " + line) self._address_map[last] += "\n \-> inlined by: " + line
continue continue
if match.group("result") == '?? ??:0': if match.group("result") == "?? ??:0":
continue continue
self._address_map[match.group("addr")] = match.group("result") self._address_map[match.group("addr")] = match.group("result")
last = match.group("addr") last = match.group("addr")
def fill(self, parser): 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: for line in parser.stack:
addresses.extend(line.content) addresses.extend(line.content)
@ -257,8 +296,10 @@ def print_stack(lines, resolver):
def print_result(parser, resolver, platform, full=True, stack_only=False): def print_result(parser, resolver, platform, full=True, stack_only=False):
if platform == 'ESP8266' and not stack_only: if platform == "ESP8266" and not stack_only:
print('Exception: {} ({})'.format(parser.exception, EXCEPTIONS[parser.exception])) print(
"Exception: {} ({})".format(parser.exception, EXCEPTIONS[parser.exception])
)
print("") print("")
print_addr("epc1", parser.epc1, resolver) print_addr("epc1", parser.epc1, resolver)
@ -285,15 +326,33 @@ def print_result(parser, resolver, platform, full=True, stack_only=False):
def parse_args(): def parse_args():
parser = argparse.ArgumentParser(description="decode ESP Stacktraces.") parser = argparse.ArgumentParser(description="decode ESP Stacktraces.")
parser.add_argument("-p", "--platform", help="The platform to decode from", choices=PLATFORMS.keys(), parser.add_argument(
default="ESP32") "-p",
parser.add_argument("-t", "--tool", help="Path to the xtensa toolchain", "--platform",
default="~/.platformio/packages/toolchain-xtensa32/") help="The platform to decode from",
parser.add_argument("-e", "--elf", help="path to elf file", choices=PLATFORMS.keys(),
default=".pio/build/esp32/firmware.elf") default="ESP32",
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(
parser.add_argument("file", help="The file to read the exception data from ('-' for STDIN)", default="-") "-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() return parser.parse_args()
@ -309,10 +368,12 @@ if __name__ == "__main__":
sys.exit(1) sys.exit(1)
file = open(args.file, "r") file = open(args.file, "r")
addr2line = os.path.join(os.path.abspath(os.path.expanduser(args.tool)), addr2line = os.path.join(
"bin/xtensa-" + PLATFORMS[args.platform] + "-elf-addr2line") os.path.abspath(os.path.expanduser(args.tool + TOOLS[args.platform])),
if os.name == 'nt': "bin/" + PLATFORMS[args.platform] + "-elf-addr2line",
addr2line += '.exe' )
if os.name == "nt":
addr2line += ".exe"
if not os.path.exists(addr2line): if not os.path.exists(addr2line):
print("ERROR: addr2line not found (" + addr2line + ")") print("ERROR: addr2line not found (" + addr2line + ")")

View File

@ -138,6 +138,7 @@ class ButtonThread : public concurrency::OSThread
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) != if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
moduleConfig.canned_message.inputbroker_pin_press) || moduleConfig.canned_message.inputbroker_pin_press) ||
!(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) ||
!moduleConfig.canned_message.enabled) { !moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS); powerFSM.trigger(EVENT_PRESS);
} }

View File

@ -7,9 +7,9 @@
#include "main.h" #include "main.h"
#include <SPI.h> #include <SPI.h>
// #ifdef HELTEC_WIRELESS_PAPER #ifdef HELTEC_WIRELESS_PAPER
// SPIClass *hspi = NULL; SPIClass *hspi = NULL;
// #endif #endif
#define COLORED GxEPD_BLACK #define COLORED GxEPD_BLACK
#define UNCOLORED GxEPD_WHITE #define UNCOLORED GxEPD_WHITE
@ -47,7 +47,7 @@
#elif defined(HELTEC_WIRELESS_PAPER) #elif defined(HELTEC_WIRELESS_PAPER)
// #define TECHO_DISPLAY_MODEL GxEPD2_213_T5D // #define TECHO_DISPLAY_MODEL GxEPD2_213_T5D
#define TECHO_DISPLAY_MODEL GxEPD2_213_BN #define TECHO_DISPLAY_MODEL GxEPD2_213_FC1
#endif #endif
GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay; GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
@ -71,7 +71,7 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY
// setGeometry(GEOMETRY_RAWMODE, 200, 200); // setGeometry(GEOMETRY_RAWMODE, 200, 200);
#elif defined(HELTEC_WIRELESS_PAPER) #elif defined(HELTEC_WIRELESS_PAPER)
// setGeometry(GEOMETRY_RAWMODE, 212, 104); // GxEPD2_213_BN - 2.13 inch b/w 250x122
setGeometry(GEOMETRY_RAWMODE, 250, 122); setGeometry(GEOMETRY_RAWMODE, 250, 122);
#elif defined(MAKERPYTHON) #elif defined(MAKERPYTHON)
// GxEPD2_290_T5D // GxEPD2_290_T5D
@ -119,7 +119,6 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK); // tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
for (uint32_t y = 0; y < displayHeight; y++) { for (uint32_t y = 0; y < displayHeight; y++) {
for (uint32_t x = 0; x < displayWidth; x++) { for (uint32_t x = 0; x < displayWidth; x++) {
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficient // get src pixel in the page based ordering the OLED lib uses FIXME, super inefficient
auto b = buffer[x + (y / 8) * displayWidth]; auto b = buffer[x + (y / 8) * displayWidth];
auto isset = b & (1 << (y & 7)); auto isset = b & (1 << (y & 7));
@ -148,7 +147,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
#elif defined(PCA10059) || defined(M5_COREINK) #elif defined(PCA10059) || defined(M5_COREINK)
adafruitDisplay->nextPage(); adafruitDisplay->nextPage();
#elif defined(HELTEC_WIRELESS_PAPER)
adafruitDisplay->nextPage();
#elif defined(PRIVATE_HW) || defined(my) #elif defined(PRIVATE_HW) || defined(my)
adafruitDisplay->nextPage(); adafruitDisplay->nextPage();
@ -231,13 +231,16 @@ bool EInkDisplay::connect()
} }
#elif defined(HELTEC_WIRELESS_PAPER) #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<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel); adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
// hspi = new SPIClass(HSPI); adafruitDisplay->init();
// 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->setRotation(3); adafruitDisplay->setRotation(3);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
} }
#elif defined(PCA10059) #elif defined(PCA10059)
{ {

View File

@ -0,0 +1,78 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#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 */

View File

@ -5,4 +5,7 @@ build_flags =
${esp32s3_base.build_flags} -D HELTEC_WIRELESS_PAPER -I variants/heltec_wireless_paper ${esp32s3_base.build_flags} -D HELTEC_WIRELESS_PAPER -I variants/heltec_wireless_paper
lib_deps = lib_deps =
${esp32s3_base.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

View File

@ -15,7 +15,16 @@
#define PIN_EINK_SCLK 3 #define PIN_EINK_SCLK 3
#define PIN_EINK_MOSI 2 #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 BUTTON_PIN 0
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage #define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage