예제 #1
0
/**
 * Copy backup area application to application entry.
 *
 * @param user_app_addr application entry address
 * @param app_size application size
 *
 * @return result
 */
FlashErrCode flash_copy_app_from_bak(uint32_t user_app_addr, size_t app_size) {
    size_t cur_size;
    uint32_t app_cur_addr, bak_cur_addr;
    FlashErrCode result = FLASH_NO_ERR;
    /* 32 words size buffer */
    uint32_t buff[32];

    /* cycle copy data */
    for (cur_size = 0; cur_size < app_size; cur_size += sizeof(buff)) {
        app_cur_addr = user_app_addr + cur_size;
        bak_cur_addr = get_bak_app_start_addr() + cur_size;
        flash_read(bak_cur_addr, buff, sizeof(buff));
        result = flash_write(app_cur_addr, buff, sizeof(buff));
        if (result != FLASH_NO_ERR) {
            break;
        }
    }

    switch (result) {
    case FLASH_NO_ERR: {
        FLASH_INFO("Write data to application entry OK.\n");
        break;
    }
    case FLASH_WRITE_ERR: {
        FLASH_INFO("Warning: Write data to application entry fault!\n");
        break;
    }
    }

    return result;
}
예제 #2
0
/**
 * Copy backup area bootloader to bootloader entry.
 *
 * @param bl_addr bootloader entry address
 * @param bl_size bootloader size
 *
 * @return result
 */
FlashErrCode flash_copy_bl_from_bak(uint32_t bl_addr, size_t bl_size) {
    size_t cur_size;
    uint32_t bl_cur_addr, bak_cur_addr;
    FlashErrCode result = FLASH_NO_ERR;
    /* 32 words buffer */
    uint32_t buff[32];

    /* cycle copy data by 32bytes buffer */
    for (cur_size = 0; cur_size < bl_size; cur_size += sizeof(buff)) {
        bl_cur_addr = bl_addr + cur_size;
        bak_cur_addr = get_bak_app_start_addr() + cur_size;
        flash_read(bak_cur_addr, buff, sizeof(buff));
        result = flash_write(bl_cur_addr, buff, sizeof(buff));
        if (result != FLASH_NO_ERR) {
            break;
        }
    }

    switch (result) {
    case FLASH_NO_ERR: {
        FLASH_INFO("Write data to bootloader entry OK.\n");
        break;
    }
    case FLASH_WRITE_ERR: {
        FLASH_INFO("Warning: Write data to bootloader entry fault!\n");
        break;
    }
    }

    return result;
}
예제 #3
0
/**
 * If the ENV is not exist, create it.
 * @see flash_write_env
 *
 * @param key ENV name
 * @param value ENV value
 *
 * @return result
 */
static FlashErrCode create_env(const char *key, const char *value) {
    FlashErrCode result = FLASH_NO_ERR;

    FLASH_ASSERT(key);
    FLASH_ASSERT(value);

    if (*key == NULL) {
        FLASH_INFO("Flash ENV name must be not empty!\n");
        return FLASH_ENV_NAME_ERR;
    }

    if (strstr(key, "=")) {
        FLASH_INFO("Flash ENV name can't contain '='.\n");
        return FLASH_ENV_NAME_ERR;
    }

    /* find ENV */
    if (find_env(key)) {
        FLASH_INFO("The name of \"%s\" is already exist.\n", key);
        return FLASH_ENV_NAME_EXIST;
    }
    /* write ENV at the end of cache */
    result = write_env(key, value);

    return result;
}
예제 #4
0
/**
 * Save current using data section address to flash.
 *
 * @param cur_data_addr current using data section address
 *
 * @return result
 */
static FlashErrCode save_cur_using_data_addr(uint32_t cur_data_addr) {
    FlashErrCode result = FLASH_NO_ERR;
    /* erase ENV system section */
    result = flash_erase(get_env_start_addr(), 4);
    if (result == FLASH_NO_ERR) {
        /* write current using data section address to flash */
        result = flash_write(get_env_start_addr(), &cur_data_addr, 4);
        if (result == FLASH_WRITE_ERR) {
            FLASH_INFO("Error: Write system section fault!\n");
            FLASH_INFO("Note: The ENV can not be used.\n");
        }
    } else {
        FLASH_INFO("Error: Erased system section fault!\n");
        FLASH_INFO("Note: The ENV can not be used\n");
    }
    return result;
}
예제 #5
0
/**
 * Erase user old application
 *
 * @param user_app_addr application entry address
 * @param app_size application size
 *
 * @return result
 */
