如何解决从ESP32蓝牙库生成的回调访问地图/矢量时,空键/值的问题 硬件:回溯已解码: Arduino Sketch NodeESP.h NodeESP.cpp 示例程序
我试图每次ESP32节点收到某个字符时都触发一个函数。我可以接收数据并从我制作的数据包结构中解析出char。我将所有操作注册在
typedef void (*callback_function)(void);
这个想法是我将所有字符链接到它们各自的功能。然后,我可以解析出一个char并找到指向我想轻松触发的函数的指针。唯一的缺点是我必须保留对全局对象的引用,才能从bluetooth_callback
内部访问此映射。我已经进行了将近2天的测试,并且编写了一些没有espressif API的示例代码。就我自己而言,我的代码似乎可以正常运行,并且也可以在ESP32上运行。但是,如果我在espressif API注册之后让bluetooth_callback被调用(即,让真正的蓝牙事件触发回调),则该行为变得不确定。映射的大小与我添加到其中的对的数量仍然正确,但是所有的值和键均为null或未定义,并且如果我尝试访问它们,则会收到Guru Meditation Error。我一直在尝试解决这个问题很多,这种行为对我来说很奇怪。如果我手动调用回调函数,那么一切似乎都可以正常工作,但是如果我让它被蓝牙事件调用,则会出现不确定的行为并崩溃。我不确定我是不是在c ++上做错了事,还是这是esp32特有的问题。我可能犯了一个愚蠢的错误。我已经附加了我的Arduino脚本,正在处理的库的头文件和cpp文件,以及一个示例应用程序,该应用程序应显示我的工作意图。谢谢您的帮助。
硬件:
主板:ESP32开发模块(Sparkfun ESP32东西)
核心安装版本:1.0.3
IDE名称:Arduino IDE
闪光频率:40Mhz
启用PSRAM:否
上传速度:115200
计算机操作系统:Windows 10
回溯
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x400014e8 PS : 0x00060430 A0 : 0x800d2410 A1 : 0x3ffcf1a0
A2 : 0x000000fe A3 : 0x000000fc A4 : 0x000000ff A5 : 0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x800d2228 A9 : 0x3ffcf170
A10 : 0x3ffbed90 A11 : 0x3f40148b A12 : 0x3f40148b A13 : 0x0000ff00
A14 : 0x00ff0000 A15 : 0xff000000 SAR : 0x00000010 EXCCAUSE: 0x0000001c
EXCVADDR: 0x000000fc LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xfffffffb
Backtrace: 0x400014e8:0x3ffcf1a0 0x400d240d:0x3ffcf1b0 0x400d242d:0x3ffcf1d0 0x400d14a2:0x3ffcf1f0 0x400d1501:0x3ffcf210 0x400df881:0x3ffcf230 0x400d8362:0x3ffcf280 0x4008d83d:0x3ffcf2b0
已解码:
PC:0x400014e8 EXCVADDR:0x000000fc
Decoding stack results
0x400d240d: Print::write(char const*) at C:\Users\Jake Booth\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.3\cores\esp32/Print.h line 66
0x400d242d: Print::print(char const*) at C:\Users\Jake Booth\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.3\cores\esp32\Print.cpp line 89
0x400d14a2: NodeESP::act_message(char*) at C:\Users\Jake Booth\Documents\Arduino\libraries\NodeESP\NodeESP.cpp line 336
0x400d1501: NodeESP::bluetooth_callback(esp_spp_cb_event_t,esp_spp_cb_param_t*) at C:\Users\Jake Booth\Documents\Arduino\libraries\NodeESP\NodeESP.cpp line 176
0x400df881: btc_spp_cb_handler at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c line 152
0x400d8362: btc_task at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/bt/bluedroid/btc/core/btc_task.c line 110
0x4008d83d: vPortTaskWrapper at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/port.c line 143
我在下面突出显示了第336行,以方便地显示它是哪一个。
Arduino Sketch
#include "NodeESP.h"
#define LED_PIN 5
#define TOGGLE_LED_CHAR 'l'
#define TURN_ON_LED_CHAR 'p'
void setup() {
// put your setup code here,to run once:
Serial.begin(115200);
pinMode(LED_PIN,OUTPUT);
char l = TOGGLE_LED_CHAR;
char p = TURN_ON_LED_CHAR;
esp_spp_cb_param_t ex_param;
ex_param.data_ind.data = (uint8_t*)l;
ex_param.data_ind.len = 1;
//ex_param_ptr = *ex_param;
NodeESP node_esp;
node_esp.add_func(&p,toggle_LED);
node_esp.add_func(&l,turn_on_LED);
node_esp.begin("TEST_1");
//Just calling it manually works,but when the espressif API calls it I get undefined behaviour.
// NodeESP::bluetooth_callback(ESP_SPP_DATA_IND_EVT,&ex_param);
}
void toggle_LED()
{
Serial.println("toggle_LED()");
}
void turn_on_LED()
{
Serial.println("turn_on_LED()");
}
void loop() {
// put your main code here,to run repeatedly:
while(1)
{
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
NodeESP.h
/*
NodeESP.cpp - Library for automatically connecting to and using esp32 microcontrollers
Created by Jacob Booth 11/9/2020
*/
#ifndef NodeESP_h
#define NodeESP_h
#include "Arduino.h"
#include <ESPmDNS.h>
#include <WiFi.h>
#include <map>
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_spp_api.h"
#include "esp_gap_bt_api.h"
//---Define buffer constants--------------------------
#define RCV_BUF_SIZE 128
#define TX_BUF_SIZE 256
//---Define communication constants-------------------
#define RFCOMM_CHANNEL 1
#define RFCOMM_MAX_FRAME_SIZE 0xffff
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! please run 'make menuconfig' to enable it
#endif
class NodeESP
{
public:
//Constructor
NodeESP();
//Begin
bool begin(const char *_name);
//Typedef
typedef void (*callback_function)(void);
//Variables
uint32_t bt_handle;
const char *_name;
std::map<char*,callback_function> funcs;
char rx_buf[RCV_BUF_SIZE];
char tx_buf[RCV_BUF_SIZE];
WiFiServer server;
WiFiClient client;
//Generic
void add_func(char* command,callback_function func);
void act_message(char* trigger);
//Bluetooth
void bluetooth_write(char *buf,int len);
bool bluetooth_spp_init();
bool bluetooth_init(const char *deviceName);
static char parse_data(uint8_t *rcvd,uint16_t len);
static void bluetooth_callback(esp_spp_cb_event_t event,esp_spp_cb_param_t *param);
String toString(const IPAddress & address);
private:
};
#endif
NodeESP.cpp
/*
NodeESP.cpp - Library for automatically connecting to and using esp32 microcontrollers
Created by Jacob Booth 11/9/2020
*/
#include "Arduino.h"
#include <ESPmDNS.h>
#include <WiFi.h>
#include <map>
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_spp_api.h"
#include "esp_gap_bt_api.h"
#include "NodeESP.h"
using namespace std;
//---State Machine Variables---
//State enum that helps the state machine track its way through
//connecting to wifi.
enum state_t {
UNDEFINED,DISCONNECTED,WIFI_CON,SERVER_CON
};
enum comm_t {
s,NONE,WIFI,BLUETOOTH,q
};
//The current communication protocol we are using
comm_t cur_comm = s;
//The current state
state_t cur_state = UNDEFINED;
char tx_buf[TX_BUF_SIZE];
char rx_buf[RCV_BUF_SIZE];
//---Wifi
WiFiServer server(0);
WiFiClient client;
//---Bluetooth
uint32_t bt_handle;
void* example_obj;
//---Main Init--------------------------------------------------------
NodeESP::NodeESP()
{
this->_name = "default";
example_obj = (void*)this;
}
bool NodeESP::begin(const char *_name)
{
this->_name = _name;
//For testing set the current communication method to bluetooth
cur_comm = BLUETOOTH;
switch (cur_comm)
{
case UNDEFINED:
return false;
break;
case NONE:
return false;
break;
case WIFI:
return true;
break;
case BLUETOOTH:
if (!this->bluetooth_init(_name))
{
return false;
}
break;
}
return true;
}
//---Bluetooth Functions--------------------------------
bool NodeESP::bluetooth_init(const char *deviceName)
{
//Start Bluetooth
if (!btStart())
{
return false;
}
//Start BlueDroid (bluetooth stack)
if (esp_bluedroid_init()!= ESP_OK)
{
return false;
}
//Enable BlueDroid
if (esp_bluedroid_enable()!= ESP_OK)
{
return false;
}
//Set device name
esp_bt_dev_set_device_name(deviceName);
//Set sannable and discoverable
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
//Init spp server
if (!this->bluetooth_spp_init())
{
return false;
}
//Set send bytes to the correct callback
//send_bytes = write_bluetooth;
return true;
}
bool NodeESP::bluetooth_spp_init()
{
if (esp_spp_register_callback(&bluetooth_callback) != ESP_OK)
{
return false;
}
if (esp_spp_init(ESP_SPP_MODE_CB) != ESP_OK)
{
return false;
}
if (esp_spp_start_srv(ESP_SPP_SEC_NONE,ESP_SPP_ROLE_SLAVE,1,"") != ESP_OK)
{
return false;
}
return true;
}
void NodeESP::bluetooth_write(char *buf,int len)
{
esp_spp_write(bt_handle,len,(uint8_t*)buf);
}
void NodeESP::bluetooth_callback(esp_spp_cb_event_t event,esp_spp_cb_param_t *param)
{
switch (event)
{
case ESP_SPP_SRV_OPEN_EVT:
{
NodeESP* self = (NodeESP*) example_obj;
self->bt_handle = param->srv_open.handle;
break;
}
case ESP_SPP_CL_INIT_EVT:
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_NONE);
break;
case ESP_SPP_OPEN_EVT:
break;
case ESP_SPP_DATA_IND_EVT:
{
NodeESP* self = (NodeESP*) example_obj;
//char trig = self->parse_data(param->data_ind.data,param->data_ind.len);
self->act_message((char*)param->data_ind.data);
break;
}
case ESP_SPP_CLOSE_EVT:
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
case ESP_SPP_WRITE_EVT:
break;
case ESP_SPP_CONG_EVT:
break;
}
return;
}
//---Parsing functions-------------------------------
//TODO: Add circular buffer
char NodeESP::parse_data(uint8_t *rcvd,uint16_t len)
{
char body_buf[RCV_BUF_SIZE];
uint8_t len_buf[2];
uint8_t rcvd_bytes = 0;
uint8_t recive_stage = 0;
uint16_t calc_len = 0;
//Loop through each char recieved
for (uint16_t i = 0; i < len; i++)
{
uint8_t cur_char = rcvd[i];
rcvd_bytes++;
//If we haven't recieved the length or body
//And we recieve a start delim
if (recive_stage == 0 && cur_char == 0x7E)
{
//We are ready to read the length of the message (next 2 bytes)
recive_stage = 1;
rcvd_bytes = 0;
}
else if (recive_stage == 1)//If we are recieving the length
{
//Next two bytes get stored in the length buffer
len_buf[rcvd_bytes - 1] = cur_char;
//If we have recieved the 2 length bytes
if (rcvd_bytes == 2)
{
//Decode the length
calc_len = ((uint16_t)len_buf[0]) << 8 | (uint16_t)len_buf[1];
//Ready to recieve the body
recive_stage = 2;
rcvd_bytes = 0;
}
}
else if (recive_stage == 2)//If we are recieving the body
{
//Store the recieved bytes
body_buf[rcvd_bytes - 1] = cur_char;
if (rcvd_bytes == calc_len)
{
//Reset
rcvd_bytes = 0;
recive_stage = 0;
return(cur_char);
}
}
}
return '/';
}
void NodeESP::add_func(char* command,callback_function func)
{
Serial.println("Added new callback...");
std::pair<char*,callback_function>* new_pair = new std::pair<char*,callback_function>(command,func);
this->funcs.insert(*new_pair);
}
void NodeESP::act_message(char* trigger)
{
Serial.println("[act message]");
Serial.print("funcs.size() = ");
Serial.print(this->funcs.size()); //Always returns the correct size all of the time
Serial.println("");
for (std::map<char*,callback_function>::iterator it = this->funcs.begin();
it != this->funcs.end();
++it)
{
Serial.print("funcs[i].first = ");
Serial.print(it->first); //Line 336,accessing the first element of the iterator
Serial.println(""); //This works properly when I don't call the function through the callback.
if (trigger == it->first)
{
(it->second)();
}
}
}
String NodeESP::toString(const IPAddress & address)
{
return String(address[0]) + "." + address[1] + "." + address[2] + "." + address[3];
}
示例程序
这是一个示例程序,显示了我想要发生的事情并且可以正常运行。
// Example program
#include <iostream>
#include <string>
#include <map>
//Global object to access the instance from within static function
using namespace std;
class example
{
public:
example();
void begin();
typedef void (*callback_function)(void);
std::map<char,callback_function> funcs;
void add_func(char command,callback_function func);
void do_something(char trigger);
static void example_callback(char cb);
};
void* example_obj;
example::example()
{
example_obj = (void*)this;
}
void example::begin()
{
//Set up everything to do with external library,peripherals,ect...
//Register the callback with the library
//register_callback(&example_callback);
}
//Static func that does something
void example::example_callback(char cb)
{
//Have to do this because the args need to match the library's requirements
example* self = (example*) example_obj;
//Do some processing...
self->do_something(cb);
}
//Add a function pointer and its command char to the vector
void example::add_func(char command,callback_function func)
{
std::pair<char,callback_function>* new_pair = new std::pair<char,func);
this->funcs.insert(*new_pair);
}
//This function is called from the callback
void example::do_something(char trigger)
{
cout << "funcs.size() = "<< (this->funcs.size())<<"\n"; //Always returns the correct size all of the time
for (std::map<char,callback_function>::iterator it = this->funcs.begin();
it != this->funcs.end();
++it)
{
cout << "funcs[i].first = "<< (it->first)<<"\n";
if (trigger == it->first)
{
(it->second)();
}
}
}
void callback()
{
cout << "Callback Called!";
}
int main()
{
cout << "Starting program...\n";
cout << "Creating example object...\n";
example ex;
cout << "Adding some callbacks...\n";
ex.add_func('x',callback);
ex.add_func('y',callback);
ex.add_func('z',callback);
cout << "Firing callback...\n";
example::example_callback('z');
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。