Is it normal for RTOS took twice as much time as normal task?

So I'm using GPRS module with ESP32 to do https request to google maps API. It works fine with TinyGsmClient library. I get the result that I want. But then, I migrate it to FreeRTOS so I can multitask, but it doesn't work as fine. My FreeRtos code look like:

void httpsGETTask(void *pvParameters) {

  while(1){
    int timer=esp_timer_get_time(); //I put timer here and at the end of the code to see how long this task executed
          if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
        SerialMon.println(" fail");
        vTaskDelay(pdMS_TO_TICKS(10000));
        return;
      }
      SerialMon.print(F("Performing HTTPS GET request... "));
      http.connectionKeepAlive();  // Currently, this is needed for HTTPS
      int err = http.get(resource);
      if (err != 0) {
        SerialMon.println(F("failed to connect"));
        vTaskDelay(pdMS_TO_TICKS(10000));
        return;
      }

      int status = http.responseStatusCode();
      SerialMon.print(F("Response status code: "));
      SerialMon.println(status);
      if (!status) {
        vTaskDelay(pdMS_TO_TICKS(10000));
        return;
      }

      String body = http.responseBody();
      String instruction= findHtmlInstructions(body);
      SerialMon.println(F("Response:"));
      SerialMon.println(instruction);
      
      int duration=esp_timer_get_time()-timer;
      SerialMon.print("duration: ");
      SerialMon.println(duration);
    } 
      
}

// Task handles
TaskHandle_t httpsTaskHandle = NULL;
void setup() {
  // Set console baud rate
  SerialMon.begin(115200);
  delay(10);

  // !!!!!!!!!!!
  // Set your reset, enable, power pins here
  // !!!!!!!!!!!

  SerialMon.println("Wait...");
  setupGSM();
  SerialMon.println("Connecting: ");
  xTaskCreate(httpsGETTask, "HTTPTask", 10*1024, NULL, 1, &httpsTaskHandle);
  delay(10);
  SerialMon.println("Connecting done ");
}



void loop() {
  // The loop function is not used in this example.
  vTaskDelete(nullptr);
}

At first try I got

E (22228) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (22228) task_wdt:  - IDLE (CPU 0)
E (22228) task_wdt: Tasks currently running:
E (22228) task_wdt: CPU 0: HTTPTask
E (22228) task_wdt: CPU 1: IDLE
E (22228) task_wdt: Aborting.

That mean the task took longer then watchdog timer. Well, I have done https request before using Wifi but this never happened, so I guess GPRS is much slower so it wait too long for the response.

I searched for the solution online, and found that I should put this task at lower priority. So I change it to:

xTaskCreate(httpsGETTask, "HTTPTask", 50*1024, NULL, 0, &httpsTaskHandle);

and the error was solved, but I found that it took so long for the request to finish. I put some timer mechanism, and found that the normal code took around 15s to executed while task with freeRTOS took around 37s to executed.

Edit:
I look at it again, and found that it took 37s for the task, but only 10s for the https request, and the rest is to get the string answer:
String body = http.responseBody();
This one line took 27 s

Is it normal that the RTOS task took so long?

when using the Arduino framework you were likely keeping the loop looping and that was patting the dog for you, even if it was taking longer than the timeout for the watchdog. your task httpsGETTask does not do that

(and you can use tasks within the Arduino framework)

this is hard to believe it's just the parsing. It might be to get the full answer

Ups, yeah it's to get the full answer. That was a poor choices of words from me. Anyway, that answer took a lot, but I don't even need all of it. Is there a way to only receive like the first 5 line of the string? or is it a bad practice?

the loop task pats the dog..
instead of deleting the loop task just put a delay(10) inside it and let it pat the dog for you..

good luck.. ~q

I'm not sure the API lets you do that.

This is interesting. I try to put delay(10) and set task back to priority 1:
xTaskCreate(httpsGETTask, "HTTPTask", 10*1024, NULL, 1, &httpsTaskHandle);

So, I found that it still has the previous error. But, after I set it to delay(100), I got:

Initializing modem...

Connecting:

Performing HTTPS GET request... Response status code: 200

duration before body: 7974099

duration after body: 12484338

Response:

Head \u003cb\u003esoutheast\u003c/b\u003e

duration: 12484660

E (20012) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:

E (20012) task_wdt: - IDLE (CPU 0)

E (20012) task_wdt: Tasks currently running:

E (20012) task_wdt: CPU 0: HTTPTask

E (20012) task_wdt: CPU 1: IDLE

E (20012) task_wdt: Aborting.

abort() was called at PC 0x400da6b5 on core 0

