I have a strange problem here with my ESP8266 (Wemos D1 mini). I'm wrting a library for building a network with the nRF24L01 transmitter.
I have defined a gloabl uint8_t arry which represents my receive buffer. When receiving a transmission from an other device, the array gets filled. After filling the array, I start to parse the buffer, to identify if there is a valid Header/Frame. The header contains some typical data like sender, checksum... If the header is valid the data of frame gets parsed. The structure of the data is always the same. There can be x so called DataTriples. A DataTriple is a combination of Key (cstring), Type of Value (uint8_t) and the Value itself. The type of value can be basic types like INT8, UINT8 or FLOAT or STRING.
And now the stange thing.
To save memory I do not copy the values from the buffer into dedicated variables. I alway point to the positions in the buffer. And when I want to read a value, I do a simple pointer cast and read out the values. This is perfectly working if the value is a string or a simple 1 byte long uint8_t. But if it is a float or an uint32_t I get a LoadStoreAlignmentCause Excetion that's telling me, that I want to access not alligned memory. How can this be? The pointers are definitly pointing to the correct buffer positon. I checked this, because if I create a new float variable and do a memcpy from the buffer to the variables address, everything is good. But I a create a float pointer and point to the position in the buffer, I get a this exception.
Can somebody tell me the reason or tell me what I'm doing wrong?
Here are some code fragment, to get a better understanding.
bool SBSmartHomeBasicDevice::parseDataTriples() {
if (_IncommingTransmission) {
uint8_t* iCurrentPos;
uint8_t iDataTripleCount = 0;
// _LastReceivedFrame.Payload points to the receive buffer
for (iCurrentPos = _LastReceivedFrame.Payload; iCurrentPos < (_LastReceivedFrame.Payload + _LastReceivedFrame.Header.PayloadSize); iCurrentPos) {
// Catch the type of the triple
uint8_t type = *((uint8_t*)iCurrentPos);
// increase the pointer about uint8_t size
iCurrentPos += sizeof(uint8_t);
// Catch the key of the triple
char* key;
key = (char*)(iCurrentPos);
// increase the pointer about strlen of key + 1
iCurrentPos += strlen((char*)iCurrentPos) + 1;
// catch the value
void* value = (void*)(iCurrentPos);
_LastReceivedTriples[iDataTripleCount].setType(type);
_LastReceivedTriples[iDataTripleCount].setKey(key);
// ***
// Here starts the interesting part
// ***
float* fTmp = (float*)iCurrentPos;
// The following works perfect
// ****
float f;
memcpy(&f, fTmp, sizeof(float));
Serial.println(f);
// ****
// The following causes an exception
Serial.println(*fTmp);
// *** EXCEPTION ***
_LastReceivedTriples[iDataTripleCount].setValue(iCurrentPos);
// now increase the pointer
switch (type) {
case SMART_HOME_VALUE_TYPE_STRING:
iCurrentPos += strlen((char*)iCurrentPos) + 1;
break;
case SMART_HOME_VALUE_TYPE_INT8:
case SMART_HOME_VALUE_TYPE_UINT8:
iCurrentPos += sizeof(int8_t);
break;
case SMART_HOME_VALUE_TYPE_INT16:
case SMART_HOME_VALUE_TYPE_UINT16:
iCurrentPos += sizeof(int16_t);
break;
case SMART_HOME_VALUE_TYPE_FLOAT:
iCurrentPos += sizeof(float);
break;
case SMART_HOME_VALUE_TYPE_INT32:
case SMART_HOME_VALUE_TYPE_UINT32:
iCurrentPos += sizeof(int32_t);
break;
default:
Serial.println("parseDataTriples(): Unknown ValueType");
}
_LastReceivedTriples[iDataTripleCount].print();
iDataTripleCount++;
_LastReceivedTriplesCount = iDataTripleCount;
}
return true;
}
return false;
}
An Thanks a lot for taking the time and helping me.
Greets Schullebernd