invalid use of non-static member function xTaskCreate

I’m trying to write an ESP32 lib that is compatible with the Arduino IDE and uses classes, but I’m getting the following error:

/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp: In member function 'void BleMouse::init()':
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp:19:57: error: invalid use of non-static member function
   xTaskCreate(taskServer, "server", 20000, NULL, 5, NULL);
                                                         ^
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp: In member function 'void BleMouse::taskServer(void*)':
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp:80:12: error: 'LOG_TAG' was not declared in this scope
   ESP_LOGD(LOG_TAG, "Advertising started!");
            ^
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp:80:43: error: 'ESP_LOGD' was not declared in this scope
   ESP_LOGD(LOG_TAG, "Advertising started!");
                                           ^
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp:81:22: error: 'delay' was not declared in this scope
   delay(portMAX_DELAY);
                      ^
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp: In function 'void rawAction(uint8_t, char)':
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp:89:3: error: invalid use of 'this' in non-member function
   this->inputMouse->setValue(msg, msgSize);
   ^
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp:90:3: error: invalid use of 'this' in non-member function
   this->inputMouse->notify();
   ^
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp: In member function 'void BleMouse::scrollDown(char)':
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp:95:47: error: narrowing conversion of '-(int)unit' from 'int' to 'uint8_t {aka unsigned char}' inside { } [-Werror=narrowing]
     uint8_t msg[] = { 0x00, 0x00, 0x00, -unit };
                                               ^
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp:96:27: error: invalid conversion from 'uint8_t* {aka unsigned char*}' to 'uint8_t {aka unsigned char}' [-fpermissive]
     this->rawAction(msg, 4);
                           ^
In file included from /home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp:12:0:
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.h:18:8: note:   initializing argument 1 of 'void BleMouse::rawAction(uint8_t, char)'
   void rawAction(uint8_t msg, char msgSize);
        ^
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp: In member function 'void BleMouse::scrollUp(char)':
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp:103:27: error: invalid conversion from 'uint8_t* {aka unsigned char*}' to 'uint8_t {aka unsigned char}' [-fpermissive]
     this->rawAction(msg, 4);
                           ^
In file included from /home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.cpp:12:0:
/home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleMouse.h:18:8: note:   initializing argument 1 of 'void BleMouse::rawAction(uint8_t, char)'
   void rawAction(uint8_t msg, char msgSize);
        ^
cc1plus: some warnings being treated as errors
Using library ESP32-BLE-Mouse at version 1.0 in folder: /home/fedora/Arduino/libraries/ESP32-BLE-Mouse 
Using library BLE at version 1.0.1 in folder: /home/fedora/.arduino15/packages/esp32/hardware/esp32/1.0.2/libraries/BLE 
exit status 1
Error compiling for board ESP32 Dev Module.

when I try to compile this:

/**
 * This example turns the ESP32 into a Bluetooth LE mouse that scrolls down every 2 seconds.
 */
#include <BleMouse.h>

BleMouse bleMouse;

void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");
  bleMouse.init();
}

void loop() {
  if(bleMouse.isConnected()) {
    Serial.println("Scroll Down by 1 unit");
    bleMouse.scrollDown(1);
  }
  delay(2000);
}

The code for the BleMouse and BleConnectionStatus classes can be found in my Github repo, but I also include it in this post in case that’s easier:

BleMouse.h

#ifndef ESP32_BLE_MOUSE_H
#define ESP32_BLE_MOUSE_H
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)

#include "BleConnectionStatus.h"
#include "BLEHIDDevice.h"
#include "BLECharacteristic.h"

class BleMouse {
public:
  BleMouse();
  void init();

  bool isConnected();
  void scrollDown(char units);
  void scrollUp(char units);
  void rawAction(uint8_t msg, char msgSize);

private:
  BleConnectionStatus* connectionStatus;
  BLEHIDDevice* hid;
  BLECharacteristic* inputMouse;
  void taskServer(void*);
};

#endif // CONFIG_BT_ENABLED
#endif // ESP32_BLE_MOUSE_H

