I'm trying to use the queue API that FreeRTOS provides to read a string data from an Interrupt Service Routine (ISR) on an ESP32 device.
As strings are quite large data, I actually send the address of the string using a pointer. This seems to work as I can read the correct pointer adress (see example below).
However, I'm stuck to understand why I'm unable to get the string value when dereferencing this pointer. I'm not used to deal with pointers but reading various examples on the web, I don't see what I'm doing wrong.
QueueHandle_t qGsmEventData;
void IRAM_ATTR ISR_GSM_RI(){
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
String sGsmEventData = "String sent from ISR";
String * pGsmEventData = &sGsmEventData;
Serial.print("Pointer address added to queue: ");
Serial.println((unsigned int)pGsmEventData);
Serial.print("String length: ");
Serial.println(sGsmEventData.length());
xQueueSendToBackFromISR(qGsmEventData, &pGsmEventData, &xHigherPriorityTaskWoken);
}
void setup() {
[...]
qGsmEventData = xQueueCreate(10, sizeof(String *));
attachInterrupt(digitalPinToInterrupt(GSM_INT_PIN), ISR_GSM_RI, RISING);
}
void loop() {
String *pGsmEventData;
xQueueReceive(qGsmEventData, &(pGsmEventData), portMAX_DELAY);
Serial.print("Pointer address get from queue: ");
Serial.println((unsigned int)pGsmEventData);
String sGsmEventData = *pGsmEventData;
Serial.print("String length: ");
Serial.println(sGsmEventData.length());
delay(500);
}
and i'm getting on the serial console output :
Pointer address added to queue: 1073475016
String length: 20
Pointer address get from queue: 1073475016
String length: 0
So the queue seems to work as I get the correct pointer address but why I get a 0 length string when deferencing this pointer ? How to get the string value ?
CodePudding user response:
Basically the pointers outlive the objects they point to.
Let's break the ISR down as an example:
void IRAM_ATTR ISR_GSM_RI(){
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
String sGsmEventData = "String sent from ISR";
//string is created on the stack
String * pGsmEventData = &sGsmEventData;
//its address is taken
Serial.print("Pointer address added to queue: ");
Serial.println((unsigned int)pGsmEventData);
Serial.print("String length: ");
Serial.println(sGsmEventData.length());
//String object is valid thus so are the logs
xQueueSendToBackFromISR(qGsmEventData, &pGsmEventData, &xHigherPriorityTaskWoken);
//its address is sent
} //string's destructor is called, it no longer exists
//pointer points to now empty place in memory
After reception, you're dereferencing the no longer valid pointer, so anything can happen really, the behaviour is undefined. And this is generally true for objects of any type, save string literals.