Added test firmware for zynq
Signed-off-by: Joppe Blondel <joppe@blondel.nl>
This commit is contained in:
2
examples/zynq7000/SW/.gitignore
vendored
Normal file
2
examples/zynq7000/SW/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
build
|
||||||
|
DISASS
|
67
examples/zynq7000/SW/Makefile
Normal file
67
examples/zynq7000/SW/Makefile
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
.SILENT:
|
||||||
|
|
||||||
|
TARGET := app.elf
|
||||||
|
|
||||||
|
BUILDDIR := build
|
||||||
|
|
||||||
|
SRCDIRS := src
|
||||||
|
SRCFILESC := $(shell find $(SRCDIRS) -type f -name "*.c")
|
||||||
|
OBJFILESC := $(SRCFILESC:%.c=$(BUILDDIR)/%.c.o) $(BUILDDIR)/src/ps7_init.o
|
||||||
|
DEPFILESC := $(SRCFILESC:%.c=$(BUILDDIR)/%.c.d)
|
||||||
|
SRCFILESA := $(shell find $(SRCDIRS) -type f -name "*.S")
|
||||||
|
OBJFILESA := $(SRCFILESA:%.S=$(BUILDDIR)/%.S.o)
|
||||||
|
DEPFILESA := $(SRCFILESA:%.S=$(BUILDDIR)/%.S.d)
|
||||||
|
SRCFILES := $(SRCFILESC) $(SRCFILESA)
|
||||||
|
OBJFILES := $(OBJFILESA) $(OBJFILESC)
|
||||||
|
DEPFILES := $(DEPFILESC) $(DEPFILESA)
|
||||||
|
|
||||||
|
FILESTOCLEAN := $(OBJFILES) $(DEPFILES) $(BUILDDIR)/$(TARGET)
|
||||||
|
|
||||||
|
CROSS_COMPILE ?= arm-none-eabi-
|
||||||
|
CC := $(CROSS_COMPILE)gcc
|
||||||
|
AS := $(CROSS_COMPILE)as
|
||||||
|
LD := $(CROSS_COMPILE)gcc
|
||||||
|
|
||||||
|
CC_WARNING := -Wall -Wextra
|
||||||
|
CC_LIBS := -lgcc
|
||||||
|
CC_FLAGS := -nostdlib -fno-builtin -g -mcpu=cortex-a9
|
||||||
|
CC_INCLUDES := -I src -I ../OUT/ip/zynqps
|
||||||
|
LD_FLAGS := -Wl,-Tlinker.ld
|
||||||
|
|
||||||
|
.PHONY: $(TARGET) all clean
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
# PHONY RULES
|
||||||
|
# -----------
|
||||||
|
|
||||||
|
$(TARGET): $(BUILDDIR)/$(TARGET)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
echo CLEAN FILES FOR $(TARGET)
|
||||||
|
-rm -r $(FILESTOCLEAN)
|
||||||
|
|
||||||
|
# SPECIFIC BUILD RULES
|
||||||
|
# --------------------
|
||||||
|
|
||||||
|
$(BUILDDIR)/$(TARGET): $(OBJFILES)
|
||||||
|
echo 'LD ' $@
|
||||||
|
$(LD) $(CC_FLAGS) $(LD_FLAGS) -o $(BUILDDIR)/$(TARGET) $(OBJFILES) $(CC_LIBS)
|
||||||
|
$(XILINX_BASE)/bin/$(CROSS_COMPILE)objdump -D $(BUILDDIR)/$(TARGET) > DISASS
|
||||||
|
|
||||||
|
$(BUILDDIR)/src/ps7_init.o : ../OUT/ip/zynqps/ps7_init.c ../OUT/ip/zynqps/ps7_init.h
|
||||||
|
echo 'CC ' $@
|
||||||
|
-mkdir -p $(shell dirname $@)
|
||||||
|
$(CC) $(CC_FLAGS) $(CC_WARNING) $(CC_INCLUDES) -MD -o $(BUILDDIR)/src/ps7_init.o -c ../OUT/ip/zynqps/ps7_init.c
|
||||||
|
|
||||||
|
$(OBJFILES): $(BUILDDIR)/%.c.o: %.c
|
||||||
|
echo 'CC ' $@
|
||||||
|
-mkdir -p $(shell dirname $@)
|
||||||
|
$(CC) $(CC_FLAGS) $(CC_WARNING) $(CC_INCLUDES) -MD -o $@ -c $<
|
||||||
|
|
||||||
|
$(OBJFILESA): $(BUILDDIR)/%.S.o: %.S
|
||||||
|
echo 'AS ' $@
|
||||||
|
-mkdir -p $(shell dirname $@)
|
||||||
|
$(CC) $(CC_FLAGS) $(CC_WARNING) $(CC_INCLUDES) -MD -o $@ -c $<
|
||||||
|
|
||||||
|
# Add DEPFILE dependencies
|
||||||
|
-include $(DEPFILES)
|
89
examples/zynq7000/SW/linker.ld
Normal file
89
examples/zynq7000/SW/linker.ld
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
OUTPUT_FORMAT ("elf32-littlearm")
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
SRAM_0 : ORIGIN = 0x00000000, LENGTH = 0x00030000 /* 192k */
|
||||||
|
SRAM_1 : ORIGIN = 0xFFFF0000, LENGTH = 0x00010000 /* 64k */
|
||||||
|
DDR_PS : ORIGIN = 0x00100000, LENGTH = 0x0FF00000 /* 256M */
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN(__stack_size);
|
||||||
|
ASSERT(__stack_size, "Must provide a non-zero stack size");
|
||||||
|
|
||||||
|
EXTERN(_start);
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
__stext = .;
|
||||||
|
*(.vectortable) /* Vector table */
|
||||||
|
*(.text .text.*) /* Standard Code */
|
||||||
|
*(.rodata .rodata.*) /* Constants, strings, ... */
|
||||||
|
*(.glue_7) /* Glue ARM to thumb code */
|
||||||
|
*(.glue_7t) /* Glue thumb to ARM code */
|
||||||
|
__etext = .;
|
||||||
|
} >DDR_PS
|
||||||
|
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
__sdata = .;
|
||||||
|
*(.data .data.*)
|
||||||
|
__edata = .;
|
||||||
|
|
||||||
|
} >DDR_PS
|
||||||
|
|
||||||
|
.bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
__bss_start__ = .; /* Used for zeroing bss on startup */
|
||||||
|
*(.bss .bss.*)
|
||||||
|
__bss_end__ = .;
|
||||||
|
} >DDR_PS
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
end = .;
|
||||||
|
|
||||||
|
/* Place all stacks in SRAM_1 - need to avoid filling addresses */
|
||||||
|
/* 0xfffffe00 to 0xfffffff0 - proc1 is halted running code in this range */
|
||||||
|
/* TODO: assert stacks do not step on proc1's code out of reset */
|
||||||
|
.stack (NOLOAD) :
|
||||||
|
{
|
||||||
|
. += __stack_size;
|
||||||
|
__proc0_irq_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
__proc0_fiq_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
__proc0_svc_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
__proc0_abt_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
__proc0_und_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
__proc0_sys_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
__proc1_irq_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
__proc1_fiq_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
__proc1_svc_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
__proc1_abt_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
__proc1_und_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
__proc1_sys_stack = .;
|
||||||
|
. += __stack_size;
|
||||||
|
} >SRAM_1
|
||||||
|
|
||||||
|
.data.ddr :
|
||||||
|
{
|
||||||
|
*(.data_in_ddr)
|
||||||
|
} >DDR_PS
|
||||||
|
|
||||||
|
.note.gnu.build-id : {
|
||||||
|
KEEP (*(.note.gnu.build-id))
|
||||||
|
} >DDR_PS
|
||||||
|
}
|
87
examples/zynq7000/SW/src/boot.S
Normal file
87
examples/zynq7000/SW/src/boot.S
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
.syntax unified /* Use the unified instruction syntax */
|
||||||
|
.arm /* Assemble ARM instruction set, not thumb */
|
||||||
|
|
||||||
|
.equ PROC1_RESET_VECTOR_TABLE, 0xFFFFFFF0
|
||||||
|
|
||||||
|
.equ CPSR_MODE_USER, 0x10
|
||||||
|
.equ CPSR_MODE_FIQ, 0x11
|
||||||
|
.equ CPSR_MODE_IRQ, 0x12
|
||||||
|
.equ CPSR_MODE_SVC, 0x13
|
||||||
|
.equ CPSR_MODE_ABORT, 0x17
|
||||||
|
.equ CPSR_MODE_UNDEFINED, 0x8B
|
||||||
|
.equ CPSR_MODE_SYSTEM, 0x1F
|
||||||
|
|
||||||
|
.equ CPSR_IRQ, 0x80 /* disable IRQ interrupts */
|
||||||
|
.equ CPSR_FIQ, 0x40 /* disable FIQ interrupts */
|
||||||
|
|
||||||
|
.global __stack_size
|
||||||
|
.equ __stack_size, 0x1000
|
||||||
|
|
||||||
|
// ------------------
|
||||||
|
.section .vectortable
|
||||||
|
// ------------------
|
||||||
|
.global vectortable
|
||||||
|
vectortable:
|
||||||
|
/* Exception Processor Mode Event Return Sequence */
|
||||||
|
b reset_handler /* MODE_SVC System Reset n/a */
|
||||||
|
b undef_handler /* MODE_UNDEFINED Undefined Instruction MOVS PC, LR (if emulating) */
|
||||||
|
b SVC_handler /* MODE_SVC SVC instruction MOVS PC, LR */
|
||||||
|
b prefetch_abort_handler /* MODE_ABORT Invalid inst. address SUBS PC, LR, #4 */
|
||||||
|
b data_abort_handler /* MODE_ABORT R/W to invalid address SUBS PC, LR, #8 (to retry) */
|
||||||
|
b hypervisor_handler /* MODE_HYP Hypervisor entry ERET */
|
||||||
|
b IRQ_handler /* MODE_IRQ IRQ Input Asserted SUBS PC, LR, #4 */
|
||||||
|
b FIQ_handler /* MODE_FIQ FIQ Input Asserted SUBS PC, LR, #4 */
|
||||||
|
|
||||||
|
reset_handler:
|
||||||
|
b _start
|
||||||
|
|
||||||
|
undef_handler:
|
||||||
|
b .
|
||||||
|
|
||||||
|
SVC_handler:
|
||||||
|
b .
|
||||||
|
|
||||||
|
prefetch_abort_handler:
|
||||||
|
b .
|
||||||
|
|
||||||
|
data_abort_handler:
|
||||||
|
b .
|
||||||
|
|
||||||
|
hypervisor_handler:
|
||||||
|
b .
|
||||||
|
|
||||||
|
IRQ_handler:
|
||||||
|
b .
|
||||||
|
|
||||||
|
FIQ_handler:
|
||||||
|
b .
|
||||||
|
|
||||||
|
// -----------
|
||||||
|
.section .text
|
||||||
|
// -----------
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_IRQ) /* switch to MODE_IRQ */
|
||||||
|
ldr sp, =__proc0_irq_stack /* load IRQ mode stack pointer */
|
||||||
|
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_FIQ) /* switch to MODE_FIQ */
|
||||||
|
ldr sp, =__proc0_fiq_stack /* load FIQ mode stack pointer */
|
||||||
|
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_ABORT) /* switch to MODE_ABT */
|
||||||
|
ldr sp, =__proc0_abt_stack /* load ABT mode stack pointer */
|
||||||
|
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_UNDEFINED) /* switch to MODE_UND */
|
||||||
|
ldr sp, =__proc0_und_stack /* load UND mode stack pointer */
|
||||||
|
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_SYSTEM) /* switch to MODE_SYS */
|
||||||
|
ldr sp, =__proc0_sys_stack /* load SYS mode stack pointer */
|
||||||
|
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_SVC) /* switch to MODE_SVC */
|
||||||
|
ldr sp, =__proc0_svc_stack /* load SVC mode stack pointer */
|
||||||
|
/* We are now in SVC mode */
|
||||||
|
|
||||||
|
/* Set vector table base address */
|
||||||
|
ldr r0, =vectortable
|
||||||
|
mcr p15, #0, r0, c12, c0, #0
|
||||||
|
|
||||||
|
b main
|
||||||
|
|
||||||
|
_hang:
|
||||||
|
b _hang
|
||||||
|
|
||||||
|
.end
|
15
examples/zynq7000/SW/src/main.c
Normal file
15
examples/zynq7000/SW/src/main.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "ps7_init.h"
|
||||||
|
#include "zynq.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "printf.h"
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
cpu_disable_interrups();
|
||||||
|
// Initialize ZYNQ Processing System
|
||||||
|
ps7_init();
|
||||||
|
// Start UART
|
||||||
|
uart_setup();
|
||||||
|
|
||||||
|
printf("Hello World!\n");
|
||||||
|
|
||||||
|
}
|
452
examples/zynq7000/SW/src/printf.c
Normal file
452
examples/zynq7000/SW/src/printf.c
Normal file
@ -0,0 +1,452 @@
|
|||||||
|
#include "printf.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
#define NULL 0
|
||||||
|
|
||||||
|
extern int putchar(int c);
|
||||||
|
static void print_double_float(double val, unsigned int precision);
|
||||||
|
|
||||||
|
static void simple_outputchar(char **str, char c)
|
||||||
|
{
|
||||||
|
if (str) {
|
||||||
|
**str = c;
|
||||||
|
++(*str);
|
||||||
|
} else {
|
||||||
|
uart_send(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum flags {
|
||||||
|
PAD_ZERO = 1,
|
||||||
|
PAD_RIGHT = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int prints(char **out, const char *string, int width, int flags)
|
||||||
|
{
|
||||||
|
int pc = 0, padchar = ' ';
|
||||||
|
|
||||||
|
if (width > 0) {
|
||||||
|
int len = 0;
|
||||||
|
const char *ptr;
|
||||||
|
for (ptr = string; *ptr; ++ptr) ++len;
|
||||||
|
if (len >= width) width = 0;
|
||||||
|
else width -= len;
|
||||||
|
if (flags & PAD_ZERO)
|
||||||
|
padchar = '0';
|
||||||
|
}
|
||||||
|
if (!(flags & PAD_RIGHT)) {
|
||||||
|
for ( ; width > 0; --width) {
|
||||||
|
simple_outputchar(out, padchar);
|
||||||
|
++pc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ( ; *string ; ++string) {
|
||||||
|
simple_outputchar(out, *string);
|
||||||
|
++pc;
|
||||||
|
}
|
||||||
|
for ( ; width > 0; --width) {
|
||||||
|
simple_outputchar(out, padchar);
|
||||||
|
++pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRINT_BUF_LEN 64
|
||||||
|
|
||||||
|
static int simple_outputi(char **out, long long i, int base, int sign, int width, int flags, int letbase)
|
||||||
|
{
|
||||||
|
char print_buf[PRINT_BUF_LEN];
|
||||||
|
char *s;
|
||||||
|
int t, neg = 0, pc = 0;
|
||||||
|
unsigned long long u = i;
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
print_buf[0] = '0';
|
||||||
|
print_buf[1] = '\0';
|
||||||
|
return prints(out, print_buf, width, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sign && base == 10 && i < 0) {
|
||||||
|
neg = 1;
|
||||||
|
u = -i;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = print_buf + PRINT_BUF_LEN-1;
|
||||||
|
*s = '\0';
|
||||||
|
|
||||||
|
while (u) {
|
||||||
|
t = u % base;
|
||||||
|
if( t >= 10 )
|
||||||
|
t += letbase - '0' - 10;
|
||||||
|
*--s = t + '0';
|
||||||
|
u /= base;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (neg) {
|
||||||
|
if( width && (flags & PAD_ZERO) ) {
|
||||||
|
simple_outputchar (out, '-');
|
||||||
|
++pc;
|
||||||
|
--width;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*--s = '-';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pc + prints (out, s, width, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int simple_vsprintf(char **out, char *format, va_list ap)
|
||||||
|
{
|
||||||
|
int width, flags;
|
||||||
|
int pc = 0;
|
||||||
|
char scr[2];
|
||||||
|
union {
|
||||||
|
char c;
|
||||||
|
char *s;
|
||||||
|
int i;
|
||||||
|
unsigned int u;
|
||||||
|
long li;
|
||||||
|
unsigned long lu;
|
||||||
|
long long lli;
|
||||||
|
unsigned long long llu;
|
||||||
|
short hi;
|
||||||
|
unsigned short hu;
|
||||||
|
signed char hhi;
|
||||||
|
unsigned char hhu;
|
||||||
|
void *p;
|
||||||
|
double d;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
for (; *format != 0; ++format) {
|
||||||
|
if (*format == '%') {
|
||||||
|
++format;
|
||||||
|
width = flags = 0;
|
||||||
|
if (*format == '\0')
|
||||||
|
break;
|
||||||
|
if (*format == '%')
|
||||||
|
goto out;
|
||||||
|
if (*format == '-') {
|
||||||
|
++format;
|
||||||
|
flags = PAD_RIGHT;
|
||||||
|
}
|
||||||
|
while (*format == '0') {
|
||||||
|
++format;
|
||||||
|
flags |= PAD_ZERO;
|
||||||
|
}
|
||||||
|
if (*format == '*') {
|
||||||
|
width = va_arg(ap, int);
|
||||||
|
format++;
|
||||||
|
} else {
|
||||||
|
for ( ; *format >= '0' && *format <= '9'; ++format) {
|
||||||
|
width *= 10;
|
||||||
|
width += *format - '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (*format) {
|
||||||
|
case('d'):
|
||||||
|
u.i = va_arg(ap, int);
|
||||||
|
pc += simple_outputi(out, u.i, 10, 1, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('u'):
|
||||||
|
u.u = va_arg(ap, unsigned int);
|
||||||
|
pc += simple_outputi(out, u.u, 10, 0, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('x'):
|
||||||
|
u.u = va_arg(ap, unsigned int);
|
||||||
|
pc += simple_outputi(out, u.u, 16, 0, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('X'):
|
||||||
|
u.u = va_arg(ap, unsigned int);
|
||||||
|
pc += simple_outputi(out, u.u, 16, 0, width, flags, 'A');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('c'):
|
||||||
|
u.c = va_arg(ap, int);
|
||||||
|
scr[0] = u.c;
|
||||||
|
scr[1] = '\0';
|
||||||
|
pc += prints(out, scr, width, flags);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('f'):
|
||||||
|
u.d = va_arg(ap, double);
|
||||||
|
print_double_float(u.d, width);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('s'):
|
||||||
|
u.s = va_arg(ap, char *);
|
||||||
|
pc += prints(out, u.s ? u.s : "(null)", width, flags);
|
||||||
|
break;
|
||||||
|
case('l'):
|
||||||
|
++format;
|
||||||
|
switch (*format) {
|
||||||
|
case('d'):
|
||||||
|
u.li = va_arg(ap, long);
|
||||||
|
pc += simple_outputi(out, u.li, 10, 1, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('u'):
|
||||||
|
u.lu = va_arg(ap, unsigned long);
|
||||||
|
pc += simple_outputi(out, u.lu, 10, 0, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('x'):
|
||||||
|
u.lu = va_arg(ap, unsigned long);
|
||||||
|
pc += simple_outputi(out, u.lu, 16, 0, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('X'):
|
||||||
|
u.lu = va_arg(ap, unsigned long);
|
||||||
|
pc += simple_outputi(out, u.lu, 16, 0, width, flags, 'A');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('l'):
|
||||||
|
++format;
|
||||||
|
switch (*format) {
|
||||||
|
case('d'):
|
||||||
|
u.lli = va_arg(ap, long long);
|
||||||
|
pc += simple_outputi(out, u.lli, 10, 1, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('u'):
|
||||||
|
u.llu = va_arg(ap, unsigned long long);
|
||||||
|
pc += simple_outputi(out, u.llu, 10, 0, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('x'):
|
||||||
|
u.llu = va_arg(ap, unsigned long long);
|
||||||
|
pc += simple_outputi(out, u.llu, 16, 0, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('X'):
|
||||||
|
u.llu = va_arg(ap, unsigned long long);
|
||||||
|
pc += simple_outputi(out, u.llu, 16, 0, width, flags, 'A');
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case('h'):
|
||||||
|
++format;
|
||||||
|
switch (*format) {
|
||||||
|
case('d'):
|
||||||
|
u.hi = va_arg(ap, int);
|
||||||
|
pc += simple_outputi(out, u.hi, 10, 1, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('u'):
|
||||||
|
u.hu = va_arg(ap, unsigned int);
|
||||||
|
pc += simple_outputi(out, u.lli, 10, 0, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('x'):
|
||||||
|
u.hu = va_arg(ap, unsigned int);
|
||||||
|
pc += simple_outputi(out, u.lli, 16, 0, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('X'):
|
||||||
|
u.hu = va_arg(ap, unsigned int);
|
||||||
|
pc += simple_outputi(out, u.lli, 16, 0, width, flags, 'A');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('h'):
|
||||||
|
++format;
|
||||||
|
switch (*format) {
|
||||||
|
case('d'):
|
||||||
|
u.hhi = va_arg(ap, int);
|
||||||
|
pc += simple_outputi(out, u.hhi, 10, 1, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('u'):
|
||||||
|
u.hhu = va_arg(ap, unsigned int);
|
||||||
|
pc += simple_outputi(out, u.lli, 10, 0, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('x'):
|
||||||
|
u.hhu = va_arg(ap, unsigned int);
|
||||||
|
pc += simple_outputi(out, u.lli, 16, 0, width, flags, 'a');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case('X'):
|
||||||
|
u.hhu = va_arg(ap, unsigned int);
|
||||||
|
pc += simple_outputi(out, u.lli, 16, 0, width, flags, 'A');
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out:
|
||||||
|
simple_outputchar (out, *format);
|
||||||
|
++pc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (out) **out = '\0';
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int printf(char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
r = simple_vsprintf(NULL, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sprintf(char *buf, char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
r = simple_vsprintf(&buf, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hexDump (const char * desc, const void * addr, const int len) {
|
||||||
|
int i;
|
||||||
|
unsigned char buff[17];
|
||||||
|
const unsigned char * pc = (const unsigned char *)addr;
|
||||||
|
|
||||||
|
// Output description if given.
|
||||||
|
|
||||||
|
if (desc != NULL)
|
||||||
|
printf ("%s:\n", desc);
|
||||||
|
|
||||||
|
// Length checks.
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
printf(" ZERO LENGTH\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (len < 0) {
|
||||||
|
printf(" NEGATIVE LENGTH: %d\n", len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process every byte in the data.
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
// Multiple of 16 means new line (with line offset).
|
||||||
|
|
||||||
|
if ((i % 16) == 0) {
|
||||||
|
// Don't print ASCII buffer for the "zeroth" line.
|
||||||
|
|
||||||
|
if (i != 0)
|
||||||
|
printf (" %s\n", buff);
|
||||||
|
|
||||||
|
// Output the offset.
|
||||||
|
|
||||||
|
printf (" %04x ", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now the hex code for the specific character.
|
||||||
|
printf (" %02x", pc[i]);
|
||||||
|
|
||||||
|
// And buffer a printable ASCII character for later.
|
||||||
|
|
||||||
|
if ((pc[i] < 0x20) || (pc[i] > 0x7e)) // isprint() may be better.
|
||||||
|
buff[i % 16] = '.';
|
||||||
|
else
|
||||||
|
buff[i % 16] = pc[i];
|
||||||
|
buff[(i % 16) + 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pad out last line if not exactly 16 characters.
|
||||||
|
|
||||||
|
while ((i % 16) != 0) {
|
||||||
|
printf (" ");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// And print the final ASCII buffer.
|
||||||
|
|
||||||
|
printf (" %s\n", buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_PRECISION 50
|
||||||
|
|
||||||
|
#define IsNaN(n) (n != n)
|
||||||
|
|
||||||
|
// %f: double/single precision support (double or promoted float, 64-bits)
|
||||||
|
static void print_double_float(double val, unsigned int precision)
|
||||||
|
{
|
||||||
|
unsigned int cur_prec = 1;
|
||||||
|
if(precision==0)
|
||||||
|
precision = MAX_PRECISION;
|
||||||
|
|
||||||
|
// if the user-defined precision is out-of-bounds, normalize it
|
||||||
|
if(precision > MAX_PRECISION)
|
||||||
|
precision = MAX_PRECISION;
|
||||||
|
|
||||||
|
// if it's negative, show it!
|
||||||
|
if(val < 0)
|
||||||
|
{
|
||||||
|
printf("-");
|
||||||
|
|
||||||
|
// change to a positive value
|
||||||
|
val = -val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check to see if it is Not-a-Number
|
||||||
|
if(IsNaN(val))
|
||||||
|
{
|
||||||
|
printf("NaN");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the integer part of the floating point
|
||||||
|
printf("%d", (int)val);
|
||||||
|
|
||||||
|
// if precision == 0, only print the integer part
|
||||||
|
if(!precision)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// now on to the decimal potion
|
||||||
|
printf(".");
|
||||||
|
|
||||||
|
// remove the integer part
|
||||||
|
val -= (double)((int)val);
|
||||||
|
|
||||||
|
/* on every iteration, make sure there are still decimal places left that are non-zero,
|
||||||
|
and make sure we're still within the user-defined precision range. */
|
||||||
|
while(val > (double)((int)val) && cur_prec++ < precision+1)
|
||||||
|
{
|
||||||
|
// move the next decimal into the integer portion and print it
|
||||||
|
val *= 10;
|
||||||
|
printf("%d", (int)val);
|
||||||
|
|
||||||
|
/* if the value is == the floored value (integer portion),
|
||||||
|
then there are no more decimal places that are non-zero. */
|
||||||
|
if(val == (double)((int)val))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// subtract the integer portion
|
||||||
|
val -= (double)((int)val);
|
||||||
|
}
|
||||||
|
}
|
11
examples/zynq7000/SW/src/printf.h
Normal file
11
examples/zynq7000/SW/src/printf.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef __H_KPRINTF
|
||||||
|
#define __H_KPRINTF 1
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
int printf(char * fmt, ...);
|
||||||
|
int sprintf(char * buf, char * fmt, ...);
|
||||||
|
|
||||||
|
void hexDump (const char * desc, const void * addr, const int len);
|
||||||
|
|
||||||
|
#endif
|
105
examples/zynq7000/SW/src/uart.c
Normal file
105
examples/zynq7000/SW/src/uart.c
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#include "uart.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
#define XUARTPS_CR_TXRST 0x00000002U /**< TX logic reset */
|
||||||
|
#define XUARTPS_CR_RXRST 0x00000001U /**< RX logic reset */
|
||||||
|
|
||||||
|
#define XUARTPS_CR_OFFSET 0x0000U /**< Control Register [8:0] */
|
||||||
|
#define XUARTPS_MR_OFFSET 0x0004U /**< Mode Register [9:0] */
|
||||||
|
#define XUARTPS_BAUDGEN_OFFSET 0x0018U /**< Baud Rate Generator [15:0] */
|
||||||
|
#define XUARTPS_BAUDDIV_OFFSET 0x0034U /**< Baud Rate Divider [7:0] */
|
||||||
|
#define XUARTPS_FIFO_OFFSET 0x0030U /**< FIFO [7:0] */
|
||||||
|
#define XUARTPS_SR_OFFSET 0x002CU /**< Channel Status [14:0] */
|
||||||
|
#define XPS_UART1_BASEADDR 0xE0001000U
|
||||||
|
|
||||||
|
#define XUARTPS_MR_CHMODE_NORM 0x00000000U /**< Normal mode */
|
||||||
|
#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000U /**< 1 stop bit */
|
||||||
|
#define XUARTPS_MR_PARITY_NONE 0x00000020U /**< No parity mode */
|
||||||
|
#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000U /**< 8 bits data */
|
||||||
|
#define XUARTPS_MR_CLKSEL 0x00000001U /**< Input clock selection */
|
||||||
|
|
||||||
|
#define XUARTPS_SR_TNFUL 0x00004000U /**< TX FIFO Nearly Full Status */
|
||||||
|
#define XUARTPS_SR_TACTIVE 0x00000800U /**< TX active */
|
||||||
|
#define XUARTPS_SR_RXEMPTY 0x00000002U /**< RX FIFO empty */
|
||||||
|
|
||||||
|
#define XUARTPS_CR_TX_DIS 0x00000020U /**< TX disabled. */
|
||||||
|
#define XUARTPS_CR_TX_EN 0x00000010U /**< TX enabled */
|
||||||
|
#define XUARTPS_CR_RX_DIS 0x00000008U /**< RX disabled. */
|
||||||
|
#define XUARTPS_CR_RX_EN 0x00000004U /**< RX enabled */
|
||||||
|
|
||||||
|
#define POINTER_TO_REGISTER(REG) ( *((volatile uint32_t*)(REG)))
|
||||||
|
|
||||||
|
#define UART_BASE XPS_UART1_BASEADDR
|
||||||
|
#define UART_CTRL POINTER_TO_REGISTER(UART_BASE + XUARTPS_CR_OFFSET) // Control Register
|
||||||
|
#define UART_MODE POINTER_TO_REGISTER(UART_BASE + XUARTPS_MR_OFFSET) // Mode Register
|
||||||
|
|
||||||
|
#define UART_BAUD_GEN POINTER_TO_REGISTER(UART_BASE + XUARTPS_BAUDGEN_OFFSET) // Baud Rate Generator "CD"
|
||||||
|
#define UART_BAUD_DIV POINTER_TO_REGISTER(UART_BASE + XUARTPS_BAUDDIV_OFFSET) // Baud Rate Divider "BDIV"
|
||||||
|
#define UART_FIFO POINTER_TO_REGISTER(UART_BASE + XUARTPS_FIFO_OFFSET) // FIFO
|
||||||
|
#define UART_STATUS POINTER_TO_REGISTER(UART_BASE + XUARTPS_SR_OFFSET) // Channel Status
|
||||||
|
|
||||||
|
#define BUFLEN 127
|
||||||
|
|
||||||
|
static uint16_t end_ndx;
|
||||||
|
static char buf[BUFLEN+1];
|
||||||
|
#define buf_len ((end_ndx - start_ndx) % BUFLEN)
|
||||||
|
static inline int inc_ndx(int n) { return ((n + 1) % BUFLEN); }
|
||||||
|
static inline int dec_ndx(int n) { return (((n + BUFLEN) - 1) % BUFLEN); }
|
||||||
|
|
||||||
|
void uart_send(char c) {
|
||||||
|
while (UART_STATUS & XUARTPS_SR_TNFUL);
|
||||||
|
UART_FIFO = c;
|
||||||
|
while (UART_STATUS & XUARTPS_SR_TACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char uart_recv() {
|
||||||
|
if ((UART_STATUS & XUARTPS_SR_RXEMPTY) == XUARTPS_SR_RXEMPTY)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return UART_FIFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
char uart_recv_blocking() {
|
||||||
|
while ((UART_STATUS & XUARTPS_SR_RXEMPTY) == XUARTPS_SR_RXEMPTY);
|
||||||
|
return UART_FIFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_setup(void) {
|
||||||
|
uint32_t r = 0; // Temporary value variable
|
||||||
|
r = UART_CTRL;
|
||||||
|
r &= ~(XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN); // Clear Tx & Rx Enable
|
||||||
|
r |= XUARTPS_CR_RX_DIS | XUARTPS_CR_TX_DIS; // Tx & Rx Disable
|
||||||
|
UART_CTRL = r;
|
||||||
|
|
||||||
|
UART_MODE = 0;
|
||||||
|
UART_MODE &= ~XUARTPS_MR_CLKSEL; // Clear "Input clock selection" - 0: clock source is uart_ref_clk
|
||||||
|
UART_MODE |= XUARTPS_MR_CHARLEN_8_BIT; // Set "8 bits data"
|
||||||
|
UART_MODE |= XUARTPS_MR_PARITY_NONE; // Set "No parity mode"
|
||||||
|
UART_MODE |= XUARTPS_MR_STOPMODE_1_BIT; // Set "1 stop bit"
|
||||||
|
UART_MODE |= XUARTPS_MR_CHMODE_NORM; // Set "Normal mode"
|
||||||
|
|
||||||
|
// baud_rate = sel_clk / (CD * (BDIV + 1) (ref: UG585 - TRM - Ch. 19 UART)
|
||||||
|
UART_BAUD_DIV = 6; // ("BDIV")
|
||||||
|
UART_BAUD_GEN = 124; // ("CD")
|
||||||
|
// Baud Rate = 100Mhz / (124 * (6 + 1)) = 115200 bps
|
||||||
|
|
||||||
|
UART_CTRL |= (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST); // TX & RX logic reset
|
||||||
|
|
||||||
|
r = UART_CTRL;
|
||||||
|
r |= XUARTPS_CR_RX_EN | XUARTPS_CR_TX_EN; // Set TX & RX enabled
|
||||||
|
r &= ~(XUARTPS_CR_RX_DIS | XUARTPS_CR_TX_DIS); // Clear TX & RX disabled
|
||||||
|
UART_CTRL = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_back_up(void){
|
||||||
|
end_ndx = dec_ndx(end_ndx);
|
||||||
|
uart_send('\010');
|
||||||
|
uart_send(' ');
|
||||||
|
uart_send('\010');
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_puts(char * s){
|
||||||
|
while(*s){
|
||||||
|
uart_send(*(s++));
|
||||||
|
}
|
||||||
|
}
|
11
examples/zynq7000/SW/src/uart.h
Normal file
11
examples/zynq7000/SW/src/uart.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef __H_UART
|
||||||
|
#define __H_UART 1
|
||||||
|
|
||||||
|
void uart_send(char c);
|
||||||
|
char uart_recv();
|
||||||
|
char uart_recv_blocking();
|
||||||
|
void uart_setup(void);
|
||||||
|
void uart_back_up(void);
|
||||||
|
void uart_puts(char * s);
|
||||||
|
|
||||||
|
#endif
|
0
examples/zynq7000/SW/src/xil_io.h
Normal file
0
examples/zynq7000/SW/src/xil_io.h
Normal file
33
examples/zynq7000/SW/src/zynq.h
Normal file
33
examples/zynq7000/SW/src/zynq.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef __H_ZYNQ
|
||||||
|
#define __H_ZYNQ 1
|
||||||
|
|
||||||
|
#define ZYNQ_PERIPH_PHY_BASE 0xF8000000
|
||||||
|
|
||||||
|
#define ZYNQ_PERIPH_TTC0_BASE (ZYNQ_PERIPH_PHY_BASE + 0x1000)
|
||||||
|
|
||||||
|
#define ZYNQ_PRI_PERIPH_PHYS_BASE 0xF8F00000
|
||||||
|
#define ZYNQ_PERIPH_SIZE 0x2000
|
||||||
|
|
||||||
|
#define ZYNQ_SCU_PHYS_BASE (ZYNQ_PRI_PERIPH_PHYS_BASE + 0)
|
||||||
|
#define ZYNQ_SCU_SIZE 0x0100
|
||||||
|
|
||||||
|
#define ZYNQ_GIC_CPU_PHYS_BASE (ZYNQ_PRI_PERIPH_PHYS_BASE + 0x100)
|
||||||
|
#define ZYNQ_GIC_CPU_SIZE 0x0100
|
||||||
|
|
||||||
|
#define ZYNQ_GTIMER_PHYS_BASE (ZYNQ_PRI_PERIPH_PHYS_BASE + 0x200)
|
||||||
|
#define ZYNQ_GTIMER_SIZE 0x0100
|
||||||
|
|
||||||
|
#define ZYNQ_PTIMER_WDT_PHYS_BASE (ZYNQ_PRI_PERIPH_PHYS_BASE + 0x600)
|
||||||
|
#define ZYNQ_PTIMER_WDT_SIZE 0x0100
|
||||||
|
|
||||||
|
#define ZYNQ_GIC_DIST_PHYS_BASE (ZYNQ_PRI_PERIPH_PHYS_BASE + 0x1000)
|
||||||
|
#define ZYNQ_GIC_DIST_SIZE 0x1000
|
||||||
|
|
||||||
|
#define WRITE32(_reg, _val) (*(volatile uint32_t*)&_reg = _val)
|
||||||
|
#define WRITE16(_reg, _val) (*(volatile uint16_t*)&_reg = _val)
|
||||||
|
#define WRITE8(_reg, _val) (*(volatile uint8_t*)&_reg = _val)
|
||||||
|
|
||||||
|
#define cpu_disable_interrups() asm ("cpsid if")
|
||||||
|
#define cpu_enable_interrups() asm ("cpsie if")
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue
Block a user