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; }
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; }