FlashErrCode flash_erase_user_app(uint32_t user_app_addr, size_t app_size) {
    FlashErrCode result = FLASH_NO_ERR;

    result = flash_erase(user_app_addr, app_size);
    switch (result) {
    case FLASH_NO_ERR: {
        FLASH_INFO("Erased user application OK.\n");
        break;
    }
    case FLASH_ERASE_ERR: {
        FLASH_INFO("Warning: Erase user application fault!\n");
        /* will return when erase fault */
        return result;
    }
    }

    return result;
}
예제 #6
0
/**
 * Erase backup area application data.
 *
 * @param app_size application size
 *
 * @return result
 */
FlashErrCode flash_erase_bak_app(size_t app_size) {
    FlashErrCode result = FLASH_NO_ERR;

    result = flash_erase(get_bak_app_start_addr(), app_size);
    switch (result) {
    case FLASH_NO_ERR: {
        FLASH_INFO("Erased backup area application OK.\n");
        break;
    }
    case FLASH_ERASE_ERR: {
        FLASH_INFO("Warning: Erase backup area application fault!\n");
        /* will return when erase fault */
        return result;
    }
    }

    return result;
}
예제 #7
0
/**
 * Erase old bootloader
 *
 * @param bl_addr bootloader entry address
 * @param bl_size bootloader size
 *
 * @return result
 */
FlashErrCode flash_erase_bl(uint32_t bl_addr, size_t bl_size) {
    FlashErrCode result = FLASH_NO_ERR;

    result = flash_erase(bl_addr, bl_size);
    switch (result) {
    case FLASH_NO_ERR: {
        FLASH_INFO("Erased bootloader OK.\n");
        break;
    }
    case FLASH_ERASE_ERR: {
        FLASH_INFO("Warning: Erase bootloader fault!\n");
        /* will return when erase fault */
        return result;
    }
    }

    return result;
}
예제 #8
0
/**
 * Delete an ENV in cache.
 *
 * @param key ENV name
 *
 * @return result
 */
FlashErrCode flash_del_env(const char *key){
    FlashErrCode result = FLASH_NO_ERR;
    char *del_env_str = NULL;
    size_t del_env_length, remain_env_length;

    FLASH_ASSERT(key);

    if (*key == NULL) {
        FLASH_INFO("Flash ENV name must be not NULL!\n");
        return FLASH_ENV_NAME_ERR;
    }

    if (strstr(key, "=")) {
        FLASH_INFO("Flash ENV name or value can't contain '='.\n");
        return FLASH_ENV_NAME_ERR;
    }

    /* find ENV */
    del_env_str = (char *) find_env(key);
    if (!del_env_str) {
        FLASH_INFO("Not find \"%s\" in ENV.\n", key);
        return FLASH_ENV_NAME_ERR;
    }
    del_env_length = strlen(del_env_str);
    /* '\0' also must be as ENV length */
    del_env_length ++;
    /* the address must multiple of 4 */
    if (del_env_length % 4 != 0) {
        del_env_length = (del_env_length / 4 + 1) * 4;
    }
    /* calculate remain ENV length */
    remain_env_length = get_env_detail_size()
            - (((uint32_t) del_env_str + del_env_length) - ((uint32_t) env_cache + ENV_PARAM_PART_BYTE_SIZE));
    /* remain ENV move forward */
    memcpy(del_env_str, del_env_str + del_env_length, remain_env_length);
    /* reset ENV end address */
    set_env_detail_end_addr(get_env_detail_end_addr() - del_env_length);

    return result;
}
예제 #9
0
/**
 * Write data of application to backup area.
 *
 * @param data a part of application
 * @param size data size
 * @param cur_size current write application size
 * @param total_size application total size
 *
 * @return result
 */
FlashErrCode flash_write_data_to_bak(uint8_t *data, size_t size, uint32_t *cur_size,
        size_t total_size) {
    FlashErrCode result = FLASH_NO_ERR;

    /* make sure don't write excess data */
    if (*cur_size + size > total_size) {
        size = total_size - *cur_size;
    }

    result = flash_write(get_bak_app_start_addr() + *cur_size, (uint32_t *) data, size);
    switch (result) {
    case FLASH_NO_ERR: {
        *cur_size += size;
        FLASH_INFO("Write data to backup area OK.\n");
        break;
    }
    case FLASH_WRITE_ERR: {
        FLASH_INFO("Warning: Write data to backup area fault!\n");
        break;
    }
    }

    return result;
}
예제 #10
0
/**
 * Load flash ENV to ram.
 */
