gin66 / FastAccelStepper

A high speed stepper library for Atmega 168/328p (nano), Atmega32u4, Atmega 2560, ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C6 and Atmel SAM Due
MIT License
316 stars 73 forks source link

ESP32 Core panic in "apply_command" #55

Closed oaklandGman closed 3 years ago

oaklandGman commented 3 years ago

I have a very basic sketch, a simple webserver and websocket server, currently hosting a static page, but eventually there will be more. In loop() I'm polling the stepper every 500ms, to see if it's moving, pretty much just running the motor back and forth continuously, different amounts and different speeds.

The ESP32 runs the stepper just fine, until I talk to the webserver, or connect via websocket, then the ESP reboots. I've tried pinning my stepper code to core 0, core 1, or leaving it in loop, no change.

Here's the code I'm using to move the motor, via freertos pinned task

From what I'm reading, it has to do with accessing data / routines from outside the ISR? Whoosh over my head,

void runStepper(void * parameter) {
  unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  uint localMove = 0;

  for (;;) { // loop forever
    currentMillis = millis();  

    if (currentMillis - previousMillis >= 500) {
      previousMillis = millis();
      if (!big_motor->isMotorRunning()) { // test to see if motor is done moving
        Serial.println("Big motor done!");

        big_motor->setSpeedInHz(bigmotorSpeed);
        bigmotorDir = bigmotorDir ^ 1; // flip direction
        if (bigmotorDir) {
          localMove = bigmotorMove;
        } else {
          bigmotorSpeed = bigmotorSpeed + 100; // increase speed
          if (bigmotorSpeed > BIG_MOTOR_HZ) { // reset speed
            bigmotorSpeed = 100;
          }
          localMove = bigmotorMove * (-1);
          bigmotorMove = bigmotorMove + 50; // increase travel
          if (bigmotorMove > 1000) { // reset travel
            bigmotorMove = 50;
          }
        }

        big_motor->move(localMove);
        Serial.printf("Big motor speed %u, moving %i steps\n", bigmotorSpeed, localMove);
      } else {
        Serial.println("M");
      }
    }

    delay(5);

  } 
}

Here's the full panic and stack dump decode.

Guru Meditation Error: Core  1 panic'ed (Cache disabled but cached memory region accessed)
Core 1 register dump:
PC      : 0x40080ff1  PS      : 0x00060034  A0      : 0x800811a5  A1      : 0x3ffbe720
A2      : 0x3ffc1664  A3      : 0x3ffc16d0  A4      : 0x00060021  A5      : 0x3ff5e000
A6      : 0x00000001  A7      : 0x3f401950  A8      : 0x00000001  A9      : 0x00000001
A10     : 0x0000000a  A11     : 0x3ffd4ed0  A12     : 0x80154e3e  A13     : 0x3ffd4e80
A14     : 0x00000100  A15     : 0x3ffd0b80  SAR     : 0x0000001e  EXCCAUSE: 0x00000007  
EXCVADDR: 0x00000000  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0x00000000
Core 1 was running in ISR context:
EPC1    : 0x4009280a  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x40080ff1

Backtrace: 0x40080ff1:0x3ffbe720 0x400811a2:0x3ffbe750 0x40081241:0x3ffbe770 0x400851c2:0x3ffbe790 0x400824ed:0x3ffbe7b0 0x40084a81:0x3ffbe7d0 0x40092807:0x3ffd4e40 0x40093091:0x3ffd4e60 0x40087534:0x3ffd4e80 0x40154e3b:0x3ffd4ef0 0x400f5e85:0x3ffd4f20 0x400f60bf:0x3ffd4f50 0x400f7633:0x3ffd4f80 0x400f91ae:0x3ffd4fc0 0x400f5a70:0x3ffd5000 0x400f4778:0x3ffd5030 0x401205c9:0x3ffd5090 0x4000bcc5:0x3ffd50b0 0x40184d85:0x3ffd50d0 0x40176959:0x3ffd50f0 0x40175e48:0x3ffd5170 0x40175e6f:0x3ffd51a0 0x400d874f:0x3ffd51c0 0x400d8941:0x3ffd5270 0x400d8aa5:0x3ffd52b0 0x400ddcbe:0x3ffd52e0 0x400dad65:0x3ffd5310 0x400dae65:0x3ffd5350 0x400db0c9:0x3ffd5390 0x40175299:0x3ffd53b0 0x40175315:0x3ffd53f0 0x401759ba:0x3ffd5410 0x40088ec9:0x3ffd5440

