crownstone / bluenet

Bluenet is the in-house firmware on Crownstone hardware. Functions: switching, dimming, energy monitoring, presence detection, indoor localization, switchcraft.
https://crownstone.rocks
91 stars 62 forks source link

Feature/microapp fault detection #178

Closed mrquincle closed 2 years ago

mrquincle commented 2 years ago

Addresses issue on microapp management https://github.com/crownstone/bluenet/issues/147

In whatever kind of circumstances, infinite loops, segfaults, etc., a microapp has to be blamed for things going wrong. This is implemented with these commits.

Will be converted in non-draft PR after I've tested it on dev. boards (somehow I don't have them here now).

mrquincle commented 2 years ago

There was a lot of activity on the main branch, so a resubmit of this PR might be appropriate.

It narrows done to defining an additional IPC struct, say with index IPC_INDEX_MICROAPP_STATE and then setting and getting it. Something like this:

void MicroappController::setOperatingState(uint8_t appIndex, MicroappRuntimeState state) {
    _microappRuntimeData.appState[appIndex] = state;
    setRamData(
            IPC_INDEX_MICROAPP_STATE, reinterpret_cast<uint8_t*>(&_microappRuntimeData), sizeof(_microappRuntimeData));
}

MicroappRuntimeState MicroappController::getOperatingState(uint8_t appIndex) {
    uint8_t returnedDataSize = 0;
    getRamData(
            IPC_INDEX_MICROAPP_STATE,
            reinterpret_cast<uint8_t*>(&_microappRuntimeData),
            sizeof(_microappRuntimeData),
            &returnedDataSize);
    if (returnedDataSize != sizeof(_microappRuntimeData)) {
        LOGi("Incorrect data size");
    }
    return _microappRuntimeData.appState[appIndex];
}

/*
 * We resume the previously started coroutine.
 * We resume the previously started coroutine. If we extend to multiple coroutines, nextCoroutine needs to get a
 * microapp id as argument (as well as this function itself).
 */
void MicroappController::callMicroapp() {
#if DEVELOPER_OPTION_DISABLE_COROUTINE == 0
    const uint8_t appIndex = 0;
    setOperatingState(appIndex, MicroappRuntimeState::CS_MICROAPP_RUNNING);
    if (nextCoroutine()) {
        setOperatingState(appIndex, MicroappRuntimeState::CS_MICROAPP_NOT_RUNNING);
        return;
    }
#else
mrquincle commented 2 years ago

And first https://github.com/crownstone/bluenet/pull/182 must be merged.

mrquincle commented 2 years ago

Tested with https://github.com/crownstone/crownstone-microapp/blob/master/examples/faulty.ino microapp.

mrquincle commented 2 years ago

I didn't realize we needed a new IPC segment for this. I guess a central place to use that segment is indeed the way to go later.

You're kidding I hope.