From edb5181e64bb2ac2ad4f29a6de7e4b4988be8142 Mon Sep 17 00:00:00 2001 From: imi415 Date: Sat, 30 May 2020 22:42:07 +0800 Subject: [PATCH] Initial commit. --- Makefile | 57 ++++++++++++++++++++++++ linker.ld | 87 ++++++++++++++++++++++++++++++++++++ main.c | 42 ++++++++++++++++++ startup.s | 102 +++++++++++++++++++++++++++++++++++++++++++ syscalls.c | 20 +++++++++ system_handlers.c | 14 ++++++ system_init.c | 21 +++++++++ system_peripherals.c | 5 +++ xilinx_ip_defs.h | 53 ++++++++++++++++++++++ 9 files changed, 401 insertions(+) create mode 100644 Makefile create mode 100644 linker.ld create mode 100644 main.c create mode 100644 startup.s create mode 100644 syscalls.c create mode 100644 system_handlers.c create mode 100644 system_init.c create mode 100644 system_peripherals.c create mode 100644 xilinx_ip_defs.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..43bbe6d --- /dev/null +++ b/Makefile @@ -0,0 +1,57 @@ +BUILD_DIR = build + +C_SOURCES = \ +system_handlers.c \ +system_peripherals.c \ +system_init.c \ +syscalls.c \ +main.c + +ASM_SOURCES = \ +startup.s + +LDSCRIPT = linker.ld + +TARGET = hello + +CC = /home/imi415/Softwares/Arch/RISC-V/toolchains/rv32imc/bin/riscv32-unknown-elf-gcc +AS = /home/imi415/Softwares/Arch/RISC-V/toolchains/rv32imc/bin/riscv32-unknown-elf-gcc +CP = /home/imi415/Softwares/Arch/RISC-V/toolchains/rv32imc/bin/riscv32-unknown-elf-objcopy +SZ = /home/imi415/Softwares/Arch/RISC-V/toolchains/rv32imc/bin/riscv32-unknown-elf-size + +HEX = $(CP) -O ihex +BIN = $(CP) -O binary + +CFLAGS += -mabi=ilp32 -march=rv32imc -g +ASFLAGS += -mabi=ilp32 -march=rv32imc -g +LDFLAGS += -nostartfiles -specs=nano.specs -lc -lm -lnosys + + +LDFLAGS += -T$(LDSCRIPT) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map -Wl,--print-memory-usage + +all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin + +OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) +vpath %.c $(sort $(dir $(C_SOURCES))) + +OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o))) +vpath %.s $(sort $(dir $(ASM_SOURCES))) + +$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) + $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ + +$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR) + $(AS) -c $(CFLAGS) $< -o $@ + +$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile + $(CC) $(OBJECTS) $(LDFLAGS) -o $@ + $(SZ) $@ + +$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR) + $(HEX) $< $@ + +$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR) + $(BIN) $< $@ + +$(BUILD_DIR): + mkdir $@ \ No newline at end of file diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..c9595b6 --- /dev/null +++ b/linker.ld @@ -0,0 +1,87 @@ +_entry_point = _vectors_start + 0x80; + +ENTRY(_entry_point) + +_estack = 0x42040000; +_minimum_stack_size = 0x2000; +_minimum_heap_size = 0x2000; + +MEMORY +{ + RO_CODE (rx) : ORIGIN = 0x42000000, LENGTH = 128K + RW_DATA (xrw) : ORIGIN = 0x42020000, LENGTH = 128K +} + +SECTIONS +{ + .isr_vectors : + { + . = ALIGN(4); + _vectors_start = .; + KEEP(*(.isr_vectors)) + _vectors_end = .; + . = ALIGN(4); + } >RO_CODE + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + } >RO_CODE + + .data : + { + . = ALIGN(4); + _sdata = .; + __global_pointer$ = . + 0x800; + *(.data) + *(.data*) + *(.sdata) + *(.sdata*) + . = ALIGN(4); + _edata = .; + } >RW_DATA AT> RO_CODE + + _sidata = LOADADDR(.data); + + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = ALIGN(4); + } >RO_CODE + + .bss : + { + . = ALIGN(4); + _sbss = .; + _bss_start = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + _bss_end = _ebss; + } >RW_DATA + + ._heap_stack_space : + { + . = ALIGN(8); + PROVIDE(end = .); + PROVIDE(_end = .); + . = . + _minimum_heap_size; + . = . + _minimum_stack_size; + . = ALIGN(8); + } >RW_DATA + + .riscv.attributes 0 : + { + *(.riscv.attributes) + } +} \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..dd811cf --- /dev/null +++ b/main.c @@ -0,0 +1,42 @@ +#include +#include + +#include "xilinx_ip_defs.h" + +#define DDR_BASE 0x1FC00000 +#define DDR_LENGTH 0x100 + +int main(int argc, char *argv[]) { + GPIO0->TRI = 0xFFFFFFFD; + GPIO0->DATA = 0x00; + printf("Dumping first 256 bytes of DDR memory...\r\n"); + for(uint32_t i = DDR_BASE; i < DDR_BASE + DDR_LENGTH; i++) { + printf("%02x ", *(uint8_t *)i); + if((i + 1) % 16 == 0) { + printf("\r\n"); + } + } + printf("Dump done.\r\n"); + printf("== RISC-V: The Free and Open RISC Instruction Set Architecture ==\r\n"); + printf("Running on LowRISC Ibex\r\n"); + + printf("System core frequency: %ld\r\n", GetCoreClock()); + + volatile uint32_t reg_buf = 0; + asm volatile("csrr %0, misa\n" : "=r"(reg_buf)); + printf("MISA: 0x%08x\r\n", reg_buf); + + asm volatile("csrr %0, mhartid\n" : "=r"(reg_buf)); + printf("MHARTID: 0x%08x\r\n", reg_buf); + + uint32_t previous_tick = GetTick(); + + while(1) { + if(GetTick() - previous_tick >= 500) { + previous_tick = SysTick; + GPIO0->DATA ^= 0x02; + printf("SysTick: %lu\r\n", GetTick()); + } + } + return 0; +} \ No newline at end of file diff --git a/startup.s b/startup.s new file mode 100644 index 0000000..c4c78d5 --- /dev/null +++ b/startup.s @@ -0,0 +1,102 @@ +.section .text + +.global Reset_Handler + +Reset_Handler: + mv x1, x0 + mv x2, x1 + mv x3, x1 + mv x4, x1 + mv x5, x1 + mv x6, x1 + mv x7, x1 + mv x8, x1 + mv x9, x1 + mv x10, x1 + mv x11, x1 + mv x12, x1 + mv x13, x1 + mv x14, x1 + mv x15, x1 + mv x16, x1 + mv x17, x1 + mv x18, x1 + mv x19, x1 + mv x20, x1 + mv x21, x1 + mv x22, x1 + mv x23, x1 + mv x24, x1 + mv x25, x1 + mv x26, x1 + mv x27, x1 + mv x28, x1 + mv x29, x1 + mv x30, x1 + mv x31, x1 + +.option push +.option norelax + la gp, __global_pointer$ +.option pop + + la sp, _estack + + la x25, _sidata + la x26, _sdata + la x27, _edata + + bge x26, x27, copy_data_end + +copy_data: + lw x24, 0(x25) + sw x24, 0(x26) + addi x25, x25, 4 + addi x26, x26, 4 + + ble x26, x27, copy_data + +copy_data_end: + +/* Zero .bss section */ + la x26, _sbss + la x27, _ebss + + bge x26, x27, zero_bss_end + +zero_bss: + sw x0, 0(x26) + addi x26, x26, 4 + ble x26, x27, zero_bss + +zero_bss_end: + jal x1, System_Init + + addi x10, x0, 0 + addi x11, x0, 0 + jal x1, main + +inf_loop: + jal x0, inf_loop + +Default_IRQHandler: + jal x0, Generic_ExceptionCallback + +Timer_IRQHandler: + jal x0, Generic_TimerCallback + +/* ISR vector table */ +.section .isr_vectors, "ax" +.option norvc; + +.org 0x00 +.rept 7 + jal x0, Default_IRQHandler +.endr + jal x0, Timer_IRQHandler +.rept 23 + jal x0, Default_IRQHandler +.endr + +.org 0x80 + jal x0, Reset_Handler diff --git a/syscalls.c b/syscalls.c new file mode 100644 index 0000000..5c52ace --- /dev/null +++ b/syscalls.c @@ -0,0 +1,20 @@ +#include +#include "xilinx_ip_defs.h" + + +void _putchar(char ch) +{ + while(((UART0->STAT & 0x04) == 0) || UART0->STAT & 0x08) { + // Waits for TX FIFO empty. + } + UART0->TX_FIFO = ch; +} + +int _write(int handle, char *data, int size ) { + int count; + handle = handle; + for( count = 0; count < size; count++) { + _putchar(data[count]); + } + return count; +} \ No newline at end of file diff --git a/system_handlers.c b/system_handlers.c new file mode 100644 index 0000000..b3d8acb --- /dev/null +++ b/system_handlers.c @@ -0,0 +1,14 @@ +#include +#include + +#include "xilinx_ip_defs.h" + +void Generic_ExceptionCallback(void) { + for(;;) { + } +} + +__attribute__((interrupt)) void Generic_TimerCallback(void) { + TIMER0->TCSR0 |= (1 << 0x08); // Clear interrupt; + SysTick++; +} \ No newline at end of file diff --git a/system_init.c b/system_init.c new file mode 100644 index 0000000..3d430af --- /dev/null +++ b/system_init.c @@ -0,0 +1,21 @@ +#include "xilinx_ip_defs.h" + +__IO uint32_t SysTick; + +void System_Init(void) { + // Clear UARTLite FIFOs + UART0->CTRL = 0x03; + + SysTick = 0; + + // Enable interrupts + asm volatile("csrs mie, %0\n" : : "r"(0x80)); // Enable timer interrupt + asm volatile("csrs mstatus, %0\n" : : "r"(0x8)); // Enable global interrupt + + // Setup systick timer + TIMER0->TCSR0 = 0x12; // Generate mode, down count, auto-reload + TIMER0->TCR0 = 0; // Clear counter + TIMER0->TLR0 = SYS_CLK_FREQ / SYS_TICK_RATE; // Set reload value + + TIMER0->TCSR0 |= (1 << 0x06U) | (1 << 0x07U); // Enable timer interrupt, enable counter. +} \ No newline at end of file diff --git a/system_peripherals.c b/system_peripherals.c new file mode 100644 index 0000000..5f7147f --- /dev/null +++ b/system_peripherals.c @@ -0,0 +1,5 @@ +#include "xilinx_ip_defs.h" + +__IO UartLite_TypeDef *UART0 = (UartLite_TypeDef *)UART0_BASE; +__IO GPIO_TypeDef *GPIO0 = (GPIO_TypeDef *)GPIO0_BASE; +__IO Timer_TypeDef *TIMER0 = (Timer_TypeDef *)TIMER0_BASE; \ No newline at end of file diff --git a/xilinx_ip_defs.h b/xilinx_ip_defs.h new file mode 100644 index 0000000..c697cb8 --- /dev/null +++ b/xilinx_ip_defs.h @@ -0,0 +1,53 @@ +#ifndef __XILINX_IP_DEFS_H +#define __XILINX_IP_DEFS_H + +#include + +#define __IO volatile + +typedef struct { + __IO uint32_t RX_FIFO; + __IO uint32_t TX_FIFO; + __IO uint32_t STAT; + __IO uint32_t CTRL; +} UartLite_TypeDef; + +typedef struct { + __IO uint32_t DATA; + __IO uint32_t TRI; + __IO uint32_t DATA2; + __IO uint32_t TRI2; +} GPIO_TypeDef; + +typedef struct { + __IO uint32_t TCSR0; + __IO uint32_t TLR0; + __IO uint32_t TCR0; + __IO uint32_t RSVD; + __IO uint32_t TCSR1; + __IO uint32_t TLR1; + __IO uint32_t TCR1; +} Timer_TypeDef; + +#define UART0_BASE 0x40010000 +#define GPIO0_BASE 0x40000000 +#define TIMER0_BASE 0x40020000 + +#define SYS_CLK_FREQ 48000000 +#define SYS_TICK_RATE 1000 + +extern __IO UartLite_TypeDef *UART0; +extern __IO GPIO_TypeDef *GPIO0; +extern __IO Timer_TypeDef *TIMER0; + +extern __IO uint32_t SysTick; + +static inline uint32_t GetTick() { + return SysTick; +} + +static inline uint32_t GetCoreClock() { + return SYS_CLK_FREQ; +} + +#endif \ No newline at end of file