From 15da939f0b01e83ebd9482bc5cc28e21424f43f6 Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Tue, 26 Dec 2023 02:14:52 -0500 Subject: [PATCH] bootl: refactor; add uartboot --- sw/bootloader/Makefile | 6 +- sw/bootloader/include/common.h | 20 +- sw/bootloader/main.c | 34 +-- sw/bootloader/target/hydrogensoc/boot.c | 66 +++-- sw/bootloader/target/hydrogensoc/flashboot.c | 85 +++++++ sw/bootloader/target/hydrogensoc/flashboot.h | 83 +------ sw/bootloader/target/hydrogensoc/uartboot.c | 245 +++++++++++++++++++ sw/bootloader/target/hydrogensoc/uartboot.h | 27 ++ 8 files changed, 430 insertions(+), 136 deletions(-) create mode 100644 sw/bootloader/target/hydrogensoc/flashboot.c create mode 100644 sw/bootloader/target/hydrogensoc/uartboot.c create mode 100644 sw/bootloader/target/hydrogensoc/uartboot.h diff --git a/sw/bootloader/Makefile b/sw/bootloader/Makefile index 6edcc5af..2c98c20d 100644 --- a/sw/bootloader/Makefile +++ b/sw/bootloader/Makefile @@ -16,13 +16,15 @@ include ../../common.mk ############################################################################## EXEC:= bootloader -SRCS:= main.c crt0.S target/$(soctarget)/boot.c +SRCS:= crt0.S main.c +SRCS+= $(wildcard target/$(soctarget)/*.c) +SRCS+= $(wildcard target/$(soctarget)/*.S) RVPREFIX:= riscv64-unknown-elf CFLAGS:= -march=$(shell cfgparse.py $(RVATOM)/rtl/config/$(soctarget).json -a isa) CFLAGS+= -mabi=$(shell cfgparse.py $(RVATOM)/rtl/config/$(soctarget).json -a abi) CFLAGS+= -Wall -nostartfiles -ffreestanding -g -Os -CFLAGS+= -I $(RVATOM_LIB)/include -I include +CFLAGS+= -I $(RVATOM_LIB)/include -I include -I target/$(soctarget) CFLAGS+= $(shell cfgparse.py $(RVATOM)/rtl/config/$(soctarget).json -d) CFLAGS+= -DTARGET_$(shell echo $(soctarget) | tr 'a-z' 'A-Z') ifeq ($(sim), 1) diff --git a/sw/bootloader/include/common.h b/sw/bootloader/include/common.h index 457585fc..725fd23b 100644 --- a/sw/bootloader/include/common.h +++ b/sw/bootloader/include/common.h @@ -12,14 +12,26 @@ #define P(x) #endif +#define STRINGIFY(s) #s +#define EXPAND_AND_STRINGIFY(s) STRINGIFY(s) + +/////////////////////////////////////////////////////////////////////////////// // Return codes + +// General #define RCODE_OK 0 #define RCODE_EXCEPTION 1 #define RCODE_UNREACHABLE 2 -#define RCODE_INIT_FAIL 3 -#define RCODE_FLASHBOOT_INVALID_DEVICE 4 -#define RCODE_FLASHBOOT_COPY_FAIL 5 +#define RCODE_PLATFORM_INIT_FAIL 3 + +// Flashboot +#define RCODE_FLASHBOOT_NOSPI 10 +#define RCODE_FLASHBOOT_INVALID_DEVICE 11 + +// UARTBOOT +#define RCODE_UARTBOOT_NOUART 20 +#define RCODE_UARTBOOT_FAILED 21 void puthex(unsigned val); -void __attribute__((noreturn)) boot_panic(int code); +void __attribute__((noreturn)) boot_panic(int code, char *msg); void * platform_init(); diff --git a/sw/bootloader/main.c b/sw/bootloader/main.c index 8527d7e7..18e2016b 100644 --- a/sw/bootloader/main.c +++ b/sw/bootloader/main.c @@ -14,32 +14,17 @@ void puthex(unsigned val) { } void boot_panic_handler(){ - boot_panic(RCODE_EXCEPTION); + #ifdef __EN_PRINTS + puts("Exception: cause=0x"); puthex(CSR_read(CSR_MCAUSE)); + puts(", addr=0x"); puthex(CSR_read(CSR_MEPC)); + #endif + exit(RCODE_EXCEPTION); } -void boot_panic(int code){ +void boot_panic(int code, char * msg){ #ifdef __EN_PRINTS puts("boot-panic: "); - switch (code) { - case RCODE_EXCEPTION: - puts("exception: cause=0x"); puthex(CSR_read(CSR_MCAUSE)); - puts(", addr=0x"); puthex(CSR_read(CSR_MEPC)); - break; - case RCODE_UNREACHABLE: - puts("unreachable"); - break; - case RCODE_INIT_FAIL: - puts("init fail"); - break; - case RCODE_FLASHBOOT_INVALID_DEVICE: - puts("flashboot: invalid device"); - break; - case RCODE_FLASHBOOT_COPY_FAIL: - puts("flashboot: no spi IP"); - break; - default: - puts("unknown"); - }; + puts(msg ? msg : "?"); putchar('\n'); #endif exit(code); @@ -63,8 +48,7 @@ int main(){ // ********** Platform specific initialization ********** void * jump_addr = platform_init(); if(jump_addr == NULL) { - - boot_panic(RCODE_INIT_FAIL); + boot_panic(RCODE_PLATFORM_INIT_FAIL, "Platform init failure"); } // Jump to target @@ -73,5 +57,5 @@ int main(){ app_main(); // Unreachable - boot_panic(RCODE_UNREACHABLE); + boot_panic(RCODE_UNREACHABLE, "Unreachable"); } \ No newline at end of file diff --git a/sw/bootloader/target/hydrogensoc/boot.c b/sw/bootloader/target/hydrogensoc/boot.c index 3a96518d..f27afdb4 100644 --- a/sw/bootloader/target/hydrogensoc/boot.c +++ b/sw/bootloader/target/hydrogensoc/boot.c @@ -1,16 +1,12 @@ -#include - -#include "common.h" - #include +#include #include #include #include -#include -#include "flashboot.h" -#define STRINGIFY(s) #s -#define EXPAND_AND_STRINGIFY(s) STRINGIFY(s) +#include "common.h" +#include "flashboot.h" +#include "uartboot.h" extern uint32_t __approm_start; extern uint32_t __approm_size; @@ -23,19 +19,20 @@ extern uint32_t __approm_size; // Address offset at which image resides #define FLASH_IMG_OFFSET 0x000c0000 -// Size of Image -#define FLASH_IMG_SIZE 32 * 1024 // 32 KB - // number of flashes to indicate entering of bootloader #define START_LED_FLASHES 3 // number of flashes to indicate entering of user application #define END_LED_FLASHES 1 +// Time period of LED flashes +#define LED_FLASH_TIMEPERIOD 100 + // Bootmodes #define BOOTMODE_FLASHBOOT 0 #define BOOTMODE_JUMP_TO_RAM 1 -#define BOOTMODE_INF_LOOP 2 +#define BOOTMODE_UARTBOOT 2 +#define BOOTMODE_INF_LOOP 3 #define BOOTMODE_DEFAULT BOOTMODE_JUMP_TO_RAM //------------------------------------------------------- @@ -45,11 +42,11 @@ extern uint32_t __approm_size; * * @param pin led pin * @param count number of times to blink - * @param time_period time_period in of one ON & OFF + * @param period_ms time_period in of one ON & OFF */ -void led_blink(int pin, int count, int time_period) +void led_blink(int pin, int count, int period_ms) { - int halfperiod = time_period >> 1; + int halfperiod = period_ms >> 1; #ifdef SIM halfperiod = 0; #endif @@ -73,46 +70,67 @@ void * platform_init(){ gpio_setmode(BOOTMODE_PIN1, INPUT); // Blink LED START_LED_FLASHES times (signal entering of bootloader) - led_blink(BOOTLED_PIN, START_LED_FLASHES, 50); + led_blink(BOOTLED_PIN, START_LED_FLASHES, LED_FLASH_TIMEPERIOD); // get bootmode uint8_t pin0_val = (uint8_t)gpio_read(BOOTMODE_PIN0); uint8_t pin1_val = (uint8_t)gpio_read(BOOTMODE_PIN1); bootmode = pin0_val | pin1_val << 1; #else - P(puts("nogpio: using default bootmode\n");) + P(puts("no gpio: using default bootmode\n");) #endif + // Print Bootmode - P(puts("bootmode: ");) + P(puts("bootmode: 0x");) P(putchar('0'+bootmode);) - P(puts(": ");) + P(putchar('\n');) // Perform action according to bootmode + bool wait_for_keypress = false; switch (bootmode) { case BOOTMODE_FLASHBOOT: #ifdef SOC_EN_SPI - flashboot((uint8_t *)&__approm_start, FLASH_IMG_OFFSET, FLASH_IMG_SIZE); + flashboot((uint8_t *)&__approm_start, FLASH_IMG_OFFSET, (unsigned)&__approm_size); #else - boot_panic(RCODE_FLASHBOOT_COPY_FAIL); + boot_panic(RCODE_FLASHBOOT_NOSPI, "No SPI IP"); #endif break; case BOOTMODE_JUMP_TO_RAM: - P(puts("jmptoram\n");) + P(puts("Jumping to RAM\n");) + break; + + case BOOTMODE_UARTBOOT: + wait_for_keypress = true; + #ifdef SOC_EN_UART + uartboot((uint8_t *)&__approm_start, (unsigned)&__approm_size); + #else + boot_panic(RCODE_UARTBOOT_NOUART, "No UART IP"); // TODO: fixme + #endif break; case BOOTMODE_INF_LOOP: default: - P(puts("infloop\n");) + P(puts("Infinite loop\n");) while(1){ asm volatile(""); } } + #ifdef SIM + wait_for_keypress = false; + #endif + + if(wait_for_keypress){ + puts("\nPress ENTER to continue...\n"); + while(serial_read()!='\r') + asm volatile (""); + } + #ifdef SOC_EN_GPIO // Blink single (signal jump to user code) - led_blink(BOOTLED_PIN, END_LED_FLASHES, 50); + led_blink(BOOTLED_PIN, END_LED_FLASHES, LED_FLASH_TIMEPERIOD); #endif // return start address of approm diff --git a/sw/bootloader/target/hydrogensoc/flashboot.c b/sw/bootloader/target/hydrogensoc/flashboot.c new file mode 100644 index 00000000..85ea1d3c --- /dev/null +++ b/sw/bootloader/target/hydrogensoc/flashboot.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include + +#include "flashboot.h" +#include "common.h" + +// Flash definitions +#define FLASH_CMD_READ 0x03 +#define FLASH_CMD_READID 0X9f + +#define SPI_REG_SCKDIV_OFFSET 0x00 +#define SPI_REG_SCTRL_OFFSET 0x04 +#define SPI_REG_TDATA_OFFSET 0x08 +#define SPI_REG_RDATA_OFFSET 0x0c +#define SPI_REG_CSCTRL_OFFSET 0x10 +#define SPI_REG_DCTRL_OFFSET 0x14 + +static char flashgetid(struct SPI_Config *cfg){ + // select + REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET) = bitset(REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET), 24+cfg->device_num); + spi_transfer(cfg, FLASH_CMD_READID); + char id = spi_transfer(cfg, 0x0); + // deselect + REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET) = bitclear(REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET), 24+cfg->device_num); + return id; +} + +static int flashcpy(struct SPI_Config *cfg, uint8_t *dest, uint32_t src_addr, uint32_t len) { + // select + REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET) = bitset(REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET), 24+cfg->device_num); + spi_transfer(cfg, FLASH_CMD_READ); + spi_transfer(cfg, src_addr >> 16); + spi_transfer(cfg, src_addr >> 8); + spi_transfer(cfg, src_addr); + + while(len--) { + REG8(cfg->base_addr, SPI_REG_TDATA_OFFSET) = 0x0; + while(REG32(SPI_ADDR, SPI_REG_SCTRL_OFFSET) >> 31) + asm volatile(""); + *(dest++) = REG8(cfg->base_addr, SPI_REG_RDATA_OFFSET); + } + + // deselect + REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET) = bitclear(REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET), 24+cfg->device_num); + return 0; +} + +void flashboot(uint8_t *dest, uint32_t src_addr, uint32_t len) { + // Init + struct SPI_Config cfg = { + cfg.base_addr = SPI_ADDR, + cfg.enable = true, + cfg.pha = false, + cfg.pol = false, + cfg.lsb_first = false, + cfg.baudrate = 1000000, + cfg.device_num = 0, + cfg.cs_mode = CSMODE_DISABLE, + cfg.post_cs_low_delay = 1, + cfg.pre_cs_high_delay = 1, + cfg.loopback_enable=false + }; + spi_init(&cfg); + + // Check ID + uint8_t manufacturer_id = flashgetid(&cfg); + P(puts("flashboot: manuf id = 0x");) + P(puthex(manufacturer_id);) + P(putchar('\n');) + if(manufacturer_id == 0x00 || manufacturer_id == 0xff){ + boot_panic(RCODE_FLASHBOOT_INVALID_DEVICE, "Invalid FLASH Device"); + } + + // Copy + P(puts("\nflashboot: copying from " EXPAND_AND_STRINGIFY(FLASH_IMG_OFFSET));) + flashcpy(&cfg, dest, src_addr, len); + P(puts(" - OK\n");) + + // Deinit + cfg.cs_mode = CSMODE_AUTO; + spi_init(&cfg); +} diff --git a/sw/bootloader/target/hydrogensoc/flashboot.h b/sw/bootloader/target/hydrogensoc/flashboot.h index 33af1e05..99b75649 100644 --- a/sw/bootloader/target/hydrogensoc/flashboot.h +++ b/sw/bootloader/target/hydrogensoc/flashboot.h @@ -1,84 +1,5 @@ #pragma once - -#include "common.h" - #include -#include -#include -#include - -// Flash definitions -#define FLASH_CMD_READ 0x03 -#define FLASH_CMD_READID 0X9f -#define SPI_REG_SCKDIV_OFFSET 0x00 -#define SPI_REG_SCTRL_OFFSET 0x04 -#define SPI_REG_TDATA_OFFSET 0x08 -#define SPI_REG_RDATA_OFFSET 0x0c -#define SPI_REG_CSCTRL_OFFSET 0x10 -#define SPI_REG_DCTRL_OFFSET 0x14 - -char flashgetid(struct SPI_Config *cfg){ - // select - REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET) = bitset(REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET), 24+cfg->device_num); - spi_transfer(cfg, FLASH_CMD_READID); - char id = spi_transfer(cfg, 0x0); - // deselect - REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET) = bitclear(REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET), 24+cfg->device_num); - return id; -} - -int flashcpy(struct SPI_Config *cfg, uint8_t *dest, uint32_t src_addr, uint32_t len) { - // select - REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET) = bitset(REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET), 24+cfg->device_num); - spi_transfer(cfg, FLASH_CMD_READ); - spi_transfer(cfg, src_addr >> 16); - spi_transfer(cfg, src_addr >> 8); - spi_transfer(cfg, src_addr); - - while(len--) { - REG8(cfg->base_addr, SPI_REG_TDATA_OFFSET) = 0x0; - while(REG32(SPI_ADDR, SPI_REG_SCTRL_OFFSET) >> 31) - asm volatile(""); - *(dest++) = REG8(cfg->base_addr, SPI_REG_RDATA_OFFSET); - } - - // deselect - REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET) = bitclear(REG32(cfg->base_addr, SPI_REG_CSCTRL_OFFSET), 24+cfg->device_num); - return 0; -} - -void flashboot(uint8_t *dest, uint32_t src_addr, uint32_t len) { - // Init - struct SPI_Config cfg = { - cfg.base_addr = SPI_ADDR, - cfg.enable = true, - cfg.pha = false, - cfg.pol = false, - cfg.lsb_first = false, - cfg.baudrate = 1000000, - cfg.device_num = 0, - cfg.cs_mode = CSMODE_DISABLE, - cfg.post_cs_low_delay = 1, - cfg.pre_cs_high_delay = 1, - cfg.loopback_enable=false - }; - spi_init(&cfg); - - // Check ID - uint8_t manufacturer_id = flashgetid(&cfg); - P(puts("flashboot: manuf id = 0x");) - P(puthex(manufacturer_id);) - P(putchar('\n');) - if(manufacturer_id == 0x00 || manufacturer_id == 0xff){ - boot_panic(RCODE_FLASHBOOT_INVALID_DEVICE); - } - - // Copy - P(puts("\nflashboot: copying from " EXPAND_AND_STRINGIFY(FLASH_IMG_OFFSET));) - flashcpy(&cfg, dest, src_addr, len); - P(puts(" - OK\n");) - // Deinit - cfg.cs_mode = CSMODE_AUTO; - spi_init(&cfg); -} +// Flashboot: Copied data from flash to memory +void flashboot(uint8_t *dest, uint32_t src_addr, uint32_t len); diff --git a/sw/bootloader/target/hydrogensoc/uartboot.c b/sw/bootloader/target/hydrogensoc/uartboot.c new file mode 100644 index 00000000..cb86e152 --- /dev/null +++ b/sw/bootloader/target/hydrogensoc/uartboot.c @@ -0,0 +1,245 @@ +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "uartboot.h" + +// Xmodem timeout +#define XMODEM_WAIT_TIMEOUT_SEC 120 + +// Getchar timeout +#ifdef SIM +#define GETCHAR_TIMEOUT_MS 10 +#else +#define GETCHAR_TIMEOUT_MS 50 +#endif + +#define XMODEM_PACKET_SZ 128 + +// Register Offsets +#define UART_REG_RBR 0x00 +#define UART_REG_THR 0x00 +#define UART_REG_LCR 0x04 +#define UART_REG_LSR 0x08 + +////////////////////////////////////////////////////////// +// UART Driver Functions + +// Get a char from uart (with timeout) +static int _inbyte(uint64_t timeout_ms) +{ + clock_t t_end = cycle() + ((timeout_ms*CLK_FREQ)/1000); + while (!bitcheck(REG32(UART_ADDR, UART_REG_LSR), 0)) { + if (cycle() > t_end) + return -1; // Timeout + } + return (int) REG8(UART_ADDR, UART_REG_RBR); +} + +// Sends a char to uart +static void _outbyte(unsigned char c) +{ + while(!bitcheck(REG32(UART_ADDR, UART_REG_LSR), 1)) { + asm volatile(""); + // udelay(1000); + } + REG8(UART_ADDR, UART_REG_THR) = c; +} + +// Flushes uart rxbuf +static void flush_input() +{ + while(bitcheck(REG32(UART_ADDR, UART_REG_LSR), 0)) + REG8(UART_ADDR, UART_REG_RBR); +} + + +// Flushes uart txbuf +static void flush_output() +{ + while(!bitcheck(REG32(UART_ADDR, UART_REG_LCR), 1)) + asm volatile(""); +} + + +////////////////////////////////////////////////////////////// +// CRC Functions + +const uint16_t crc16tab[256]= { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +static uint16_t crc16_ccitt(const void *buf, register int len) +{ + register uint16_t crc = 0; + while(len--) + crc = ((crc<<8)&0xff00) ^ crc16tab[((crc>>8)&0xff) ^ (*(char *)buf++ & 0x00FF)]; + return crc; +} + +////////////////////////////////////////////////////////////// +// Xmodem Functions + +static int get_packet(uint8_t pkt_num, uint8_t *buf) +{ + uint8_t n = _inbyte(GETCHAR_TIMEOUT_MS); + uint8_t ni = _inbyte(GETCHAR_TIMEOUT_MS); + for(uint8_t i=0; i + +#define SOH 0x01 +#define STX 0x02 +#define EOT 0x04 +#define ACK 0x06 +#define NAK 0x15 +#define CAN 0x18 +#define CTRLZ 0x1A + +typedef enum { + OK = 0, + NOK = 1, + S_EOT = 2, + S_TERM = 3, + R_TERM = 4, + UNKCHAR = 5, + TIMEOUT = 6, + SUCCESS = 7, + FAILURE = 8 +} xmod_status; + +xmod_status xmodemReceive(uint8_t * bf, uint32_t len); + +// UART Boot: Copies data from uart stream to memory using XMODEM protocol +void uartboot(uint8_t *dest, uint32_t len); \ No newline at end of file