phoddie / node-red-mcu

Node-RED for microcontrollers
124 stars 18 forks source link

node-red-mcu & Watchdog: Communication to xsbug/editor not operational #58

Closed ralphwetzel closed 1 year ago

ralphwetzel commented 1 year ago

Hello Peter! I'm trying to add watchdog support to node-red-mcu, following the example given by @mkellner. The implementation is quite easy, yet if compiled with this, the MCU doesn't connect to xsbug anymore - and thus the connection to the editor is broken as well. The MCU still launches as expected & even runs the flow smoothly... I've setup this small flow to test w/ an esp32/m5atom_lite:

image
Test case ```json [ { "id": "f29b4bc20ba7697c", "type": "tab", "label": "Flow 11", "disabled": false, "info": "", "env": [], "_mcu": { "mcu": true } }, { "id": "2101829c33a21b57", "type": "debug", "z": "f29b4bc20ba7697c", "name": "debug 66", "active": true, "tosidebar": true, "console": false, "tostatus": true, "complete": "true", "targetType": "full", "statusVal": "payload", "statusType": "msg", "_mcu": { "mcu": true }, "x": 600, "y": 280, "wires": [] }, { "id": "7f45f705c6d6e0c6", "type": "inject", "z": "f29b4bc20ba7697c", "name": "3s", "props": [ { "p": "payload" } ], "repeat": "3", "crontab": "", "once": true, "onceDelay": "3", "topic": "", "payload": "", "payloadType": "date", "_mcu": { "mcu": true }, "x": 450, "y": 220, "wires": [ [ "44d0407a75448df9", "2101829c33a21b57" ] ] }, { "id": "f9a82948d74db494", "type": "mcu-function", "z": "f29b4bc20ba7697c", "name": "LED", "func": "let np = context.get(\"np\");\nif (!np) return;\n\nlet on = msg.payload;\nlet rgb = on === true ? np.makeRGB(255, 255, 255) : np.makeRGB(0, 0, 0);\nnp.fill(rgb);\nnp.update();\n\nnode.status(on ? {fill: \"yellow\", shape:\"dot\"} : {});\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "// Der Code hier wird ausgeführt,\n// wenn der Node gestartet wird\ncontext.set(\"np\", globalThis.lights);", "libs": [], "_mcu": { "mcu": true }, "x": 730, "y": 220, "wires": [ [] ] }, { "id": "44d0407a75448df9", "type": "trigger", "z": "f29b4bc20ba7697c", "name": "0,5s", "op1": "true", "op2": "false", "op1type": "bool", "op2type": "bool", "duration": "500", "extend": false, "overrideDelay": false, "units": "ms", "reset": "", "bytopic": "all", "topic": "topic", "outputs": 1, "_mcu": { "mcu": true }, "x": 590, "y": 220, "wires": [ [ "f9a82948d74db494" ] ] } ] ```

WDT support is enabled by adding SDKCONFIGPATH to the created manifest.json section build, pointing to a directory that holds a single file called sdkconfig.defaults with the content shown in the example (no modifications).

As said: The flow builds & runs as expected; just the link to xsbug is not operational. In fact, there's no message emitted by the MCU at all - even in debug mode w/ mcconfig -d -m -p esp32/m5atom_lite. Is this by design or something we can address?

phoddie commented 1 year ago

It isn't by design. In theory it could work. We don't generally use the watchdog with debug builds, however. That's because being paused in a breakpoint in the debugger could be enough to trigger the watchdog (the task is blocked!). And the Node-RED MCU plugin depends on the debugger connection. You say that the flow works, so the problem is not that the watchdog is constantly causing a reset. I'll take a look to see what might be going on.

phoddie commented 1 year ago

For some reason, enabling the watch-dog timer prevents the xsbug handshake from succeeding. The MCU initiates the connection, but it doesn't see the response, so it timeout trying to connect, and runs without the debugger connection.

The interrupt watch-dog (enabled with CONFIG_INT_WDT does not cause problems. It is enabling the task watch-dog (CONFIG_TASK_WDT=y) that causes the problem. It seems unrelated to the watch-dog timeout value as increasing CONFIG_TASK_WDT_TIMEOUT_S from 10 to 100 does not change the behavior.

Strictly speaking, I don't think this is a Node-RED MCU Edition issue, some unpleasant interplay of ESP-IDF features. We can leave it open here for now.

phoddie commented 1 year ago

When the watchdog is enabled, the bytes sent over serial to the ESP32 are garbled. I have no idea why. The workaround is to drop the baud rate to 115200 from 460800. That makes debugging slower, but it works. You configure that by setting DEBUGGER_SPEED=115200 in your environment variables.

Additionally, the ESP-IDF has changed the macro names for the watchdog. This is an updated SDKCONFIG fragment for enabling the watchdog. The ESP-IDF automatically maps the older names, but better to be up-to-date:

CONFIG_ESP_INT_WDT=y
CONFIG_ESP_INT_WDT_TIMEOUT_MS=300
CONFIG_ESP_INT_WDT_CHECK_CPU1=y
CONFIG_ESP_TASK_WDT=y
CONFIG_ESP_TASK_WDT_PANIC=y
CONFIG_ESP_TASK_WDT_TIMEOUT_S=10
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y

I've updated the Moddable SDK code to use the newer names. That will be available in the coming days.

When stopped at a breakpoint, the FreeRTOS idle tasks get starved while XS blocks execution. That causes the watchdog will fire on the IDLE tasks, even if it is reset for the running task. To avoid that, the watchdog needs to be reset in fxReceiveLoop (I've made that change too). And... you need to disable the watchdog in the idle tasks:

CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=n

But... my advice: don't enable the watchdog for debug builds. It is a feature to catch catastrophic failures in production. If your scripts get stuck while developing, you can just stop in xsbug with Break to debug the code.