Refactored structure, implemented UARTLite and GPIO driver.

This commit is contained in:
imi415 2020-05-31 15:49:49 +08:00
parent edb5181e64
commit 8b4c7855cc
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
22 changed files with 268 additions and 97 deletions

View File

@ -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

7
include/ibex_system.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef __IBEX_SYSTEM_H
#define __IBEX_SYSTEM_H
void __enable_irqs(void);
void __disable_irqs(void);
#endif

9
include/main.h Normal file
View File

@ -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

34
include/soc_peripherals.h Normal file
View File

@ -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

13
include/system_defs.h Normal file
View File

@ -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

23
include/xilinx_gpio.h Normal file
View File

@ -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

16
include/xilinx_timer.h Normal file
View File

@ -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

21
include/xilinx_uartlite.h Normal file
View File

@ -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

View File

@ -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

35
src/drivers/xilinx_gpio.c Normal file
View File

@ -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;
}

View File

@ -0,0 +1,2 @@
#include "xilinx_timer.h"

View File

@ -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;
}

View File

@ -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(;;) {

9
src/ibex_system.c Normal file
View File

@ -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));
}

View File

@ -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());
}
}

5
src/soc_peripherals.c Normal file
View File

@ -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;

29
src/syscalls.c Normal file
View File

@ -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;
}
}

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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