Ejemplo n.º 1
0
/**
 * EasyFlash system initialize.
 *
 * @return result
 */
EfErrCode easyflash_init(void) {
    extern EfErrCode ef_port_init(uint32_t *env_addr, size_t *env_total_size,
            size_t *erase_min_size, ef_env const **default_env, size_t *default_env_size,
            size_t *log_size);
    extern EfErrCode ef_env_init(uint32_t start_addr, size_t total_size, size_t erase_min_size,
            ef_env const *default_env, size_t default_env_size);
    extern EfErrCode ef_iap_init(uint32_t start_addr);
    extern EfErrCode ef_log_init(uint32_t start_addr, size_t log_size, size_t erase_min_size);

    uint32_t env_start_addr;
    size_t env_total_size = 0, erase_min_size = 0, default_env_set_size = 0, log_size = 0;
    const ef_env *default_env_set;
    EfErrCode result = EF_NO_ERR;

    result = ef_port_init(&env_start_addr, &env_total_size, &erase_min_size, &default_env_set,
            &default_env_set_size, &log_size);

#ifdef EF_USING_ENV
    if (result == EF_NO_ERR) {
        result = ef_env_init(env_start_addr, env_total_size, erase_min_size, default_env_set,
                default_env_set_size);
    }
#endif

#ifdef EF_USING_IAP
    if (result == EF_NO_ERR) {
        result = ef_iap_init(env_start_addr + env_total_size + log_size);
    }
#endif

#ifdef EF_USING_LOG
    if (result == EF_NO_ERR) {
        result = ef_log_init(env_start_addr + env_total_size, log_size, erase_min_size);
    }
#endif

    if (result == EF_NO_ERR) {
        EF_DEBUG("EasyFlash V%s is initialize success.\n", EF_SW_VERSION);
    } else {
        EF_DEBUG("EasyFlash V%s is initialize fail.\n", EF_SW_VERSION);
    }

    return result;
}
Ejemplo n.º 2
0
/**
 * Find the log store start address and end address.
 * It's like a ring buffer which implement by flash.
 * The flash log area has two state when find start address and end address.
 *                       state 1                                state 2
 *                   |============|                         |============|
 * log area start--> |############| <-- start address       |############| <-- end address
 *                   |############|                         |   empty    |
 *                   |------------|                         |------------|
 *                   |############|                         |############| <-- start address
 *                   |############|                         |############|
 *                   |------------|                         |------------|
 *                   |     .      |                         |     .      |
 *                   |     .      |                         |     .      |
 *                   |     .      |                         |     .      |
 *                   |------------|                         |------------|
 *                   |############| <-- end address         |############|
 *                   |   empty    |                         |############|
 *  log area end --> |============|                         |============|
 *
 *  LOG_AREA_SIZE = log area end - log area star
 *
 */
