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
|
BUILD_DIR = build
|
||||||
|
|
||||||
C_SOURCES = \
|
C_SOURCES = \
|
||||||
system_handlers.c \
|
src/drivers/xilinx_gpio.c \
|
||||||
system_peripherals.c \
|
src/drivers/xilinx_uartlite.c \
|
||||||
system_init.c \
|
src/drivers/xilinx_timer.c \
|
||||||
syscalls.c \
|
src/ibex_it.c \
|
||||||
main.c
|
src/ibex_system.c \
|
||||||
|
src/soc_peripherals.c \
|
||||||
|
src/system_init.c \
|
||||||
|
src/syscalls.c \
|
||||||
|
src/main.c
|
||||||
|
|
||||||
|
INCLUDES = \
|
||||||
|
-Iinclude
|
||||||
|
|
||||||
ASM_SOURCES = \
|
ASM_SOURCES = \
|
||||||
startup.s
|
startup.s
|
||||||
|
@ -22,7 +29,7 @@ SZ = /home/imi415/Softwares/Arch/RISC-V/toolchains/rv32imc/bin/riscv32-unknown-e
|
||||||
HEX = $(CP) -O ihex
|
HEX = $(CP) -O ihex
|
||||||
BIN = $(CP) -O binary
|
BIN = $(CP) -O binary
|
||||||
|
|
||||||
CFLAGS += -mabi=ilp32 -march=rv32imc -g
|
CFLAGS += -mabi=ilp32 -march=rv32imc -g $(INCLUDES)
|
||||||
ASFLAGS += -mabi=ilp32 -march=rv32imc -g
|
ASFLAGS += -mabi=ilp32 -march=rv32imc -g
|
||||||
LDFLAGS += -nostartfiles -specs=nano.specs -lc -lm -lnosys
|
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_start = _sbss;
|
||||||
*(.bss)
|
*(.bss)
|
||||||
*(.bss*)
|
*(.bss*)
|
||||||
|
*(.sbss)
|
||||||
|
*(.sbss*)
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_ebss = .;
|
_ebss = .;
|
||||||
|
@ -73,9 +75,10 @@ SECTIONS
|
||||||
._heap_stack_space :
|
._heap_stack_space :
|
||||||
{
|
{
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
PROVIDE(end = .);
|
_heap_start = .;
|
||||||
PROVIDE(_end = .);
|
|
||||||
. = . + _minimum_heap_size;
|
. = . + _minimum_heap_size;
|
||||||
|
_heap_end = .;
|
||||||
|
. = ALIGN(8);
|
||||||
. = . + _minimum_stack_size;
|
. = . + _minimum_stack_size;
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
} >RW_DATA
|
} >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 <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "xilinx_ip_defs.h"
|
#include "soc_peripherals.h"
|
||||||
|
#include "xilinx_timer.h"
|
||||||
|
|
||||||
void Generic_ExceptionCallback(void) {
|
void Generic_ExceptionCallback(void) {
|
||||||
for(;;) {
|
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 <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "xilinx_ip_defs.h"
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
#define DDR_BASE 0x1FC00000
|
#define DDR_BASE 0x1FC00000
|
||||||
#define DDR_LENGTH 0x100
|
#define DDR_LENGTH 0x100
|
||||||
|
|
||||||
|
xilinx_uartlite_handle_t soc_uart;
|
||||||
|
xilinx_gpio_handle_t soc_gpio;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
GPIO0->TRI = 0xFFFFFFFD;
|
|
||||||
GPIO0->DATA = 0x00;
|
|
||||||
printf("Dumping first 256 bytes of DDR memory...\r\n");
|
printf("Dumping first 256 bytes of DDR memory...\r\n");
|
||||||
for(uint32_t i = DDR_BASE; i < DDR_BASE + DDR_LENGTH; i++) {
|
for(uint32_t i = DDR_BASE; i < DDR_BASE + DDR_LENGTH; i++) {
|
||||||
printf("%02x ", *(uint8_t *)i);
|
printf("%02x ", *(uint8_t *)i);
|
||||||
|
@ -31,10 +33,13 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
uint32_t previous_tick = GetTick();
|
uint32_t previous_tick = GetTick();
|
||||||
|
|
||||||
|
xilinx_gpio_pinmode(&soc_gpio, 1, 1);
|
||||||
|
xilinx_gpio_write(&soc_gpio, 1, 0);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if(GetTick() - previous_tick >= 500) {
|
if(GetTick() - previous_tick >= 500) {
|
||||||
previous_tick = SysTick;
|
previous_tick = GetTick();
|
||||||
GPIO0->DATA ^= 0x02;
|
xilinx_gpio_toggle(&soc_gpio, 1);
|
||||||
printf("SysTick: %lu\r\n", GetTick());
|
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;
|
__IO uint32_t SysTick;
|
||||||
|
|
||||||
void System_Init(void) {
|
void System_Init(void) {
|
||||||
// Clear UARTLite FIFOs
|
soc_uart.instance = UART0;
|
||||||
UART0->CTRL = 0x03;
|
xilinx_uartlite_init(&soc_uart);
|
||||||
|
|
||||||
|
soc_gpio.instance = GPIO0;
|
||||||
|
xilinx_gpio_init(&soc_gpio);
|
||||||
|
|
||||||
SysTick = 0;
|
SysTick = 0;
|
||||||
|
|
|
@ -54,7 +54,7 @@ copy_data:
|
||||||
addi x25, x25, 4
|
addi x25, x25, 4
|
||||||
addi x26, x26, 4
|
addi x26, x26, 4
|
||||||
|
|
||||||
ble x26, x27, copy_data
|
blt x26, x27, copy_data
|
||||||
|
|
||||||
copy_data_end:
|
copy_data_end:
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ copy_data_end:
|
||||||
zero_bss:
|
zero_bss:
|
||||||
sw x0, 0(x26)
|
sw x0, 0(x26)
|
||||||
addi x26, x26, 4
|
addi x26, x26, 4
|
||||||
ble x26, x27, zero_bss
|
blt x26, x27, zero_bss
|
||||||
|
|
||||||
zero_bss_end:
|
zero_bss_end:
|
||||||
jal x1, System_Init
|
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