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