void flash_load_env(void) {
    uint32_t *env_cache_bak, env_end_addr, using_data_addr;

    /* read current using data section address */
    flash_read(get_env_start_addr(), &using_data_addr, 4);
    /* if ENV is not initialize or flash has dirty data, set default for it */
    if ((using_data_addr == 0xFFFFFFFF)
            || (using_data_addr > get_env_start_addr() + flash_get_env_total_size())
            || (using_data_addr < get_env_start_addr() + flash_erase_min_size)) {
        /* initialize current using data section address */
        set_cur_using_data_addr(get_env_start_addr() + flash_erase_min_size);
        /* save current using data section address to flash*/
        save_cur_using_data_addr(get_cur_using_data_addr());
        /* set default ENV */
        flash_env_set_default();
    } else {
        /* set current using data section address */
        set_cur_using_data_addr(using_data_addr);
        /* read ENV detail part end address from flash */
        flash_read(get_cur_using_data_addr() + ENV_PARAM_PART_INDEX_END_ADDR * 4, &env_end_addr, 4);
        /* if ENV end address has error, set default for ENV */
        if (env_end_addr > get_env_start_addr() + flash_get_env_total_size()) {
            flash_env_set_default();
        } else {
            /* set ENV detail part end address */
            set_env_detail_end_addr(env_end_addr);

            env_cache_bak = env_cache + ENV_PARAM_PART_WORD_SIZE;
            /* read all ENV from flash */
            flash_read(get_env_detail_addr(), env_cache_bak, get_env_detail_size());

#ifdef FLASH_ENV_USING_CRC_CHECK
            /* read ENV CRC code from flash */
            flash_read(get_cur_using_data_addr() + ENV_PARAM_PART_INDEX_DATA_CRC * 4,
                    &env_cache[ENV_PARAM_PART_INDEX_DATA_CRC], 4);

            /* if ENV CRC32 check is fault, set default for it */
            if (!env_crc_is_ok()) {
                FLASH_INFO("Warning: ENV CRC check failed. Set it to default.\n");
                flash_env_set_default();
            }
        }
#endif

    }
}
예제 #11
0
/**
 * Find ENV.
 *
 * @param key ENV name
 *
 * @return index of ENV in ram cache
 */
static uint32_t *find_env(const char *key) {
    uint32_t *env_cache_addr = NULL;
    char *env_start, *env_end, *env, *env_bak;

    FLASH_ASSERT(cur_using_data_addr);

    if (*key == NULL) {
        FLASH_INFO("Flash ENV name must be not empty!\n");
        return NULL;
    }

    /* from data section start to data section end */
    env_start = (char *) ((char *) env_cache + ENV_PARAM_PART_BYTE_SIZE);
    env_end = (char *) ((char *) env_cache + ENV_PARAM_PART_BYTE_SIZE + get_env_detail_size());

    /* ENV is null */
    if (env_start == env_end) {
        return NULL;
    }

    env = env_start;
    while (env < env_end) {
        /* storage model is key=value\0 */
        env_bak = strstr(env, key);
        /* the key name length must be equal */
        if (env_bak && (env_bak[strlen(key)] == '=')) {
            env_cache_addr = (uint32_t *) env_bak;
            break;
        } else {
            /* next ENV and word alignment */
            if ((strlen(env) + 1) % 4 == 0) {
                env += strlen(env) + 1;
            } else {
                env += ((strlen(env) + 1) / 4 + 1) * 4;
            }
        }
    }
    return env_cache_addr;
}
예제 #12
0
파일: spi-flash.c 프로젝트: mirsys/xboot
	char * name;
	unsigned char id[6];
	int id_len;
	int sector_size;
	int sector_count;
	int flags;
};

struct spi_flash_private_data_t {
	struct spi_device_t * dev;
	struct spi_flash_id_t * id;
};