BleMouse.cpp

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include "BLE2902.h"
#include "BLEHIDDevice.h"
#include "HIDTypes.h"
#include "HIDKeyboardTypes.h"
#include <driver/adc.h>
#include "sdkconfig.h"

#include "BleConnectionStatus.h"
#include "BleMouse.h"

BleMouse::BleMouse() {
  this->connectionStatus = new BleConnectionStatus(this->inputMouse);
}

void BleMouse::init() {
  xTaskCreate(this->taskServer, "server", 20000, NULL, 5, NULL);
}

void BleMouse::taskServer(void*) {
  BLEDevice::init("ESP32-BLE-Mouse");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(this->connectionStatus);

  this->hid = new BLEHIDDevice(pServer);
  this->inputMouse = this->hid->inputReport(1); // <-- input REPORTID from report map

  std::string name = "chegewara";
  this->hid->manufacturer()->setValue(name);

  this->hid->pnp(0x02, 0xe502, 0xa111, 0x0210);
  this->hid->hidInfo(0x00,0x02);

  BLESecurity *pSecurity = new BLESecurity();

  pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND);

  const uint8_t reportMapMouse[] = {
    USAGE_PAGE(1),      0x01,
    USAGE(1),           0x02,
    COLLECTION(1),      0x01,
    REPORT_ID(1),       0x01,
    USAGE(1),           0x01,
    COLLECTION(1),      0x00,
    USAGE_PAGE(1),      0x09,
    USAGE_MINIMUM(1),   0x1,
    USAGE_MAXIMUM(1),   0x3,
    LOGICAL_MINIMUM(1), 0x0,
    LOGICAL_MAXIMUM(1), 0x1,
    REPORT_COUNT(1),    0x3,
    REPORT_SIZE(1),     0x1,
    0x80|0x01,          0x2,    // (Data, Variable, Absolute), ;3 button bits
    REPORT_COUNT(1),    0x1,
    REPORT_SIZE(1),     0x5,
    0x80|0x01,          0x1,    //(Constant), ;5 bit padding
    USAGE_PAGE(1),      0x1,    //(Generic Desktop),
    USAGE(1),           0x30,
    USAGE(1),           0x31,
    USAGE(1),           0x38,
    LOGICAL_MINIMUM(1), 0x81,
    LOGICAL_MAXIMUM(1), 0x7f,
    REPORT_SIZE(1),     0x8,
    REPORT_COUNT(1),    0x3,
    0x80|0x01,          0x6,    //(Data, Variable, Relative), ;2 position bytes (X & Y)
    END_COLLECTION(0),
    END_COLLECTION(0)
  };

  this->hid->reportMap((uint8_t*)reportMapMouse, sizeof(reportMapMouse));
  this->hid->startServices();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->setAppearance(HID_MOUSE);
  pAdvertising->addServiceUUID(this->hid->hidService()->getUUID());
  pAdvertising->start();
  this->hid->setBatteryLevel(7);

  ESP_LOGD(LOG_TAG, "Advertising started!");
  delay(portMAX_DELAY);
}

bool BleMouse::isConnected() {
  return this->connectionStatus->connected;
}

void rawAction(uint8_t msg, char msgSize) {
  this->inputMouse->setValue(msg, msgSize);
  this->inputMouse->notify();
}

void BleMouse::scrollDown(char unit) {
  if(this->isConnected()) {
    uint8_t msg[] = { 0x00, 0x00, 0x00, -unit };
    this->rawAction(msg, 4);
  }
}

void BleMouse::scrollUp(char unit) {
  if(this->isConnected()) {
    uint8_t msg[] = { 0x00, 0x00, 0x00, unit };
    this->rawAction(msg, 4);
  }
}

BleConnectionStatus.h

#ifndef ESP32_BLE_CONNECTION_STATUS_H
#define ESP32_BLE_CONNECTION_STATUS_H
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)

#include <BLEServer.h>
#include "BLE2902.h"
#include "BLECharacteristic.h"