Rebooting...
ets Jun  8 2016 00:22:57

PC: 0x40080ff1: apply_command(StepperQueue*, queue_entry const*) at .pio\libdeps\wifi\FastAccelStepper\src\StepperISR_esp32.cpp line 98
EXCVADDR: 0x00000000

Decoding stack results
0x40080ff1: apply_command(StepperQueue*, queue_entry const*) at .pio\libdeps\wifi\FastAccelStepper\src\StepperISR_esp32.cpp line 98
0x400811a2: what_is_next(StepperQueue*) at .pio\libdeps\wifi\FastAccelStepper\src\StepperISR_esp32.cpp line 189
0x40081241: pcnt_isr_service(void*) at .pio\libdeps\wifi\FastAccelStepper\src\StepperISR_esp32.cpp line 204
0x400851c2: pcnt_intr_service at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/pcnt.c line 303
0x400824ed: shared_intr_isr at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/intr_alloc.c line 504
0x40092807: esp_rom_spiflash_read_data at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/spi_flash_rom_patch.c line 222
0x40093091: esp_rom_spiflash_read at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/spi_flash_rom_patch.c line 587
0x40087534: spi_flash_read at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/flash_ops.c line 567
0x40154e3b: esp_partition_read at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/partition.c line 242
0x400f5e85: spiffs_api_read at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/spiffs_api.c line 36
0x400f60bf: spiffs_phys_rd at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/spiffs/src/spiffs_cache.c line 161
0x400f7633: spiffs_obj_lu_find_entry_visitor at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/spiffs/src/spiffs_nucleus.c line 166
0x400f91ae: spiffs_object_find_object_index_header_by_name at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/spiffs/src/spiffs_nucleus.c line 1694
0x400f5a70: SPIFFS_stat at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/spiffs/src/spiffs_hydrogen.c line 765
0x400f4778: vfs_spiffs_stat at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/esp_spiffs.c line 536
0x401205c9: esp_vfs_stat at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/vfs/vfs.c line 492
0x40184d85: stat at ../../../.././newlib/libc/syscalls/sysstat.c line 12
0x40176959: VFSImpl::open(char const*, char const*) at C:\users\glmcl\.platformio\packages\framework-arduinoespressif32\libraries\FS\src\vfs_api.cpp line 41
0x40175e48: fs::FS::open(char const*, char const*) at C:\users\glmcl\.platformio\packages\framework-arduinoespressif32\libraries\FS\src\FS.cpp line 191
0x40175e6f: fs::FS::open(String const&, char const*) at C:\users\glmcl\.platformio\packages\framework-arduinoespressif32\libraries\FS\src\FS.cpp line 182
0x400d874f: AsyncStaticWebHandler::_fileExists(AsyncWebServerRequest*, String const&) at .pio\libdeps\wifi\ESP Async WebServer\src\WebHandlers.cpp line 152
0x400d8941: AsyncStaticWebHandler::_getFile(AsyncWebServerRequest*) at .pio\libdeps\wifi\ESP Async WebServer\src\WebHandlers.cpp line 116
0x400d8aa5: AsyncStaticWebHandler::canHandle(AsyncWebServerRequest*) at .pio\libdeps\wifi\ESP Async WebServer\src\WebHandlers.cpp line 90
0x400ddcbe: AsyncWebServer::_attachHandler(AsyncWebServerRequest*) at .pio\libdeps\wifi\ESP Async WebServer\src\WebServer.cpp line 116
0x400dad65: AsyncWebServerRequest::_parseLine() at .pio\libdeps\wifi\ESP Async WebServer\src\WebRequest.cpp line 571
0x400dae65: AsyncWebServerRequest::_onData(void*, unsigned int) at .pio\libdeps\wifi\ESP Async WebServer\src\WebRequest.cpp line 123
0x400db0c9: std::_Function_handler   >::_M_invoke(const std::_Any_data &, void *&&, AsyncClient *&&, void *&&, unsigned int &&) at .pio\libdeps\wifi\ESP Async WebServer\src\WebRequest.cpp line 76
0x40175299: AsyncClient::_recv(tcp_pcb*, pbuf*, signed char) at c:\users\glmcl\.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional line 2271
0x40175315: AsyncClient::_s_recv(void*, tcp_pcb*, pbuf*, signed char) at .pio\libdeps\wifi\AsyncTCP\src\AsyncTCP.cpp line 1191
0x401759ba: _async_service_task(void*) at .pio\libdeps\wifi\AsyncTCP\src\AsyncTCP.cpp line 159
0x40088ec9: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143
gin66 commented 3 years ago

