ESP8266 int alignment fun

OK. Pop quiz. What’s wrong with the following C++ code?

unsigned char * chPtr;
int * intPtr;

// point chPtr at a buffer somewhere

// get an integer out of the buffer
intPtr = (int *) chPtr;
Serial.println(*intPtr);

Perhaps a bit of context would help. I use commands like this to tell my Connected Little Boxes what to do:

{"process":"pixels","command":"setrandomcolour",
"pixelSpeed":10, "sensor":"button","trigger":"pressed"}

This command means “send the command setrandomcolour” to the pixels process when the user presses a button. Fade the colour over 10 “ticks”. This means that each time the user presses the button on the box the lights will change colour.

The box is smart enough to understand this tiny chunk of JSON but I don’t want to have to decode the command every time the button is pressed. So the program assembles a block of memory containing things like the “10” value for pixelspeed and this is read when the sensor event is triggered and used to control the command. Works very well. Except sometimes. Sometimes the code throws Exception(9) and the processor resets.

The error came from nowhere and I spent ages checking the code that I’d just written to find what I’d broken. After a while I took the trouble to look up what Exception(9) actually means, and that’s when I discovered the stupid thing I’d done.

The code above uses a pointer to an 8 bit location somewhere in memory and then fetches an integer from that place. it’s what gets the stored pixelspeed value for the pixels process to use. But the ESP8266 stores integers in a block of four memory locations as a 32 bit value and it insists that these are always aligned. In other words, you put the first value in the bytes at locations 0 to 3, the second at locations 4 to 7 and so on, using the convention that the memory is addressed starting at location number 0. If a program tries to load a value from an “odd” location the processor crashes.

This means that if store something in memory and then try to read it back as an integer I have a 1 in four chance of it working and a 3 in 4 chance of it failing. Up until now I’d been lucky, but today I wasn’t.

When you write an assembly language program you can use special directives to line the data up in the right locations. The same thing happens in C++ when you make a structure. The compiler will insert extra space to make things line up when they should. One way to fix it would be to make sure that I always line things up in my program but this would have been a bit of a pain, so I wrote the function below:

int getUnalignedInt(unsigned char * source)
{
    int result;
    memcpy((unsigned char *)&result,source,sizeof(int));
    return result;
}

You pass the function a pointer to anywhere in memory. It copies some integer bytes into a lined up integer value and then returns the value. It seems to work fine. It’s not the most efficient solution but I can live with that for now..

Alarms are complicated

I’ve always found it surprising how simple things end up being complicated. Take adding alarms to my Connected Little Boxes…. I want to have alarms that I can set in the device. When an alarm time is reached I want the device to perform an assigned action, perhaps make a sound, drive a servo or change the colour of a light. This is simple I say to myself. And I write a function to celebrate:

bool atAlarmTime(struct ClockAlarm *alarm, struct clockReading *reading)
{
    if (alarm->hour != reading->hour)
    {
        return false;
    }

    if (alarm->minute != reading->minute)
    {
        return false;
    }

    return true;
}

The function will return true when the clock reaches the alarm time. I can use this to trigger whatever action is bound to the alarm. Simple.

Well, not really. My program will be repeatedly checking the alarm to see if it has triggered. So if I just use the above function I will find that an alarm will trigger continuously for the entire alarm minute when it due. And what about when I turn the device on or change the time? Do I want it to ignore “past” alarms or not? If my device was controlling a heating system I’d want it to respond to an alarm even to turn the heating on even if that event was in the past. Otherwise I’d turn the system on at 12:00 and freeze because the event that turned on the boiler was set to 7:00am.

I’ve ended up setting up options and flags and writing code that spins through the set alarms looking for ones that should have been triggered and triggering them if that is what the user wants. Yep. Alarms are complicated.