SOS Heap error after vector.push_back

Hi,

I’m having trouble fixing my code. My device goes into SOS after my rain guage gives a high signal and the ISR (code below) is triggered. I’ve tested with different PCB’s, rain guages and controllers.
After hardware troubleshooting I looked into code and isolated the ISR as the root of the problem by commenting the attachInterrupt. Then the controller was fine. After commenting the vector opperations I found out that the rainTicks.push_back(Time.now()); is the cause of the problem.

The code is still doing fine on my other devices, they are all running 1.0.or 1.0.1 of the device OS. This device is running 1.4.0. Has something changed in the deviceOS related to vector operations? Also, Argon and Boron are fine.

I could use a suggestion how to fix this. I’m using vector because I need to have a local backup of data to run a decision algorithm for when the server connection is lost. I also have a wind sensor that is using just a counter to store the events because I don’t need the historical windspeed for the algorithm.

void storeRainTick() {
    /*  Interupt function for storing the rain tick in a global array
    */
    static int prevRainState = LOW;            // Previous state of rain pin

    // Read current state of rain pin
    int curRainState = pinReadFast(rainPin);
    
    // If current state is HIGH and different than previous state
    if(curRainState != prevRainState && curRainState == HIGH) {
        // If more than 510 ticks in the last 24 hours (142.5mm), delete the first element
        // This will prevent an overflow of the vector
        if (rainTicks.size() > 510) {
            rainTicks.erase (rainTicks.begin());
        }
        // Push timestamp to rainvector
        rainTicks.push_back(Time.now());
    }
    
    // Set current state to previous state variable
    prevRainState = curRainState;
}

Code is setup:

void setup() {
    // Reserve memory for the rain vector (otherwise interrupt will crash in particle firmware version 1.0.0)
    rainTicks.reserve(511);

}

Variable definition:

// Interrupt global variables
std::vector<uint32_t> rainTicks;        // Vector for storing the timestamps of the rain ticks

I’ve also tried reducing vector size from 512 to 256.

Dynamic memory allocation is not allowed in an ISR.
That was already true prior to the the update but since the system didn’t guard against it memory leaks were inevitable.
Now these leaks can’t occure since the device OS prevents any attempt immediately via an SOS+14 panic.

While vectors may be easy to use, there are other options which don’t involve dynamic memory allocation in an ISR (or at all).

2 Likes

Ok, thanks for the feedback.

As a solution I’m thinking on creating a pre allocated array and process the data in that array into the vector in a function that is called in the loop.

It seems that Time.now() is also triggering a SOS. Is there another way to get a timestamp? I do like to have the ability to store multiple interrupts in the time the big processes are run (reading all sensors takes 750ms and one function takes even 5s).

Yup, that is another sore point I’ve already mentioned to Particle. Time does internally also use dynamic memory despite not really needed in all circumstances (i.e. Time.now()).

You could capture isrMillis = millis(); in your ISR and use this in your function ts = Time.now() - (millis() - isrMillis()) / 1000.0.

1 Like