Thanks for the detailed and informative report. Till now, I haven't used FastAccelStepper on esp32 with webserver/websocket and too haven't run into this problem.

Two things:

oaklandGman commented 3 years ago

Here is my code ... you should be able to see the motor getting movement commands, then make a request to /hello or /head and esp will panic. The code block to move the stepper can be in a task, or in loop(), the crash remains the same.

I'll give the latest commit a try and report back! Thanks for the response.

#include <Arduino.h>
#include <ArduinoOTA.h>
#include <SPIFFS.h>
#include <FastAccelStepper.h>
#include <ESPAsyncWebServer.h>
#include <ESPmDNS.h>
#include <SPIFFSEditor.h>

AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
AsyncEventSource events("/events");

const char* ssid = "xxx";
const char* password = "xxx";
const char* PARAM_MESSAGE = "Machine Control";
const char * hostName = "machine";
const char* http_username = "xxx";
const char* http_password = "xxx";

// IO pin assignments
const int BIG_MOTOR_STEP = 19;
const int BIG_MOTOR_DIR = 21;
const int BIG_MOTOR_SLEEP = 22;
const int SMALL_MOTOR_STEP = 25;
const int SMALL_MOTOR_DIR = 23;
const int SMALL_MOTOR_SLEEP = 26;

const int EMERGENCY_STOP_PIN = 35; //define the IO pin the emergency stop switch is connected to
const int LIMIT_SW1 = 33;
const int LIMIT_SW2 = 27;

// Speed settings
const unsigned int BIG_MOTOR_HZ = 9000;
const unsigned int BIG_MOTOR_ACCEL = 40000;
const unsigned int SMALL_MOTOR_HZ = 200;
const unsigned int SMALL_MOTOR_ACCEL = 4294967295;

unsigned int bigmotorSpeed = 100;
unsigned int smallmotorSpeed = SMALL_MOTOR_HZ;
unsigned int bigmotorMove = 50;
bool bigmotorDir = true;

TaskHandle_t taskStepper;
TaskHandle_t taskOTA;

FastAccelStepperEngine engine = FastAccelStepperEngine();
FastAccelStepper *big_motor = NULL;
FastAccelStepper *small_motor = NULL;

