diff options
author | Sergey Nazaryev <sergey@nazaryev.ru> | 2018-10-07 03:49:58 +0000 |
---|---|---|
committer | Lera Pastova <lelik95@gmail.com> | 2018-10-11 10:16:13 +0300 |
commit | e75b1fc5a564b5f029fe9b765cbf72373c76128f (patch) | |
tree | 6b0ba06dafdd5760458889d1058629cb7ab00e1e | |
download | zybo-z7-baremetal-e75b1fc5a564b5f029fe9b765cbf72373c76128f.zip zybo-z7-baremetal-e75b1fc5a564b5f029fe9b765cbf72373c76128f.tar.gz zybo-z7-baremetal-e75b1fc5a564b5f029fe9b765cbf72373c76128f.tar.bz2 |
Initial commit
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | README.md | 64 | ||||
-rw-r--r-- | bsp/Makefile.inc | 53 | ||||
-rw-r--r-- | bsp/Zynq.ld | 86 | ||||
-rw-r--r-- | bsp/boot.S | 254 | ||||
-rw-r--r-- | bsp/ps7_init_gpl.c | 297 | ||||
-rw-r--r-- | bsp/ps7_init_gpl.h | 47 | ||||
-rw-r--r-- | bsp/ps7_spl_init.c | 141 | ||||
-rw-r--r-- | examples/blink/Makefile | 6 | ||||
-rw-r--r-- | examples/blink/blink.c | 29 | ||||
-rw-r--r-- | examples/uart/Makefile | 6 | ||||
-rw-r--r-- | examples/uart/uart.c | 114 |
12 files changed, 1101 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e341069 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +tags +*.elf +*.log diff --git a/README.md b/README.md new file mode 100644 index 0000000..a039e0c --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# Digilent Zybo Z7-10 (bare metal) + +This repository is aimed to simplify the interaction with Digilent +Zybo Z7-10 by using standard Linux open source utilities (such as +gcc, gdb, openocd) instead of proprietary Xilinx SDK. It is something +like [libopencm3][3] but for Xilinx Zynq 7010. + +## Quick Start + + 1. Check if you have these apps installed: + + - `openocd` + - `arm-none-eabi-gdb` + - `arm-none-eabi-gcc` + - `arm-none-eabi-newlib` + + 2. Check whether the jumper JP5 set in JTAG mode on board; + + 3. Connect your Zybo Z7 via USB (PROG/UART) to PC and turn the + switch "ON/OFF" on; + + 4. Open terminal and check for `/dev/ttyUSB0` and `/dev/ttyUSB1`: + +```bash +$ ls -al /dev/ttyUSB* +crw-rw---- 1 root uucp 188, 0 Oct 10 15:50 /dev/ttyUSB0 +crw-rw---- 1 root uucp 188, 1 Oct 10 15:50 /dev/ttyUSB1 +``` + + 5. Add your user to the group that owns ttyUSB1 (usually `dialout` or + `uucp`) for getting access to UART without root permissions: + +```bash +sudo usermod -aG uucp "${LOGNAME}" +newgrp uucp +``` + + 6. Create file /etc/udev/rules.d/49-digilent.rules (change the + group from p.5) for getting access to JTAG without root + permissions: + +``` +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", GROUP="uucp", MODE:="0660" +``` + + 7. Turn off and on board; + + 8. Now you can run blink example for testing purpose: + +```bash +cd examples/blink +make +make openocd & +make run +``` + +## Credits + + - `bsp/boot.S` & `bsp/Zynq.ld` from [bigbrett/zybo-baremetal][1] + - `bsp/ps7_init_gpl.{c,h}` & `bsp/ps7_spl_init.c` from [Das U-boot][2] + +[1]: https://github.com/bigbrett/zybo-baremetal +[2]: http://git.denx.de/?p=u-boot.git;a=summary +[3]: https://github.com/libopencm3/libopencm3 diff --git a/bsp/Makefile.inc b/bsp/Makefile.inc new file mode 100644 index 0000000..a39362e --- /dev/null +++ b/bsp/Makefile.inc @@ -0,0 +1,53 @@ +CROSS_COMPILE ?= arm-none-eabi- + +AS = $(CROSS_COMPILE)as +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld +SZ = $(CROSS_COMPILE)size +GDB = $(CROSS_COMPILE)gdb +OOCD = openocd + +CFLAGS = -I$(BSPDIR) -mcpu=cortex-a9 -O0 -g3 -Wall -Werror -Wpedantic +LDFLAGS = -nostdlib -T$(BSPDIR)/Zynq.ld +ASFLAGS = -g -mcpu=cortex-a9 + +BSP = $(BSPDIR)/boot.S \ + $(BSPDIR)/ps7_init_gpl.c \ + $(BSPDIR)/ps7_spl_init.c + +OBJECTS = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(SOURCES) $(BSP))) + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(LD) $(LDFLAGS) -o $@ $^ + @$(SZ) $(TARGET) + +%.o: %.S + $(AS) $(ASFLAGS) -c -o $@ $< + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + rm -f $(TARGET) $(OBJECTS) + +openocd: + $(OOCD) -f interface/ftdi/digilent-hs1.cfg \ + -f target/zynq_7000.cfg + +debug: $(TARGET) + $(GDB) -iex "target remote localhost:3333" \ + -iex "monitor halt" \ + -ex "load" \ + -ex "continue" "$(TARGET)" + +run: $(TARGET) + $(GDB) -iex "target remote localhost:3333" \ + -iex "monitor halt" \ + -ex "load" \ + -ex "continue" \ + -ex "set confirm no" \ + -ex "quit" "$(TARGET)" + +.PHONY: clean debug openocd diff --git a/bsp/Zynq.ld b/bsp/Zynq.ld new file mode 100644 index 0000000..e94fafc --- /dev/null +++ b/bsp/Zynq.ld @@ -0,0 +1,86 @@ +OUTPUT_FORMAT ("elf32-littlearm") + +MEMORY +{ + SRAM_0 : ORIGIN = 0x00000000, LENGTH = 0x00030000 /* 192k */ + SRAM_1 : ORIGIN = 0xFFFF0000, LENGTH = 0x00010000 /* 64k */ + DDR_PS : ORIGIN = 0x00100000, LENGTH = 0x1FF00000 /* 512M */ +} + +EXTERN(__stack_size) +ASSERT(__stack_size, "Must provide a non-zero stack size"); +/* TODO: Also make sure stack size is 32-bit aligned */ + +__heap_end = __stext + LENGTH(SRAM_0); +__heap_start = __end; + +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 = .; + } >SRAM_0 + + .data : + { + . = ALIGN(4); + __sdata = .; + *(.data .data.*) + __edata = .; + + } >SRAM_0 + + .bss (NOLOAD) : + { + . = ALIGN(4); + __sbss = .; /* Used for zeroing bss on startup */ + *(.bss .bss.*) + __ebss = .; + } >SRAM_0 + + . = 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 =0xFEEDBEEF + + .data.ddr : + { + *(.data_in_ddr) + } >DDR_PS +} diff --git a/bsp/boot.S b/bsp/boot.S new file mode 100644 index 0000000..f948aaf --- /dev/null +++ b/bsp/boot.S @@ -0,0 +1,254 @@ +/* + * Init.s + * + * Initial system initialization code (1st-stage boot-loader) + */ + + .syntax unified /* Use the unified instruction syntax */ + .arm /* Assemble ARM instruction set, not thumb */ + +/* + * + * References: + * [1] Zynq-7000 Extensible Processing Platform - Technical Reference Manual UG585 (v1.0) + * May 8, 2012 http://www.xilinx.com + * Section 6.x "Boot and Configuration" + * + * [2] Zynq-7000 EPP Software Developers Guide - UG821 (v2.0) April 24, 2012 + * http://www.xilinx.com + * Section 3.x "Boot and Configuration" + * + * [3] ZedBoard Hardware User Guide v1.1. August 1st, 2012. + * Retrieved from Digilent website + * Page 29. + * + * [4] Cortex-A Series Programmer's Guide, Version 2.0. + * http:/www.arm.com + * + * The Zynq processor boot includes two mandatory stages: stage 0 and stage 1. + * Stage 0 is the on-chip, immutable boot ROM. This code is called on reset/ + * warm restart. + * + * The first-stage bootloader (FSBL) starts after boot. It is either run from + * on-chip memory starting at address 0x00000000 (populated by 0-th stage bootloader) + * or it executes in place (XIP) from unencrypted memory-maped flash depending on the + * BootROM header description. First-stage bootloader is responsible for initialization + * of the PS (ARM core) using the PS data provided by XPS, programming the PL (FPGA) using + * a bit-stream, loading second-stage bootloader or bare-metal application code into memory + * and starting execution of the second-stage bootloader or bare-metal application. + * NOTE: the default FSBL disables the MMU before starting the 2nd stage code. + * + * The files ps7_init.c and ps7_init.h are used to initialize CLK, DDR and MIO. The same + * initialization can be performed by ps7_init.tcl. When debugging with XMD, the ps7_init.tcl + * code is run by XMD, bypassing the need for a first-stage bootloader. + * + * For now, all development is done using XPS, with ps7_init.tcl utilized to perform the + * 1st stage bootloader behavior. When the program is moved to QSPI Flash or SD, refer + * to [2] section 3.4 and 3.5 for details about how to generate boot images. + * + * When the JTAG boot source is selected, the CPU halts imediately after it disables + * access to all security-related items and enables the JTAG port. It is the user's + * responsibility to manage downloading the boot image into OC RAM or DDR memory via + * JTAG before waking up the CPU and continuing the boot process (See [1] pp 129). + * + * 5 mode pins (Boot_Mode[4:0] - mapped to physical pins MIO[6:2]) determing the boot source. + * On the ZedBoard these are JP7-JP11 on the upper-right corner. + * + * MIO[2] (Boot_Mode[3]) determines JTAG configuration. Open (default) cascades both + * the processor and FPGA resources - so they are both available from the same JTAG + * interface. + * + * NOTE: the BootRom has two methods for communicating status information in the event + * of a startup failure. The primary metho is through the REBOOT_STATUS register. Non-secure + * boot failures result in the BootROM disabling access to the AES engine, clearing the PL + * and enabling JTAG. After JTAG is enabled, the REBOOT_STATUS register can be read to find the + * source of boot failure. See Table 6-9 in [1]. + * + * MIO[5:3] (Boot_Mode[2:0]) determine boot device. Three useful configurations are: + * MIO[5] MIO[4] MIO[3] + * 0 0 0 = Boot from JTAG-provided image + * 1 0 0 = Boot from Q-SPI + * 1 1 0 = Boot from SD Card + * + * MIO[6] (Boot-Mode[4]) enables or disables the PLLs during 0-stage bootloader. + * The default is 0 (open), or enabled. + * + * After BootROM, the PS is in the following state: + * - MMU, Icache, Dcache, L2 cache are all disabled + * - Both processors are in the supervisor state + * - ROM code is masked and inaccessible + * - 192 kB of OCM is accessible starting at address 0x0 + * - 64 kB of OCM is accessible starting at address 0xFFFF0000 + * - CPU0 branches into the stage1 image if no failure occurs + * - CPU1 is in a WFE state while executing code at address 0xFFFFFE00 to 0xFFFFFFF0 + * + * CPU0 is in charge of starting any addtional code on CPU1. The BootROM keeps CPU1 + * in a reset-type state (WFE). When CPU1 receives a system event it reads the contents + * of address 0xFFFFFFF0 and jumps to that address. Only ARM-32 ISA code is supported + * at the jump target placed in 0xFFFFFFF0. The destination address must be 32-bit + * aligned and must be a valid ARM-32 instruction. + */ + .equ PROC1_RESET_VECTOR_TABLE, 0xFFFFFFF0 +/* + * See sectoin 6.3.7 of [1] for more information on PS (CPU0,1) state after BootROM exit + * + * The ARM Cortex-A series processors have 7 standard modes (an 8th mode + * is utilized by the TrustZone security architecure and in systems with + * virtualization extensions a 9th mode is utilized by the hypervisor) + * associated with the standard modes. + * + * MODE_USER and MODE_SYSTEM are the normal operating modes. The former + * is for unprivileged user code and the latter for privileged execution. + * They share a common stack and register set (thus 7 modes, 6 stacks). + * + * MODE_SVC (Supervisor) is used to handle software-generated exceptions, + * such as system requests generated by user code. + * + * MODE_ABORT and MODE_UNDEFINED support fault and undefined instruction + * states. + * + * Two interrupt request signals, IRQ and FIQ, are used to interrupt the + * processor. The procesor has two modes, MODE_IRQ and MODE_FIQ, for + * handling these interupts. The FIQ ("Fast Interrupt Request") has + * additional hardware support and placement optimizations to increase + * its responsiveness. + * + * Mode is determined by the value in the MODE field of the CPSR register. + * These can be set using the "CPS" instruction, ie "CPS CPSR_MODE_USER": + */ + /* TODO THESE ARE MACROS DEFINING THE HARDWARE MODE OF THE PROCESSOR */ + .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 + +/* + * Stack placement is handled in the linker script - see Zynq.ld. The + * stack size for each is defined by __stack_size, below. Stacks are + * placed in the high 64k block of OCM. There are 14 stacks and + * we can't step on the last ~256 bytes of this block (as it is used + * by proc1 on start-up - see below) so limited to ~4k stack size. + */ + .equ __stack_size, 0x1000 /* See linker script */ + .global __stack_size + +/* + * The IRQ and FIQ exceptions are enabled/disabled by flags in the CPSR. + * They are enabled/disabled using the CPSIE/CPSID instructions followed by + * an argument describing which interupt to alter, 'i' for IRQ and 'f' for FIQ: + * + * cpsie i - enables IRQ interrupts + * cpsid d - disables IRQ interupts // TODO should this be cpsid i? + * cpsie f - enables FIQ interrupts + * cpsid f - disables FIQ interrupts + * + * These can also be set by writing directly to the CPSR register - which is done + * below during initialization to set up stacks and interrupt masks for the + * multiple processor modes + */ + .equ CPSR_IRQ, 0x80 /* disable IRQ interrupts */ + .equ CPSR_FIQ, 0x40 /* disable FIQ interrupts */ + +/* + * The linker script (Zynq.ld) places text in the "bootimage" section at the + * start of the image. The interrupt jump table (vector) lives at address 0x00000000 and + * contains branch instructions to appropriate handlers. Single-instruction + * branches cannot jump further than 2^24 bits, so common practice is to + * branch to a locally placed handler, or branch to a locally placed + * verneer that allows a longer jump to a handler. Note that in general + * the FIQ is the last entry, allowing the FIQ handler to begin execution + * at the jump table address (rather than jumping to the handler) as no + * addtional jump table entries exist after it. In BEAR we take the + * performance hit and jump to a handler. + * + * Exception Modes and handling are described in [4] Section 10. Note there + * are different recommended return instructions for each mode; these are + * captured in the comments in the jump table below. + * + * Unimplemented handlers halt by looping in the jump table below. + * + * _init (reset handler), svc_Handler (supervisor call) and fiq_handler (interrupts) + * are assumed to live in the OCM, well within the 2^24 max jump distance restriction + * on the "b <target>" instruction. + * + * FIQ_handler and SVC_handler are defined in interrupts.S + */ + .section .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 */ + + .text + +reset_handler: +proc0_init: +main: + /* For xilinx debugger - IDE debugger init searches for this function */ + /* Switch between the various modes and initialize stack pointers */ + /* When finished with this block, we'll be in the supervisor (privledged user) mode */ + /* set all the stack pointers */ + /* NOTE: ONLY NEED TO SET STACK POINTERS FOR THE MODE IM RUNNING IN (SVC and IRQ) + Jason reccomends only using the last 2 lines of code + NOTE: this also disables interrupts in each of these modes as the default setting */ + 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 */ + + + /* Clear the .bss section (zero inits) */ + ldr r1, =__sbss // where in memory is start of bss (get from linker script) + ldr r2, =__ebss // where in memory is end of bss (get from linker script) + mov r3, #0 +clearbss: + cmp r1, r2 + stmialt r1!,{r3} + blt clearbss + + bl ps7_init + /* Finally, transfer control to the user program */ + b init + +undef_handler: + b undef_handler + +SVC_handler: + b SVC_handler + +prefetch_abort_handler: + b prefetch_abort_handler + +data_abort_handler: + b data_abort_handler + +hypervisor_handler: + b hypervisor_handler + +IRQ_handler: + /* IRQ only used for scheduling */ + b IRQ_handler + +FIQ_handler: + b FIQ_handler + + +.end diff --git a/bsp/ps7_init_gpl.c b/bsp/ps7_init_gpl.c new file mode 100644 index 0000000..d97640e --- /dev/null +++ b/bsp/ps7_init_gpl.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (c) Copyright 2010-2014 Xilinx, Inc. All rights reserved. + * + * Procedure to generate this file (using Vivado Webpack 2018.2): + * + Install board files from digilent/vivado-boards repository + * (commit 6a45981 from 2018-06-05) + * + Start Vivado and create a new RTL project with the Zybo-z7-20 board + * + Create a block design + * - Add "ZYNQ7 Processing System" IP + * - Run "Block Automation" (Check "Apply Board Preset") + * - Connect ports FCLK_CLK0 and M_AXI_GP0_ACLK + * - Save diagram changes + * - Go to sources view, select the block diagram, + * and select "Generate Output Products" + * + Copy the generated "ps7_init_gpl.c" file + * + Perform manual editions based on existing Zynq boards + * and the checkpatch.pl script + * + */ + +#include "ps7_init_gpl.h" + +static unsigned long ps7_pll_init_data_3_0[] = { + EMIT_WRITE(0xF8000008, 0x0000DF0DU), + EMIT_MASKWRITE(0xF8000110, 0x003FFFF0U, 0x000FA220U), + EMIT_MASKWRITE(0xF8000100, 0x0007F000U, 0x00028000U), + EMIT_MASKWRITE(0xF8000100, 0x00000010U, 0x00000010U), + EMIT_MASKWRITE(0xF8000100, 0x00000001U, 0x00000001U), + EMIT_MASKWRITE(0xF8000100, 0x00000001U, 0x00000000U), + EMIT_MASKPOLL(0xF800010C, 0x00000001U), + EMIT_MASKWRITE(0xF8000100, 0x00000010U, 0x00000000U), + EMIT_MASKWRITE(0xF8000120, 0x1F003F30U, 0x1F000200U), + EMIT_MASKWRITE(0xF8000114, 0x003FFFF0U, 0x0012C220U), + EMIT_MASKWRITE(0xF8000104, 0x0007F000U, 0x00020000U), + EMIT_MASKWRITE(0xF8000104, 0x00000010U, 0x00000010U), + EMIT_MASKWRITE(0xF8000104, 0x00000001U, 0x00000001U), + EMIT_MASKWRITE(0xF8000104, 0x00000001U, 0x00000000U), + EMIT_MASKPOLL(0xF800010C, 0x00000002U), + EMIT_MASKWRITE(0xF8000104, 0x00000010U, 0x00000000U), + EMIT_MASKWRITE(0xF8000124, 0xFFF00003U, 0x0C200003U), + EMIT_MASKWRITE(0xF8000118, 0x003FFFF0U, 0x001452C0U), + EMIT_MASKWRITE(0xF8000108, 0x0007F000U, 0x0001E000U), + EMIT_MASKWRITE(0xF8000108, 0x00000010U, 0x00000010U), + EMIT_MASKWRITE(0xF8000108, 0x00000001U, 0x00000001U), + EMIT_MASKWRITE(0xF8000108, 0x00000001U, 0x00000000U), + EMIT_MASKPOLL(0xF800010C, 0x00000004U), + EMIT_MASKWRITE(0xF8000108, 0x00000010U, 0x00000000U), + EMIT_WRITE(0xF8000004, 0x0000767BU), + EMIT_EXIT(), +}; + +static unsigned long ps7_clock_init_data_3_0[] = { + EMIT_WRITE(0xF8000008, 0x0000DF0DU), + EMIT_MASKWRITE(0xF8000128, 0x03F03F01U, 0x00700F01U), + EMIT_MASKWRITE(0xF8000138, 0x00000011U, 0x00000001U), + EMIT_MASKWRITE(0xF8000140, 0x03F03F71U, 0x00100801U), + EMIT_MASKWRITE(0xF800014C, 0x00003F31U, 0x00000501U), + EMIT_MASKWRITE(0xF8000150, 0x00003F33U, 0x00001401U), + EMIT_MASKWRITE(0xF8000154, 0x00003F33U, 0x00000A02U), + EMIT_MASKWRITE(0xF8000168, 0x00003F31U, 0x00000501U), + EMIT_MASKWRITE(0xF8000170, 0x03F03F30U, 0x00400500U), + EMIT_MASKWRITE(0xF80001C4, 0x00000001U, 0x00000001U), + EMIT_MASKWRITE(0xF800012C, 0x01FFCCCDU, 0x01EC044DU), + EMIT_WRITE(0xF8000004, 0x0000767BU), + EMIT_EXIT(), +}; + +static unsigned long ps7_ddr_init_data_3_0[] = { + EMIT_MASKWRITE(0xF8006000, 0x0001FFFFU, 0x00000080U), + EMIT_MASKWRITE(0xF8006004, 0x0007FFFFU, 0x00001081U), + EMIT_MASKWRITE(0xF8006008, 0x03FFFFFFU, 0x03C0780FU), + EMIT_MASKWRITE(0xF800600C, 0x03FFFFFFU, 0x02001001U), + EMIT_MASKWRITE(0xF8006010, 0x03FFFFFFU, 0x00014001U), + EMIT_MASKWRITE(0xF8006014, 0x001FFFFFU, 0x0004281AU), + EMIT_MASKWRITE(0xF8006018, 0xF7FFFFFFU, 0x44E458D2U), + EMIT_MASKWRITE(0xF800601C, 0xFFFFFFFFU, 0x720238E5U), + EMIT_MASKWRITE(0xF8006020, 0x7FDFFFFCU, 0x270872D0U), + EMIT_MASKWRITE(0xF8006024, 0x0FFFFFC3U, 0x00000000U), + EMIT_MASKWRITE(0xF8006028, 0x00003FFFU, 0x00002007U), + EMIT_MASKWRITE(0xF800602C, 0xFFFFFFFFU, 0x00000008U), + EMIT_MASKWRITE(0xF8006030, 0xFFFFFFFFU, 0x00040930U), + EMIT_MASKWRITE(0xF8006034, 0x13FF3FFFU, 0x000116D4U), + EMIT_MASKWRITE(0xF8006038, 0x00000003U, 0x00000000U), + EMIT_MASKWRITE(0xF800603C, 0x000FFFFFU, 0x00000777U), + EMIT_MASKWRITE(0xF8006040, 0xFFFFFFFFU, 0xFFF00000U), + EMIT_MASKWRITE(0xF8006044, 0x0FFFFFFFU, 0x0F666666U), + EMIT_MASKWRITE(0xF8006048, 0x0003F03FU, 0x0003C008U), + EMIT_MASKWRITE(0xF8006050, 0xFF0F8FFFU, 0x77010800U), + EMIT_MASKWRITE(0xF8006058, 0x00010000U, 0x00000000U), + EMIT_MASKWRITE(0xF800605C, 0x0000FFFFU, 0x00005003U), + EMIT_MASKWRITE(0xF8006060, 0x000017FFU, 0x0000003EU), + EMIT_MASKWRITE(0xF8006064, 0x00021FE0U, 0x00020000U), + EMIT_MASKWRITE(0xF8006068, 0x03FFFFFFU, 0x00284141U), + EMIT_MASKWRITE(0xF800606C, 0x0000FFFFU, 0x00001610U), + EMIT_MASKWRITE(0xF8006078, 0x03FFFFFFU, 0x00466111U), + EMIT_MASKWRITE(0xF800607C, 0x000FFFFFU, 0x00032222U), + EMIT_MASKWRITE(0xF80060A4, 0xFFFFFFFFU, 0x10200802U), + EMIT_MASKWRITE(0xF80060A8, 0x0FFFFFFFU, 0x0690CB73U), + EMIT_MASKWRITE(0xF80060AC, 0x000001FFU, 0x000001FEU), + EMIT_MASKWRITE(0xF80060B0, 0x1FFFFFFFU, 0x1CFFFFFFU), + EMIT_MASKWRITE(0xF80060B4, 0x00000200U, 0x00000200U), + EMIT_MASKWRITE(0xF80060B8, 0x01FFFFFFU, 0x00200066U), + EMIT_MASKWRITE(0xF80060C4, 0x00000003U, 0x00000000U), + EMIT_MASKWRITE(0xF80060C8, 0x000000FFU, 0x00000000U), + EMIT_MASKWRITE(0xF80060DC, 0x00000001U, 0x00000000U), + EMIT_MASKWRITE(0xF80060F0, 0x0000FFFFU, 0x00000000U), + EMIT_MASKWRITE(0xF80060F4, 0x0000000FU, 0x00000008U), + EMIT_MASKWRITE(0xF8006114, 0x000000FFU, 0x00000000U), + EMIT_MASKWRITE(0xF8006118, 0x7FFFFFCFU, 0x40000001U), + EMIT_MASKWRITE(0xF800611C, 0x7FFFFFCFU, 0x40000001U), + EMIT_MASKWRITE(0xF8006120, 0x7FFFFFCFU, 0x40000001U), + EMIT_MASKWRITE(0xF8006124, 0x7FFFFFCFU, 0x40000001U), + EMIT_MASKWRITE(0xF800612C, 0x000FFFFFU, 0x00027000U), + EMIT_MASKWRITE(0xF8006130, 0x000FFFFFU, 0x00027000U), + EMIT_MASKWRITE(0xF8006134, 0x000FFFFFU, 0x00026C00U), + EMIT_MASKWRITE(0xF8006138, 0x000FFFFFU, 0x00028800U), + EMIT_MASKWRITE(0xF8006140, 0x000FFFFFU, 0x00000035U), + EMIT_MASKWRITE(0xF8006144, 0x000FFFFFU, 0x00000035U), + EMIT_MASKWRITE(0xF8006148, 0x000FFFFFU, 0x00000035U), + EMIT_MASKWRITE(0xF800614C, 0x000FFFFFU, 0x00000035U), + EMIT_MASKWRITE(0xF8006154, 0x000FFFFFU, 0x0000007AU), + EMIT_MASKWRITE(0xF8006158, 0x000FFFFFU, 0x0000007AU), + EMIT_MASKWRITE(0xF800615C, 0x000FFFFFU, 0x0000007CU), + EMIT_MASKWRITE(0xF8006160, 0x000FFFFFU, 0x00000073U), + EMIT_MASKWRITE(0xF8006168, 0x001FFFFFU, 0x000000F1U), + EMIT_MASKWRITE(0xF800616C, 0x001FFFFFU, 0x000000F1U), + EMIT_MASKWRITE(0xF8006170, 0x001FFFFFU, 0x000000F0U), + EMIT_MASKWRITE(0xF8006174, 0x001FFFFFU, 0x000000F7U), + EMIT_MASKWRITE(0xF800617C, 0x000FFFFFU, 0x000000BAU), + EMIT_MASKWRITE(0xF8006180, 0x000FFFFFU, 0x000000BAU), + EMIT_MASKWRITE(0xF8006184, 0x000FFFFFU, 0x000000BCU), + EMIT_MASKWRITE(0xF8006188, 0x000FFFFFU, 0x000000B3U), + EMIT_MASKWRITE(0xF8006190, 0x6FFFFEFEU, 0x00040080U), + EMIT_MASKWRITE(0xF8006194, 0x000FFFFFU, 0x0001FC82U), + EMIT_MASKWRITE(0xF8006204, 0xFFFFFFFFU, 0x00000000U), + EMIT_MASKWRITE(0xF8006208, 0x000703FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF800620C, 0x000703FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF8006210, 0x000703FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF8006214, 0x000703FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF8006218, 0x000F03FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF800621C, 0x000F03FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF8006220, 0x000F03FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF8006224, 0x000F03FFU, 0x000003FFU), + EMIT_MASKWRITE(0xF80062A8, 0x00000FF5U, 0x00000000U), + EMIT_MASKWRITE(0xF80062AC, 0xFFFFFFFFU, 0x00000000U), + EMIT_MASKWRITE(0xF80062B0, 0x003FFFFFU, 0x00005125U), + EMIT_MASKWRITE(0xF80062B4, 0x0003FFFFU, 0x000012A8U), + EMIT_MASKPOLL(0xF8000B74, 0x00002000U), + EMIT_MASKWRITE(0xF8006000, 0x0001FFFFU, 0x00000081U), + EMIT_MASKPOLL(0xF8006054, 0x00000007U), + EMIT_EXIT(), +}; + +static unsigned long ps7_mio_init_data_3_0[] = { + EMIT_WRITE(0xF8000008, 0x0000DF0DU), + EMIT_MASKWRITE(0xF8000B40, 0x00000FFFU, 0x00000600U), + EMIT_MASKWRITE(0xF8000B44, 0x00000FFFU, 0x00000600U), + EMIT_MASKWRITE(0xF8000B48, 0x00000FFFU, 0x00000672U), + EMIT_MASKWRITE(0xF8000B4C, 0x00000FFFU, 0x00000672U), + EMIT_MASKWRITE(0xF8000B50, 0x00000FFFU, 0x00000674U), + EMIT_MASKWRITE(0xF8000B54, 0x00000FFFU, 0x00000674U), + EMIT_MASKWRITE(0xF8000B58, 0x00000FFFU, 0x00000600U), + EMIT_MASKWRITE(0xF8000B5C, 0xFFFFFFFFU, 0x0018C068U), + EMIT_MASKWRITE(0xF8000B60, 0xFFFFFFFFU, 0x00F98068U), + EMIT_MASKWRITE(0xF8000B64, 0xFFFFFFFFU, 0x00F98068U), + EMIT_MASKWRITE(0xF8000B68, 0xFFFFFFFFU, 0x00F98068U), + EMIT_MASKWRITE(0xF8000B6C, 0x00007FFFU, 0x00000260U), + EMIT_MASKWRITE(0xF8000B70, 0x00000001U, 0x00000001U), + EMIT_MASKWRITE(0xF8000B70, 0x00000021U, 0x00000020U), + EMIT_MASKWRITE(0xF8000B70, 0x07FEFFFFU, 0x00000823U), + EMIT_MASKWRITE(0xF8000700, 0x00003FFFU, 0x00001600U), + EMIT_MASKWRITE(0xF8000704, 0x00003FFFU, 0x00001602U), + EMIT_MASKWRITE(0xF8000708, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF800070C, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF8000710, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF8000714, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF8000718, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF800071C, 0x00003FFFU, 0x00000600U), + EMIT_MASKWRITE(0xF8000720, 0x00003FFFU, 0x00000602U), + EMIT_MASKWRITE(0xF8000724, 0x00003FFFU, 0x00001600U), + EMIT_MASKWRITE(0xF8000728, 0x00003FFFU, 0x00001600U), + EMIT_MASKWRITE(0xF800072C, 0x00003FFFU, 0x00001600U), + EMIT_MASKWRITE(0xF8000730, 0x00003FFFU, 0x00001600U), + EMIT_MASKWRITE(0xF8000734, 0x00003FFFU, 0x00001600U), + EMIT_MASKWRITE(0xF8000738, 0x00003FFFU, 0x00001600U), + EMIT_MASKWRITE(0xF800073C, 0x00003FFFU, 0x00001600U), + EMIT_MASKWRITE(0xF8000740, 0x00003FFFU, 0x00001302U), + EMIT_MASKWRITE(0xF8000744, 0x00003FFFU, 0x00001302U), + EMIT_MASKWRITE(0xF8000748, 0x00003FFFU, 0x00001302U), + EMIT_MASKWRITE(0xF800074C, 0x00003FFFU, 0x00001302U), + EMIT_MASKWRITE(0xF8000750, 0x00003FFFU, 0x00001302U), + EMIT_MASKWRITE(0xF8000754, 0x00003FFFU, 0x00001302U), + EMIT_MASKWRITE(0xF8000758, 0x00003FFFU, 0x00001303U), + EMIT_MASKWRITE(0xF800075C, 0x00003FFFU, 0x00001303U), + EMIT_MASKWRITE(0xF8000760, 0x00003FFFU, 0x00001303U), + EMIT_MASKWRITE(0xF8000764, 0x00003FFFU, 0x00001303U), + EMIT_MASKWRITE(0xF8000768, 0x00003FFFU, 0x00001303U), + EMIT_MASKWRITE(0xF800076C, 0x00003FFFU, 0x00001303U), + EMIT_MASKWRITE(0xF8000770, 0x00003FFFU, 0x00001304U), + EMIT_MASKWRITE(0xF8000774, 0x00003FFFU, 0x00001305U), + EMIT_MASKWRITE(0xF8000778, 0x00003FFFU, 0x00001304U), + EMIT_MASKWRITE(0xF800077C, 0x00003FFFU, 0x00001305U), + EMIT_MASKWRITE(0xF8000780, 0x00003FFFU, 0x00001304U), + EMIT_MASKWRITE(0xF8000784, 0x00003FFFU, 0x00001304U), + EMIT_MASKWRITE(0xF8000788, 0x00003FFFU, 0x00001304U), + EMIT_MASKWRITE(0xF800078C, 0x00003FFFU, 0x00001304U), + EMIT_MASKWRITE(0xF8000790, 0x00003FFFU, 0x00001305U), + EMIT_MASKWRITE(0xF8000794, 0x00003FFFU, 0x00001304U), + EMIT_MASKWRITE(0xF8000798, 0x00003FFFU, 0x00001304U), + EMIT_MASKWRITE(0xF800079C, 0x00003FFFU, 0x00001304U), + EMIT_MASKWRITE(0xF80007A0, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007A4, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007A8, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007AC, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007B0, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007B4, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007B8, 0x00003FFFU, 0x00001200U), + EMIT_MASKWRITE(0xF80007BC, 0x00003F01U, 0x00001201U), + EMIT_MASKWRITE(0xF80007C0, 0x00003FFFU, 0x000012E0U), + EMIT_MASKWRITE(0xF80007C4, 0x00003FFFU, 0x000012E1U), + EMIT_MASKWRITE(0xF80007C8, 0x00003FFFU, 0x00001200U), + EMIT_MASKWRITE(0xF80007CC, 0x00003FFFU, 0x00001200U), + EMIT_MASKWRITE(0xF80007D0, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF80007D4, 0x00003FFFU, 0x00001280U), + EMIT_MASKWRITE(0xF8000830, 0x003F003FU, 0x002F0037U), + EMIT_WRITE(0xF8000004, 0x0000767BU), + EMIT_EXIT(), +}; + +static unsigned long ps7_peripherals_init_data_3_0[] = { + EMIT_WRITE(0xF8000008, 0x0000DF0DU), + EMIT_MASKWRITE(0xF8000B48, 0x00000180U, 0x00000180U), + EMIT_MASKWRITE(0xF8000B4C, 0x00000180U, 0x00000180U), + EMIT_MASKWRITE(0xF8000B50, 0x00000180U, 0x00000180U), + EMIT_MASKWRITE(0xF8000B54, 0x00000180U, 0x00000180U), + EMIT_WRITE(0xF8000004, 0x0000767BU), + EMIT_MASKWRITE(0xE0001034, 0x000000FFU, 0x00000006U), + EMIT_MASKWRITE(0xE0001018, 0x0000FFFFU, 0x0000007CU), + EMIT_MASKWRITE(0xE0001000, 0x000001FFU, 0x00000017U), + EMIT_MASKWRITE(0xE0001004, 0x000003FFU, 0x00000020U), + EMIT_MASKWRITE(0xE000D000, 0x00080000U, 0x00080000U), + EMIT_MASKWRITE(0xF8007000, 0x20000000U, 0x00000000U), + EMIT_MASKWRITE(0xE000A244, 0x003FFFFFU, 0x00004000U), + EMIT_MASKWRITE(0xE000A008, 0xFFFFFFFFU, 0xBFFF4000U), + EMIT_MASKWRITE(0xE000A248, 0x003FFFFFU, 0x00004000U), + EMIT_MASKWRITE(0xE000A008, 0xFFFFFFFFU, 0xBFFF0000U), + EMIT_MASKDELAY(0xF8F00200, 1), + EMIT_MASKWRITE(0xE000A008, 0xFFFFFFFFU, 0xBFFF4000U), + EMIT_EXIT(), +}; + +static unsigned long ps7_post_config_3_0[] = { + EMIT_WRITE(0xF8000008, 0x0000DF0DU), + EMIT_MASKWRITE(0xF8000900, 0x0000000FU, 0x0000000FU), + EMIT_MASKWRITE(0xF8000240, 0xFFFFFFFFU, 0x00000000U), + EMIT_WRITE(0xF8000004, 0x0000767BU), + EMIT_EXIT(), +}; + +int ps7_post_config(void) +{ + int ret = -1; + + ret = ps7_config(ps7_post_config_3_0); + if (ret != PS7_INIT_SUCCESS) + return ret; + + return PS7_INIT_SUCCESS; +} + +int ps7_init(void) +{ + int ret; + + ret = ps7_config(ps7_mio_init_data_3_0); + if (ret != PS7_INIT_SUCCESS) + return ret; + + ret = ps7_config(ps7_pll_init_data_3_0); + if (ret != PS7_INIT_SUCCESS) + return ret; + + ret = ps7_config(ps7_clock_init_data_3_0); + if (ret != PS7_INIT_SUCCESS) + return ret; + + ret = ps7_config(ps7_ddr_init_data_3_0); + if (ret != PS7_INIT_SUCCESS) + return ret; + + ret = ps7_config(ps7_peripherals_init_data_3_0); + if (ret != PS7_INIT_SUCCESS) + return ret; + + return PS7_INIT_SUCCESS; +} diff --git a/bsp/ps7_init_gpl.h b/bsp/ps7_init_gpl.h new file mode 100644 index 0000000..bd46a9b --- /dev/null +++ b/bsp/ps7_init_gpl.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (c) Copyright 2010-2014 Xilinx, Inc. All rights reserved. + * (c) Copyright 2016 Topic Embedded Products. + */ + +#ifndef _ASM_ARCH_PS7_INIT_GPL_H +#define _ASM_ARCH_PS7_INIT_GPL_H + +/* Opcode exit is 0 all the time */ +#define OPCODE_EXIT 0U +#define OPCODE_MASKWRITE 0U +#define OPCODE_MASKPOLL 1U +#define OPCODE_MASKDELAY 2U +#define OPCODE_WRITE 3U +#define OPCODE_ADDRESS_MASK (~3U) + +/* Sentinel */ +#define EMIT_EXIT() OPCODE_EXIT +/* Opcode is in lower 2 bits of address, address is always 4-byte aligned */ +#define EMIT_MASKWRITE(addr, mask, val) OPCODE_MASKWRITE | addr, mask, val +#define EMIT_MASKPOLL(addr, mask) OPCODE_MASKPOLL | addr, mask +#define EMIT_MASKDELAY(addr, mask) OPCODE_MASKDELAY | addr, mask +#define EMIT_WRITE(addr, val) OPCODE_WRITE | addr, val + +/* Returns codes of ps7_init* */ +#define PS7_INIT_SUCCESS (0) +#define PS7_INIT_CORRUPT (1) +#define PS7_INIT_TIMEOUT (2) +#define PS7_POLL_FAILED_DDR_INIT (3) +#define PS7_POLL_FAILED_DMA (4) +#define PS7_POLL_FAILED_PLL (5) + +#define PCW_SILICON_VERSION_1 0 +#define PCW_SILICON_VERSION_2 1 +#define PCW_SILICON_VERSION_3 2 + +/* Called by spl.c */ +int ps7_init(void); +int ps7_post_config(void); + +/* Defined in ps7_init_common.c */ +int ps7_config(unsigned long *ps7_config_init); + +unsigned long ps7GetSiliconVersion(void); + +#endif /* _ASM_ARCH_PS7_INIT_GPL_H */ diff --git a/bsp/ps7_spl_init.c b/bsp/ps7_spl_init.c new file mode 100644 index 0000000..5914042 --- /dev/null +++ b/bsp/ps7_spl_init.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (c) Copyright 2010-2017 Xilinx, Inc. All rights reserved. + * (c) Copyright 2016 Topic Embedded Products. + */ + +#include "ps7_init_gpl.h" + +/* For delay calculation using global registers*/ +#define SCU_GLOBAL_TIMER_COUNT_L32 0xF8F00200 +#define SCU_GLOBAL_TIMER_COUNT_U32 0xF8F00204 +#define SCU_GLOBAL_TIMER_CONTROL 0xF8F00208 +#define SCU_GLOBAL_TIMER_AUTO_INC 0xF8F00218 +#define APU_FREQ 666666666 + +#define PS7_MASK_POLL_TIME 100000000 + +#define __arch_getb(a) (*(volatile unsigned char *)(a)) +#define __arch_getw(a) (*(volatile unsigned short *)(a)) +#define __arch_getl(a) (*(volatile unsigned int *)(a)) +#define __arch_getq(a) (*(volatile unsigned long long *)(a)) + +#define __arch_putb(v,a) (*(volatile unsigned char *)(a) = (v)) +#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v)) +#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v)) +#define __arch_putq(v,a) (*(volatile unsigned long long *)(a) = (v)) + +#define __raw_writeb(v,a) __arch_putb(v,a) +#define __raw_writew(v,a) __arch_putw(v,a) +#define __raw_writel(v,a) __arch_putl(v,a) +#define __raw_writeq(v,a) __arch_putq(v,a) + +#define __raw_readb(a) __arch_getb(a) +#define __raw_readw(a) __arch_getw(a) +#define __raw_readl(a) __arch_getl(a) +#define __raw_readq(a) __arch_getq(a) + +/* IO accessors. No memory barriers desired. */ +static inline void iowrite(unsigned long val, unsigned long addr) +{ + __raw_writel(val, addr); +} + +static inline unsigned long ioread(unsigned long addr) +{ + return __raw_readl(addr); +} + +/* start timer */ +static void perf_start_clock(void) +{ + iowrite((1 << 0) | /* Timer Enable */ + (1 << 3) | /* Auto-increment */ + (0 << 8), /* Pre-scale */ + SCU_GLOBAL_TIMER_CONTROL); +} + +/* Compute mask for given delay in miliseconds*/ +static unsigned long get_number_of_cycles_for_delay(unsigned long delay) +{ + return (APU_FREQ / (2 * 1000)) * delay; +} + +/* stop timer */ +static void perf_disable_clock(void) +{ + iowrite(0, SCU_GLOBAL_TIMER_CONTROL); +} + +/* stop timer and reset timer count regs */ +static void perf_reset_clock(void) +{ + perf_disable_clock(); + iowrite(0, SCU_GLOBAL_TIMER_COUNT_L32); + iowrite(0, SCU_GLOBAL_TIMER_COUNT_U32); +} + +static void perf_reset_and_start_timer(void) +{ + perf_reset_clock(); + perf_start_clock(); +} + +int ps7_config(unsigned long *ps7_config_init) +{ + unsigned long *ptr = ps7_config_init; + unsigned long opcode; + unsigned long addr; + unsigned long val; + unsigned long mask; + unsigned int numargs; + int i; + unsigned long delay; + + for (;;) { + opcode = ptr[0]; + if (opcode == OPCODE_EXIT) + return PS7_INIT_SUCCESS; + addr = (opcode & OPCODE_ADDRESS_MASK); + + switch (opcode & ~OPCODE_ADDRESS_MASK) { + case OPCODE_MASKWRITE: + numargs = 3; + mask = ptr[1]; + val = ptr[2]; + iowrite((ioread(addr) & ~mask) | (val & mask), addr); + break; + + case OPCODE_WRITE: + numargs = 2; + val = ptr[1]; + iowrite(val, addr); + break; + + case OPCODE_MASKPOLL: + numargs = 2; + mask = ptr[1]; + i = 0; + while (!(ioread(addr) & mask)) { + if (i == PS7_MASK_POLL_TIME) + return PS7_INIT_TIMEOUT; + i++; + } + break; + + case OPCODE_MASKDELAY: + numargs = 2; + mask = ptr[1]; + delay = get_number_of_cycles_for_delay(mask); + perf_reset_and_start_timer(); + while (ioread(addr) < delay) + ; + break; + + default: + return PS7_INIT_CORRUPT; + } + + ptr += numargs; + } +} diff --git a/examples/blink/Makefile b/examples/blink/Makefile new file mode 100644 index 0000000..c786ea2 --- /dev/null +++ b/examples/blink/Makefile @@ -0,0 +1,6 @@ +BSPDIR = ../../bsp + +TARGET = blink.elf +SOURCES = blink.c + +include $(BSPDIR)/Makefile.inc diff --git a/examples/blink/blink.c b/examples/blink/blink.c new file mode 100644 index 0000000..759a858 --- /dev/null +++ b/examples/blink/blink.c @@ -0,0 +1,29 @@ +#include <stdint.h> + +#define MIO_PIN07_CTRL *((uint32_t *)0xF800071C) +#define MIO_PIN07_CTRL_GPIO0 0x00003200 + +#define GPIO_DIRM0 *((uint32_t *)0xE000A204) +#define GPIO_OEN0 *((uint32_t *)0xE000A208) +#define GPIO_DATA0 *((uint32_t *)0xE000A040) + +#define GPIO0_PIN7 0x80 + +void delay(uint32_t delay) { + for(volatile uint32_t i = 0; i < delay; i++); +} + +void init(void) +{ + MIO_PIN07_CTRL = MIO_PIN07_CTRL_GPIO0; + + GPIO_DIRM0 |= GPIO0_PIN7; + GPIO_OEN0 |= GPIO0_PIN7; + + while(1) { + GPIO_DATA0 &= ~GPIO0_PIN7; + delay(1000000); + GPIO_DATA0 |= GPIO0_PIN7; + delay(1000000); + } +} diff --git a/examples/uart/Makefile b/examples/uart/Makefile new file mode 100644 index 0000000..6ebdd6e --- /dev/null +++ b/examples/uart/Makefile @@ -0,0 +1,6 @@ +BSPDIR = ../../bsp + +TARGET = uart.elf +SOURCES = uart.c + +include $(BSPDIR)/Makefile.inc diff --git a/examples/uart/uart.c b/examples/uart/uart.c new file mode 100644 index 0000000..8fcd8df --- /dev/null +++ b/examples/uart/uart.c @@ -0,0 +1,114 @@ +#include <stdint.h> + +#define MIO_PIN07_CTRL *((uint32_t *)0xF800071C) +#define MIO_PIN07_CTRL_GPIO0 0x00003200 +#define GPIO_DIRM0 *((uint32_t *)0xE000A204) +#define GPIO_OEN0 *((uint32_t *)0xE000A208) +#define GPIO_DATA0 *((uint32_t *)0xE000A040) +#define GPIO0_PIN7 0x80 + +#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 POuint32_tER_TO_REGISTER(REG) ( *((volatile uint32_t*)(REG))) //u32 (xil_types.h) data type is declared as uuint32_t32_t (stduint32_t.h) + +#define UART_BASE XPS_UART1_BASEADDR // Base Address +#define UART_CTRL POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_CR_OFFSET) // Control Register +#define UART_MODE POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_MR_OFFSET) // Mode Register + +#define UART_BAUD_GEN POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_BAUDGEN_OFFSET) // Baud Rate Generator "CD" +#define UART_BAUD_DIV POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_BAUDDIV_OFFSET) // Baud Rate Divider "BDIV" +#define UART_FIFO POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_FIFO_OFFSET) // FIFO +#define UART_STATUS POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_SR_OFFSET) // Channel Status + +#define BUFFER_SIZE 20 + +static char str[] = "\tHello World\r"; + +// Send one character through UART interface +void uart_send(char c) { + while (UART_STATUS & XUARTPS_SR_TNFUL); + UART_FIFO = c; + while (UART_STATUS & XUARTPS_SR_TACTIVE); +} + +// Send string (character array) through UART interface +void uart_send_string(char str[BUFFER_SIZE]) { + char *ptr = str; + + while (*ptr != '\0') { + uart_send(*ptr); + ptr++; + } + } + +// Check if UART receive FIFO is not empty and return the new data +char uart_receive() { + if ((UART_STATUS & XUARTPS_SR_RXEMPTY) == XUARTPS_SR_RXEMPTY) return 0; + return UART_FIFO; +} + +void init(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; + + while(1) { + // Count to big number before exiting for loop - delay loop + for(uint32_t i = 1; i < (1 << 20); i++){ + uart_receive(); // polling UART receive buffer + } + + static char c = '0'; + uart_send(c++); // Send and increment character variable c + // If incremented over 'Z', initialize to '0' (ref: see ASCII character table) + if (c > 'Z') c = '0'; + uart_send_string(str); // Send character array variable str + + } +} |