Implement simple uart-based updater for the bootrom (#2267)

This commit is contained in:
Gregor Haas 2024-06-19 02:24:01 -07:00 committed by GitHub
parent 9df64701bd
commit c92245b20b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 77 additions and 1 deletions

View file

@ -7,12 +7,71 @@
#include "sd.h"
#include "gpt.h"
// 1 second at 50MHz
#define SECOND_CYCLES (50 * 1000 * 1000)
#define WAIT_SECONDS (5)
static inline uintptr_t get_cycle_count() {
uintptr_t cycle;
__asm__ volatile ("csrr %0, cycle" : "=r" (cycle));
return cycle;
}
int update(uint8_t *dest)
{
int i;
uint32_t size = 0;
print_uart("receiving boot image\r\nsize: ");
for(i = 0; i < sizeof(uint32_t); i++) {
while(!read_serial(&((uint8_t *) &size)[i]));
}
print_uart_int(size);
print_uart("\r\nreceiving ");
for(i = 0; i < size; i++) {
while(!read_serial(&dest[i]));
if(i % (size >> 4) == 0) {
print_uart(".");
}
}
print_uart(" done!\r\n");
return 0;
}
int main()
{
int i, ret = 0;
uint8_t uart_res = 0;
uintptr_t start;
init_uart(CLOCK_FREQUENCY, UART_BITRATE);
print_uart("Hello World!\r\n");
int res = gpt_find_boot_partition((uint8_t *)0x80000000UL, 2 * 16384);
// See if we should enter update mode
print_uart("Hit any key to enter update mode ");
for(i = 0; i < WAIT_SECONDS && !ret; i++) {
print_uart(".");
start = get_cycle_count();
while(get_cycle_count() - start < SECOND_CYCLES) {
ret = read_serial(&uart_res);
if(ret) {
break;
}
}
}
int res;
if(ret) {
print_uart(" updating!\r\n");
res = update((uint8_t *)0x80000000UL);
} else {
print_uart(" booting!\r\n");
res = gpt_find_boot_partition((uint8_t *)0x80000000UL, 2 * 16384);
}
if (res == 0)
{

View file

@ -20,6 +20,11 @@ int is_transmit_empty()
return read_reg_u8(UART_LINE_STATUS) & 0x20;
}
int is_receive_empty()
{
return !(read_reg_u8(UART_LINE_STATUS) & 0x1);
}
void write_serial(char a)
{
while (is_transmit_empty() == 0) {};
@ -27,6 +32,16 @@ void write_serial(char a)
write_reg_u8(UART_THR, a);
}
int read_serial(uint8_t *res)
{
if(is_receive_empty()) {
return 0;
}
*res = read_reg_u8(UART_RBR);
return 1;
}
void init_uart(uint32_t freq, uint32_t baud)
{
uint32_t divisor = freq / (baud << 4);

View file

@ -22,6 +22,8 @@
void init_uart();
int read_serial(uint8_t *res);
void print_uart(const char* str);
void print_uart_int(uint32_t addr);