class BleConnectionStatus : public BLEServerCallbacks {
public:
  BleConnectionStatus(BLECharacteristic* inputMouse);
  bool connected = false;
  void onConnect(BLEServer* pServer);
  void onDisconnect(BLEServer* pServer);
private:
  BLECharacteristic* inputMouse;
};

#endif // CONFIG_BT_ENABLED
#endif // ESP32_BLE_CONNECTION_STATUS_H

BleConnectionStatus.cpp:

#include "BleConnectionStatus.h"

BleConnectionStatus::BleConnectionStatus(BLECharacteristic* inputMouse) {
  this->inputMouse = inputMouse;
}

void BleConnectionStatus::onConnect(BLEServer* pServer) {
  this->connected = true;
  BLE2902* desc = (BLE2902*)inputMouse->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
  desc->setNotifications(true);
}

void BleConnectionStatus::onDisconnect(BLEServer* pServer) {
  this->connected = false;
  BLE2902* desc = (BLE2902*)inputMouse->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
  desc->setNotifications(false);
}

Before I turned everything into classes, it worked and looked like this

Have I seen this query in another thread ?

You will find information on using freeRTOS in classes at https://esp32.com/ and https://www.freertos.org/.

As I said, my code was already working. I just wrapped it into two classes and now I get these errors. So it must be a general C++ coding error not directly related to freertos or anything like that.

I think the first error is because the xTaskCreate() can't take an object method as an argument because without the matching object the method can't be called. If you are creating multiple instances of BleMouse you need a way to tell the single task which object it is working on. Maybe you can make the 'taskServer' method 'static' (belonging to all objects) and pass the object as the pvParameter argument:

void BleMouse::init() {
  xTaskCreate(this->taskServer, "server", 20000, (void *)this, 5, NULL);
}

A good read: Standard C++

why do you repost ? I had answered in the other thread...

johnwasser:
Maybe you can make the 'taskServer' method 'static' (belonging to all objects) and pass the object as the pvParameter argument

that would not work as you can't use non static variables in a static member function and the call back is not under his control since this is in the RTOS and tied to xTaskCreate() -> needs to match a specific prototype

J-M-L:
that would not work as you can't use non static variables in a static member function and the call back is not under his control since this is in the RTOS and tied to xTaskCreate() -> needs to match a specific prototype

You probably know more about the RTOS calls than I do but it looks to me like the pvParameter value is passed to the task. If the task ('taskServer') is a class member function and has a pointer to the object, could it not call at least the public methods?