Backtrace: 0x40083415:0x3ffbe9dc |<-CORRUPTED

Now it is kind of work.... but I still get the error at the end, I see the duration and it is a lot faster then when I put it in priority 0. So now I know that I need to put it into higher priority to be faster, but when I try to use delay(1000) and higher, doesn't seems to fix the issue but it getting worse. It seems to "work" only at delay(100)

what's your full code?

ok, no try adding a vtaskdelay for 1 second, just after you print the last duration..
maybe you're hogging too much..

~q

here:

#define TINY_GSM_MODEM_SIM808
// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial
HardwareSerial SerialAT(2);  

#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 650
#endif
// set GSM PIN, if any
#define GSM_PIN ""
// Below is GPRS Https request part

// Your GPRS credentials, if any
const char apn[]      = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";

// Server details
const char server[]   = "maps.googleapis.com";
const char resource[] = "/maps/api/directions/json?origin=-7.282058008443928,112.79494675412441&destination=-7.288465791966643,112.80169150994796&mode=walking&key=AIzaSyCu7ZP3tACUVSbS_tHCHfD3Ix76BRwz4IQ";
const int  port       = 443;

#include <TinyGsmClient.h>
#include <HttpClient.h>
TinyGsm             modem(SerialAT);
TinyGsmClientSecure client(modem);
HttpClient          http(client, server, port);

/// Util
String findHtmlInstructions(const String& jsonString) {
  String target = "\"html_instructions\" : \"";
  int startIndex = jsonString.indexOf(target);
  if (startIndex != -1) {
    startIndex += target.length();
    int endIndex = jsonString.indexOf("\"", startIndex);
    if (endIndex != -1) {
      return jsonString.substring(startIndex, endIndex);
    }
  }
  return "";  // Return an empty string if not found
}

void setupGSM(){
    // Set GSM module baud rate
  // TinyGsmAutoBaud(SerialAT, GSM_AUTOBAUD_MIN, GSM_AUTOBAUD_MAX);
  SerialAT.begin(57600);
  delay(6000);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  modem.init();

  if (GSM_PIN && modem.getSimStatus() != 3) { modem.simUnlock(GSM_PIN); }
}


unsigned long lastTime = 0;
unsigned long timerDelay = 2000;

void httpsGETTask(void *pvParameters) {

  while(1){
    int timer=esp_timer_get_time();
          if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
        SerialMon.println(" fail");
        vTaskDelay(pdMS_TO_TICKS(10000));
        return;
      }
      SerialMon.print(F("Performing HTTPS GET request... "));
      http.connectionKeepAlive();  // Currently, this is needed for HTTPS
      int err = http.get(resource);
      if (err != 0) {
        SerialMon.println(F("failed to connect"));
        vTaskDelay(pdMS_TO_TICKS(10000));
        return;
      }

      int status = http.responseStatusCode();
      http.skipResponseHeaders();
      SerialMon.print(F("Response status code: "));
      SerialMon.println(status);
      if (!status) {
        vTaskDelay(pdMS_TO_TICKS(10000));
        return;
      }
      int durationBeforeParsing=esp_timer_get_time()-timer;
      SerialMon.print("duration before body: ");
      SerialMon.println(durationBeforeParsing);

      String body = http.responseBody();
      int durationAfterParsing=esp_timer_get_time()-timer;
      SerialMon.print("duration after body: ");
      SerialMon.println(durationAfterParsing);
      String instruction= findHtmlInstructions(body);
      SerialMon.println(F("Response:"));
      SerialMon.println(instruction);
      
      int duration=esp_timer_get_time()-timer;
      SerialMon.print("duration: ");
      SerialMon.println(duration);
    } 
      
}

// Task handles
TaskHandle_t httpsTaskHandle = NULL;
void setup() {
  // Set console baud rate
  SerialMon.begin(115200);
  delay(10);

  // !!!!!!!!!!!
  // Set your reset, enable, power pins here
  // !!!!!!!!!!!

  SerialMon.println("Wait...");
  setupGSM();
  SerialMon.println("Connecting: ");
  xTaskCreate(httpsGETTask, "HTTPTask", 10*1024, NULL, 0, &httpsTaskHandle);

}



void loop() {
  // The loop function is not used in this example.
  vTaskDelay(150);
}

what happens If you keeps the loop() just empty?

It gets the same watchdog error, and then reboot the module:

