Add new bootloader

The new bootloader supports booting from SD card
This commit is contained in:
Moritz Schneider 2018-11-23 16:11:59 +01:00
parent 44d0f28c4d
commit 44ba444ed6
22 changed files with 2514 additions and 217 deletions

View file

@ -1 +0,0 @@
../../bootrom/.gitignore

5
fpga/src/bootrom/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
venv
*.elf
*.o
*.img
*.bin

View file

@ -1,26 +1,48 @@
bootrom_img = bootrom.img bootrom.sv
CROSSCOMPILE ?= riscv64-unknown-elf-
CC = ${CROSSCOMPILE}gcc
GCC=riscv64-unknown-elf-gcc
OBJCOPY=riscv64-unknown-elf-objcopy
DTB=ariane.dtb
PYTHON=python
CFLAGS = -Os -ggdb -march=rv64imac -mabi=lp64 -Wall -mcmodel=medany -mexplicit-relocs
CCASFLAGS = -mcmodel=medany -mexplicit-relocs
LDFLAGS = -nostdlib -nodefaultlibs -nostartfiles
all: $(bootrom_img)
INCLUDES = -I./ -I./src
SRCS_C = src/main.c src/uart.c src/spi.c src/sd.c src/gpt.c
SRCS_ASM = startup.S
OBJS_C = $(SRCS_C:.c=.o)
OBJS_S = $(SRCS_ASM:.S=.o)
MAIN = bootrom.elf
MAIN_BIN = $(MAIN:.elf=.bin)
MAIN_IMG = $(MAIN:.elf=.img)
#.PHONY: clean
$(MAIN): ariane.dtb $(OBJS_C) $(OBJS_S) linker.lds
$(CC) $(CFLAGS) $(LDFLAGS) $(INCLUDES) -Tlinker.lds $(OBJS_S) $(OBJS_C) -o $(MAIN)
@echo "LD >= $(MAIN)"
%.img: %.bin
dd if=$< of=$@ bs=128
%.bin: %.elf
$(OBJCOPY) -O binary $< $@
$(CROSSCOMPILE)objcopy -O binary $< $@
%.elf: %.S linker.ld bootrom.S $(DTB)
$(GCC) -Tlinker.ld $< -nostdlib -static -Wl,--no-gc-sections -o $@
%.o: %.c
@$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
@echo "CC <= $<"
%.o: %.S
@$(CC) $(CFLAGS) $(CCASFLAGS) $(INCLUDES) -c $< -o $@
@echo "CC <= $<"
%.dtb: %.dts
dtc -I dts $< -O dtb -o $@
%.sv: %.img
$(PYTHON) ./gen_rom.py $<
clean:
rm $(bootrom_img) $(DTB)
$(RM) $(OBJS_C) $(OBJS_S) $(MAIN) $(MAIN_BIN) $(MAIN_IMG) *.dtb
all: $(MAIN) $(MAIN_BIN) $(MAIN_IMG)
@echo "zero stage bootloader has been compiled!"
# DO NOT DELETE THIS LINE -- make depend needs it

View file

@ -0,0 +1,33 @@
# First Stage Bootloader for Ariane
## How-To prepare SD card
The bootloader requires a GPT partition table so you first have to create one with gdisk.
```bash
$ sudo fdisk -l # search for the corresponding disk label (e.g. /dev/sdb)
$ sudo sgdisk --clear --new=1:2048:67583 --new=2 --typecode=1:3000 --typecode=2:8300 /dev/sde # create a new gpt partition table and two partitions: 1st partition: 32mb (ONIE boot), second partition: rest (Linux root)
```
Now you have to make the linux kernel with the [ariane-sdk](https://github.com/pulp-platform/ariane-sdk):
```bash
$ cd /path/to/ariane-sdk
$ make bbl_binary # make the linux kernel with the ariane-sdk repository
```
Then the bbl+linux kernel image can get copied to the sd card with `dd`. __Careful:__ use the same disk label that you found before with `fdisk -l` but with a 1 in the end, e.g. `/dev/sdb` -> `/dev/sdb1`.
```bash
$ sudo dd if=bbl_binary of=/dev/sdb1 status=progress oflag=sync bs=1M
```
## Features
- uart
- spi
- sd card reading
- GPT partitions
## TODO
- file systems (fat16/fat32)
- elf loader
- zeroing of the `.bss` section of the second stage boot loader

View file

@ -52,7 +52,7 @@
interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
reg = <0x0 0xc000000 0x0 0x4000000>;
riscv,max-priority = <7>;
riscv,ndev = <2>;
riscv,ndev = <3>;
};
debug-controller@0 {
compatible = "riscv,debug-013";
@ -70,11 +70,41 @@
reg-shift = <2>; // regs are spaced on 32 bit boundary
reg-io-width = <4>; // only 32-bit access are supported
};
xps-spi@20000000 {
compatible = "xlnx,xps-spi-2.00.b", "xlnx,xps-spi-2.00.a";
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&PLIC0>;
interrupts = < 2 2 >;
reg = < 0x0 0x20000000 0x0 0x1000 >;
xlnx,family = "kintex7";
xlnx,fifo-exist = <0x1>;
xlnx,num-ss-bits = <0x1>;
xlnx,num-transfer-bits = <0x8>;
xlnx,sck-ratio = <0x4>;
mmc@0 {
compatible = "mmc-spi-slot";
reg = <0>;
spi-max-frequency = <12500000>;
voltage-ranges = <3300 3300>;
disable-wp;
};
// mmc-slot@0 {
// compatible = "fsl,mpc8323rdb-mmc-slot", "mmc-spi-slot";
// reg = <0>; //Chip select 0
// spi-max-frequency = <12500000>;
// voltage-ranges = <3300 3300>;
// //interrupts = < 2 2 >;
// //interrupt-parent = <&PLIC0>;
// };
};
xlnx_axi_ethernetlite: ethernet@30000000 {
compatible = "xlnx,axi-ethernetlite-3.0", "xlnx,xps-ethernetlite-1.00.a";
device_type = "network";
interrupt-parent = <&PLIC0>;
interrupts = <2 0>;
interrupts = <3 0>;
local-mac-address = [00 0a 35 00 01 22];
phy-handle = <&phy0>;
reg = <0x0 0x30000000 0x0 0x10000>;
@ -102,16 +132,5 @@
};
};
};
// axi_spi@11000000 {
// compatible = "xlnx.xps-spic-2.00.b";
// clock-names = "axi_clk", "axi4_clk", "spi_clk";
// clocks = <&clkc 71>, <&clkc 72>, <&clkc 73>;
// interrupt-parent = <&intc>;
// interrupts = <0 31 1>;
// reg = <0x41e00000 0x10000>;
// num-cs = <0x1>;
// fifo-size = <256>;
// bits-per-word = <8>;
// }
};
};

