Refactored structure, implemented UARTLite and GPIO driver.
This commit is contained in:
parent
edb5181e64
commit
8b4c7855cc
19
Makefile
19
Makefile
|
@ -1,11 +1,18 @@
|
|||
BUILD_DIR = build
|
||||
|
||||
C_SOURCES = \
|
||||
system_handlers.c \
|
||||
system_peripherals.c \
|
||||
system_init.c \
|
||||
syscalls.c \
|
||||
main.c
|
||||
src/drivers/xilinx_gpio.c \
|
||||
src/drivers/xilinx_uartlite.c \
|
||||
src/drivers/xilinx_timer.c \
|
||||
src/ibex_it.c \
|
||||
src/ibex_system.c \
|
||||
src/soc_peripherals.c \
|
||||
src/system_init.c \
|
||||
src/syscalls.c \
|
||||
src/main.c
|
||||
|
||||
INCLUDES = \
|
||||
-Iinclude
|
||||
|
||||
ASM_SOURCES = \
|
||||
startup.s
|
||||
|
@ -22,7 +29,7 @@ SZ = /home/imi415/Softwares/Arch/RISC-V/toolchains/rv32imc/bin/riscv32-unknown-e
|
|||
HEX = $(CP) -O ihex
|
||||
BIN = $(CP) -O binary
|
||||
|
||||
CFLAGS += -mabi=ilp32 -march=rv32imc -g
|
||||
CFLAGS += -mabi=ilp32 -march=rv32imc -g $(INCLUDES)
|
||||
ASFLAGS += -mabi=ilp32 -march=rv32imc -g
|
||||
LDFLAGS += -nostartfiles -specs=nano.specs -lc -lm -lnosys
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef __IBEX_SYSTEM_H
|
||||
#define __IBEX_SYSTEM_H
|
||||
|
||||
void __enable_irqs(void);
|
||||
void __disable_irqs(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef __MAIN_H
|
||||
#define __MAIN_H
|
||||
|
||||
#include "soc_peripherals.h"
|
||||
|
||||
extern xilinx_uartlite_handle_t soc_uart;
|
||||
extern xilinx_gpio_handle_t soc_gpio;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef __SOC_PERIPHERALS_H
|
||||
#define __SOC_PERIPHERALS_H
|
||||
|
||||
#include "xilinx_uartlite.h"
|
||||
#include "xilinx_gpio.h"
|
||||
#include "xilinx_timer.h"
|
||||
|
||||
// Peripheral defines
|
||||
#define UART0_BASE 0x40010000
|
||||
#define GPIO0_BASE 0x40000000
|
||||
#define TIMER0_BASE 0x40020000
|
||||
|
||||
|
||||
// SoC config
|
||||
#define SYS_CLK_FREQ 48000000
|
||||
#define SYS_TICK_RATE 1000
|
||||
|
||||
// Peripherals
|
||||
extern __IO xilinx_uartlite_t *UART0;
|
||||
extern __IO xilinx_gpio_t *GPIO0;
|
||||
extern __IO xilinx_timer_t *TIMER0;
|
||||
|
||||
// SysTick
|
||||
extern volatile uint32_t SysTick;
|
||||
|
||||
static inline uint32_t GetTick() {
|
||||
return SysTick;
|
||||
}
|
||||
|
||||
static inline uint32_t GetCoreClock() {
|
||||
return SYS_CLK_FREQ;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef __XILINX_IP_DEFS_H
|
||||
#define __XILINX_IP_DEFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define __IO volatile
|
||||
|
||||
#define RET_OK 0
|
||||
#define RET_ERR 1
|
||||
|
||||
typedef int sys_ret_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef __XILINX_GPIO_H
|
||||
#define __XILINX_GPIO_H
|
||||
|
||||
#include "system_defs.h"
|
||||
|
||||
typedef struct {
|
||||
__IO uint32_t DATA;
|
||||
__IO uint32_t TRI;
|
||||
__IO uint32_t DATA2;
|
||||
__IO uint32_t TRI2;
|
||||
} xilinx_gpio_t;
|
||||
|
||||
typedef struct {
|
||||
__IO xilinx_gpio_t *instance;
|
||||
} xilinx_gpio_handle_t;
|
||||
|
||||
sys_ret_t xilinx_gpio_init(xilinx_gpio_handle_t *handle);
|
||||
sys_ret_t xilinx_gpio_pinmode(xilinx_gpio_handle_t *handle, uint32_t pin, uint8_t output);
|
||||
sys_ret_t xilinx_gpio_write(xilinx_gpio_handle_t *handle, uint32_t pin, uint8_t value);
|
||||
uint8_t xilinx_gpio_read(xilinx_gpio_handle_t *handle, uint32_t pin);
|
||||
sys_ret_t xilinx_gpio_toggle(xilinx_gpio_handle_t *handle, uint32_t pin);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef __XILINX_TIMER_H
|
||||
#define __XILINX_TIMER_H
|
||||
|
||||
#include "system_defs.h"
|
||||
|
||||
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;
|
||||
} xilinx_timer_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef __XILINX_UARTLITE_H
|
||||
#define __XILINX_UARTLITE_H
|
||||
|
||||
#include "system_defs.h"
|
||||
|
||||
typedef struct {
|
||||
__IO uint32_t RX_FIFO;
|
||||
__IO uint32_t TX_FIFO;
|
||||
__IO uint32_t STAT;
|
||||
__IO uint32_t CTRL;
|
||||
} xilinx_uartlite_t;
|
||||
|
||||
typedef struct {
|
||||
__IO xilinx_uartlite_t *instance;
|
||||
} xilinx_uartlite_handle_t;
|
||||
|
||||
sys_ret_t xilinx_uartlite_init(xilinx_uartlite_handle_t *handle);
|
||||
sys_ret_t xilinx_uartlite_send(xilinx_uartlite_handle_t *handle, uint8_t *data, uint32_t len);
|
||||
sys_ret_t xilinx_uartlite_receive(xilinx_uartlite_handle_t *handle, uint8_t *data, uint32_t len);
|
||||
|
||||
#endif
|
|
@ -64,6 +64,8 @@ SECTIONS
|
|||
_bss_start = _sbss;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(.sbss)
|
||||
*(.sbss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
|
@ -73,9 +75,10 @@ SECTIONS
|
|||
._heap_stack_space :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE(end = .);
|
||||
PROVIDE(_end = .);
|
||||
_heap_start = .;
|
||||
. = . + _minimum_heap_size;
|
||||
_heap_end = .;
|
||||
. = ALIGN(8);
|
||||
. = . + _minimum_stack_size;
|
||||
. = ALIGN(8);
|
||||
} >RW_DATA
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#include "xilinx_gpio.h"
|
||||
|
||||
sys_ret_t xilinx_gpio_init(xilinx_gpio_handle_t *handle) {
|
||||
handle->instance->TRI = 0xFFFFFFFF;
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
sys_ret_t xilinx_gpio_pinmode(xilinx_gpio_handle_t *handle, uint32_t pin, uint8_t output) {
|
||||
if(output) {
|
||||
handle->instance->TRI &= ~(1U << pin);
|
||||
}
|
||||
else {
|
||||
handle->instance->TRI |= (1U << pin);
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
sys_ret_t xilinx_gpio_write(xilinx_gpio_handle_t *handle, uint32_t pin, uint8_t value) {
|
||||
if(value) {
|
||||
handle->instance->DATA |= (1U << pin);
|
||||
}
|
||||
else {
|
||||
handle->instance->DATA &= ~(1U << pin);
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
uint8_t xilinx_gpio_read(xilinx_gpio_handle_t *handle, uint32_t pin) {
|
||||
return (handle->instance->DATA & (1U << pin)) ? 1 : 0;
|
||||
}
|
||||
|
||||
sys_ret_t xilinx_gpio_toggle(xilinx_gpio_handle_t *handle, uint32_t pin) {
|
||||
handle->instance->DATA ^= (1U << pin);
|
||||
return RET_OK;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
#include "xilinx_timer.h"
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#include "xilinx_uartlite.h"
|
||||
|
||||
sys_ret_t xilinx_uartlite_init(xilinx_uartlite_handle_t *handle) {
|
||||
handle->instance->CTRL |= 0x03; // Reset FIFO
|
||||
}
|
||||
|
||||
sys_ret_t xilinx_uartlite_send(xilinx_uartlite_handle_t *handle, uint8_t *data, uint32_t len) {
|
||||
for(uint32_t i = 0; i < len; i++) {
|
||||
while(handle->instance->STAT & (1U << 0x03) || !(handle->instance->STAT & (1U << 0x02))) { // Check if TX FIFO is full
|
||||
// TODO: Unless we figure out where systick should be.
|
||||
}
|
||||
handle->instance->TX_FIFO = data[i];
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
sys_ret_t xilinx_uartlite_receive(xilinx_uartlite_handle_t *handle, uint8_t *data, uint32_t len) {
|
||||
for(uint32_t i = 0; i < len; i++) {
|
||||
while(handle->instance->STAT & 0x01U == 0) { // Check if RX FIFO is empty
|
||||
// TODO: Unless we figure out where our systick should be.
|
||||
}
|
||||
data[i] = handle->instance->RX_FIFO & 0xFF;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "xilinx_ip_defs.h"
|
||||
#include "soc_peripherals.h"
|
||||
#include "xilinx_timer.h"
|
||||
|
||||
void Generic_ExceptionCallback(void) {
|
||||
for(;;) {
|
|
@ -0,0 +1,9 @@
|
|||
#include "ibex_system.h"
|
||||
|
||||
void __attribute__((naked)) __enable_irqs(void) {
|
||||
asm volatile("csrs mstatus, %0\n" : : "r"(0x8));
|
||||
}
|
||||
|
||||
void __attribute__((naked)) __disable_irqs(void) {
|
||||
asm volatile("csrc mstatus, %0\n" : : "r"(0x08));
|
||||
}
|
|
@ -1,14 +1,16 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "xilinx_ip_defs.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define DDR_BASE 0x1FC00000
|
||||
#define DDR_LENGTH 0x100
|
||||
|
||||
xilinx_uartlite_handle_t soc_uart;
|
||||
xilinx_gpio_handle_t soc_gpio;
|
||||
|
||||
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);
|
||||
|
@ -31,10 +33,13 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
uint32_t previous_tick = GetTick();
|
||||
|
||||
xilinx_gpio_pinmode(&soc_gpio, 1, 1);
|
||||
xilinx_gpio_write(&soc_gpio, 1, 0);
|
||||
|
||||
while(1) {
|
||||
if(GetTick() - previous_tick >= 500) {
|
||||
previous_tick = SysTick;
|
||||
GPIO0->DATA ^= 0x02;
|
||||
previous_tick = GetTick();
|
||||
xilinx_gpio_toggle(&soc_gpio, 1);
|
||||
printf("SysTick: %lu\r\n", GetTick());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#include "soc_peripherals.h"
|
||||
|
||||
__IO xilinx_uartlite_t *UART0 = (xilinx_uartlite_t *) UART0_BASE;
|
||||
__IO xilinx_gpio_t *GPIO0 = (xilinx_gpio_t *) GPIO0_BASE;
|
||||
__IO xilinx_timer_t *TIMER0 = (xilinx_timer_t *) TIMER0_BASE;
|
|
@ -0,0 +1,29 @@
|
|||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
extern int _heap_start;
|
||||
extern int _heap_end;
|
||||
static void *_old_heap = &_heap_start;
|
||||
|
||||
int _write(int handle, char *data, int size) {
|
||||
int count;
|
||||
handle = handle;
|
||||
xilinx_uartlite_send(&soc_uart, data, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
void *_sbrk(int nbytes) {
|
||||
char *_old = _old_heap;
|
||||
if(&_heap_start == &_heap_end) {
|
||||
errno = -ENOMEM;
|
||||
return (void *)-1;
|
||||
}
|
||||
if((_old + nbytes) < (char *)&_heap_end) {
|
||||
_old += nbytes;
|
||||
} else {
|
||||
errno = -ENOMEM;
|
||||
return (void *)-1;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,15 @@
|
|||
#include "xilinx_ip_defs.h"
|
||||
#include "xilinx_timer.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
__IO uint32_t SysTick;
|
||||
|
||||
void System_Init(void) {
|
||||
// Clear UARTLite FIFOs
|
||||
UART0->CTRL = 0x03;
|
||||
soc_uart.instance = UART0;
|
||||
xilinx_uartlite_init(&soc_uart);
|
||||
|
||||
soc_gpio.instance = GPIO0;
|
||||
xilinx_gpio_init(&soc_gpio);
|
||||
|
||||
SysTick = 0;
|
||||
|
|
@ -54,7 +54,7 @@ copy_data:
|
|||
addi x25, x25, 4
|
||||
addi x26, x26, 4
|
||||
|
||||
ble x26, x27, copy_data
|
||||
blt x26, x27, copy_data
|
||||
|
||||
copy_data_end:
|
||||
|
||||
|
@ -67,7 +67,7 @@ copy_data_end:
|
|||
zero_bss:
|
||||
sw x0, 0(x26)
|
||||
addi x26, x26, 4
|
||||
ble x26, x27, zero_bss
|
||||
blt x26, x27, zero_bss
|
||||
|
||||
zero_bss_end:
|
||||
jal x1, System_Init
|
||||
|
|
20
syscalls.c
20
syscalls.c
|
@ -1,20 +0,0 @@
|
|||
#include <stdint.h>
|
||||
#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;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
#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;
|
|
@ -1,53 +0,0 @@
|
|||
#ifndef __XILINX_IP_DEFS_H
|
||||
#define __XILINX_IP_DEFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
Loading…
Reference in New Issue