void BleMouse::taskServer(void * pvParameter) {
  BleMouse * this = (BleMouse *) pvParameter;
  BLEDevice::init("ESP32-BLE-Mouse");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(this->connectionStatus);

Perhaps the 'this' keyword is reserved and some other name, like 'mouse', would have to be used.

I'm no expert on RTOS.

I believe you are right, as long as the instance is alive when the tasks runs, then the pvParameters could be initialized at this (self) and then re-cast to a BleMouse pointer in the task indeed. (yes this is reserved so would have to use something else)

@J-M-L It was bad timing. I decided that it would make more sense to create a new thread because the new error had nothing to do with the title of the old thread. I mentioned that in the edit of my last post in the previous thread, but you were probably already writing your answer when I made my edit.
I'm not a fan of global variables though. It tends to create more headaches than it solved. But I understand the issue now.

I changed the code to:

void BleMouse::init() {
  xTaskCreate(this->taskServer, "server", 20000, (void *)this, 5, NULL);
}

void BleMouse::taskServer(void* pvParameter) {
  BleMouse* bleMouseInstance = (BleMouse *) pvParameter;
...

replaced all occurences of "this" within that function with "bleMouseInstance" and in the header file declared it as "static void taskServer(void* pvParameter);"

That indeed appears to fix the error, thank you so much! :slight_smile:

I then managed to fix a bunch of other errors:

For some reason it was complaining about "LOG_TAG" not existing, so I added:

#if defined(CONFIG_ARDUHAL_ESP_LOG)
#include "esp32-hal-log.h"
#define LOG_TAG ""
#else
#include "esp_log.h"
static const char* LOG_TAG = "BLEDevice";
#endif

Then it complained that "'delay' was not declared in this scope". But I found an alternative called "vTaskDelay" which apparently does exist in that scope.

I also made a mistake with the rawAction method I wrote. After changing it to:

"void BleMouse::rawAction(uint8_t msg, char msgSize)"

everything compiled though.

Unfortunately nothing happens though. I can't find the Bluetooth device with my phone.

On the serial monitor it just continuously prints the following:

Starting BLE work!
Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC      : 0x400d39b8  PS      : 0x00060130  A0      : 0x800d2722  A1      : 0x3ffd5a90  
A2      : 0x00000018  A3      : 0x2e5470b4  A4      : 0xf0000000  A5      : 0x003ffe46  
A6      : 0xb03ffb00  A7      : 0x0001fe46  A8      : 0x3ffc607c  A9      : 0x3ffd5ad0  
A10     : 0x3ffe914c  A11     : 0x0000001c  A12     : 0x3ffe950c  A13     : 0x3ffe9554  
A14     : 0x00000002  A15     : 0x3ffd87e0  SAR     : 0x00000018  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000024  LBEG    : 0x4000c349  LEND    : 0x4000c36b  LCOUNT  : 0xffffffff  

Backtrace: 0x400d39b8:0x3ffd5a90 0x400d271f:0x3ffd5af0 0x400d13ed:0x3ffd5b30 0x400d6019:0x3ffd5b70 0x400d3bd9:0x3ffd5bd0 0x400e440a:0x3ffd5bf0 0x400df23e:0x3ffd5c30 0x40090461:0x3ffd5c60

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

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:0x3fff0018,len:4
load:0x3fff001c,len:1100
load:0x40078000,len:9232
load:0x40080400,len:6400
entry 0x400806a8

Any ideas what that could mean?

Edit:

I found a tool to decode the error:

PC: 0x400d39b8: BLEDescriptorMap::getByUUID(BLEUUID) at /home/fedora/.arduino15/packages/esp32/hardware/esp32/1.0.2/libraries/BLE/src/BLEDescriptorMap.cpp line 33
EXCVADDR: 0x00000024

Decoding stack results
0x400d39b8: BLEDescriptorMap::getByUUID(BLEUUID) at /home/fedora/.arduino15/packages/esp32/hardware/esp32/1.0.2/libraries/BLE/src/BLEDescriptorMap.cpp line 33
0x400d271f: BLECharacteristic::getDescriptorByUUID(BLEUUID) at /home/fedora/.arduino15/packages/esp32/hardware/esp32/1.0.2/libraries/BLE/src/BLECharacteristic.cpp line 135
0x400d13ed: BleConnectionStatus::onConnect(BLEServer*) at /home/fedora/Arduino/libraries/ESP32-BLE-Mouse/BleConnectionStatus.cpp line 9
0x400d6019: BLEServer::handleGATTServerEvent(esp_gatts_cb_event_t, unsigned char, esp_ble_gatts_cb_param_t*) at /home/fedora/.arduino15/packages/esp32/hardware/esp32/1.0.2/libraries/BLE/src/BLEServer.cpp line 171
0x400d3bd9: BLEDevice::gattServerEventHandler(esp_gatts_cb_event_t, unsigned char, esp_ble_gatts_cb_param_t*) at /home/fedora/.arduino15/packages/esp32/hardware/esp32/1.0.2/libraries/BLE/src/BLEDevice.cpp line 129
0x400e440a: btc_gatts_cb_handler at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c line 54
0x400df23e: btc_task at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/bt/bluedroid/btc/core/btc_task.c line 110
0x40090461: vPortTaskWrapper at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/port.c line 143

I then corrected line 9 in BleConnectionStatus.cpp from

BLE2902* desc = (BLE2902*)inputMouse->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));

to

BLE2902* desc = (BLE2902*)this->inputMouse->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));

But the error remained the same.

Hi ok fair for the new post, makes sense

Not sure I can help with what you see (or actually don’t see) - it’s way too specific

Okay, maybe it's best if I ask in the esp32.com forums. But thanks for the help so far @J-M-L and @johnwasser!