static void find_start_and_end_addr(void) {
    size_t cur_size = 0;
    EfSecrorStatus cur_sec_status, last_sec_status;
    uint32_t cur_using_sec_addr = 0;
    /* all status sector counts */
    size_t empty_sec_counts = 0, using_sec_counts = 0, full_sector_counts = 0;
    /* total sector number */
    size_t total_sec_num = LOG_AREA_SIZE / EF_ERASE_MIN_SIZE;
    /* see comment of find_start_and_end_addr function */
    uint8_t cur_log_sec_state = 0;

    /* get the first sector status */
    cur_sec_status = ef_get_sector_status(log_area_start_addr, EF_ERASE_MIN_SIZE);
    last_sec_status = cur_sec_status;

    for (cur_size = EF_ERASE_MIN_SIZE; cur_size < LOG_AREA_SIZE; cur_size += EF_ERASE_MIN_SIZE) {
        /* get current sector status */
        cur_sec_status = ef_get_sector_status(log_area_start_addr + cur_size, EF_ERASE_MIN_SIZE);
        /* compare last and current status */
        switch (last_sec_status) {
        case EF_SECTOR_EMPTY: {
            switch (cur_sec_status) {
            case EF_SECTOR_EMPTY:
                break;
            case EF_SECTOR_USING:
                EF_DEBUG("Error: Log area error! Now will clean all log area.\n");
                ef_log_clean();
                return;
            case EF_SECTOR_FULL:
                EF_DEBUG("Error: Log area error! Now will clean all log area.\n");
                ef_log_clean();
                return;
            }
            empty_sec_counts++;
            break;
        }
        case EF_SECTOR_USING: {
            switch (cur_sec_status) {
            case EF_SECTOR_EMPTY:
                /* like state 1 */
                cur_log_sec_state = 1;
                log_start_addr = log_area_start_addr;
                cur_using_sec_addr = log_area_start_addr + cur_size - EF_ERASE_MIN_SIZE;
                break;
            case EF_SECTOR_USING:
                EF_DEBUG("Error: Log area error! Now will clean all log area.\n");
                ef_log_clean();
                return;
            case EF_SECTOR_FULL:
                /* like state 2 */
                cur_log_sec_state = 2;
                log_start_addr = log_area_start_addr + cur_size;
                cur_using_sec_addr = log_area_start_addr + cur_size - EF_ERASE_MIN_SIZE;
                break;
            }
            using_sec_counts++;
            break;
        }
        case EF_SECTOR_FULL: {
            switch (cur_sec_status) {
            case EF_SECTOR_EMPTY:
                /* like state 1 */
                if (cur_log_sec_state == 2) {
                    EF_DEBUG("Error: Log area error! Now will clean all log area.\n");
                    ef_log_clean();
                    return;
                } else {
                    cur_log_sec_state = 1;
                    log_start_addr = log_area_start_addr;
                    /* word alignment */
                    log_end_addr = log_area_start_addr + cur_size - 4;
                    cur_using_sec_addr = log_area_start_addr + cur_size - EF_ERASE_MIN_SIZE;
                }
                break;
            case EF_SECTOR_USING:
                if(total_sec_num <= 2) {
                    /* like state 1 */
                    cur_log_sec_state = 1;
                    log_start_addr = log_area_start_addr;
                    cur_using_sec_addr = log_area_start_addr + cur_size;
                } else {
                    /* like state 2 when the sector is the last one */
                    if (cur_size + EF_ERASE_MIN_SIZE >= LOG_AREA_SIZE) {
                        cur_log_sec_state = 2;
                        log_start_addr = log_area_start_addr + cur_size;
                        cur_using_sec_addr = log_area_start_addr + cur_size - EF_ERASE_MIN_SIZE;
                    }
                }
                break;
            case EF_SECTOR_FULL:
                break;
            }
            full_sector_counts++;
            break;
        }
        }
        last_sec_status = cur_sec_status;
    }

    /* the last sector status counts */
    if (cur_sec_status == EF_SECTOR_EMPTY) {
        empty_sec_counts++;
    } else if (cur_sec_status == EF_SECTOR_USING) {
        using_sec_counts++;
    } else if (cur_sec_status == EF_SECTOR_FULL) {
        full_sector_counts++;
    }

    if (using_sec_counts > 1) {
        EF_DEBUG("Error: Log area error! Now will clean all log area.\n");
        ef_log_clean();
        return;
    } else if (empty_sec_counts == total_sec_num) {
        log_start_addr = log_end_addr = log_area_start_addr;
    } else if (full_sector_counts == total_sec_num) {
        /* this state is almost impossible */
        EF_DEBUG("Error: Log area error! Now will clean all log area.\n");
        ef_log_clean();
        return;
    } else if (((cur_log_sec_state == 1) && (cur_using_sec_addr != 0))
            || (cur_log_sec_state == 2)) {
        /* find the end address */
        log_end_addr = ef_find_sec_using_end_addr(cur_using_sec_addr, EF_ERASE_MIN_SIZE);
    }
}