Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simple UART bootloader example #571

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions bootloaders/uart/uart-pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
{
"start": "128K",
"size": "32K",
Copy link
Contributor

Choose a reason for hiding this comment

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

If this is intended as a "generic UART bootloader", should we increase the size of this partition to allow for bigger UF2s?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The issue is that this simple bootloader just loads the whole partition onto the other device, so the larger the partition the longer it takes. From a quick play it takes 0.35s for this 32kiB partition, vs 5.6s for a full 512kiB partition (which would be the maximum size, as that fills the RP2350 SRAM)

Copy link
Contributor

@lurch lurch Nov 20, 2024

Choose a reason for hiding this comment

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

Ah, that makes sense. I guess in theory a more complicated UART bootloader could look at the IMAGE_DEF and only copy the part of the partition that it needed to?

I've not played with partitions on the RP2350 yet, but what happens if you try drag'n'dropping a 128kiB image into a partition that's only 32kiB big?

EDIT: And in hindsight I've just realised that this can't be a "generic UART bootloader" anyway, because it forcefully resets the other RP2350 if it doesn't receive the string "Hello" over the UART 😀

"families": ["rp2350-arm-s"],
"families": ["rp2350-arm-s", "rp2350-riscv"],
"permissions": {
"secure": "rw",
"nonsecure": "rw",
"bootloader": "rw"
}
}
]
}
}
82 changes: 73 additions & 9 deletions bootloaders/uart/uart_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ void reset_chip() {

void uart_boot() {
uint knocks = 0;
char in = 0;
while (true) {
// Send the knock sequence
uart_putc_raw(UART_ID, 0x56);
Expand All @@ -36,13 +37,17 @@ void uart_boot() {
uart_putc_raw(UART_ID, 'n');

if (uart_is_readable_within_us(UART_ID, 1000)) {
char in = uart_getc(UART_ID);
assert(in == 'n');
in = uart_getc(UART_ID);
if (in != 'n') {
printf("Incorrect response - resetting\n");
reset_chip();
return;
}
printf("%c\n", in);
break;
} else {
if (knocks > 10) {
printf("No response - resetting\n");
printf("No response - resetting\n");
reset_chip();
return;
}
Expand Down Expand Up @@ -83,25 +88,84 @@ void uart_boot() {
reset_chip();
return;
}
char in = uart_getc(UART_ID);
printf("%c\n", in);
assert(in == 'w');
in = uart_getc(UART_ID);
if (in != 'w') {
printf("Incorrect response - resetting\n");
reset_chip();
return;
}
current_addr += 32;
}

uint32_t time_end = time_us_32();
printf("Write took %dus\n", time_end - time_start);
printf("Write complete - executing\n");
printf("Write complete - resetting pointer\n");

uart_putc_raw(UART_ID, 'c');
if (!uart_is_readable_within_us(UART_ID, 500)) {
// Detect hangs and reset the chip
printf("Clear has hung - resetting\n");
reset_chip();
return;
}
in = uart_getc(UART_ID);
printf("%c\n", in);
if (in != 'c') {
printf("Incorrect response - resetting\n");
reset_chip();
return;
}

printf("Verifying binary\n");
time_start = time_us_32();
current_addr = start_addr;
while (current_addr < end_addr) {
uart_putc_raw(UART_ID, 'r');
char *buf = (char*)current_addr;
if (!uart_is_readable_within_us(UART_ID, 500)) {
// Detect hangs and reset the chip
printf("Verify has hung - resetting\n");
reset_chip();
return;
}
int i = 0;
while (uart_is_readable_within_us(UART_ID, 10) && i < 32) {
in = uart_getc(UART_ID);
if (in != buf[i]) {
printf("Verify has incorrect data at 0x%08x - resetting\n", current_addr - start_addr + SRAM_BASE);
}
i++;
}
if (i != 32) {
printf("Verify has incorrect data size - resetting\n");
}
in = uart_getc(UART_ID);
if (in != 'r') {
printf("Incorrect response - resetting\n");
reset_chip();
return;
}
current_addr += 32;
Copy link
Contributor

Choose a reason for hiding this comment

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

Or I guess you could do += i 😉

}

time_end = time_us_32();
printf("Verify took %dus\n", time_end - time_start);
printf("Verify complete - executing\n");

uart_putc_raw(UART_ID, 'x');
if (!uart_is_readable_within_us(UART_ID, 500)) {
// Detect hangs and reset the chip
printf("Execute has hung - resetting\n");
reset_chip();
return;
}
char in = uart_getc(UART_ID);
in = uart_getc(UART_ID);
printf("%c\n", in);
assert(in == 'x');
if (in != 'x') {
printf("Incorrect response - resetting\n");
reset_chip();
return;
}
}


Expand Down
Loading