Search code examples
arduinoesp8266nodemcuarduino-esp8266

StoreProhibitedCause Exception with linked list on ESP8266


I have implemented a linked list class as follows for storage of sensor data readings.

(Note the total code is ~4000 lines so I can't provide it all, hopefully this gives an idea of what's done).

struct DataItem {
  String   _dataType;
  float    _dataArray[dataArraySize_const];
  float    _calibratedData = -1.0;
  float    _rawData        = -1.0;
  DataItem *_next;
  uint8_t  _dataArraySize = dataArraySize_const;
  float    *_calibrationParameters;
  uint8_t  _numCalibrationParameters;
};

class DataContainer {

  public:
    DataContainer() {
      _head = NULL;
      _tail = NULL;
    };

    DataItem* addDataItem(String dataTypeIn, float calibrationParameters[10], uint8_t numberOfCalibrationParameters) {
      DataItem *temp = new DataItem;

      temp->_dataType        = dataTypeIn;
      temp->_calibratedData  = -1.0;
      temp->_rawData         = -1.0;
      for (uint8_t i = 0; i < dataArraySize_const; i++) { temp->_dataArray[i] = 0; } //Setting all the data array to 0
      temp->_calibrationParameters    = calibrationParameters;
      temp->_numCalibrationParameters = numberOfCalibrationParameters;


      temp->_next = NULL;

      if(_head == NULL) {
        _head = temp;
        _tail = temp;
        temp = NULL;
      }
      else {    
        _tail->_next = temp;
        _tail = temp;
      }
      return temp;
    };

    uint8_t setDataValue(String dataType, float value, uint8_t arrayIndex) {
      DataItem *temp = new DataItem;
      temp = _head;
      Serial.println("Addresses: ");
      while(temp != NULL) {
        Serial.print("temp address:     0x");
        Serial.println((unsigned long)temp, HEX);
        Serial.print("head address:     0x");
        Serial.println((unsigned long)_head, HEX);
        Serial.print("temp add address: 0x");
        Serial.println((unsigned long)&temp, HEX);
        if      (temp->_dataType == dataType) { break; }
        else if (temp == NULL)                { return 1; }
        temp = temp->_next;
      }
      temp->_dataArray[arrayIndex] = value;

      float sum = 0.0;
      for (uint8_t i = 0; i < dataArraySize_const; i++) {
        sum += temp->_dataArray[i];
      }
      temp->_rawData = sum/dataArraySize_const;
      Serial.println("Pre calibration");
      this->calibrate(temp);
      Serial.println("Finished calibration");
      return 0;
    };

    void calibrate(DataItem *temp) {
      temp->_calibratedData = temp->_calibrationParameters[0];
      for (uint8_t i = 1; i <= temp->_numCalibrationParameters; i++) {
        temp->_calibratedData += temp->_calibrationParameters[i] * pow(temp->_rawData, i);
      }
    }

    uint8_t setCalibrationParameters(String dataType, float calibrationParameters[10]) {
      DataItem *temp = new DataItem;
      temp = _head;
      while(temp != NULL) {
        if      (temp->_dataType == dataType) { break; }
        else if (temp == NULL)                { return 1; }
        temp = temp->_next;
      }
      temp->_calibrationParameters = calibrationParameters;

      return 0;
    };


  private:
    DataItem *_head, *_tail;
};

uint8_t numUsedCalibrationParameters = 10;
float   calibrationParam[numUsedCalibrationParameters] = {0,1,0,0,0,0,0,0,0,0};

uint8_t dataArrayPosition = 0;
uint8_t dataArraySize     = 10;

void setup(void) {
  Serial.begin(115200);
  Serial.setDebugOutput(false);
  delay(20);
  Serial.println("\n\nbegin");
  pinMode(A0, INPUT);
  dataContainer.addDataItem("ADC",calibrationParam,numUsedCalibrationParameters);

void loop(void) {
  dataContainer.setDataValue("ADC", analogRead(A0), dataArrayPosition);

  if (dataArrayPosition < dataArraySize) { ++dataArrayPosition; }
  else                                   { dataArrayPosition = 0; }

  delay(100);
}

After around 31000 loops (just under 2^15 which is suspicious to me), I get a StoreProhibitedCause Exception. If I comment out dataContainer.setDataValue("ADC", analogRead(A0), dataArrayPosition);, I no longer get the exception. I suspect it's some way that I have implemented the linked list and it has a memory issue but I have tried printing out the addresses of everything and it doesn't look like anything is running away.

Exception:

Exception (29):
epc1=0x4000df64 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

>>>stack>>>

ctx: sys
sp: 3fffec10 end: 3fffffb0 offset: 01a0
3fffedb0:  4024576b 3fff0b08 00000002 40245700 
.....

===================== SOLVED ===================== DataItem *temp = new DataItem; should be DataItem *temp; for setDataValue() and setCalibrationParameters().

Otherwise it keeps on creating new structs for every addition.


Solution

  • DataItem *temp = new DataItem; should be DataItem *temp; for setDataValue() and setCalibrationParameters().

    Otherwise it keeps on creating new structs for every addition.

    (I can't mark it solved without having an answer).