View file

@ -1,24 +0,0 @@
#define DRAM_BASE 0x80000000
.section .text.start, "ax", @progbits
.globl _start
_start:
li s0, DRAM_BASE
csrr a0, mhartid
la a1, _dtb
jr s0
.section .text.hang, "ax", @progbits
.globl _hang
_hang:
csrr a0, mhartid
la a1, _dtb
1:
wfi
j 1b
.section .rodata.dtb, "a", @progbits
.globl _dtb
.align 5, 0
_dtb:
.incbin "ariane.dtb"

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -20,39 +20,175 @@ module bootrom (
input logic [63:0] addr_i,
output logic [63:0] rdata_o
);
localparam int RomSize = 337;
localparam int RomSize = 835;
const logic [RomSize-1:0][63:0] mem = {
64'h00000000_0065646f,
64'h6d2d7968_70006f69,
64'h646d2d73_61682c78,
64'h6e6c7800_6c616e72,
64'h65746e69_2d657375,
64'h2c786e6c_7800676e,
64'h6f702d67_6e69702d,
64'h78742c78_6e6c7800,
64'h68746469_772d6469,
64'h2d697861_2d732c78,
64'h6e6c7800_676e6f70,
64'h2d676e69_702d7872,
64'h2c786e6c_78006563,
64'h6e617473_6e692c78,
64'h6e6c7800_6f69646d,
64'h00000000_00000000,
64'h46454443_42413938,
64'h37363534_33323130,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h0a0d2165_6e6f6420,
64'h00000000_00206567,
64'h616d6920_746f6f62,
64'h20676e69_79706f63,
64'h00000000_00000009,
64'h3a656d61_6e090a0d,
64'h00093a73_65747562,
64'h69727474_61090a0d,
64'h00000009_3a61626c,
64'h20747361_6c090a0d,
64'h0000093a_61626c20,
64'h74737269_66090a0d,
64'h00000000_00000000,
64'h09202020_20203a64,
64'h69756720_6e6f6974,
64'h69747261_70090a0d,
64'h00000000_00000000,
64'h093a6469_75672065,
64'h70797420_6e6f6974,
64'h69747261_70090a0d,
64'h00000000_20797274,
64'h6e65206e_6f697469,
64'h74726170_20747067,
64'h00000009_20203a73,
64'h65697274_6e65206e,
64'h6f697469_74726170,
64'h20657a69_73090a0d,
64'h00000009_3a736569,
64'h72746e65_206e6f69,
64'h74697472_61702072,
64'h65626d75_6e090a0d,
64'h00000009_2020203a,
64'h61626c20_73656972,
64'h746e6520_6e6f6974,
64'h69747261_70090a0d,
64'h00093a61_646c2070,
64'h756b6361_62090a0d,
64'h00000000_00000000,
64'h093a6162_6c20746e,
64'h65727275_63090a0d,
64'h00000009_3a646576,
64'h72657365_72090a0d,
64'h00093a72_65646165,
64'h685f6372_63090a0d,
64'h00000000_00000909,
64'h3a657a69_73090a0d,
64'h00000009_3a6e6f69,
64'h73697665_72090a0d,
64'h0000093a_65727574,
64'h616e6769_73090a0d,
64'h00000000_003a7265,
64'h64616568_20656c62,
64'h6174206e_6f697469,
64'h74726170_20747067,
64'h0000203a_65756c61,
64'h76206e72_75746572,
64'h2079706f_63206473,
64'h00000000_0000000a,
64'h0d216465_7a696c61,
64'h6974696e_69206473,
64'h00000000_0a0d676e,
64'h69746978_65202e2e,
64'h2e647320_657a696c,
64'h61697469_6e692074,
64'h6f6e2064_6c756f63,
64'h00000000_0000002e,
64'h0000000a_0d202e2e,
64'h2e445320_676e697a,
64'h696c6169_74696e69,
64'h00000031_34646d63,
64'h00000035_35646d63,
64'h00000000_30646d63,
64'h00000020_3a206573,
64'h6e6f7073_65720920,
64'h00000000_0020646e,
64'h616d6d6f_63204453,
64'h00000000_00000a0d,
64'h65736e6f_70736572,
64'h20647320_64696c61,
64'h7620646e_69662074,
64'h6f6e2064_6c756f63,
64'h00000000_203f3f79,
64'h74706d65_20746f6e,
64'h206f6669_66207872,
64'h00000000_00000a0d,
64'h2164657a_696c6169,
64'h74696e69_20495053,
64'h00000000_00007830,
64'h203a7375_74617473,
64'h00000000_00000a0d,
64'h49505320_74696e69,
64'h00000a0d_21646c72,
64'h6f57206f_6c6c6548,
64'h00000000_00006564,
64'h6f6d2d79_6870006f,
64'h69646d2d_7361682c,
64'h786e6c78_006c616e,
64'h7265746e_692d6573,
64'h752c786e_6c780067,
64'h6e6f702d_676e6970,
64'h2d78742c_786e6c78,
64'h00687464_69772d64,
64'h692d6978_612d732c,
64'h786e6c78_00676e6f,
64'h702d676e_69702d78,
64'h722c786e_6c780065,
64'h636e6174_736e692c,
64'h786e6c78_006f6964,
64'h6d2d6564_756c636e,
64'h692c786e_6c78006b,
64'h63616270_6f6f6c2d,
64'h6c616e72_65746e69,
64'h2d656475_6c636e69,
64'h2c786e6c_78006b63,
64'h6162706f_6f6c2d6c,
64'h616e7265_746e692d,
64'h6564756c_636e692c,
64'h786e6c78_00737265,
64'h66667562_2d6c6162,
64'h6f6c672d_6564756c,
64'h636e692c_786e6c78,
64'h0078656c_7075642c,
64'h786e6c78_00656c64,
64'h6e61682d_79687000,
64'h73736572_6464612d,
64'h63616d2d_6c61636f,
64'h6c006874_6469772d,
64'h2c786e6c_78007372,
64'h65666675_622d6c61,
64'h626f6c67_2d656475,
64'h6c636e69_2c786e6c,
64'h78007865_6c707564,
64'h2c786e6c_7800656c,
64'h646e6168_2d796870,
64'h00737365_72646461,
64'h2d63616d_2d6c6163,
64'h6f6c0070_772d656c,
64'h62617369_64007365,
64'h676e6172_2d656761,
64'h746c6f76_0079636e,
64'h65757165_72662d78,
64'h616d2d69_7073006f,
64'h69746172_2d6b6373,
64'h2c786e6c_78007374,
64'h69622d72_6566736e,
64'h6172742d_6d756e2c,
64'h786e6c78_00737469,
64'h622d7373_2d6d756e,
64'h2c786e6c_78007473,
64'h6978652d_6f666966,
64'h2c786e6c_7800796c,
64'h696d6166_2c786e6c,
64'h78006874_6469772d,
64'h6f692d67_65720074,
64'h66696873_2d676572,
64'h00737470_75727265,
@ -120,39 +256,39 @@ module bootrom (
64'h00000000_6f69646d,
64'h01000000_00000000,
64'h64692d69_696d6772,
64'h23020000_09000000,
64'ha2020000_09000000,
64'h03000000_01000000,
64'h15020000_04000000,
64'h94020000_04000000,
64'h03000000_00000000,
64'h03020000_04000000,
64'h82020000_04000000,
64'h03000000_01000000,
64'hf1010000_04000000,
64'h70020000_04000000,
64'h03000000_04000000,
64'hdd010000_04000000,
64'h5c020000_04000000,
64'h03000000_01000000,
64'hcb010000_04000000,
64'h4a020000_04000000,
64'h03000000_00657469,
64'h6c74656e_72656874,
64'h655f6978_615f786e,
64'h6c785f69_bd010000,
64'h6c785f69_3c020000,
64'h18000000_03000000,
64'h01000000_ab010000,
64'h01000000_2a020000,
64'h04000000_03000000,
64'h00000000_8c010000,
64'h00000000_0b020000,
64'h04000000_03000000,
64'h01000000_70010000,
64'h01000000_ef010000,
64'h04000000_03000000,
64'h01000000_64010000,
64'h01000000_e3010000,
64'h04000000_03000000,
64'h00000100_00000000,
64'h00000030_00000000,
64'h67000000_10000000,
64'h03000000_03000000,
64'h59010000_04000000,
64'hd8010000_04000000,
64'h03000000_00002201,
64'h00350a00_47010000,
64'h00350a00_c6010000,
64'h06000000_03000000,
64'h00000000_02000000,
64'h00000000_03000000,
64'h25010000_08000000,
64'h03000000_02000000,
64'h14010000_04000000,
@ -171,6 +307,52 @@ module bootrom (
64'h30303030_30303340,
64'h74656e72_65687465,
64'h01000000_02000000,
64'h02000000_bb010000,
64'h00000000_03000000,
64'he40c0000_e40c0000,
64'hac010000_08000000,
64'h03000000_20bcbe00,
64'h9a010000_04000000,
64'h03000000_00000000,
64'h67000000_04000000,
64'h03000000_00000000,
64'h746f6c73_2d697073,
64'h2d636d6d_1b000000,
64'h0d000000_03000000,
64'h00000030_40636d6d,
64'h01000000_04000000,
64'h8b010000_04000000,
64'h03000000_08000000,
64'h74010000_04000000,
64'h03000000_01000000,
64'h63010000_04000000,
64'h03000000_01000000,
64'h53010000_04000000,
64'h03000000_00377865,
64'h746e696b_47010000,
64'h08000000_03000000,
64'h00100000_00000000,
64'h00000020_00000000,
64'h67000000_10000000,
64'h03000000_02000000,
64'h02000000_25010000,
64'h08000000_03000000,
64'h02000000_14010000,
64'h04000000_03000000,
64'h00000000_0f000000,
64'h04000000_03000000,
64'h01000000_00000000,
64'h04000000_03000000,
64'h00612e30_302e322d,
64'h6970732d_7370782c,
64'h786e6c78_00622e30,
64'h302e322d_6970732d,
64'h7370782c_786e6c78,
64'h1b000000_28000000,
64'h03000000_00000000,
64'h30303030_30303032,
64'h40697073_2d737078,
64'h01000000_02000000,
64'h04000000_3a010000,
64'h04000000_03000000,
64'h02000000_30010000,
@ -211,7 +393,7 @@ module bootrom (
64'hbb000000_04000000,
64'h03000000_02000000,
64'hb5000000_04000000,
64'h03000000_02000000,
64'h03000000_03000000,
64'hfb000000_04000000,
64'h03000000_07000000,
64'he8000000_04000000,
@ -339,27 +521,343 @@ module bootrom (
64'h00000000_01000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'ha0070000_2c020000,
64'h10090000_ab020000,
64'h00000000_10000000,
64'h11000000_28000000,
64'hd8070000_38000000,
64'h040a0000_edfe0dd0,
64'h48090000_38000000,
64'hf30b0000_edfe0dd0,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_0000a001,
64'h840202a5_85930000,
64'h059701f4_14130010,
64'h041bd5df_f0ef057e,
64'h65a14505_f42ff0ef,
64'hc4050513_00001517,
64'hf1cff0ef_e4061141,
64'hb375815a_f5aff0ef,
64'hf3850513_00001517,
64'hc61ff0ef_855e8662,
64'h020aa583_f72ff0ef,
64'hf3850513_00001517,
64'hf59910e3_08048493,
64'h080a0993_f8aff0ef,
64'h2905cca5_05130000,
64'h1517ff3a_1be3861f,
64'hf0ef0a05_000a4503,
64'hfa6ff0ef_f5c50513,
64'h00001517_835ff0ef,
64'h6888fb8f_f0eff5e5,
64'h05130000_1517847f,
64'hf0ef6488_fcaff0ef,
64'hf6050513_00001517,
64'h859ff0ef_fb898a13,
64'h6088fe0f_f0eff665,
64'h05130000_1517fe9a,
64'h1be38b5f_f0ef0a05,
64'h000a4503_f9098a13,
64'hffeff0ef_f6450513,
64'h00001517_ffaa19e3,
64'h8d3ff0ef_0a050007,
64'hc503014d_87b34a01,
64'h81fff0ef_f8098d93,
64'hf6850513_00001517,
64'h8f3ff0ef_0ff97513,
64'h837ff0ef_f6450513,
64'h00001517_4c914d41,
64'h020a8493_080a8993,
64'h84fff0ef_d8c50513,
64'h00001517_8ddff0ef,
64'h8526861f_f0efe7e5,
64'h05130000_1517c105,
64'h84aa8a8a_d6dff0ef,
64'h850a4605_710144ac,
64'h87fff0ef_dbc50513,
64'h00001517_8cdff0ef,
64'h48e8891f_f0eff9e5,
64'h05130000_15178dff,
64'hf0ef48a8_8a3ff0ef,
64'hf9050513_00001517,
64'h931ff0ef_64a88b5f,
64'hf0eff825_05130000,
64'h1517943f_f0ef7088,
64'h8c7ff0ef_f8450513,
64'h00001517_955ff0ef,
64'h6c888d9f_f0eff7e5,
64'h05130000_1517927f,
64'hf0ef48c8_8ebff0ef,
64'hf8050513_00001517,
64'h939ff0ef_48888fdf,
64'hf0eff825_05130000,
64'h151794bf_f0ef44c8,
64'h90fff0ef_f8450513,
64'h00001517_95dff0ef,
64'h4488921f_f0eff865,
64'h05130000_15179aff,
64'hf0ef6088_933ff0ef,
64'hf8850513_00001517,
64'h93fff0ef_f7450513,
64'h00001517_94bff0ef,
64'he8850513_00001517,
64'h9d9ff0ef_854e95df,
64'hf0eff7a5_05130000,
64'h1517c105_89aa848a,
64'he69ff0ef_850a4585,
64'h46057101_8b0a97df,
64'hf0eff825_05130000,
64'h1517892a_80826165,
64'h6da26d42_6ce27c02,
64'h7ba27b42_7ae26a06,
64'h69a66946_64e67406,
64'h70a6f904_01139adf,
64'hf0eff8a5_05130000,
64'h1517c905_e19ff0ef,
64'h8c2e8baa_1880e46e,
64'he86aec66_f85afc56,
64'he0d2e4ce_e8caeca6,
64'hf486f062_f45ef0a2,
64'h7159bfe1_54798082,
64'h61696baa_6b4a6aea,
64'h7a0a79aa_794a74ea,
64'h640e60ae_8522c7df,
64'hf0efc89f_f0ef4531,
64'h45814605_4401f890,
64'h46e32009_091314fd,
64'ha17ff0ef_fec50513,
64'h00001517_e7990364,
64'he7b30489_94639041,
64'h29811442_8c49cb5f,
64'hf0ef9041_03051413,
64'h0085151b_cc3ff0ef,
64'hfd241ae3_04040413,
64'hff7a17e3_89aaf11f,
64'hf0ef0a05_854e0007,
64'hc5830144_07b30400,
64'h0b934a01_c67ff0ef,
64'h850a0400_05938622,
64'h4981ff55_1ee3cfdf,
64'hf0efe009_04133e80,
64'h0b130fe0_0a932009,
64'h09139081_1482bff5,
64'hd17ff0ef_c501d25f,
64'hf0ef4549_85a20ff6,
64'h76130016_66130015,
64'h161bf53f_f0ef0ff4,
64'h7593f5bf_f0ef0ff5,
64'hf5930084_559bf67f,
64'hf0ef0ff5_f5930104,
64'h559bf73f_f0ef4501,
64'h0184559b_fee79be3,
64'h078500c6_802300f1,
64'h06b30800_0713567d,
64'h4781842e_892ae55e,
64'he95aed56_f152f54e,
64'he58684b2_f94afd26,
64'he1a27155_80829141,
64'h15428d3d_8ff90057,
64'h979b1701_67090107,
64'hd79b0105_179b4105,
64'h551b0105_151b8d2d,
64'h00c59513_8da9893d,
64'h0045d51b_8da99141,
64'h15428d5d_05220085,
64'h579b8082_07f57513,
64'h8d2d0045_15938d2d,
64'h8d3d0045_d51b0075,
64'hd79b8de9_80820141,
64'h853e6402_60a257f5,
64'he1114781_f89ff0ef,
64'hc51157f9_efbff0ef,
64'hc91157fd_ec9ff0ef,
64'hfc6de09f_f0ef347d,
64'h4429b91f_f0ef14e5,
64'h05130000_1517c8bf,
64'hf0efe022_e4061141,
64'h80826105_00153513,
64'h64a26442_60e20004,
64'h051bfc94_0ce3e3df,
64'hf0efec5f_f0ef1765,
64'h05130000_151785aa,
64'h842ae59f_f0ef0290,
64'h05134000_05b70770,
64'h0613fbdf_f0ef4485,
64'he822ec06_e4261101,
64'h80820141_00153513,
64'h157d6402_60a20004,
64'h051bf05f_f0ef1b05,
64'h051385a2_00001517,
64'he8fff0ef_842ae9df,
64'hf0efe022_e4060370,
64'h05134581_06500613,
64'h11418082_61056902,
64'h64a26442_60e20015,
64'h3513f565_05130004,
64'h051b0124_986388bd,
64'h00f91b63_45014785,
64'hecfff0ef_ed3ff0ef,
64'h842aed9f_f0ef84aa,
64'hedfff0ef_ee3ff0ef,
64'hee7ff0ef_892aef5f,
64'hf0efe04a_e426e822,
64'hec064521_1aa00593,
64'h08700613_11018082,
64'h61054505_64a26442,
64'h60e2fe94_10e3f99f,
64'hf0ef23c5_051385a2,
64'h00001517_f23ff0ef,
64'h842af31f_f0ef4501,
64'h09500613_45814485,
64'he822ec06_e4261101,
64'hcbfff06f_61051fe5,
64'h05130000_151760e2,
64'h6442d95f_f0ef852e,
64'h65a2cd9f_f0ef26e5,
64'h05130000_1517ce5f,
64'hf0ef8522_cebff0ef,
64'he42eec06_27450513,
64'h00001517_842ae822,
64'h11018082_614564e2,
64'h85267402_70a2d0df,
64'hf0ef26a5_05130000,
64'h1517f475_147d0007,
64'hda6384aa_4187d79b,
64'h0185179b_fabff0ef,
64'heb5ff0ef_85320640,
64'h04136622_ec1ff0ef,
64'h0ff47513_ec9ff0ef,
64'h0ff57513_0084551b,
64'hed5ff0ef_0ff57513,
64'h0104551b_ee1ff0ef,
64'h0184551b_ee9ff0ef,
64'h0404e513_febff0ef,
64'h84aa842e_ec26f022,
64'he432f406_7179f03f,
64'hf06f0ff0_05138082,
64'h557db7d9_00d70023,
64'h078500f6_073306c8,
64'h2683ff69_8b055178,
64'hb77dd6b8_07850007,
64'h470300f5_07338082,
64'h4501d3b8_4719dbb8,
64'h577d2000_07b702b6,
64'he1630007_869b2000,
64'h08372000_0537fff5,
64'h8b85537c_20000737,
64'hd3b82000_07b71060,
64'h0713fff5_37fd0001,
64'h03200793_04b76163,
64'h0007871b_47812000,
64'h06b7dbb8_57792000,
64'h07b706b7_ee631000,
64'h07938082_610564a2,
64'hd3b84719_dbb86442,
64'h60e20ff4_7513577d,
64'h200007b7_e23ff0ef,
64'h36050513_00001517,
64'heb1ff0ef_91011502,
64'h4088e39f_f0ef37e5,
64'h05130000_1517e395,
64'h8b852401_53fc57e0,
64'hff658b05_06478493,
64'h53f8d3b8_10600713,
64'h200007b7_fff537fd,
64'h00010640_0793d7a8,
64'hdbb85779_e426e822,
64'hec062000_07b71101,
64'he7fff06f_61053ae5,
64'h05130000_151764a2,
64'h60e26442_d03c4799,
64'he97ff0ef_3d450513,
64'h00001517_f25ff0ef,
64'h91010204_95132481,
64'heafff0ef_3cc50513,
64'h00001517_5064d03c,
64'h16600793_ec3ff0ef,
64'h40050513_00001517,
64'hf51ff0ef_91010204,
64'h95132481_edbff0ef,
64'h3f850513_00001517,
64'h5064d03c_10400793,
64'h20000437_fff537fd,
64'h000147a9_c3b84729,
64'h200007b7_f03ff0ef,
64'he426e822_ec064185,
64'h05131101_00001517,
64'h80822501_41088082,
64'hc10c8082_610560e2,
64'hee1ff0ef_00914503,
64'hee9ff0ef_00814503,
64'hf55ff0ef_ec06002c,
64'h11018082_61456942,
64'h64e27402_70a2fe94,
64'h10e3f0bf_f0ef0091,
64'h4503f13f_f0ef3461,
64'h00814503_f81ff0ef,
64'h0ff57513_002c0089,
64'h553354e1_03800413,
64'h892af406_e84aec26,
64'hf0227179_80826145,
64'h694264e2_740270a2,
64'hfe9410e3_f4dff0ef,
64'h00914503_f55ff0ef,
64'h34610081_4503fc3f,
64'hf0ef0ff5_7513002c,
64'h0089553b_54e14461,
64'h892af406_e84aec26,
64'hf0227179_808200f5,
64'h80230007_c78300e5,
64'h80a397aa_81110007,
64'h4703973e_00f57713,
64'h88078793_00002797,
64'hb7f50405_fa5ff0ef,
64'h80820141_640260a2,
64'he5090004_4503842a,
64'he406e022_11418082,
64'h00e78823_02000713,
64'h00e78423_fc700713,
64'h00e78623_470d0007,
64'h822300e7_8023476d,
64'h00e78623_f8000713,
64'h00078223_100007b7,
64'h808200a7_0023dfe5,
64'h0207f793_01474783,
64'h10000737_80820205,
64'h75130147_c5031000,
64'h07b78082_00054503,
64'h808200b5_00238082,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_0000bff5,
64'h10500073_03c58593,
64'h00000597_f1402573,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00008402_07458593,
64'h00000597_f1402573,
64'h01f41413_0010041b
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00048067_01f49493,
64'h0010049b_9e458593,
64'h00001597_f1402573,
64'hff24c6e3_4009091b,
64'h02000937_00448493,
64'hfe091ee3_0004a903,
64'h00092023_00990933,
64'h00291913_f1402973,
64'h020004b7_fe090ae3,
64'h00897913_34402973,
64'h10500073_ff24c6e3,
64'h4009091b_02000937,
64'h00448493_0124a023,
64'h00100913_020004b7,
64'h1f5000ef_fec10113,
64'h01000117_03249663,
64'hf1402973_00000493,
64'h30491073_00800913
};
logic [$clog2(RomSize)-1:0] addr_q;

View file

@ -1,21 +0,0 @@
SECTIONS
{
ROM_BASE = 0x10000; /* ... but actually position independent */
. = ROM_BASE;
.text.start : { *(.text.start) }
. = ROM_BASE + 0x40;
.text.hang : { *(.text.hang) }
. = ROM_BASE + 0x80;
.rodata.dtb : { *(.rodata.dtb) }
.bss : ALIGN(0x100) {
_BSS_START_ = .;
*(.bss)
_BSS_END_ = .;
}
PROVIDE(_sp = 0x84000000);
PROVIDE(_heap_end = _sp - 0x800);
}

View file

@ -0,0 +1,38 @@
ENTRY(main)
SECTIONS
{
ROM_BASE = 0x10000; /* ... but actually position independent */
. = ROM_BASE;
.text.init : { *(.text.init) }
.text : ALIGN(0x100) {
_TEXT_START_ = .;
*(.text)
_TEXT_END_ = .;
}
.data : ALIGN(0x100) {
_DATA_START_ = .;
*(.data)
_DATA_END_ = .;
}
PROVIDE(_data = ADDR(.data));
PROVIDE(_data_lma = LOADADDR(.data));
PROVIDE(_edata = .);
.bss : ALIGN(0x100) {
_BSS_START_ = .;
*(.bss)
_BSS_END_ = .;
}
PROVIDE(_sp = 0x84000000);
PROVIDE(_heap_end = _sp - 0x80000);
/*.rodata.dtb : { *(.rodata.dtb) }*/
}

View file

@ -0,0 +1,93 @@
#include "gpt.h"
#include "sd.h"
#include "uart.h"
#include <stddef.h>
void gpt_find_boot_partition(uint8_t* dest, uint32_t size)
{
int ret = init_sd();
if (ret != 0) {
print_uart("could not initialize sd... exiting\r\n");
return;
}
print_uart("sd initialized!\r\n");
// load LBA1
size_t block_size = 512;
uint8_t lba1_buf[block_size];
int res = sd_copy(lba1_buf, 1, 1);
if (res != 0)
{
print_uart("sd copy return value: ");
print_uart_addr(res);
print_uart("\r\n");
}
gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf;
print_uart("gpt partition table header:");
print_uart("\r\n\tsignature:\t");
print_uart_addr(lba1->signature);
print_uart("\r\n\trevision:\t");
print_uart_int(lba1->revision);
print_uart("\r\n\tsize:\t\t");
print_uart_int(lba1->header_size);
print_uart("\r\n\tcrc_header:\t");
print_uart_int(lba1->crc_header);
print_uart("\r\n\treserved:\t");
print_uart_int(lba1->reserved);
print_uart("\r\n\tcurrent lba:\t");
print_uart_addr(lba1->current_lba);
print_uart("\r\n\tbackup lda:\t");
print_uart_addr(lba1->backup_lba);
print_uart("\r\n\tpartition entries lba: \t");
print_uart_addr(lba1->partition_entries_lba);
print_uart("\r\n\tnumber partition entries:\t");
print_uart_int(lba1->nr_partition_entries);
print_uart("\r\n\tsize partition entries: \t");
print_uart_int(lba1->size_partition_entry);
print_uart("\r\n");
uint8_t lba2_buf[block_size];
res = sd_copy(lba2_buf, lba1->partition_entries_lba, 1);
if (res != 0)
{
print_uart("sd copy return value: ");
print_uart_addr(res);
print_uart("\r\n");
}
for (int i = 0; i < 4; i++)
{
partition_entries_t *part_entry = (partition_entries_t *)(lba2_buf + (i * 128));
print_uart("gpt partition entry ");
print_uart_byte(i);
print_uart("\r\n\tpartition type guid:\t");
for (int j = 0; j < 16; j++)
print_uart_byte(part_entry->partition_type_guid[j]);
print_uart("\r\n\tpartition guid: \t");
for (int j = 0; j < 16; j++)
print_uart_byte(part_entry->partition_guid[j]);
print_uart("\r\n\tfirst lba:\t");
print_uart_addr(part_entry->first_lba);
print_uart("\r\n\tlast lba:\t");
print_uart_addr(part_entry->last_lba);
print_uart("\r\n\tattributes:\t");
print_uart_addr(part_entry->attributes);
print_uart("\r\n\tname:\t");
for (int j = 0; j < 72; j++)
print_uart_byte(part_entry->name[j]);
print_uart("\r\n");
}
partition_entries_t *boot = (partition_entries_t *)(lba2_buf);
print_uart("copying boot image ");
res = sd_copy(dest, boot->first_lba, size);
print_uart(" done!\r\n");
}

View file

@ -0,0 +1,39 @@
#pragma once
#include <stdint.h>
// LBA 0: Protective MBR
// ignored here
// Partition Table Header (LBA 1)
typedef struct gpt_pth
{
uint64_t signature;
uint32_t revision;
uint32_t header_size; //! little endian, usually 0x5c = 92
uint32_t crc_header;
uint32_t reserved; //! must be 0
uint64_t current_lba;
uint64_t backup_lba;
uint64_t first_usable_lba;
uint64_t last_usable_lba;
uint8_t disk_guid[16];
uint64_t partition_entries_lba;
uint32_t nr_partition_entries;
uint32_t size_partition_entry; //! usually 0x80 = 128
uint32_t crc_partition_entry;
} gpt_pth_t;
// Partition Entries (LBA 2-33)
typedef struct partition_entries
{
uint8_t partition_type_guid[16];
uint8_t partition_guid[16];
uint64_t first_lba;
uint64_t last_lba; //! inclusive
uint64_t attributes;
uint8_t name[72]; //! utf16 encoded
} partition_entries_t;
// Find boot partition and load it to the destination
void gpt_find_boot_partition(uint8_t* dest, uint32_t size);

View file

@ -0,0 +1,29 @@
#include "uart.h"
#include "spi.h"
#include "sd.h"
#include "gpt.h"
int main()
{
init_uart();
print_uart("Hello World!\r\n");
gpt_find_boot_partition((uint8_t *)0x80000000UL, 2*16384);
// jump to the address
__asm__ volatile(
"li s0, 0x80000000;"
"la a1, _dtb;"
"jr s0"
);
while (1)
{
// do nothing
}
}
void handle_trap(void)
{
// print_uart("trap\r\n");
}

202
fpga/src/bootrom/src/sd.c Normal file
View file

@ -0,0 +1,202 @@
#include "sd.h"
#include "spi.h"
#include "uart.h"
// spi full duplex: send 0xff to receive byte
uint8_t sd_dummy()
{
return spi_txrx(0xFF);
}
uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc)
{
unsigned long n;
uint8_t r;
sd_dummy();
spi_txrx(0x40 | cmd);
spi_txrx(arg >> 24);
spi_txrx(arg >> 16);
spi_txrx(arg >> 8);
spi_txrx(arg);
spi_txrx(crc);
n = 100;
do
{
r = sd_dummy();
if (!(r & 0x80))
{
break;
}
} while (--n > 0);
if (n == 0)
print_uart("could not find valid sd response\r\n");
return r;
}
void print_status(const char *cmd, uint8_t response)
{
print_uart("SD command ");
print_uart(cmd);
print_uart(" \tresponse : ");
print_uart_byte(response);
print_uart("\r\n");
}
int sd_cmd0()
{
uint8_t r = 0xff;
while (r != 0x1)
{
r = sd_cmd(0, 0, 0x95);
sd_dummy(); // R1: 1 Byte response
print_status("cmd0", r);
}
return r == 0x1;
}
int sd_cmd8()
{
uint8_t r1 = sd_cmd(8, 0x1aa, 0x87);
sd_dummy(); /* command version; reserved */
sd_dummy(); /* reserved */
uint8_t r4 = sd_dummy(); /* voltage */
uint8_t r5 = sd_dummy(); /* check pattern */
sd_dummy();
sd_dummy(); // additional 0xff for good measure
return r1 == 0x1 && (r4 & 0xf) == 0x1 && r5 == 0xaa;
}
int sd_cmd55()
{
uint8_t r = sd_cmd(55, 0x0, 0x65);
sd_dummy();
print_status("cmd55", r);
return r == 0x1;
}
int sd_acmd41()
{
uint8_t r;
do
{
sd_cmd55();
r = sd_cmd(41, 0x40000000, 0x77); /* HCS = 1 */
print_status("cmd41", r);
sd_dummy();
} while (r == 0x1);
return (r == 0x00);
}
int init_sd()
{
spi_init();
print_uart("initializing SD... \r\n");
// mostly taken from
// https://electronics.stackexchange.com/questions/77417/what-is-the-correct-command-sequence-for-microsd-card-initialization-in-spi
// and the siFive implementation:
// https://github.com/sifive/freedom-u540-c000-bootloader/blob/09ac8c24dae741e6234e2b1e663784294367e147/sd/sd.c
// send 10 bytes 0xff
for (int i = 0; i < 10; i++)
sd_dummy();
if (!sd_cmd0())
return SD_INIT_ERROR_CMD0;
if (!sd_cmd8())
return SD_INIT_ERROR_CMD8;
if (!sd_acmd41())
return SD_INIT_ERROR_ACMD41;
return 0;
}
uint8_t crc7(uint8_t prev, uint8_t in)
{
// CRC polynomial 0x89
uint8_t remainder = prev & in;
remainder ^= (remainder >> 4) ^ (remainder >> 7);
remainder ^= remainder << 4;
return remainder & 0x7f;
}
uint16_t crc16(uint16_t crc, uint8_t data)
{
// CRC polynomial 0x11021
crc = (uint8_t)(crc >> 8) | (crc << 8);
crc ^= data;
crc ^= (uint8_t)(crc >> 4) & 0xf;
crc ^= crc << 12;
crc ^= (crc & 0xff) << 5;
return crc;
}
int sd_copy(void *dst, uint32_t src_lba, uint32_t size)
{
volatile uint8_t *p = dst;
long i = size;
int rc = 0;
uint8_t ff[128];
for (int j = 0; j < 128; j++)
ff[j] = 0xff;
uint8_t crc = 0;
crc = crc7(crc, 0x40 | SD_CMD_READ_BLOCK_MULTIPLE);
crc = crc7(crc, (src_lba >> 24) & 0xff);
crc = crc7(crc, (src_lba >> 16) & 0xff);
crc = crc7(crc, (src_lba >> 8) & 0xff);
crc = crc7(crc, src_lba & 0xff);
crc = (crc << 1) | 1;
if (sd_cmd(18, src_lba, crc) != 0x00)
{
for (int j = 0; j < 8; i++)
sd_dummy();
print_uart("could not read SD block\r\n");
return -1;
}
do
{
uint16_t crc, crc_exp;
long n;
crc = 0;
n = 512;
while (sd_dummy() != SD_DATA_TOKEN)
;
do
{
int bytes_per_transfer = 64;
spi_write_bytes(ff, bytes_per_transfer, (uint8_t *)p);
for (int i = 0; i < bytes_per_transfer; i++)
{
crc = crc16(crc, p[i]);
}
p += bytes_per_transfer;
n -= bytes_per_transfer;
// uint8_t x = sd_dummy();
// *p++ = x;
// crc = crc16(crc, x);
} while (n > 0);
crc_exp = ((uint16_t)sd_dummy() << 8);
crc_exp |= sd_dummy();
if (crc != crc_exp)
{
rc = SD_COPY_ERROR_CMD18_CRC;
break;
}
if ((i % 1000) == 0)
{
print_uart(".");
}
} while (--i > 0);
sd_cmd(SD_CMD_STOP_TRANSMISSION, 0, 0x01);
sd_dummy();
return rc;
}

20
fpga/src/bootrom/src/sd.h Normal file
View file

@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
#define SD_CMD_STOP_TRANSMISSION 12
#define SD_CMD_READ_BLOCK_MULTIPLE 18
#define SD_DATA_TOKEN 0xfe
#define SD_COPY_ERROR_CMD18 -1
#define SD_COPY_ERROR_CMD18_CRC -2
// errors
#define SD_INIT_ERROR_CMD0 -1
#define SD_INIT_ERROR_CMD8 -2
#define SD_INIT_ERROR_ACMD41 -3
int init_sd();
void put_sdcard_spi_mode();
int sd_copy(void *dst, uint32_t src_lba, uint32_t size);

View file

@ -0,0 +1,52 @@
#pragma once
// The hart that non-SMP tests should run on
#ifndef NONSMP_HART
#define NONSMP_HART 0
#endif
// The maximum number of HARTs this code supports
#define CLINT_CTRL_ADDR 0x2000000
#ifndef MAX_HARTS
#define MAX_HARTS 256
#endif
#define CLINT_END_HART_IPI CLINT_CTRL_ADDR + (MAX_HARTS * 4)
/* If your test needs to temporarily block multiple-threads, do this:
* smp_pause(reg1, reg2)
* ... single-threaded work ...
* smp_resume(reg1, reg2)
* ... multi-threaded work ...
*/
#define smp_pause(reg1, reg2) \
li reg2, 0x8; \
csrw mie, reg2; \
li reg1, NONSMP_HART; \
csrr reg2, mhartid; \
bne reg1, reg2, 42f
#define smp_resume(reg1, reg2) \
li reg1, CLINT_CTRL_ADDR; \
41:; \
li reg2, 1; \
sw reg2, 0(reg1); \
addi reg1, reg1, 4; \
li reg2, CLINT_END_HART_IPI; \
blt reg1, reg2, 41b; \
42:; \
wfi; \
csrr reg2, mip; \
andi reg2, reg2, 0x8; \
beqz reg2, 42b; \
li reg1, CLINT_CTRL_ADDR; \
csrr reg2, mhartid; \
slli reg2, reg2, 2; \
add reg2, reg2, reg1; \
sw zero, 0(reg2); \
41:; \
lw reg2, 0(reg1); \
bnez reg2, 41b; \
addi reg1, reg1, 4; \
li reg2, CLINT_END_HART_IPI; \
blt reg1, reg2, 41b

131
fpga/src/bootrom/src/spi.c Normal file
View file

@ -0,0 +1,131 @@
#include "spi.h"
#include "uart.h"
void write_reg(uintptr_t addr, uint32_t value)
{
volatile uint32_t *loc_addr = (volatile uint32_t *)addr;
*loc_addr = value;
}
uint32_t read_reg(uintptr_t addr)
{
return *(volatile uint32_t *)addr;
}
void spi_init()
{
print_uart("init SPI\r\n");
// reset the axi quadspi core
write_reg(SPI_RESET_REG, 0x0a);
for (int i = 0; i < 10; i++)
{
__asm__ volatile(
"nop");
}
write_reg(SPI_CONTROL_REG, 0x104);
uint32_t status = read_reg(SPI_STATUS_REG);
print_uart("status: 0x");
print_uart_addr(status);
print_uart("\r\n");
// clear all fifos
write_reg(SPI_CONTROL_REG, 0x166);
status = read_reg(SPI_STATUS_REG);
print_uart("status: 0x");
print_uart_addr(status);
print_uart("\r\n");
write_reg(SPI_CONTROL_REG, 0x06);
print_uart("SPI initialized!\r\n");
}
uint8_t spi_txrx(uint8_t byte)
{
// enable slave select
write_reg(SPI_SLAVE_SELECT_REG, 0xfffffffe);
write_reg(SPI_TRANSMIT_REG, byte);
for (int i = 0; i < 100; i++)
{
__asm__ volatile(
"nop");
}
// enable spi control master flag
write_reg(SPI_CONTROL_REG, 0x106);
while ((read_reg(SPI_STATUS_REG) & 0x1) == 0x1)
;
uint32_t result = read_reg(SPI_RECEIVE_REG);
if ((read_reg(SPI_STATUS_REG) & 0x1) != 0x1)
{
print_uart("rx fifo not empty?? ");
print_uart_addr(read_reg(SPI_STATUS_REG));
print_uart("\r\n");
}
// disable slave select
write_reg(SPI_SLAVE_SELECT_REG, 0xffffffff);
// disable spi control master flag
write_reg(SPI_CONTROL_REG, 0x06);
return result;
}
int spi_write_bytes(uint8_t *bytes, uint32_t len, uint8_t *ret)
{
uint32_t status;
if (len > 256) // FIFO maxdepth 256
return -1;
// enable slave select
write_reg(SPI_SLAVE_SELECT_REG, 0xfffffffe);
for (int i = 0; i < len; i++)
{
write_reg(SPI_TRANSMIT_REG, bytes[i] & 0xff);
}
for (int i = 0; i < 50; i++)
{
__asm__ volatile(
"nop");
}
// enable spi control master flag
write_reg(SPI_CONTROL_REG, 0x106);
do
{
status = read_reg(SPI_STATUS_REG);
} while ((status & 0x1) == 0x1);
for (int i = 0; i < len;)
{
status = read_reg(SPI_STATUS_REG);
if ((status & 0x1) != 0x1) // recieve fifo not empty
{
ret[i++] = read_reg(SPI_RECEIVE_REG);
}
}
// disable slave select
write_reg(SPI_SLAVE_SELECT_REG, 0xffffffff);
// disable spi control master flag
write_reg(SPI_CONTROL_REG, 0x06);
return 0;
}

View file

@ -0,0 +1,25 @@
#pragma once
#include <stdint.h>
#define SPI_BASE 0x20000000
#define SPI_RESET_REG SPI_BASE + 0x40
#define SPI_CONTROL_REG SPI_BASE + 0x60
#define SPI_STATUS_REG SPI_BASE + 0x64
#define SPI_TRANSMIT_REG SPI_BASE + 0x68
#define SPI_RECEIVE_REG SPI_BASE + 0x6C
#define SPI_SLAVE_SELECT_REG SPI_BASE + 0x70
#define SPI_TRANSMIT_OCCUPANCY SPI_BASE + 0x74
#define SPI_RECEIVE_OCCUPANCY SPI_BASE + 0x78
#define SPI_INTERRUPT_GLOBAL_ENABLE_REG SPI_BASE + 0x1c
#define SPI_INTERRUPT_STATUS_REG SPI_BASE + 0x20
#define SPI_INTERRUPT_ENABLE_REG SPI_BASE + 0x28
void spi_init();
uint8_t spi_txrx(uint8_t byte);
// return -1 if something went wrong
int spi_write_bytes(uint8_t *bytes, uint32_t len, uint8_t *ret);

View file

@ -0,0 +1,89 @@
#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;
}
void write_serial(char a)
{
while (is_transmit_empty() == 0) {};
write_reg_u8(UART_THR, a);
}
void init_uart()
{
write_reg_u8(UART_INTERRUPT_ENABLE, 0x00); // Disable all interrupts
write_reg_u8(UART_LINE_CONTROL, 0x80); // Enable DLAB (set baud rate divisor)
write_reg_u8(UART_DLAB_LSB, 0x1B); // Set divisor to 27 (lo byte) 115200 baud
write_reg_u8(UART_DLAB_MSB, 0x00); // (hi byte)
write_reg_u8(UART_LINE_CONTROL, 0x03); // 8 bits, no parity, one stop bit
write_reg_u8(UART_FIFO_CONTROL, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
write_reg_u8(UART_MODEM_CONTROL, 0x20); // Autoflow mode
}
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]);
}

