Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 37 additions & 22 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1398,7 +1398,7 @@ void info_guts(memory_access &raw_access) {
string program_name, program_build_date, program_version, program_url, program_description;
string pico_board, sdk_version, boot2_name;
vector<string> program_features, build_attributes;

uint32_t binary_end = 0;

// do a pass first to find named groups
Expand Down Expand Up @@ -1838,44 +1838,61 @@ bool load_command::execute(device_map &devices) {
}
}
}
for (auto mem_range : ranges) {
enum memory_type type = get_memory_type(mem_range.from);
// new scope for progress bar
{
progress_bar bar("Loading into " + memory_names[type] + ": ");
uint32_t batch_size = FLASH_SECTOR_ERASE_SIZE;
bool ok = true;

size_t total_size = 0;
for (auto mem_range : ranges) { total_size += mem_range.to - mem_range.from; }

{
progress_bar bar("Loading: ");
size_t loaded_size = 0;
for (auto mem_range : ranges) {
enum memory_type type = get_memory_type(mem_range.from);
vector<uint8_t> file_buf;
vector<uint8_t> device_buf;
for (uint32_t base = mem_range.from; base < mem_range.to && ok; ) {
for (uint32_t base = mem_range.from; base < mem_range.to; ) {
uint32_t batch_size = FLASH_SECTOR_ERASE_SIZE;
uint8_t block_erase_cmd = 0x20;
if (mem_range.to - base >= 0x10000) {
batch_size = 0x10000;
block_erase_cmd = 0xD8;
}
else if (mem_range.to - base >= 0x8000) {
batch_size = 0x8000;
block_erase_cmd = 0x52;
}
Comment on lines +1854 to +1862
Copy link
Contributor

@lurch lurch Feb 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably makes sense to add #define values for these different erase cmds? 🤷‍♂️
(but like you, I dunno how widely supported these commands are amongst other flash chips, and that'll be the kicker here!)

uint32_t this_batch = std::min(mem_range.to - base, batch_size);
if (type == flash) {
// we have to erase an entire page, so then fill with zeros
range aligned_range(base & ~(FLASH_SECTOR_ERASE_SIZE - 1), (base & ~(FLASH_SECTOR_ERASE_SIZE - 1)) + FLASH_SECTOR_ERASE_SIZE);
range aligned_range(base & ~(batch_size - 1), (base & ~(batch_size - 1)) + batch_size);
range read_range(base, base + this_batch);
read_range.intersect(aligned_range);
file_access.read_into_vector(read_range.from, read_range.to - read_range.from, file_buf);
// zero padding up to FLASH_SECTOR_ERASE_SIZE
// zero padding up to batch_size
file_buf.insert(file_buf.begin(), read_range.from - aligned_range.from, 0);
file_buf.insert(file_buf.end(), aligned_range.to - read_range.to, 0);
assert(file_buf.size() == FLASH_SECTOR_ERASE_SIZE);
assert(file_buf.size() == batch_size);
con.exit_xip();
con.flash_erase(aligned_range.from, FLASH_SECTOR_ERASE_SIZE);
con.flash_range_erase(aligned_range.from - FLASH_START, batch_size, batch_size, block_erase_cmd);
raw_access.write_vector(aligned_range.from, file_buf);
base = read_range.to; // about to add batch_size
} else {
file_access.read_into_vector(base, this_batch, file_buf);
raw_access.write_vector(base, file_buf);
base += this_batch;
}
bar.progress(base - mem_range.from, mem_range.to - mem_range.from);
loaded_size += this_batch;
bar.progress(loaded_size, total_size);
}
}
if (settings.load.verify) {
}

if (settings.load.verify) {
progress_bar bar("Verifying: ");
size_t verified_size = 0;
for (auto mem_range : ranges) {
bool ok = true;
{
progress_bar bar("Verifying " + memory_names[type] + ": ");
uint32_t batch_size = FLASH_SECTOR_ERASE_SIZE;
uint32_t batch_size = 0x8000;
vector<uint8_t> file_buf;
vector<uint8_t> device_buf;
uint32_t pos = mem_range.from;
Expand All @@ -1893,14 +1910,12 @@ bool load_command::execute(device_map &devices) {
}
if (ok) {
pos = base + this_batch;
verified_size += this_batch;
bar.progress(verified_size, total_size);
}
bar.progress(pos - mem_range.from, mem_range.to - mem_range.from);
}
}
if (ok) {
std::cout << " OK\n";
} else {
std::cout << " FAILED\n";
if (!ok) {
fail(ERROR_VERIFICATION_FAILED, "The device contents did not match the file");
}
}
Expand Down
17 changes: 17 additions & 0 deletions picoboot_connection/call.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.cpu cortex-m0
.thumb
push {r4, lr}
mov r4, #20
ldrh r0, [r4] // r0 = function_table
ldrh r1, args
ldrh r4, [r4, #4] // r4 = table_lookup
blx r4
mov r4, r0
ldr r0, args + 4
ldr r1, args + 8
ldr r2, args + 12
ldrb r3, args + 16
blx r4
pop {r4, pc}
.balign 4, 0
args:
22 changes: 22 additions & 0 deletions picoboot_connection/picoboot_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,28 @@ int picoboot_exec(libusb_device_handle *usb_device, uint32_t addr) {
return picoboot_cmd(usb_device, &cmd, NULL, 0);
}

// Calls flash_range_erase in the bootrom.
int picoboot_flash_range_erase(libusb_device_handle *usb_device,
uint32_t addr, uint32_t len, uint32_t block_size, uint8_t block_cmd)
{
// These bytes come from `arm-none-eabi-as -al call.s`, with the function
// lookup code and function arguments appended.
uint8_t call_asm[] = {
0x10, 0xB5, 0x14, 0x24, 0x20, 0x88, 0x05, 0x49,
0xA4, 0x88, 0xA0, 0x47, 0x04, 0x1C, 0x04, 0x48,
0x04, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0xA0, 0x47,
0x10, 0xBD, 0, 0,
'R', 'E', 0, 0,
addr, addr >> 8, addr >> 16, addr >> 24,
len, len >> 8, len >> 16, len >> 24,
block_size, block_size >> 8, block_size >> 16, block_size >> 24,
block_cmd, 0, 0, 0,
};
int ret = picoboot_write(usb_device, SRAM_START, call_asm, sizeof(call_asm));
if (ret) { return ret; }
return picoboot_exec(usb_device, SRAM_START);
}

int picoboot_flash_erase(libusb_device_handle *usb_device, uint32_t addr, uint32_t len) {
struct picoboot_cmd cmd;
if (verbose) output("FLASH_ERASE %08x+%08x\n", (uint) addr, (uint) len);
Expand Down
1 change: 1 addition & 0 deletions picoboot_connection/picoboot_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ int picoboot_enter_cmd_xip(libusb_device_handle *usb_device);
int picoboot_exit_xip(libusb_device_handle *usb_device);
int picoboot_reboot(libusb_device_handle *usb_device, uint32_t pc, uint32_t sp, uint32_t delay_ms);
int picoboot_exec(libusb_device_handle *usb_device, uint32_t addr);
int picoboot_flash_range_erase(libusb_device_handle *, uint32_t, uint32_t, uint32_t, uint8_t);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the missing parameter-names here?

Copy link
Contributor Author

@DavidEGrayson DavidEGrayson Feb 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wanted to keep the lines to a reasonable length so you can have a text editor and terminal on the same screen. It would have been OK to have the names and insert a line break instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the header-file often used as a quick-reference list of the functions and their parameters? That's why I'd argue for including the parameter-names, but ultimately that's Graham's decision.

int picoboot_flash_erase(libusb_device_handle *usb_device, uint32_t addr, uint32_t len);
int picoboot_vector(libusb_device_handle *usb_device, uint32_t addr);
int picoboot_write(libusb_device_handle *usb_device, uint32_t addr, uint8_t *buffer, uint32_t len);
Expand Down
6 changes: 6 additions & 0 deletions picoboot_connection/picoboot_connection_cxx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ void connection::exec(uint32_t addr) {
wrap_call([&] { return picoboot_exec(device, addr); });
}

void connection::flash_range_erase(uint32_t addr, uint32_t len,
uint32_t block_size, uint8_t block_cmd) {
wrap_call([&] { return picoboot_flash_range_erase(device, addr, len,
block_size, block_cmd); });
}

void connection::flash_erase(uint32_t addr, uint32_t len) {
wrap_call([&] { return picoboot_flash_erase(device, addr, len); });
}
Expand Down
1 change: 1 addition & 0 deletions picoboot_connection/picoboot_connection_cxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace picoboot {
void exit_xip();
void reboot(uint32_t pc, uint32_t sp, uint32_t delay_ms);
void exec(uint32_t addr);
void flash_range_erase(uint32_t addr, uint32_t len, uint32_t block_size, uint8_t block_cmd);
void flash_erase(uint32_t addr, uint32_t len);
void vector(uint32_t addr);
void write(uint32_t addr, uint8_t *buffer, uint32_t len);
Expand Down