static struct spi_flash_id_t spi_flash_ids[] = {
	/* Atmel */
	FLASH_INFO("at25fs010",   0x1f6601, 0, 32 * 1024,   4, SECTOR_4K),
	FLASH_INFO("at25fs040",   0x1f6604, 0, 64 * 1024,   8, SECTOR_4K),
	FLASH_INFO("at25df041a",  0x1f4401, 0, 64 * 1024,   8, SECTOR_4K),
	FLASH_INFO("at25df321a",  0x1f4701, 0, 64 * 1024,  64, SECTOR_4K),
	FLASH_INFO("at25df641",   0x1f4800, 0, 64 * 1024, 128, SECTOR_4K),
	FLASH_INFO("at26f004",    0x1f0400, 0, 64 * 1024,   8, SECTOR_4K),
	FLASH_INFO("at26df081a",  0x1f4501, 0, 64 * 1024,  16, SECTOR_4K),
	FLASH_INFO("at26df161a",  0x1f4601, 0, 64 * 1024,  32, SECTOR_4K),
	FLASH_INFO("at26df321",   0x1f4700, 0, 64 * 1024,  64, SECTOR_4K),
	FLASH_INFO("at45db081d",  0x1f2500, 0, 64 * 1024,  16, SECTOR_4K),

	/* Winbond */
	FLASH_INFO("w25x05",  0xef3010, 0, 64 * 1024,   1, SECTOR_4K),
	FLASH_INFO("w25x10",  0xef3011, 0, 64 * 1024,   2, SECTOR_4K),
	FLASH_INFO("w25x20",  0xef3012, 0, 64 * 1024,   4, SECTOR_4K),
	FLASH_INFO("w25x40",  0xef3013, 0, 64 * 1024,   8, SECTOR_4K),
예제 #13
0
/**
 * Save ENV to flash.
 */
FlashErrCode flash_save_env(void) {
    FlashErrCode result = FLASH_NO_ERR;
    uint32_t cur_data_addr_bak = get_cur_using_data_addr(), move_offset_addr;
    size_t env_detail_size = get_env_detail_size();

    /* wear leveling process, automatic move ENV to next available position */
    while (get_cur_using_data_addr() + env_detail_size
            < get_env_start_addr() + flash_get_env_total_size()) {

#ifdef FLASH_ENV_USING_CRC_CHECK
    /* calculate and cache CRC32 code */
    env_cache[ENV_PARAM_PART_INDEX_DATA_CRC] = calc_env_crc();
#endif
        /* erase ENV */
        result = flash_erase(get_cur_using_data_addr(), ENV_PARAM_PART_BYTE_SIZE + env_detail_size);
        switch (result) {
        case FLASH_NO_ERR: {
            FLASH_INFO("Erased ENV OK.\n");
            break;
        }
        case FLASH_ERASE_ERR: {
            FLASH_INFO("Warning: Erased ENV fault!\n");
            FLASH_INFO("Moving ENV to next available position.\n");
            /* Calculate move offset address.
             * Current strategy is optimistic. It will offset the flash erasure minimum size.
             */
            move_offset_addr = flash_erase_min_size;
            /* calculate and set next available data section address */
            set_cur_using_data_addr(get_cur_using_data_addr() + move_offset_addr);
            /* calculate and set next available ENV detail part end address */
            set_env_detail_end_addr(get_env_detail_end_addr() + move_offset_addr);
            continue;
        }
        }
        /* write ENV to flash */
        result = flash_write(get_cur_using_data_addr(), env_cache,
                ENV_PARAM_PART_BYTE_SIZE + env_detail_size);
        switch (result) {
        case FLASH_NO_ERR: {
            FLASH_INFO("Saved ENV OK.\n");
            break;
        }
        case FLASH_WRITE_ERR: {
            FLASH_INFO("Warning: Saved ENV fault!\n");
            FLASH_INFO("Moving ENV to next available position.\n");
            /* Calculate move offset address.
             * Current strategy is optimistic. It will offset the flash erasure minimum size.
             */
            move_offset_addr = flash_erase_min_size;
            /* calculate and set next available data section address */
            set_cur_using_data_addr(get_cur_using_data_addr() + move_offset_addr);
            /* calculate and set next available ENV detail part end address */
            set_env_detail_end_addr(get_env_detail_end_addr() + move_offset_addr);
            continue;
        }
        }
        /* save ENV success */
        if (result == FLASH_NO_ERR) {
            break;
        }
    }

    if (get_cur_using_data_addr() + env_detail_size
            < get_env_start_addr() + flash_get_env_total_size()) {
        /* current using data section address has changed, save it */
        if (get_cur_using_data_addr() != cur_data_addr_bak) {
            save_cur_using_data_addr(get_cur_using_data_addr());
        }
    } else {
        result = FLASH_ENV_FULL;
        FLASH_INFO("Error: The flash has no available space to save ENV.\n");
        /* clear current using data section address on flash */
        save_cur_using_data_addr(0xFFFFFFFF);
    }

    return result;
}