void runStepper(void * parameter) {
  unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  uint localMove = 0;

  for (;;) { // loop forever
    currentMillis = millis();  

    if (currentMillis - previousMillis >= 500) {
      previousMillis = millis();
      if (!big_motor->isMotorRunning()) { // test to see if motor is done moving
        Serial.println("Big motor done!");

        big_motor->setSpeedInHz(bigmotorSpeed);
        bigmotorDir = bigmotorDir ^ 1; // flip direction
        if (bigmotorDir) {
          localMove = bigmotorMove;
        } else {
          bigmotorSpeed = bigmotorSpeed + 100; // increase speed
          if (bigmotorSpeed > BIG_MOTOR_HZ) { // reset speed
            bigmotorSpeed = 100;
          }
          localMove = bigmotorMove * (-1);
          bigmotorMove = bigmotorMove + 50; // increase travel
          if (bigmotorMove > 1000) { // reset travel
            bigmotorMove = 50;
          }
        }

        big_motor->move(localMove);
        Serial.printf("Big motor speed %u, moving %i steps\n", bigmotorSpeed, localMove);
      } else {
        Serial.println("M");
      }

      // if (!small_motor->isMotorRunning()) {
      //   // Serial.println("Small motor done!");
      //   Serial.println("Small motor moving 1000 steps.");
      //   small_motor->move(2000);
      // } else {
      //   Serial.println("L");
      // }
    }

    delay(5);

  } 
}

void runOTA(void * parameter) {
}

void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){
  if(type == WS_EVT_CONNECT){
    //client connected
    Serial.printf("ws[%s][%u] connect\n", server->url(), client->id());
    client->printf("Hello Client %u :)", client->id());
    client->ping();
  } else if(type == WS_EVT_DISCONNECT){
    Serial.printf("ws[%s][%u] disconnect: %u\n", server->url(), client->id());

  } else if(type == WS_EVT_ERROR){
    //error was received from the other end
    Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data);
  } 
}

void setup(){
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", "Hello World");
  });

  ArduinoOTA
    .onStart([]() {
      String type;
      // big_motor.stop();
      // small_motor.stop();
      big_motor->forceStopAndNewPosition(0);
      small_motor->forceStopAndNewPosition(0);

      digitalWrite(BIG_MOTOR_SLEEP, LOW); // turn off driver
      digitalWrite(SMALL_MOTOR_SLEEP, LOW); // turn off driver
      if (ArduinoOTA.getCommand() == U_FLASH)
        type = "sketch";
      else // U_SPIFFS
        type = "filesystem";

      // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
      Serial.println("Start updating " + type);
    })
    .onEnd([]() {
      Serial.println("\nEnd");
    })
    .onProgress([](unsigned int progress, unsigned int total) {
      Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    })
    .onError([](ota_error_t error) {
      Serial.printf("Error[%u]: ", error);
      if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
      else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
      else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
      else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
      else if (error == OTA_END_ERROR) Serial.println("End Failed");
    });

  ArduinoOTA.setHostname(hostName);
  ArduinoOTA.begin();

  MDNS.addService("http","tcp",80);

  SPIFFS.begin();

  ws.onEvent(onWsEvent);
  server.addHandler(&ws);

  events.onConnect([](AsyncEventSourceClient *client){
    client->send("hello!",NULL,millis(),1000);
  });

  server.addHandler(&events);

  server.addHandler(new SPIFFSEditor(SPIFFS, http_username,http_password));

  server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", String(ESP.getFreeHeap()));
  });

  server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html");

  server.onNotFound([](AsyncWebServerRequest *request){
    Serial.printf("NOT_FOUND: ");
    if(request->method() == HTTP_GET)
      Serial.printf("GET");
    else if(request->method() == HTTP_POST)
      Serial.printf("POST");
    else if(request->method() == HTTP_DELETE)
      Serial.printf("DELETE");
    else if(request->method() == HTTP_PUT)
      Serial.printf("PUT");
    else if(request->method() == HTTP_PATCH)
      Serial.printf("PATCH");
    else if(request->method() == HTTP_HEAD)
      Serial.printf("HEAD");
    else if(request->method() == HTTP_OPTIONS)
      Serial.printf("OPTIONS");
    else
      Serial.printf("UNKNOWN");
    Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str());

    if(request->contentLength()){
      Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str());
      Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength());
    }

    int headers = request->headers();
    int i;
    for(i=0;i<headers;i++){
      AsyncWebHeader* h = request->getHeader(i);
      Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str());
    }

    int params = request->params();
    for(i=0;i<params;i++){
      AsyncWebParameter* p = request->getParam(i);
      if(p->isFile()){
        Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
      } else if(p->isPost()){
        Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
      } else {
        Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
      }
    }

    request->send(404);
  });
  server.onFileUpload([](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){
    if(!index)
      Serial.printf("UploadStart: %s\n", filename.c_str());
    Serial.printf("%s", (const char*)data);
    if(final)
      Serial.printf("UploadEnd: %s (%u)\n", filename.c_str(), index+len);
  });
  server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){
    if(!index)
      Serial.printf("BodyStart: %u\n", total);
    Serial.printf("%s", (const char*)data);
    if(index + len == total)
      Serial.printf("BodyEnd: %u\n", total);
  });

  server.begin();

  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  engine.init();
  big_motor = engine.stepperConnectToPin(BIG_MOTOR_STEP);
  small_motor = engine.stepperConnectToPin(SMALL_MOTOR_STEP);

  if (big_motor) { // set up drive motor
    big_motor->setDirectionPin(BIG_MOTOR_DIR);
    big_motor->setEnablePin(BIG_MOTOR_SLEEP);
    big_motor->setAutoEnable(false);

    big_motor->setSpeedInHz(BIG_MOTOR_HZ);      
    big_motor->setAcceleration(BIG_MOTOR_ACCEL);   
  } 

  if (small_motor) { // set up small motor
    small_motor->setDirectionPin(SMALL_MOTOR_DIR);
    small_motor->setEnablePin(SMALL_MOTOR_SLEEP);
    small_motor->setAutoEnable(true);

    small_motor->setSpeedInHz(SMALL_MOTOR_HZ);      
    small_motor->setAcceleration(SMALL_MOTOR_ACCEL);   
  }

  digitalWrite(SMALL_MOTOR_SLEEP, LOW); // turn off driver

  // small_motor->move(1000); // test motor
  // big_motor->move(1000); // test motor

  xTaskCreatePinnedToCore(
    runStepper, /* Function to implement the task */
    "taskStepper", /* Name of the task */
    10000,  /* Stack size in words */
    NULL,  /* Task input parameter */
    0,  /* Priority of the task */
    &taskStepper,  /* Task handle. */
    0); /* Core where the task should run */

  //  xTaskCreatePinnedToCore(
  //    runOTA, /* Function to implement the task */
  //    "taskOTA", /* Name of the task */
  //    10000,  /* Stack size in words */
  //    NULL,  /* Task input parameter */
  //    0,  /* Priority of the task */
  //    &taskOTA,  /* Task handle. */
  //    0); /* Core where the task should run */
}

