diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9c9b2fffd..dcbb213b5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,11 +7,12 @@ jobs: setup: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - name: Checkout submodules - uses: textbook/git-checkout-submodule-action@master + - name: Checkout code + uses: actions/checkout@v2 + with: + submodules: true - name: Setup Python - uses: actions/setup-python@master + uses: actions/setup-python@v2 with: python-version: 3.x - name: Install Platform IO @@ -31,4 +32,4 @@ jobs: - name: Build for lora-relay-v1 run: platformio run -e lora-relay-v1 - name: Build for linux - run: platformio run -e linux \ No newline at end of file + run: platformio run -e linux diff --git a/bin/nrf52840-gdbserver.sh b/bin/nrf52840-gdbserver.sh index 15fb8fbff..010c1003f 100755 --- a/bin/nrf52840-gdbserver.sh +++ b/bin/nrf52840-gdbserver.sh @@ -1,3 +1,3 @@ -JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52840_XXAA +JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52840_XXAA -SuppressInfoUpdateFW -DisableAutoUpdateFW -rtos GDBServer/RTOSPlugin_FreeRTOS diff --git a/docs/software/TODO.md b/docs/software/TODO.md index 26fb08851..1649250de 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -29,6 +29,7 @@ You probably don't care about this section - skip to the next one. * DONE release protobufs * DONE release to developers * DONE fix setch-fast in python tool +* turn off fault 8: https://github.com/meshtastic/Meshtastic-device/issues/734 * age out pendingrequests in the python API * DONE stress test channel download from python, sometimes it seems like we don't get all replies, bug was due to simultaneous android connection * DONE combine acks and responses in a single message if possible (do routing plugin LAST and drop ACK if someone else has already replied) @@ -83,17 +84,32 @@ You probably don't care about this section - skip to the next one. eink: +* DONE check email of reported issues +* DONE turn off vbus driving (in bootloader) * new battery level sensing -* measure current draw +* current draw no good * DONE: fix backlight -* USB is busted because of power enable mode? +* DONE - USB is busted because of power enable mode? +* test CPU voltage? something is bad with RAM (removing eink module does not help) +* test that board leaves bootloader always +* test USB - works in bootloader +* test LEDs +* Test BME280 +* test gps +* check GPS fast locking +* tested! dlora +* test eink backlight +* tested! eink +* test buttons +* test battery charging +* test serial flash +* send updated app and bootloader image * OHH BME280! THAT IS GREAT! * make new screen work, ask for datasheet * say I think you could ship this * leds seem busted -* usb doesn't stay connected -* check GPS works -* check GPS fast locking +* fix hw_model: "nrf52unknown" +* use larger icon for meshtastic logo * send email about variants & faster flash programming - https://github.com/geeksville/Meshtastic-esp32/commit/f110225173a77326aac029321cdb6491bfa640f6 * send PR for bootloader * fix nrf52 time/date diff --git a/platformio.ini b/platformio.ini index d8ef51b7f..742bc6db6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,6 +16,7 @@ default_envs = tbeam ;default_envs = tlora-v2 ;default_envs = lora-relay-v1 # nrf board ;default_envs = eink +;default_envs = nrf52840dk-geeksville ;default_envs = linux # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here [common] @@ -33,6 +34,8 @@ default_envs = tbeam extra_scripts = bin/platformio-custom.py ; note: we add src to our include search path so that lmic_project_config can override +; note: TINYGPS_OPTION_NO_CUSTOM_FIELDS is VERY important. We don't use custom fields and somewhere in that pile +; of code is a heap corruption bug! ; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc build_flags = -Wno-missing-field-initializers -Wno-format @@ -40,7 +43,7 @@ build_flags = -Wno-missing-field-initializers -DHW_VERSION_${sysenv.COUNTRY} -DHW_VERSION=${sysenv.HW_VERSION} -DUSE_THREAD_NAMES - -DTINYGPSPLUS_OPTION_NO_CUSTOM_FIELDS + -DTINYGPS_OPTION_NO_CUSTOM_FIELDS ; leave this commented out to avoid breaking Windows ;upload_port = /dev/ttyUSB0 @@ -74,7 +77,7 @@ lib_deps = https://github.com/meshtastic/arduino-fsm.git#2f106146071fc7bc620e1e8d4b88dc4e0266ce39 https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad https://github.com/meshtastic/RadioLib.git#07de964e929238949035fb0d5887026a3058df1a - https://github.com/meshtastic/TinyGPSPlus.git#9c1d584d2469523381e077b0b9c1bf868d6c0206 + https://github.com/meshtastic/TinyGPSPlus.git#f0f47067ef2f67c856475933188251c1ef615e79 https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460 Wire ; explicitly needed here because the AXP202 library forgets to add it SPI @@ -184,7 +187,6 @@ src_filter = ; platform = nordicnrf52 platform = https://github.com/meshtastic/platform-nordicnrf52.git#1a2639a6b0f79b5df66bea3e3089f0d5285fdc63 extends = arduino_base -debug_tool = jlink build_type = debug ; I'm debugging with ICE a lot now ; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME) build_flags = @@ -198,6 +200,26 @@ lib_ignore = BluetoothOTA monitor_port = /dev/ttyACM1 +# we pass in options to jlink so it can understand freertos (note: we don't use "jlink" as the tool) +debug_tool = jlink +debug_port = :2331 +# Note: the ARGUMENTS MUST BE on multiple lines. Otherwise platformio/commands/debug/helpers.py misparses everything into the "executable" +# attribute and leaves "arguments" empty +# /home/kevinh/.platformio/packages/tool-jlink/JLinkGDBServerCLExe +debug_server = + /usr/bin/JLinkGDBServerCLExe + -singlerun + -if + SWD + -select + USB + -device + nRF52840_xxAA + -port + 2331 + -rtos + GDBServer/RTOSPlugin_FreeRTOS + debug_extra_cmds = source gdbinit diff --git a/proto b/proto index 7c025b9a4..e56f2770c 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 7c025b9a4d54bb410ec17ee653122861b413f177 +Subproject commit e56f2770c33216ba94f289e2fb7f0b2dfd33aca2 diff --git a/src/RedirectablePrint.cpp b/src/RedirectablePrint.cpp index c60b8a502..4c460d77f 100644 --- a/src/RedirectablePrint.cpp +++ b/src/RedirectablePrint.cpp @@ -1,9 +1,9 @@ #include "RedirectablePrint.h" +#include "concurrency/OSThread.h" #include "configuration.h" #include #include #include -#include "concurrency/OSThread.h" /** * A printer that doesn't go anywhere @@ -20,7 +20,7 @@ size_t RedirectablePrint::write(uint8_t c) { // Always send the characters to our segger JTAG debugger #ifdef SEGGER_STDOUT_CH - SEGGER_RTT_PutCharSkip(SEGGER_STDOUT_CH, c); + SEGGER_RTT_PutChar(SEGGER_STDOUT_CH, c); #endif dest->write(c); @@ -38,7 +38,7 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg) va_end(arg); return 0; }; - if (len >= printBufLen) { + if (len >= (int)printBufLen) { delete[] printBuf; printBufLen *= 2; printBuf = new char[printBufLen]; @@ -55,45 +55,52 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg) size_t RedirectablePrint::logDebug(const char *format, ...) { - va_list arg; - va_start(arg, format); - - // Cope with 0 len format strings, but look for new line terminator - bool hasNewline = *format && format[strlen(format) - 1] == '\n'; - size_t r = 0; - // If we are the first message on a report, include the header - if (!isContinuationMessage) { - struct timeval tv; - if (!gettimeofday(&tv, NULL)) { - long hms = tv.tv_sec % SEC_PER_DAY; - //hms += tz.tz_dsttime * SEC_PER_HOUR; - //hms -= tz.tz_minuteswest * SEC_PER_MIN; - // mod `hms` to ensure in positive range of [0...SEC_PER_DAY) - hms = (hms + SEC_PER_DAY) % SEC_PER_DAY; + if (!inDebugPrint) { + inDebugPrint = true; - // Tear apart hms into h:m:s - int hour = hms / SEC_PER_HOUR; - int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN; - int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN + va_list arg; + va_start(arg, format); - r += printf("%02d:%02d:%02d %u ", hour, min, sec, millis() / 1000); - } else - r += printf("??:??:?? %u ", millis() / 1000); + // Cope with 0 len format strings, but look for new line terminator + bool hasNewline = *format && format[strlen(format) - 1] == '\n'; - auto thread = concurrency::OSThread::currentThread; - if(thread) { - print("["); - print(thread->ThreadName); - print("] "); + // If we are the first message on a report, include the header + if (!isContinuationMessage) { + struct timeval tv; + if (!gettimeofday(&tv, NULL)) { + long hms = tv.tv_sec % SEC_PER_DAY; + // hms += tz.tz_dsttime * SEC_PER_HOUR; + // hms -= tz.tz_minuteswest * SEC_PER_MIN; + // mod `hms` to ensure in positive range of [0...SEC_PER_DAY) + hms = (hms + SEC_PER_DAY) % SEC_PER_DAY; + + // Tear apart hms into h:m:s + int hour = hms / SEC_PER_HOUR; + int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN; + int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN + + r += printf("%02d:%02d:%02d %u ", hour, min, sec, millis() / 1000); + } else + r += printf("??:??:?? %u ", millis() / 1000); + + auto thread = concurrency::OSThread::currentThread; + if (thread) { + print("["); + // printf("%p ", thread); + // assert(thread->ThreadName.length()); + print(thread->ThreadName); + print("] "); + } } + + r += vprintf(format, arg); + va_end(arg); + + isContinuationMessage = !hasNewline; + inDebugPrint = false; } - r += vprintf(format, arg); - va_end(arg); - - isContinuationMessage = !hasNewline; - return r; } \ No newline at end of file diff --git a/src/RedirectablePrint.h b/src/RedirectablePrint.h index ca208612c..1eb60199b 100644 --- a/src/RedirectablePrint.h +++ b/src/RedirectablePrint.h @@ -19,6 +19,8 @@ class RedirectablePrint : public Print /// Used to allow multiple logDebug messages to appear on a single log line bool isContinuationMessage = false; + volatile bool inDebugPrint = false; + public: RedirectablePrint(Print *_dest) : dest(_dest) {} diff --git a/src/SerialConsole.cpp b/src/SerialConsole.cpp index 9bb539fa5..ad1cf642a 100644 --- a/src/SerialConsole.cpp +++ b/src/SerialConsole.cpp @@ -1,13 +1,21 @@ #include "SerialConsole.h" +#include "NodeDB.h" #include "PowerFSM.h" #include "configuration.h" -#include "NodeDB.h" #include #define Port Serial SerialConsole console; +void consolePrintf(const char *format, ...) +{ + va_list arg; + va_start(arg, format); + console.vprintf(format, arg); + va_end(arg); +} + SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port) { canWrite = false; // We don't send packets to our port until it has talked to us first @@ -29,7 +37,7 @@ void SerialConsole::init() void SerialConsole::handleToRadio(const uint8_t *buf, size_t len) { // Turn off debug serial printing once the API is activated, because other threads could print and corrupt packets - if(!radioConfig.preferences.debug_log_enabled) + if (!radioConfig.preferences.debug_log_enabled) setDestination(&noopPrint); canWrite = true; diff --git a/src/SerialConsole.h b/src/SerialConsole.h index 17cb16943..b4f076286 100644 --- a/src/SerialConsole.h +++ b/src/SerialConsole.h @@ -32,4 +32,7 @@ class SerialConsole : public StreamAPI, public RedirectablePrint virtual void onConnectionChanged(bool connected); }; +// A simple wrapper to allow non class aware code write to the console +void consolePrintf(const char *format, ...); + extern SerialConsole console; diff --git a/src/concurrency/BinarySemaphoreFreeRTOS.cpp b/src/concurrency/BinarySemaphoreFreeRTOS.cpp index 983ee0955..3d8097455 100644 --- a/src/concurrency/BinarySemaphoreFreeRTOS.cpp +++ b/src/concurrency/BinarySemaphoreFreeRTOS.cpp @@ -1,5 +1,6 @@ #include "concurrency/BinarySemaphoreFreeRTOS.h" #include "configuration.h" +#include #ifdef HAS_FREE_RTOS @@ -9,6 +10,7 @@ namespace concurrency BinarySemaphoreFreeRTOS::BinarySemaphoreFreeRTOS() { semaphore = xSemaphoreCreateBinary(); + assert(semaphore); } BinarySemaphoreFreeRTOS::~BinarySemaphoreFreeRTOS() diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 04aa2c7af..abf7fc270 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -25,7 +25,7 @@ uint8_t GPS::i2cAddress = 0; GPS *gps; -/// Multiple GPS instances might use the same serial port (in sequence), but we can +/// Multiple GPS instances might use the same serial port (in sequence), but we can /// only init that port once. static bool didSerialInit; @@ -33,7 +33,7 @@ bool GPS::setupGPS() { if (_serial_gps && !didSerialInit) { didSerialInit = true; - + #ifdef GPS_RX_PIN _serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN); #else @@ -73,6 +73,13 @@ bool GPS::setup() return ok; } +GPS::~GPS() +{ + // we really should unregister our sleep observer + notifySleepObserver.unobserve(); + notifyDeepSleepObserver.unobserve(); +} + // Allow defining the polarity of the WAKE output. default is active high #ifndef GPS_WAKE_ACTIVE #define GPS_WAKE_ACTIVE 1 @@ -86,8 +93,8 @@ void GPS::wake() #endif } - -void GPS::sleep() { +void GPS::sleep() +{ #ifdef PIN_GPS_WAKE digitalWrite(PIN_GPS_WAKE, GPS_WAKE_ACTIVE ? 0 : 1); pinMode(PIN_GPS_WAKE, OUTPUT); @@ -158,7 +165,8 @@ uint32_t GPS::getWakeTime() const return t; // already maxint if (t == 0) - t = radioConfig.preferences.is_router ? 5 * 60 : 15 * 60; // Allow up to 15 mins for each attempt (probably will be much less if we can find sats) or less if a router + t = radioConfig.preferences.is_router ? 5 * 60 : 15 * 60; // Allow up to 15 mins for each attempt (probably will be much + // less if we can find sats) or less if a router t *= 1000; // msecs @@ -179,8 +187,8 @@ uint32_t GPS::getSleepTime() const if (t == UINT32_MAX) return t; // already maxint - if (t == 0) // default - unset in preferences - t = radioConfig.preferences.is_router ? 24 * 60 * 60 : 2 * 60; // 2 mins or once per day for routers + if (t == 0) // default - unset in preferences + t = radioConfig.preferences.is_router ? 24 * 60 * 60 : 2 * 60; // 2 mins or once per day for routers t *= 1000; diff --git a/src/gps/GPS.h b/src/gps/GPS.h index eca2962d2..9d25b2f83 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -47,7 +47,7 @@ class GPS : private concurrency::OSThread GPS() : concurrency::OSThread("GPS") {} - virtual ~GPS() {} // FIXME, we really should unregister our sleep observer + virtual ~GPS(); /** We will notify this observable anytime GPS state has changed meaningfully */ Observable newStatus; diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 6e52abdde..e341aea0b 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -143,11 +143,13 @@ static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int1 drawIconScreen(region, display, state, x, y); } +#ifdef HAS_EINK /// Used on eink displays while in deep sleep static void drawSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { drawIconScreen("Sleeping...", display, state, x, y); } +#endif static void drawPluginFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { @@ -791,7 +793,8 @@ void Screen::setup() powerStatusObserver.observe(&powerStatus->onNewStatus); gpsStatusObserver.observe(&gpsStatus->onNewStatus); nodeStatusObserver.observe(&nodeStatus->onNewStatus); - textMessageObserver.observe(textMessagePlugin); + if(textMessagePlugin) + textMessageObserver.observe(textMessagePlugin); } void Screen::forceDisplay() @@ -849,7 +852,7 @@ int32_t Screen::runOnce() free(cmd.print_text); break; default: - DEBUG_MSG("BUG: invalid cmd"); + DEBUG_MSG("BUG: invalid cmd\n"); } } diff --git a/src/main.cpp b/src/main.cpp index 495dc2f36..3282098ba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -279,7 +279,13 @@ void setup() concurrency::hasBeenSetup = true; #ifdef SEGGER_STDOUT_CH - SEGGER_RTT_ConfigUpBuffer(SEGGER_STDOUT_CH, NULL, NULL, 1024, SEGGER_RTT_MODE_NO_BLOCK_TRIM); + auto mode = true ? SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL : SEGGER_RTT_MODE_NO_BLOCK_TRIM; +#ifdef NRF52840_XXAA + auto buflen = 4096; // this board has a fair amount of ram +#else + auto buflen = 256; // this board has a fair amount of ram +#endif + SEGGER_RTT_ConfigUpBuffer(SEGGER_STDOUT_CH, NULL, NULL, buflen, mode); #endif #ifdef USE_SEGGER @@ -583,6 +589,9 @@ void loop() #ifndef NO_ESP32 esp32Loop(); #endif +#ifdef NRF52_SERIES + nrf52Loop(); +#endif // For debugging // if (rIf) ((RadioLibInterface *)rIf)->isActivelyReceiving(); diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 414930182..ab0a64b37 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -13,7 +13,7 @@ Channels channels; uint8_t xorHash(const uint8_t *p, size_t len) { uint8_t code = 0; - for (int i = 0; i < len; i++) + for (size_t i = 0; i < len; i++) code ^= p[i]; return code; } diff --git a/src/mesh/MemoryPool.h b/src/mesh/MemoryPool.h index dc6305d17..8023aa6bc 100644 --- a/src/mesh/MemoryPool.h +++ b/src/mesh/MemoryPool.h @@ -101,25 +101,30 @@ template class MemoryPool : public Allocator /// Return a buffer for use by others virtual void release(T *p) { - assert(dead.enqueue(p, 0)); assert(p >= buf && (size_t)(p - buf) < maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool + assert(dead.enqueue(p, 0)); } #ifdef HAS_FREE_RTOS /// Return a buffer from an ISR, if higherPriWoken is set to true you have some work to do ;-) void releaseFromISR(T *p, BaseType_t *higherPriWoken) { - assert(dead.enqueueFromISR(p, higherPriWoken)); assert(p >= buf && (size_t)(p - buf) < maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool + assert(dead.enqueueFromISR(p, higherPriWoken)); } #endif protected: /// Return a queable object which has been prefilled with zeros - allow timeout to wait for available buffers (you /// probably don't want this version). - virtual T *alloc(TickType_t maxWait) { return dead.dequeuePtr(maxWait); } + virtual T *alloc(TickType_t maxWait) + { + T *p = dead.dequeuePtr(maxWait); + assert(p); + return p; + } }; diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index a8f36a140..b7df1079e 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -25,7 +25,8 @@ typedef enum _CriticalErrorCode { CriticalErrorCode_UBloxInitFailed = 5, CriticalErrorCode_NoAXP192 = 6, CriticalErrorCode_InvalidRadioSetting = 7, - CriticalErrorCode_TransmitFailed = 8 + CriticalErrorCode_TransmitFailed = 8, + CriticalErrorCode_Brownout = 9 } CriticalErrorCode; typedef enum _Routing_Error { @@ -177,8 +178,8 @@ typedef struct _ToRadio { #define _Constants_ARRAYSIZE ((Constants)(Constants_DATA_PAYLOAD_LEN+1)) #define _CriticalErrorCode_MIN CriticalErrorCode_None -#define _CriticalErrorCode_MAX CriticalErrorCode_TransmitFailed -#define _CriticalErrorCode_ARRAYSIZE ((CriticalErrorCode)(CriticalErrorCode_TransmitFailed+1)) +#define _CriticalErrorCode_MAX CriticalErrorCode_Brownout +#define _CriticalErrorCode_ARRAYSIZE ((CriticalErrorCode)(CriticalErrorCode_Brownout+1)) #define _Routing_Error_MIN Routing_Error_NONE #define _Routing_Error_MAX Routing_Error_TOO_LARGE diff --git a/src/nrf52/hardfault.cpp b/src/nrf52/hardfault.cpp index c1a82d6ae..d63829072 100644 --- a/src/nrf52/hardfault.cpp +++ b/src/nrf52/hardfault.cpp @@ -82,8 +82,34 @@ extern "C" void HardFault_Impl(uint32_t stack[]) // while (1) ; } +#ifndef INC_FREERTOS_H +// This is a generic cortex M entrypoint that doesn't assume freertos + extern "C" void HardFault_Handler(void) { asm volatile(" mrs r0,msp\n" " b HardFault_Impl \n"); } +#else + +/* The prototype shows it is a naked function - in effect this is just an +assembly function. */ +extern "C" void HardFault_Handler( void ) __attribute__( ( naked ) ); + +/* The fault handler implementation calls a function called +prvGetRegistersFromStack(). */ +extern "C" void HardFault_Handler(void) +{ + __asm volatile + ( + " tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + " ldr r1, [r0, #24] \n" + " ldr r2, handler2_address_const \n" + " bx r2 \n" + " handler2_address_const: .word HardFault_Impl \n" + ); +} +#endif diff --git a/src/nrf52/main-nrf52.cpp b/src/nrf52/main-nrf52.cpp index 8b7bb65b9..1ba0602b9 100644 --- a/src/nrf52/main-nrf52.cpp +++ b/src/nrf52/main-nrf52.cpp @@ -1,5 +1,6 @@ #include "NRF52Bluetooth.h" #include "configuration.h" +#include "error.h" #include "graphics/TFTDisplay.h" #include #include @@ -51,14 +52,14 @@ void getMacAddr(uint8_t *dmac) NRF52Bluetooth *nrf52Bluetooth; static bool bleOn = false; -static const bool enableBle = false; // Set to false for easier debugging +static const bool useSoftDevice = false; // Set to false for easier debugging void setBluetoothEnable(bool on) { if (on != bleOn) { if (on) { if (!nrf52Bluetooth) { - if (!enableBle) + if (!useSoftDevice) DEBUG_MSG("DISABLING NRF52 BLUETOOTH WHILE DEBUGGING\n"); else { nrf52Bluetooth = new NRF52Bluetooth(); @@ -87,6 +88,49 @@ int printf(const char *fmt, ...) #include "BQ25713.h" +void initBrownout() +{ + auto vccthresh = POWER_POFCON_THRESHOLD_V28; + auto vcchthresh = POWER_POFCON_THRESHOLDVDDH_V27; + + if (useSoftDevice) { + auto err_code = sd_power_pof_enable(POWER_POFCON_POF_Enabled); + assert(err_code == NRF_SUCCESS); + + err_code = sd_power_pof_threshold_set(vccthresh); + assert(err_code == NRF_SUCCESS); + } + else { + NRF_POWER->POFCON = POWER_POFCON_POF_Msk | (vccthresh << POWER_POFCON_THRESHOLD_Pos) | (vcchthresh << POWER_POFCON_THRESHOLDVDDH_Pos); + } +} + +void checkSDEvents() +{ + if (useSoftDevice) { + uint32_t evt; + while (NRF_ERROR_NOT_FOUND == sd_evt_get(&evt)) { + switch (evt) { + case NRF_EVT_POWER_FAILURE_WARNING: + recordCriticalError(CriticalErrorCode_Brownout); + break; + + default: + DEBUG_MSG("Unexpected SDevt %d\n", evt); + break; + } + } + } else { + if(NRF_POWER->EVENTS_POFWARN) + recordCriticalError(CriticalErrorCode_Brownout); + } +} + +void nrf52Loop() +{ + checkSDEvents(); +} + void nrf52Setup() { @@ -112,6 +156,8 @@ void nrf52Setup() // randomSeed(r); DEBUG_MSG("FIXME, call randomSeed\n"); // ::printf("TESTING PRINTF\n"); + + initBrownout(); } void cpuDeepSleep(uint64_t msecToWake) @@ -128,7 +174,7 @@ void cpuDeepSleep(uint64_t msecToWake) // https://devzone.nordicsemi.com/f/nordic-q-a/48919/ram-retention-settings-with-softdevice-enabled auto ok = sd_power_system_off(); - if(ok != NRF_SUCCESS) { + if (ok != NRF_SUCCESS) { DEBUG_MSG("FIXME: Ignoring soft device (EasyDMA pending?) and forcing system-off!\n"); NRF_POWER->SYSTEMOFF = 1; } diff --git a/src/plugins/ExternalNotificationPlugin.cpp b/src/plugins/ExternalNotificationPlugin.cpp index 42865f3cc..0320c7b30 100644 --- a/src/plugins/ExternalNotificationPlugin.cpp +++ b/src/plugins/ExternalNotificationPlugin.cpp @@ -114,7 +114,8 @@ int32_t ExternalNotificationPlugin::runOnce() return (INT32_MAX); } - +#else + return INT32_MAX; #endif } diff --git a/src/plugins/NodeInfoPlugin.cpp b/src/plugins/NodeInfoPlugin.cpp index f5f3ae194..5111d7b87 100644 --- a/src/plugins/NodeInfoPlugin.cpp +++ b/src/plugins/NodeInfoPlugin.cpp @@ -19,9 +19,11 @@ bool NodeInfoPlugin::handleReceivedProtobuf(const MeshPacket &mp, const User *pp // Show new nodes on LCD screen if (wasBroadcast) { String lcd = String("Joined: ") + p.long_name + "\n"; - screen->print(lcd.c_str()); + if(screen) + screen->print(lcd.c_str()); } + // DEBUG_MSG("did handleReceived\n"); return false; // Let others look at this message also if they want } diff --git a/src/plugins/SerialPlugin.cpp b/src/plugins/SerialPlugin.cpp index c93bf8521..9aab876f9 100644 --- a/src/plugins/SerialPlugin.cpp +++ b/src/plugins/SerialPlugin.cpp @@ -124,7 +124,8 @@ int32_t SerialPlugin::runOnce() return (INT32_MAX); } - +#else + return INT32_MAX; #endif } diff --git a/variants/eink/variant.h b/variants/eink/variant.h index 4cdb33e45..66a42421f 100644 --- a/variants/eink/variant.h +++ b/variants/eink/variant.h @@ -99,16 +99,16 @@ extern "C" { #define NUM_ANALOG_OUTPUTS (0) // LEDs -#define PIN_LED1 (0 + 13) // red (confirmed on 1.0 board) -#define PIN_LED2 (0 + 14) // blue (seems busted!) -#define PIN_LED3 (0 + 15) // green (seems busted!) +#define PIN_LED1 (0 + 14) // 13 red (confirmed on 1.0 board) +#define PIN_LED2 (0 + 15) // 14 blue +#define PIN_LED3 (0 + 13) // 15 green #define LED_RED PIN_LED3 -#define LED_GREEN PIN_LED1 -#define LED_BLUE PIN_LED2 +#define LED_BLUE PIN_LED1 +#define LED_GREEN PIN_LED2 -#define LED_BUILTIN LED_GREEN -#define LED_CONN PIN_BLUE +#define LED_BUILTIN LED_BLUE +#define LED_CONN PIN_GREEN #define LED_STATE_ON 0 // State when LED is lit #define LED_INVERTED 1 @@ -192,6 +192,9 @@ External serial flash WP25R1635FZUIL0 // #define LORA_DISABLE_SENDING // Define this to disable transmission for testing (power testing etc...) +// #undef SX1262_CS +// #define USE_SIM_RADIO // define to not use the lora radio hardware at all + /* * eink display pins */