예제 #1
0
// Initialize all PG records from EEPROM.
// This functions processes all PGs sequentially, scanning EEPROM for each one. This is suboptimal,
//   but each PG is loaded/initialized exactly once and in defined order.
bool loadEEPROM(void)
{
    // read in the transitional masterConfig record
    const uint8_t *p = &__config_start;
    p += sizeof(configHeader_t); // skip header
    masterConfig = *(master_t*)p;

    PG_FOREACH(reg) {
        configRecordFlags_e cls_start, cls_end;
        if (pgIsSystem(reg)) {
            cls_start = CR_CLASSICATION_SYSTEM;
            cls_end = CR_CLASSICATION_SYSTEM;
        } else {
            cls_start = CR_CLASSICATION_PROFILE1;
            cls_end = CR_CLASSICATION_PROFILE_LAST;
        }
        for (configRecordFlags_e cls = cls_start; cls <= cls_end; cls++) {
            int profileIndex = cls - cls_start;
            const configRecord_t *rec = findEEPROM(reg, cls);
            if (rec) {
                // config from EEPROM is available, use it to initialize PG. pgLoad will handle version mismatch
                pgLoad(reg, profileIndex, rec->pg, rec->size - offsetof(configRecord_t, pg), rec->version);
            } else {
                pgReset(reg, profileIndex);
            }
        }
    }
    return true;
}
예제 #2
0
// Load a PG into RAM, upgrading and downgrading as needed.
static bool loadPG(const configRecord_t *record)
{
    const pgRegistry_t *reg = pgMatcher(pgMatcherForConfigRecord, record);

    if (reg == NULL) {
        return false;
    }

    uint8_t profileIndex = 0;

    if (!pgIsSystem(reg)) {
        profileIndex = (record->flags & CR_CLASSIFICATION_MASK) - 1;
    }

    pgLoad(reg, record->pg, record->size, profileIndex);
    return true;
}
예제 #3
0
static bool writeSettingsToEEPROM(void)
{
    config_streamer_t streamer;
    config_streamer_init(&streamer);

    config_streamer_start(&streamer, (uintptr_t)&__config_start, &__config_end - &__config_start);
    uint8_t chk = 0;

    configHeader_t header = {
        .eepromConfigVersion = EEPROM_CONF_VERSION,
        .boardIdentifier = TARGET_BOARD_IDENTIFIER,
    };

    config_streamer_write(&streamer, (uint8_t *)&header, sizeof(header));
    chk = updateChecksum(chk, (uint8_t *)&header, sizeof(header));
    // write the transitional masterConfig record
    config_streamer_write(&streamer, (uint8_t *)&masterConfig, sizeof(masterConfig));
    chk = updateChecksum(chk, (uint8_t *)&masterConfig, sizeof(masterConfig));
    PG_FOREACH(reg) {
        const uint16_t regSize = pgSize(reg);
        configRecord_t record = {
            .size = sizeof(configRecord_t) + regSize,
            .pgn = pgN(reg),
            .version = pgVersion(reg),
            .flags = 0
        };

        if (pgIsSystem(reg)) {
            // write the only instance
            record.flags |= CR_CLASSICATION_SYSTEM;
            config_streamer_write(&streamer, (uint8_t *)&record, sizeof(record));
            chk = updateChecksum(chk, (uint8_t *)&record, sizeof(record));
            config_streamer_write(&streamer, reg->address, regSize);
            chk = updateChecksum(chk, reg->address, regSize);
        } else {
            // write one instance for each profile
            for (uint8_t profileIndex = 0; profileIndex < MAX_PROFILE_COUNT; profileIndex++) {
                record.flags = 0;

                record.flags |= ((profileIndex + 1) & CR_CLASSIFICATION_MASK);
                config_streamer_write(&streamer, (uint8_t *)&record, sizeof(record));
                chk = updateChecksum(chk, (uint8_t *)&record, sizeof(record));
                const uint8_t *address = reg->address + (regSize * profileIndex);
                config_streamer_write(&streamer, address, regSize);
                chk = updateChecksum(chk, address, regSize);
            }
        }
    }

    configFooter_t footer = {
        .terminator = 0,
    };

    config_streamer_write(&streamer, (uint8_t *)&footer, sizeof(footer));
    chk = updateChecksum(chk, (uint8_t *)&footer, sizeof(footer));

    // append checksum now
    chk = ~chk;
    config_streamer_write(&streamer, &chk, sizeof(chk));

    config_streamer_flush(&streamer);

    bool success = config_streamer_finish(&streamer) == 0;

    return success;
}

void writeConfigToEEPROM(void)
{
    bool success = false;
    // write it
    for (int attempt = 0; attempt < 3 && !success; attempt++) {
        if (writeSettingsToEEPROM()) {
            success = true;
        }
    }

    if (success && isEEPROMContentValid()) {
        return;
    }

    // Flash write failed - just die now
    failureMode(FAILURE_FLASH_WRITE_FAILED);
}