void loop(){
  ArduinoOTA.handle();
  ws.cleanupClients(); // clean up any disconnected ws clients

  delay(10);
}
oaklandGman commented 3 years ago

Your last commit looks like it solved the issue, I can talk to the webserver and the motor commands keep updating (via serial output), not sure if the webserver is stealing time from the ISR, I don't have the board plugged into the motors right now.

oaklandGman commented 3 years ago

Maybe I was premature in celebration. It appears if the request to the webserver takes too long, I still get a panic. I was trying to open an app called SPIFFSEDIT and poof... I don't plan to use this feature while the motors are running, so I'll need to code up a way to shut down the motors, before the esp freaks out and has a panic. My eventual use case is just monitoring motor speed and position via websockets, and sending slight corrections from a basic user interface.

Guru Meditation Error: Core  1 panic'ed (Cache disabled but cached memory region accessed)
Core 1 register dump:
PC      : 0x40080ff3  PS      : 0x00060034  A0      : 0x800811ad  A1      : 0x3ffbe730
A2      : 0x3ffc1788  A3      : 0x3ffc17e4  A4      : 0x3ff5e000  A5      : 0x3ffd4f20
A6      : 0x00000001  A7      : 0x3ffd5638  A8      : 0xbad00bad  A9      : 0x00000001
A10     : 0x0000000a  A11     : 0x3ffd5070  A12     : 0x80154dfa  A13     : 0x3ffd5020
A14     : 0x3f403d30  A15     : 0x3ffd0c98  SAR     : 0x00000015  EXCCAUSE: 0x00000007  
EXCVADDR: 0x00000000  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0x00000000
Core 1 was running in ISR context:
EPC1    : 0x40092806  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x40080ff3