Wait...
Initializing modem...
Connecting: 
Performing HTTPS GET request... E (12233) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (12233) task_wdt:  - IDLE (CPU 0)
E (12233) task_wdt: Tasks currently running:
E (12233) task_wdt: CPU 0: HTTPTask
E (12233) task_wdt: CPU 1: loopTask
E (12233) task_wdt: Aborting.

abort() was called at PC 0x400da6c1 on core 0


Backtrace: 0x40083415:0x3ffbe9dc |<-CORRUPTED

Backtrace: 0x40083415:0x3ffbe9dc |<-CORRUPTED




ELF file SHA256: c428f84338a0f352

Rebooting...
ets Jul 29 2019 12:21:46

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:13260
load:0x40080400,len:3028
entry 0x400805e4
Wait...
Initializing modem...
Connecting: 

the Wait... Initializing modem... Connecting: are from setup, so it seems to restart the esp

OK and what if you add delay(0); and or yield()at the beginning of your task

void httpsGETTask(void *pvParameters) {

  while(true) {
    delay(0); // pat the dog
    yield(); // handle anything most urgent to do?
    int timer=esp_timer_get_time();
•••

Probably it has nothing to do with your current problem. You have a few return in your httpsGETTask(). You might want to delete the current task instead.

Sorry for the late reply. I have change return to continue but nothing change

Sorry for late reply. I try it, but nothing seems to happen. The task indeed take too long. the get request int err = http.get(resource); take about 2s to complete

I try to simplified the code to:

void httpsGETTask2(void *pvParameters) {

  while(1){
    delay(0);
    yield();
    vTaskDelay(pdMS_TO_TICKS(100));
    int timer=esp_timer_get_time();
          if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
        SerialMon.println(" fail");
        vTaskDelay(pdMS_TO_TICKS(10000));
        continue;
      }
      SerialMon.print(F("Performing HTTPS GET request... "));
      http.connectionKeepAlive();  // Currently, this is needed for HTTPS
      int durationBeforeGet=esp_timer_get_time()-timer;
      SerialMon.print("duration before get: ");
      SerialMon.println(durationBeforeGet);
      int err = http.get(resource);
      int durationAfterParsing=esp_timer_get_time()-timer;
      vTaskDelay(pdMS_TO_TICKS(10));
    } 
      
}

WDT Error throw after this print: SerialMon.print(F("Performing HTTPS GET request... "));
I try to disable http.connectionKeepAlive(); but it still throw error. Seems like the error from http.get(resource);

I try to put yield(); just before it, but nothing happen.

can you add flush() to all your serial prints so that you are 100% sure where you are in the code?

Like this?

void httpsGETTask2(void *pvParameters) {

  while(1){
    delay(0);
    yield();
    vTaskDelay(pdMS_TO_TICKS(100));
    int timer=esp_timer_get_time();
          if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
        SerialMon.println(" fail");
        vTaskDelay(pdMS_TO_TICKS(10000));
        continue;
      }
      SerialMon.println(F("Performing HTTPS GET request... "));
      SerialMon.flush();
      http.connectionKeepAlive();  // Currently, this is needed for HTTPS
      int durationBeforeGet=esp_timer_get_time()-timer;
      SerialMon.print("duration before get: ");
      SerialMon.println(durationBeforeGet);
      SerialMon.flush();
      int err = http.get(resource);
      int durationAfterGet=esp_timer_get_time()-timer;
      SerialMon.print("duration after get: ");
      SerialMon.print(durationAfterGet);
      SerialMon.print("duration for get: ");
      SerialMon.println(durationAfterGet-durationBeforeGet);
      SerialMon.flush();
      vTaskDelay(pdMS_TO_TICKS(1000));
    } 
      
}

Still get the same result:

Wait...
Initializing modem...
Connecting: 
Performing HTTPS GET request... 
duration before get: 4525042
E (32407) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (32407) task_wdt:  - IDLE (CPU 0)
E (32407) task_wdt: Tasks currently running:
E (32407) task_wdt: CPU 0: HTTPTask
E (32407) task_wdt: CPU 1: IDLE
E (32407) task_wdt: Aborting.

abort() was called at PC 0x400da205 on core 0


Backtrace: 0x40083415:0x3ffbe9dc |<-CORRUPTED




ELF file SHA256: b12c83571336e0fc

Rebooting...
ets Jul 29 2019 12:21:46
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:13260
load:0x40080400,len:3028
entry 0x400805e4

Yes

so you don't even get there

when you said

you did not even get the print

Can you please explain... I don't understand. So I get the error before even have a chance to print, but the print already in buffer?

backtrace is corrupted, thinking the heap is trashed..
blowing the stack maybe in another task??
thinking you may be looking in the wrong place..

good luck.. ~q