View file

@ -0,0 +1,27 @@
#pragma once
#include <stdint.h>
#define UART_BASE 0x10000000
#define UART_RBR UART_BASE + 0
#define UART_THR UART_BASE + 0
#define UART_INTERRUPT_ENABLE UART_BASE + 4
#define UART_INTERRUPT_IDENT UART_BASE + 8
#define UART_FIFO_CONTROL UART_BASE + 8
#define UART_LINE_CONTROL UART_BASE + 12
#define UART_MODEM_CONTROL UART_BASE + 16
#define UART_LINE_STATUS UART_BASE + 20
#define UART_MODEM_STATUS UART_BASE + 24
#define UART_DLAB_LSB UART_BASE + 0
#define UART_DLAB_MSB UART_BASE + 4
void init_uart();
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);

View file

@ -0,0 +1,25 @@
# start sequence of the bootloader
#
#
#include <smp.h>
#define DRAM_BASE 0x80000000
.section .text.init
.option norvc
.globl _prog_start
_prog_start:
smp_pause(s1, s2)
la sp, _sp
call main
smp_resume(s1, s2)
csrr a0, mhartid
la a1, _dtb
li s1, DRAM_BASE
jr s1
.section .rodata
.section .rodata.dtb, "a", @progbits
.globl _dtb
.align 5, 0
_dtb:
.incbin "ariane.dtb"