Backtrace: 0x40080ff3:0x3ffbe730 0x400811aa:0x3ffbe750 0x40081249:0x3ffbe770 0x400851ca:0x3ffbe790 0x400824f5:0x3ffbe7b0 0x40084a89:0x3ffbe7d0 0x40092803:0x3ffd4fe0 0x40093099:0x3ffd5000 0x4008753c:0x3ffd5020 0x40154df7:0x3ffd5090 0x400f5e45:0x3ffd50c0 0x400f607f:0x3ffd50f0 0x400f75f3:0x3ffd5120 0x400f916e:0x3ffd5160 0x400f5a30:0x3ffd51a0 0x400f4738:0x3ffd51d0 0x40120585:0x3ffd5230 0x4000bcc5:0x3ffd5250 0x40184d41:0x3ffd5270 0x40176915:0x3ffd5290 0x40175e04:0x3ffd5310 0x40175e2b:0x3ffd5340 0x400d5dda:0x3ffd5360 0x400d9ac1:0x3ffd5470 0x400d9b85:0x3ffd54b0 0x400d9de9:0x3ffd54f0 0x40175255:0x3ffd5510 0x401752d1:0x3ffd5550 0x40175976:0x3ffd5570 0x40088ed1:0x3ffd55a0

PC: 0x40080ff3: apply_command(StepperQueue*, queue_entry const*) at .pio\libdeps\pc\FastAccelStepper@src-a564200d5afe0cb1a1a376e0516aa23f\src\StepperISR_esp32.cpp line 100
EXCVADDR: 0x00000000

Decoding stack results
0x40080ff3: apply_command(StepperQueue*, queue_entry const*) at .pio\libdeps\pc\FastAccelStepper@src-a564200d5afe0cb1a1a376e0516aa23f\src\StepperISR_esp32.cpp line 100
0x400811aa: what_is_next(StepperQueue*) at .pio\libdeps\pc\FastAccelStepper@src-a564200d5afe0cb1a1a376e0516aa23f\src\StepperISR_esp32.cpp line 191
0x40081249: pcnt_isr_service(void*) at .pio\libdeps\pc\FastAccelStepper@src-a564200d5afe0cb1a1a376e0516aa23f\src\StepperISR_esp32.cpp line 206
0x400851ca: pcnt_intr_service at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/pcnt.c line 303
0x400824f5: shared_intr_isr at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/intr_alloc.c line 504
0x40092803: esp_rom_spiflash_read_data at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/spi_flash_rom_patch.c line 221
0x40093099: esp_rom_spiflash_read at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/spi_flash_rom_patch.c line 587
0x4008753c: spi_flash_read at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/flash_ops.c line 567
0x40154df7: esp_partition_read at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/partition.c line 242
0x400f5e45: spiffs_api_read at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/spiffs_api.c line 36
0x400f607f: spiffs_phys_rd at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/spiffs/src/spiffs_cache.c line 161
0x400f75f3: spiffs_obj_lu_find_entry_visitor at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/spiffs/src/spiffs_nucleus.c line 166
0x400f916e: spiffs_object_find_object_index_header_by_name at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/spiffs/src/spiffs_nucleus.c line 1694
0x400f5a30: SPIFFS_stat at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/spiffs/src/spiffs_hydrogen.c line 765
0x400f4738: vfs_spiffs_stat at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spiffs/esp_spiffs.c line 536
0x40120585: esp_vfs_stat at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/vfs/vfs.c line 492
0x40184d41: stat at ../../../.././newlib/libc/syscalls/sysstat.c line 12
0x40176915: VFSImpl::open(char const*, char const*) at C:\users\glmcl\.platformio\packages\framework-arduinoespressif32\libraries\FS\src\vfs_api.cpp line 41
0x40175e04: fs::FS::open(char const*, char const*) at C:\users\glmcl\.platformio\packages\framework-arduinoespressif32\libraries\FS\src\FS.cpp line 191
0x40175e2b: fs::FS::open(String const&, char const*) at C:\users\glmcl\.platformio\packages\framework-arduinoespressif32\libraries\FS\src\FS.cpp line 182
0x400d5dda: SPIFFSEditor::handleRequest(AsyncWebServerRequest*) at .pio\libdeps\pc\ESP Async WebServer\src\SPIFFSEditor.cpp line 443
0x400d9ac1: AsyncWebServerRequest::_parseLine() at .pio\libdeps\pc\ESP Async WebServer\src\WebRequest.cpp line 582
0x400d9b85: AsyncWebServerRequest::_onData(void*, unsigned int) at .pio\libdeps\pc\ESP Async WebServer\src\WebRequest.cpp line 123
0x400d9de9: std::_Function_handler   >::_M_invoke(const std::_Any_data &, void *&&, AsyncClient *&&, void *&&, unsigned int &&) at .pio\libdeps\pc\ESP Async WebServer\src\WebRequest.cpp line 76
0x40175255: AsyncClient::_recv(tcp_pcb*, pbuf*, signed char) at c:\users\glmcl\.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional line 2271
0x401752d1: AsyncClient::_s_recv(void*, tcp_pcb*, pbuf*, signed char) at .pio\libdeps\pc\AsyncTCP\src\AsyncTCP.cpp line 1191
0x40175976: _async_service_task(void*) at .pio\libdeps\pc\AsyncTCP\src\AsyncTCP.cpp line 159
0x40088ed1: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143
gin66 commented 3 years ago

