diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 6e4780f55..484bddaac 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -2,421 +2,54 @@ #include "boot.h" #include "gpt.h" -/* Card type flags (card_type) */ -#define CT_MMC 0x01 /* MMC ver 3 */ -#define CT_SD1 0x02 /* SD ver 1 */ -#define CT_SD2 0x04 /* SD ver 2 */ -#define CT_SDC (CT_SD1|CT_SD2) /* SD */ -#define CT_BLOCK 0x08 /* Block addressing */ +/* int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { */ -#define CMD0 (0) /* GO_IDLE_STATE */ -#define CMD1 (1) /* SEND_OP_COND */ -#define CMD2 (2) /* SEND_CID */ -#define CMD3 (3) /* RELATIVE_ADDR */ -#define CMD4 (4) -#define CMD5 (5) /* SLEEP_WAKE (SDC) */ -#define CMD6 (6) /* SWITCH_FUNC */ -#define CMD7 (7) /* SELECT */ -#define CMD8 (8) /* SEND_IF_COND */ -#define CMD9 (9) /* SEND_CSD */ -#define CMD10 (10) /* SEND_CID */ -#define CMD11 (11) -#define CMD12 (12) /* STOP_TRANSMISSION */ -#define CMD13 (13) -#define CMD15 (15) -#define CMD16 (16) /* SET_BLOCKLEN */ -#define CMD17 (17) /* READ_SINGLE_BLOCK */ -#define CMD18 (18) /* READ_MULTIPLE_BLOCK */ -#define CMD19 (19) -#define CMD20 (20) -#define CMD23 (23) -#define CMD24 (24) -#define CMD25 (25) -#define CMD27 (27) -#define CMD28 (28) -#define CMD29 (29) -#define CMD30 (30) -#define CMD32 (32) -#define CMD33 (33) -#define CMD38 (38) -#define CMD42 (42) -#define CMD55 (55) /* APP_CMD */ -#define CMD56 (56) -#define ACMD6 (0x80+6) /* define the data bus width */ -#define ACMD41 (0x80+41) /* SEND_OP_COND (ACMD) */ +/* /\* This is not needed. This has everything to do with the FAT */ +/* filesystem stuff that I'm not including. All I need to do is */ +/* initialize the SD card and read from it. Anything in here that is */ +/* checking for potential errors, I'm going to have to temporarily */ +/* do without. */ +/* *\/ */ +/* // if (!count) return RES_PARERR; */ +/* /\* if (drv_status & STA_NOINIT) return RES_NOTRDY; *\/ */ -// Capability bits -#define SDC_CAPABILITY_SD_4BIT 0x0001 -#define SDC_CAPABILITY_SD_RESET 0x0002 -#define SDC_CAPABILITY_ADDR 0xff00 - -// Control bits -#define SDC_CONTROL_SD_4BIT 0x0001 -#define SDC_CONTROL_SD_RESET 0x0002 - -// Card detect bits -#define SDC_CARD_INSERT_INT_EN 0x0001 -#define SDC_CARD_INSERT_INT_REQ 0x0002 -#define SDC_CARD_REMOVE_INT_EN 0x0004 -#define SDC_CARD_REMOVE_INT_REQ 0x0008 - -// Command status bits -#define SDC_CMD_INT_STATUS_CC 0x0001 // Command complete -#define SDC_CMD_INT_STATUS_EI 0x0002 // Any error -#define SDC_CMD_INT_STATUS_CTE 0x0004 // Timeout -#define SDC_CMD_INT_STATUS_CCRC 0x0008 // CRC error -#define SDC_CMD_INT_STATUS_CIE 0x0010 // Command code check error - -// Data status bits -#define SDC_DAT_INT_STATUS_TRS 0x0001 // Transfer complete -#define SDC_DAT_INT_STATUS_ERR 0x0002 // Any error -#define SDC_DAT_INT_STATUS_CTE 0x0004 // Timeout -#define SDC_DAT_INT_STATUS_CRC 0x0008 // CRC error -#define SDC_DAT_INT_STATUS_CFE 0x0010 // Data FIFO underrun or overrun - - -#define ERR_EOF 30 -#define ERR_NOT_ELF 31 -#define ERR_ELF_BITS 32 -#define ERR_ELF_ENDIANNESS 33 -#define ERR_CMD_CRC 34 -#define ERR_CMD_CHECK 35 -#define ERR_DATA_CRC 36 -#define ERR_DATA_FIFO 37 -#define ERR_BUF_ALIGNMENT 38 -#define FR_DISK_ERR 39 -#define FR_TIMEOUT 40 - -struct sdc_regs { - volatile uint32_t argument; - volatile uint32_t command; - volatile uint32_t response1; - volatile uint32_t response2; - volatile uint32_t response3; - volatile uint32_t response4; - volatile uint32_t data_timeout; - volatile uint32_t control; - volatile uint32_t cmd_timeout; - volatile uint32_t clock_divider; - volatile uint32_t software_reset; - volatile uint32_t power_control; - volatile uint32_t capability; - volatile uint32_t cmd_int_status; - volatile uint32_t cmd_int_enable; - volatile uint32_t dat_int_status; - volatile uint32_t dat_int_enable; - volatile uint32_t block_size; - volatile uint32_t block_count; - volatile uint32_t card_detect; - volatile uint32_t res_50; - volatile uint32_t res_54; - volatile uint32_t res_58; - volatile uint32_t res_5c; - volatile uint64_t dma_addres; -}; - -#define MAX_BLOCK_CNT 0x1000 - -#define SDC 0x00013000; - -// static struct sdc_regs * const regs __attribute__((section(".rodata"))) = (struct sdc_regs *)0x00013000; - -// static int errno __attribute__((section(".bss"))); -// static DSTATUS drv_status __attribute__((section(".bss"))); -// static BYTE card_type __attribute__((section(".bss"))); -// static uint32_t response[4] __attribute__((section(".bss"))); -// static int alt_mem __attribute__((section(".bss"))); - -/*static const char * errno_to_str(void) { - switch (errno) { - case ERR_EOF: return "Unexpected EOF"; - case ERR_NOT_ELF: return "Not an ELF file"; - case ERR_ELF_BITS: return "Wrong ELF word size"; - case ERR_ELF_ENDIANNESS: return "Wrong ELF endianness"; - case ERR_CMD_CRC: return "Command CRC error"; - case ERR_CMD_CHECK: return "Command code check error"; - case ERR_DATA_CRC: return "Data CRC error"; - case ERR_DATA_FIFO: return "Data FIFO error"; - case ERR_BUF_ALIGNMENT: return "Bad buffer alignment"; - case FR_DISK_ERR: return "Disk error"; - case FR_TIMEOUT: return "Timeout"; - } - return "Unknown error code"; - }*/ - -static void usleep(unsigned us) { - uintptr_t cycles0; - uintptr_t cycles1; - asm volatile ("csrr %0, 0xB00" : "=r" (cycles0)); - for (;;) { - asm volatile ("csrr %0, 0xB00" : "=r" (cycles1)); - if (cycles1 - cycles0 >= us * 100) break; - } -} - -static int sdc_cmd_finish(unsigned cmd, uint32_t * response) { - struct sdc_regs * regs = (struct sdc_regs *)SDC; +/* uint32_t response[4]; */ +/* struct sdc_regs * regs = (struct sdc_regs *)SDC; */ - while (1) { - unsigned status = regs->cmd_int_status; - if (status) { - // clear interrupts - regs->cmd_int_status = 0; - while (regs->software_reset != 0) {} - if (status == SDC_CMD_INT_STATUS_CC) { - // get response - response[0] = regs->response1; - response[1] = regs->response2; - response[2] = regs->response3; - response[3] = regs->response4; - return 0; - } - /* errno = FR_DISK_ERR; - if (status & SDC_CMD_INT_STATUS_CTE) errno = FR_TIMEOUT; - if (status & SDC_CMD_INT_STATUS_CCRC) errno = ERR_CMD_CRC; - if (status & SDC_CMD_INT_STATUS_CIE) errno = ERR_CMD_CHECK;*/ - break; - } - } - return -1; -} +/* /\* Convert LBA to byte address if needed *\/ */ +/* if (!(card_type & CT_BLOCK)) sector *= 512; */ +/* while (count > 0) { */ +/* UINT bcnt = count > MAX_BLOCK_CNT ? MAX_BLOCK_CNT : count; */ +/* unsigned bytes = bcnt * 512; */ +/* if (send_data_cmd(bcnt == 1 ? CMD17 : CMD18, sector, buf, bcnt, response) < 0) return 1; */ +/* if (bcnt > 1 && send_cmd(CMD12, 0, response) < 0) return 1; */ +/* sector += (card_type & CT_BLOCK) ? bcnt : bytes; */ +/* count -= bcnt; */ +/* buf += bytes; */ +/* } */ -static int sdc_data_finish(void) { - int status; - struct sdc_regs * regs = (struct sdc_regs *)SDC; - - while ((status = regs->dat_int_status) == 0) {} - regs->dat_int_status = 0; - while (regs->software_reset != 0) {} +/* return 0;; */ +/* } */ - if (status == SDC_DAT_INT_STATUS_TRS) return 0; - /* errno = FR_DISK_ERR; - if (status & SDC_DAT_INT_STATUS_CTE) errno = FR_TIMEOUT; - if (status & SDC_DAT_INT_STATUS_CRC) errno = ERR_DATA_CRC; - if (status & SDC_DAT_INT_STATUS_CFE) errno = ERR_DATA_FIFO;*/ - return -1; -} - -static int send_data_cmd(unsigned cmd, unsigned arg, void * buf, unsigned blocks, uint32_t * response) { - struct sdc_regs * regs = (struct sdc_regs *)SDC; +int disk_read(BYTE * buf, LBA_t sector, UINT count) { - unsigned command = (cmd & 0x3f) << 8; - switch (cmd) { - case CMD0: - case CMD4: - case CMD15: - // No responce - break; - case CMD11: - case CMD13: - case CMD16: - case CMD17: - case CMD18: - case CMD19: - case CMD23: - case CMD24: - case CMD25: - case CMD27: - case CMD30: - case CMD32: - case CMD33: - case CMD42: - case CMD55: - case CMD56: - case ACMD6: - // R1 - command |= 1; // 48 bits - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - case CMD7: - case CMD12: - case CMD20: - case CMD28: - case CMD29: - case CMD38: - // R1b - command |= 1; // 48 bits - command |= 1 << 2; // busy - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - case CMD2: - case CMD9: - case CMD10: - // R2 - command |= 2; // 136 bits - command |= 1 << 3; // resp CRC - break; - case ACMD41: - // R3 - command |= 1; // 48 bits - break; - case CMD3: - // R6 - command |= 1; // 48 bits - command |= 1 << 2; // busy - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - case CMD8: - // R7 - command |= 1; // 48 bits - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - } - - if (blocks) { - command |= 1 << 5; - if ((intptr_t)buf & 3) { - // errno = ERR_BUF_ALIGNMENT; - return -1; - } - regs->dma_addres = (uint64_t)(intptr_t)buf; - regs->block_size = 511; - regs->block_count = blocks - 1; - regs->data_timeout = 0x1FFFFFF; - } - - regs->command = command; - regs->cmd_timeout = 0xFFFFF; - regs->argument = arg; - - if (sdc_cmd_finish(cmd, response) < 0) return -1; - if (blocks) return sdc_data_finish(); - - return 0; -} - -#define send_cmd(cmd, arg, response) send_data_cmd(cmd, arg, NULL, 0, response) - -static BYTE ini_sd(void) { - struct sdc_regs * regs = (struct sdc_regs *)SDC; - unsigned rca; - BYTE card_type; - uint32_t response[4]; - - /* Reset controller */ - regs->software_reset = 1; - while ((regs->software_reset & 1) == 0) {} - - // This clock divider is meant to initialize the card at - // 400kHz - - // 22MHz/400kHz = 55 (base 10) = 0x37 - 0x01 = 0x36 - regs->clock_divider = 0x36; - regs->software_reset = 0; - while (regs->software_reset) {} - usleep(5000); - - card_type = 0; - // drv_status = STA_NOINIT; - - if (regs->capability & SDC_CAPABILITY_SD_RESET) { - /* Power cycle SD card */ - regs->control |= SDC_CONTROL_SD_RESET; - usleep(1000000); - regs->control &= ~SDC_CONTROL_SD_RESET; - usleep(100000); - } - - /* Enter Idle state */ - send_cmd(CMD0, 0, response); - - card_type = CT_SD1; - if (send_cmd(CMD8, 0x1AA, response) == 0) { - if ((response[0] & 0xfff) != 0x1AA) { - // errno = ERR_CMD_CHECK; - return -1; - } - card_type = CT_SD2; - } - - /* Wait for leaving idle state (ACMD41 with HCS bit) */ - while (1) { - /* ACMD41, Set Operating Conditions: Host High Capacity & 3.3V */ - if (send_cmd(CMD55, 0, response) < 0 || send_cmd(ACMD41, 0x40300000, response) < 0) return -1; - if (response[0] & (1 << 31)) { - if (response[0] & (1 << 30)) card_type |= CT_BLOCK; - break; - } - } - - /* Enter Identification state */ - if (send_cmd(CMD2, 0, response) < 0) return -1; - - /* Get RCA (Relative Card Address) */ - rca = 0x1234; - if (send_cmd(CMD3, rca << 16, response) < 0) return -1; - rca = response[0] >> 16; - - /* Select card */ - if (send_cmd(CMD7, rca << 16, response) < 0) return -1; - - /* Clock 25MHz */ - // 22Mhz/2 = 11Mhz - regs->clock_divider = 1; - usleep(10000); - - /* Bus width 1-bit */ - regs->control = 0; - if (send_cmd(CMD55, rca << 16, response) < 0 || send_cmd(ACMD6, 0, response) < 0) return -1; - - /* Set R/W block length to 512 */ - if (send_cmd(CMD16, 512, response) < 0) return -1; - - // drv_status &= ~STA_NOINIT; - return card_type; -} - -int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { - - /* This is not needed. This has everything to do with the FAT - filesystem stuff that I'm not including. All I need to do is - initialize the SD card and read from it. Anything in here that is - checking for potential errors, I'm going to have to temporarily - do without. - */ - // if (!count) return RES_PARERR; - /* if (drv_status & STA_NOINIT) return RES_NOTRDY; */ - - uint32_t response[4]; - struct sdc_regs * regs = (struct sdc_regs *)SDC; - - /* Convert LBA to byte address if needed */ - if (!(card_type & CT_BLOCK)) sector *= 512; - while (count > 0) { - UINT bcnt = count > MAX_BLOCK_CNT ? MAX_BLOCK_CNT : count; - unsigned bytes = bcnt * 512; - if (send_data_cmd(bcnt == 1 ? CMD17 : CMD18, sector, buf, bcnt, response) < 0) return 1; - if (bcnt > 1 && send_cmd(CMD12, 0, response) < 0) return 1; - sector += (card_type & CT_BLOCK) ? bcnt : bytes; - count -= bcnt; - buf += bytes; - } - - return 0;; } +// copyFlash: -------------------------------------------------------- +// A lot happens in this function: +// * The Wally banner is printed +// * The peripherals are initialized void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { - BYTE card_type; int ret = 0; - - card_type = ini_sd(); - // BYTE * buf = (BYTE *)Dst; - - // if (disk_read(buf, (LBA_t)address, (UINT)numBlocks, card_type) < 0) /* UART Print function?*/; + // Initialize UART for messages + init_uart(); + + // Print the wally banner + print_uart(BANNER); + + + init_sd(); ret = gpt_load_partitions(card_type); } - -/* -int main() { - ini_sd(); - - - return 0; -} -*/ diff --git a/fpga/zsbl/boot.h b/fpga/zsbl/boot.h index 77d403145..cb0f4e7f3 100644 --- a/fpga/zsbl/boot.h +++ b/fpga/zsbl/boot.h @@ -19,6 +19,16 @@ typedef QWORD LBA_t; #define OPENSBI_ADDRESS 0x80000000 // FW_TEXT_START #define KERNEL_ADDRESS 0x80200000 // FW_JUMP_ADDR +#define BANNER " █▀█ █▀█ █▀█ █▀▀ █ █\n" \ +" █ █ █ █▄▀ █▄▄ ▄▄▄ █ █\n" \ +" █▄█ █▄█ █ █ █▄▄ ▀▄▀\n" \ +" ____ ____ ____ ___ ___ ____ ___\n" \ +" \\ \\ / / / \\ | | | | \\ \\ / /\n" \ +" \\ \\ __ / / / \\ | | | | \\ \\/ /\n" \ +" \\ \\/ \\/ / / /\\ \\ | | | | \\ /\n" \ +" \\ / / ____ \\ | |___ | |___ | |\n" \ +" \\___/\\___/ /___/ \\___\\|_______||_______| |___|\n\n" + // Export disk_read int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type); diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index aacea0db9..4669aeb0b 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -1,5 +1,6 @@ #include "sd.h" #include "spi.h" +#include "uart.h" // Parallel byte update CRC7-CCITT algorithm. // The result is the CRC7 result, left shifted over by 1 @@ -23,27 +24,44 @@ uint16_t crc16(uint16_t crc, uint8_t data) { return crc; } +// sd_cmd ------------------------------------------------------------ +// Sends SD card command using SPI mode. +// This function: +// * Chooses the response length based on the input command +// * Makes use of SPI's full duplex. For every byte sent, +// a byte is received. Thus for every byte sent as part of +// a command, a useless byte must be read from the receive +// FIFO. +// * Takes advantage of the Sifive SPI peripheral spec's +// watermark and interrupt features to determine when a +// transfer is complete. This should save on cycles since +// no arbitrary delays need to be added. uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { uint8_t response_len; uint8_t i; uint64_t r; uint8_t rbyte; - + + // Initialize the response with 0's. + r = 0; + + // Choose response length based on cmd input. + // Most commands return an R1 format response. switch (cmd) { - case 0: - response_len = 1; - break; case 8: - response_len = 7 + response_len = R7_RESPONSE; break; + case 12: + response_len = R1B_RESPONSE; default: - response_len = 1; + response_len = R1_RESPONSE; break; } // Make interrupt pending after response fifo receives the correct - // response length. - write_reg(SPI_RXMARK, response_len); + // response length. Probably unecessary so let's wait and see what + // happens. + // write_reg(SPI_RXMARK, response_len); // Write all 6 bytes into transfer fifo spi_sendbyte(0x40 | cmd); @@ -79,18 +97,44 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { } return r; -} +} // sd_cmd -#define cmd0() sd_cmd( 0, 0x00000000, 0x95) -#define cmd8() sd_cmd( 8, 0x000001aa, 0x87) -// CMD55 has to be sent before ACMD41 (it means the next command is -// application specific) -#define cmd55() sd_cmd(55, 0x00000000, 0x65) -#defube acmd41() sd_cmd(41, 0x40000000, 0x77) +// Utility defines for CMD0, CMD8, CMD55, and ACMD41 +#define CMD0() sd_cmd( 0, 0x00000000, 0x95) // Reset SD card into IDLE state +#define CMD8() sd_cmd( 8, 0x000001aa, 0x87) // +#define CMD55() sd_cmd(55, 0x00000000, 0x65) // +#define ACMD41() sd_cmd(41, 0x40000000, 0x77) // +// init_sd: ---------------------------------------------------------- +// This first initializes the SPI peripheral then initializes the SD +// card itself. We use the uart to display anything that goes wrong. void init_sd(){ init_spi(); - cmd0() + uint64_t r; + + print_uart("Initializing SD Card in SPI mode"); + + // Reset SD Card command + // Initializes SD card into SPI mode if CS is asserted '0' + if (!(( r = CMD0() ) & 0x10) ) { + print_uart("SD ERROR: "); + print_uart_byte(r & 0xff); + print_uart("\r\n"); + } + + // + if (!(( r = CMD8() ) & 0x10 )) { + print_uart("SD ERROR: "); + print_uart_byte(r & 0xff); + print_uart("\r\n"); + } + + do { + CMD55(); + r = ACMD41(); + } while (r == 0x1); + + print_uart("SD card is initialized"); } diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h index f08941364..a70d203e7 100644 --- a/fpga/zsbl/sd.h +++ b/fpga/zsbl/sd.h @@ -2,6 +2,16 @@ #include +// Command names +#define SD_CMD_STOP_TRANSMISSION 12 +#define SD_CMD_READ_BLOCK_MULTIPLE 18 +#define SD_DATA_TOKEN 0xfe + +// Response lengths in bytes +#define R1_RESPONSE 1 +#define R7_RESPONSE 7 +#define R1B_RESPONSE 2 + uint8_t crc7(uint8_t prev, uint8_t in); uint16_t crc16(uint16_t crc, uint8_t data); uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c new file mode 100644 index 000000000..a08690069 --- /dev/null +++ b/fpga/zsbl/uart.c @@ -0,0 +1,96 @@ +#include "uart.h" + + +void write_reg_u8(uintptr_t addr, uint8_t value) +{ + volatile uint8_t *loc_addr = (volatile uint8_t *)addr; + *loc_addr = value; +} + +uint8_t read_reg_u8(uintptr_t addr) +{ + return *(volatile uint8_t *)addr; +} + +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) {}; + + write_reg_u8(UART_THR, a); +} + +void init_uart(uint32_t freq, uint32_t baud) +{ + uint32_t divisor = freq / (baud << 4); + + write_reg_u8(UART_IER, 0x00); // Disable all interrupts + write_reg_u8(UART_LCR, 0x80); // Enable DLAB (set baud rate divisor) + write_reg_u8(UART_DLL, divisor); // divisor (lo byte) + write_reg_u8(UART_DLM, (divisor >> 8) & 0xFF); // divisor (hi byte) + write_reg_u8(UART_LCR, 0x03); // 8 bits, no parity, one stop bit + write_reg_u8(UART_FCR, 0xC7); // Enable FIFO, clear them, with 14-byte threshold +} + +void print_uart(const char *str) +{ + const char *cur = &str[0]; + while (*cur != '\0') + { + write_serial((uint8_t)*cur); + ++cur; + } +} + +uint8_t bin_to_hex_table[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + +void bin_to_hex(uint8_t inp, uint8_t res[2]) +{ + res[1] = bin_to_hex_table[inp & 0xf]; + res[0] = bin_to_hex_table[(inp >> 4) & 0xf]; + return; +} + +void print_uart_int(uint32_t addr) +{ + int i; + for (i = 3; i > -1; i--) + { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } +} + +void print_uart_addr(uint64_t addr) +{ + int i; + for (i = 7; i > -1; i--) + { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } +} + +void print_uart_byte(uint8_t byte) +{ + uint8_t hex[2]; + bin_to_hex(byte, hex); + write_serial(hex[0]); + write_serial(hex[1]); +} diff --git a/fpga/zsbl/uart.h b/fpga/zsbl/uart.h new file mode 100644 index 000000000..18710e76b --- /dev/null +++ b/fpga/zsbl/uart.h @@ -0,0 +1,26 @@ +#pragma once +#include + +#define UART_BASE 0x10000000 + +#define UART_RBR UART_BASE + 0x00 +#define UART_THR UART_BASE + 0x00 +#define UART_IER UART_BASE + 0x01 +#define UART_IIR UART_BASE + 0x02 +#define UART_FCR UART_BASE + 0x02 +#define UART_LCR UART_BASE + 0x03 +#define UART_MCR UART_BASE + 0x04 +#define UART_LSR UART_BASE + 0x05 +#define UART_MSR UART_BASE + 0x06 +#define UART_SCR UART_BASE + 0x07 +#define UART_DLL UART_BASE + 0x00 +#define UART_DLM UART_BASE + 0x01 + +void init_uart(); +void write_reg_u8(uintptr_t addr, uint8_t value); +uint8_t read_reg_u8(uintptr_t addr); +int read_serial(uint8_t *res); +void print_uart(const char* str); +void print_uart_int(uint32_t addr); +void print_uart_addr(uint64_t addr); +void print_uart_byte(uint8_t byte);