Example #1
0
error_t flash_manager_data(uint32_t addr, const uint8_t *data, uint32_t size)
{
    uint32_t size_left;
    uint32_t copy_size;
    uint32_t pos;
    error_t status = ERROR_SUCCESS;
    flash_manager_printf("flash_manager_data(addr=0x%x size=0x%x)\r\n", addr, size);

    if (state != STATE_OPEN) {
        util_assert(0);
        return ERROR_INTERNAL;
    }

    // Enforce that addresses are sequential.  Currently flash manager
    // only supports sequential addresses.  In the future flash manager
    // could be updated to support this.
    if (addr < last_addr) {
        util_assert(0);
        state = STATE_ERROR;
        return ERROR_INTERNAL;
    }

    // Setup the current sector if it is not setup already
    if (!current_sector_valid) {
        status = setup_next_sector(addr);

        if (ERROR_SUCCESS != status) {
            state = STATE_ERROR;
            return status;
        }
        current_sector_valid = true;
    }

    while (true) {
        // flush if necessary
        if (addr >= current_write_block_addr + current_write_block_size) {
            // Write out current buffer
            status = intf->program_page(current_write_block_addr, buf, current_write_block_size);
            flash_manager_printf("    intf->program_page(addr=0x%x, size=0x%x) ret=%i\r\n", current_write_block_addr, current_write_block_size, status);

            if (ERROR_SUCCESS != status) {
                state = STATE_ERROR;
                return status;
            }

            // Setup for next page
            memset(buf, 0xFF, current_write_block_size);
            buf_empty = true;
            current_write_block_addr += current_write_block_size;
        }

        // Check for end
        if (size <= 0) {
            break;
        }

        // Change sector if necessary
        if (addr >= current_sector_addr + current_sector_size) {
            status = setup_next_sector(addr);

            if (ERROR_SUCCESS != status) {
                state = STATE_ERROR;
                return status;
            }
        }

        // write buffer
        pos = addr - current_write_block_addr;
        size_left = current_write_block_size - pos;
        copy_size = MIN(size, size_left);
        memcpy(buf + pos, data, copy_size);
        buf_empty = copy_size == 0;
        // Update variables
        addr += copy_size;
        data += copy_size;
        size -= copy_size;
    }

    last_addr = addr;
    return status;
}
Example #2
0
error_t flash_manager_data(uint32_t addr, const uint8_t *data, uint32_t size)
{
    uint32_t size_left;
    uint32_t copy_size;
    uint32_t pos;
    error_t status = ERROR_SUCCESS;
    flash_manager_printf("flash_manager_data(addr=0x%x size=0x%x)\r\n", addr, size);

    if (state != STATE_OPEN) {
        util_assert(0);
        return ERROR_INTERNAL;
    }

    // Setup the current sector if it is not setup already
    if (!current_sector_valid) {
        status = setup_next_sector(addr);

        if (ERROR_SUCCESS != status) {
            state = STATE_ERROR;
            return status;
        }
        current_sector_valid = true;
        last_addr = addr;
    }
    
    //non-increasing address support
    if (ROUND_DOWN(addr, current_write_block_size) != ROUND_DOWN(last_addr, current_write_block_size)) {    
        status = flush_current_block(addr);
        if (ERROR_SUCCESS != status) {
            state = STATE_ERROR;
            return status;
        }
    }
    
    if (ROUND_DOWN(addr, current_sector_size) != ROUND_DOWN(last_addr, current_sector_size)) {
        status = setup_next_sector(addr);
        if (ERROR_SUCCESS != status) {
            state = STATE_ERROR;
            return status;
        }
    }

    while (true) {
        // flush if necessary
        if (addr >= current_write_block_addr + current_write_block_size) {
            status = flush_current_block(addr);
            if (ERROR_SUCCESS != status) {
                state = STATE_ERROR;
                return status;
            }
        }

        // Check for end
        if (size <= 0) {
            break;
        }

        // Change sector if necessary
        if (addr >= current_sector_addr + current_sector_size) {
            status = setup_next_sector(addr);

            if (ERROR_SUCCESS != status) {
                state = STATE_ERROR;
                return status;
            }
            // check is at sector boundary
            if (addr != current_write_block_addr) {
                current_write_block_addr = addr & 0xFFFFFFF0;  // 16 bytes alignment
            }
        }

        // write buffer
        pos = addr - current_write_block_addr;
        size_left = current_write_block_size - pos;
        copy_size = MIN(size, size_left);
        memcpy(buf + pos, data, copy_size);
        buf_empty = copy_size == 0;
        // Update variables
        addr += copy_size;
        data += copy_size;
        size -= copy_size;
    }

    last_addr = addr;
    return status;
}