Thanks for the code. Has taken me a while to get it compiled in ArduinoIDE due to missing libraries. That's why I prefer platformio. After successful compilation, the big motor has not run, so I changed big_motor->setAutoEnable(false); to big_motor->setAutoEnable(true);. Then the stepper has run well. With this setup web access works, but OTA has reliably sent the esp32 into reset. Even I have removed the ISR-incompatible library code, the ISR has still accessed flash for data from a const table. After moving this table into RAM, OTA runs through. Just the motor is stuttering while OTA is running. This stuttering I have not further investigated. I guess, if the StepperTask is not on Core0 should be better.

This version with the table moved into RAM is the just released 0.22.1

Please try

gin66 commented 3 years ago

After some more thoughts: that your app code is running in core0 is not the issue for the stuttering motor. Perhaps, if ota is managed from core0, then is better. But as it accesses the flash, perhaps the cyclical (4ms) Stepper Manager Task gets delayed, which may be unavoidable.

If that’s the only remaining issue, then just stop the motor on OTA start.

oaklandGman commented 3 years ago

Thanks for helping me sort this out!

Testing 0.22.1 now, running good, even the massive "spiffsedit" app (url is /edit) opens without a panic.

Sorry about the libraries in my code, I should have posted my platform.ini (doh!). The whole project is here on github now, just fyi https://github.com/oaklandGman/stepdrv04

I have tried stopping the stepper motors during ota, they don't need to keep running during a firmware update. Also trying to shut down the webserver, and suspend the task sending commands to the stepper library.

      vTaskSuspend(taskStepper); // shutdown stepper motion task

      big_motor->forceStopAndNewPosition(0);
      small_motor->forceStopAndNewPosition(0);

      ws.textAll("Shutting down for OTA update");
      server.end(); // shutdown webserver

      digitalWrite(BIG_MOTOR_SLEEP, LOW); // turn off driver
      digitalWrite(SMALL_MOTOR_SLEEP, LOW); // turn off driver
gin66 commented 3 years ago

Happy to see, that it now works for you.

Thanks for sharing your code. Always interesting to read. Something new is onsenui. Will look into this, if it suits my purposes.

As there is nothing left to do for FastAccelStepper, this issue can be closed.