diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2014-01-09 21:02:03 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2014-01-09 21:02:03 -0600 |
commit | 963b88fb0bb3a20bd4b6eb3d73095172a3760d55 (patch) | |
tree | 3e583da09ecf0406d471f1d438881dd6dd1cd05a /fpga/interface/beaglebone_black/gpmc | |
parent | 38c56c7c1fe4ecd7e5907cc14c100e4af3a87e20 (diff) | |
download | ulab-963b88fb0bb3a20bd4b6eb3d73095172a3760d55.tar.gz ulab-963b88fb0bb3a20bd4b6eb3d73095172a3760d55.zip |
Add initial GPMC test program and associated files for BeagleBone Black
Diffstat (limited to 'fpga/interface/beaglebone_black/gpmc')
4 files changed, 442 insertions, 0 deletions
diff --git a/fpga/interface/beaglebone_black/gpmc/test/BB-ULAB-00A0.dts b/fpga/interface/beaglebone_black/gpmc/test/BB-ULAB-00A0.dts new file mode 100644 index 0000000..e146171 --- /dev/null +++ b/fpga/interface/beaglebone_black/gpmc/test/BB-ULAB-00A0.dts @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2013 Tom King <ka6sox@gmail.com> + * (C) 2013 Ian McMahon <ian.mcmahon@prototechnical.com> + * (C) 2014 Timothy Pearson <kb9vqf@pearsoncomputing.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +/dts-v1/; +/plugin/; + +/ { + compatible = "ti,beaglebone", "ti,beaglebone-black"; + + /* identification */ + manufacturer = "Raptor Engineering"; + board-name = "Universal Laboratory Debug Control Interface"; + model = "ULABCTL001"; + part-number = "BB-BONE-ULAB"; + version = "0001"; + + /* state the resources this cape uses */ + exclusive-use = + /* the pin header uses */ + "P8.45", /* GPMC: gpmc_a0 */ + "P8.46", /* GPMC: gpmc_a1 */ + "P9.14", /* GPMC: gpmc_a2 */ + "P8.44", /* GPMC: gpmc_a3 */ + "P8.41", /* GPMC: gpmc_a4 */ + "P8.42", /* GPMC: gpmc_a5 */ + "P8.39", /* GPMC: gpmc_a6 */ + "P8.40", /* GPMC: gpmc_a7 */ + "P8.27", /* GPMC: gpmc_a8 */ + "P8.29", /* GPMC: gpmc_a9 */ + "P8.28", /* GPMC: gpmc_a10 */ + "P8.30", /* GPMC: gpmc_a11 */ + "P8.37", /* GPMC: gpmc_a12 */ + "P8.38", /* GPMC: gpmc_a13 */ + "P8.36", /* GPMC: gpmc_a14 */ + "P8.34", /* GPMC: gpmc_a15 */ + "P8.35", /* GPMC: gpmc_a16 */ + "P8.33", /* GPMC: gpmc_a17 */ + "P8.31", /* GPMC: gpmc_a18 */ + "P8.32", /* GPMC: gpmc_a19 */ + + "P8.25", /* GPMC: gpmc_ad0 */ + "P8.24", /* GPMC: gpmc_ad1 */ + "P8.5", /* GPMC: gpmc_ad2 */ + "P8.6", /* GPMC: gpmc_ad3 */ + "P8.23", /* GPMC: gpmc_ad4 */ + "P8.22", /* GPMC: gpmc_ad5 */ + "P8.3", /* GPMC: gpmc_ad6 */ + "P8.4", /* GPMC: gpmc_ad7 */ + + "P8.7", /* GPMC: gpmc_advn_ale */ + "P8.8", /* GPMC: gpmc_oen_ren */ + "P8.10", /* GPMC: gpmc_wen */ + + "P9.11", /* GPIO: gpio0[30] */ + "P9.13", /* GPIO: gpio0[31] */ + "P9.21", /* GPIO: gpio0[3] */ + "P9.22", /* GPIO: gpio0[2] */ + + "P8.43", /* GPIO: boot select */ + + /* the hardware IP this cape uses */ + "GPMC"; + + fragment@0 { + target = <&am33xx_pinmux>; + __overlay__ { + bb_gpmc_pins: pinmux_bb_gpmc_pins { + pinctrl-single,pins = < + + /* address bus */ + 0x0a0 0x01 /* gpmc_a0, OUTPUT_PULLDOWN | MODE1 */ + 0x0a4 0x01 /* gpmc_a1, OUTPUT_PULLDOWN | MODE1 */ + 0x048 0x00 /* gpmc_a2, OUTPUT_PULLDOWN | MODE0 */ + 0x0ac 0x01 /* gpmc_a3, OUTPUT_PULLDOWN | MODE1 */ + 0x0b0 0x01 /* gpmc_a4, OUTPUT_PULLDOWN | MODE1 */ + 0x0b4 0x01 /* gpmc_a5, OUTPUT_PULLDOWN | MODE1 */ + 0x0b8 0x01 /* gpmc_a6, OUTPUT_PULLDOWN | MODE1 */ + 0x0bc 0x01 /* gpmc_a7, OUTPUT_PULLDOWN | MODE1 */ + 0x0e0 0x01 /* gpmc_a8, OUTPUT_PULLDOWN | MODE1 */ + 0x0e4 0x01 /* gpmc_a9, OUTPUT_PULLDOWN | MODE1 */ + 0x0e8 0x01 /* gpmc_a10, OUTPUT_PULLDOWN | MODE1 */ + 0x0ec 0x01 /* gpmc_a11, OUTPUT_PULLDOWN | MODE1 */ + 0x0c0 0x01 /* gpmc_a12, OUTPUT_PULLDOWN | MODE1 */ + 0x0c4 0x01 /* gpmc_a13, OUTPUT_PULLDOWN | MODE1 */ + 0x0c8 0x01 /* gpmc_a14, OUTPUT_PULLDOWN | MODE1 */ + 0x0cc 0x01 /* gpmc_a15, OUTPUT_PULLDOWN | MODE1 */ + 0x0d0 0x01 /* gpmc_a16, OUTPUT_PULLDOWN | MODE1 */ + 0x0d4 0x01 /* gpmc_a17, OUTPUT_PULLDOWN | MODE1 */ + 0x0d8 0x01 /* gpmc_a18, OUTPUT_PULLDOWN | MODE1 */ + 0x0dc 0x01 /* gpmc_a19, OUTPUT_PULLDOWN | MODE1 */ + + /* address/data muxed bus */ + 0x000 0x30 /* gpmc_ad0, INPUT_PULLUP | MODE0 */ + 0x004 0x30 /* gpmc_ad1, INPUT_PULLUP | MODE0 */ + 0x008 0x30 /* gpmc_ad2, INPUT_PULLUP | MODE0 */ + 0x00c 0x30 /* gpmc_ad3, INPUT_PULLUP | MODE0 */ + 0x010 0x30 /* gpmc_ad4, INPUT_PULLUP | MODE0 */ + 0x014 0x30 /* gpmc_ad5, INPUT_PULLUP | MODE0 */ + 0x018 0x30 /* gpmc_ad6, INPUT_PULLUP | MODE0 */ + 0x01c 0x30 /* gpmc_ad7, INPUT_PULLUP | MODE0 */ + + /* control */ + 0x090 0x10 /* gpmc_advn_ale, OUTPUT_PULLUP | MODE0 */ + 0x094 0x10 /* gpmc_oen_ren, OUTPUT_PULLUP | MODE0 */ + 0x098 0x10 /* gpmc_wen, OUTPUT_PULLUP | MODE0 */ + + /* gpio */ + 0x070 0x07 /* gpio0[30], OUTPUT_PULLDOWN | MODE7 */ + 0x074 0x07 /* gpio0[31], OUTPUT_PULLDOWN | MODE7 */ + 0x154 0x27 /* gpio0[3], INPUT_PULLDOWN | MODE7 */ + 0x150 0x07 /* gpio0[2], OUTPUT_PULLDOWN | MODE7 */ + + >; + }; + }; + }; + + fragment@1 { + target = <&gpmc>; + depth = <1>; /* only create devices on depth 1 */ + + /* stupid warnings */ + #address-cells = <1>; + #size-cells = <1>; + + __overlay__ { + status = "okay"; + + #address-cells = <2>; + #size-cells = <1>; + + pinctrl-names = "default"; + pinctrl-0 = <&bb_gpmc_pins>; + + /* chip select ranges */ + ranges = <0 0 0x10000000 0x02000000>; /* CS0 @addr 0x01000000, size 0x02000000 */ + + sram@0 { + compatible = "raptorengineering,ulab","sram"; + address-cells = <1>; + size-cells = <1>; + bank-width = <1>; + }; + }; + }; +}; diff --git a/fpga/interface/beaglebone_black/gpmc/test/Makefile b/fpga/interface/beaglebone_black/gpmc/test/Makefile new file mode 100644 index 0000000..fc42856 --- /dev/null +++ b/fpga/interface/beaglebone_black/gpmc/test/Makefile @@ -0,0 +1,47 @@ +# Copyright (C) 2014 Timothy Pearson +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +AR = ar +RANLIB = ranlib +CC = gcc + +CFLAGS += -Wall -Os -ggdb -MD +#CFLAGS += -Wextra -Wno-unused-parameter -Werror + +help: + @echo "" + @echo "Usage:" + @echo "" + @echo " $(MAKE) bbb-gpmc-test" + @echo " .... build bbb-gpmc-test" + @echo "" + @echo " $(MAKE) all" + @echo " .... build everything" + @echo "" + @echo " $(MAKE) install" + @echo " .... install everything in /usr/" + @echo "" + +all: bbb-gpmc-test + +install: all + install -Dt /usr/bin/ bbb-gpmc-test + +bbb-gpmc-test: bbb-gpmc-test.o + +clean: + rm -f bbb-gpmc-test.o + +-include *.d + diff --git a/fpga/interface/beaglebone_black/gpmc/test/NOTES b/fpga/interface/beaglebone_black/gpmc/test/NOTES new file mode 100644 index 0000000..11a075f --- /dev/null +++ b/fpga/interface/beaglebone_black/gpmc/test/NOTES @@ -0,0 +1,3 @@ +Disable eMMC in uEnv.txt +Comment out eMMC block in /boot/dtbs/am335x-boneblack.dts (mmc@481d8000) +Compile and install uLab cape (BB-ULAB-00A0.dts) in /lib/firmware, then load it via the cape manager diff --git a/fpga/interface/beaglebone_black/gpmc/test/bbb-gpmc-test.c b/fpga/interface/beaglebone_black/gpmc/test/bbb-gpmc-test.c new file mode 100644 index 0000000..9b17634 --- /dev/null +++ b/fpga/interface/beaglebone_black/gpmc/test/bbb-gpmc-test.c @@ -0,0 +1,240 @@ +/* + * bbb-gpmc-test + * + * Copyright (C) 2014 Timothy Pearson <kb9vqf@pearsoncomputing.net> (Beaglebone Black) + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <sys/time.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> + + +/** BEGIN: Low-Level I/O Implementation **/ + +// Beaglebone Black GPMC driver + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> + +#define MEMORY_SPACE_ADDRESS_BITS 15 + +#define GPMC_BASE 0x50000000 +#define GPMC_REGLEN 0x10000000 + +#define GPMC_CHIPSELECTCONFIGDISPLACEMENT (0x30 / 4) + +#define GPMC_CONFIG (0x50 / 4) +#define GPMC_CONFIG1 (0x60 / 4) +#define GPMC_CONFIG2 (0x64 / 4) +#define GPMC_CONFIG3 (0x68 / 4) +#define GPMC_CONFIG4 (0x6c / 4) +#define GPMC_CONFIG5 (0x70 / 4) +#define GPMC_CONFIG6 (0x74 / 4) +#define GPMC_CONFIG7 (0x78 / 4) + +#define MEMORY_SIZE (1 << MEMORY_SPACE_ADDRESS_BITS) + +int mem_fd = 0; +int gpmc_mem_fd = 0; +char *gpio_mem, *gpio_map, *gpmc_map; + +// I/O access +static volatile unsigned int *gpio = NULL; +static volatile unsigned char *gpio_char = NULL; +static volatile unsigned int *gpmc = NULL; + +static void gpmc_mapregisters() +{ + /* open /dev/mem */ + if ((gpmc_mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { + printf("can't open /dev/mem \n"); + exit (-1); + } + + /* mmap GPMC */ + gpmc_map = (char *)mmap( + 0, + GPMC_REGLEN, + PROT_READ|PROT_WRITE, + MAP_SHARED, + gpmc_mem_fd, + GPMC_BASE + ); + + if (gpmc_map == MAP_FAILED) { + printf("mmap error %d\n", (int)gpmc_map); + exit (-1); + } + + // Always use volatile pointer! + gpmc = (volatile unsigned *)gpmc_map; +} + +static void gpmc_unmapregisters() +{ + munmap((void*) gpmc, GPMC_REGLEN); + if (gpmc_mem_fd != -1) { + close(gpmc_mem_fd); + } +} + +static void gpmc_setup(void) +{ + // WARNING: The GPMC runs at the L3 clock frequency! + // It is not well documented, but that frequency seems to be 200MHz on the AM335x series of chips + + gpmc_mapregisters(); + + if (gpmc != NULL) { + int chipselect = 0; + int displacement = GPMC_CHIPSELECTCONFIGDISPLACEMENT * chipselect; + + // disable before playing with the registers + *(gpmc + displacement + GPMC_CONFIG7) = 0x00000000; + + *(gpmc + displacement + GPMC_CONFIG) = 0x00000000; // Unlimited address space + *(gpmc + displacement + GPMC_CONFIG1) = 0x00000000; // No burst, async, 8-bit, non multiplexed + +// // 200MHz compatible SRAM device +// *(gpmc + displacement + GPMC_CONFIG2) = 0x00000800; // Assert CS on fclk 0, deassert CS on fclk 8 +// *(gpmc + displacement + GPMC_CONFIG3) = 0x00000200; // Assert ADV on fclk0, deassert ADV on fclk2 +// *(gpmc + displacement + GPMC_CONFIG4) = 0x06020802; // Assert WE on fclk2, deassert WE on fclk6, assert OE on fclk2, deassert OE on fclk8 +// *(gpmc + displacement + GPMC_CONFIG5) = 0x00060808; // Data valid on fclk 6, cycle time 8 fclks + + // 100MHz compatible SRAM device + *(gpmc + displacement + GPMC_CONFIG2) = 0x00001000; // Assert CS on fclk0, deassert CS on fclk16 + *(gpmc + displacement + GPMC_CONFIG3) = 0x00000400; // Assert ADV on fclk 0, deassert ADV on fclk 4 + *(gpmc + displacement + GPMC_CONFIG4) = 0x0c041004; // Assert WE on fclk4, deassert WE on fclk12, assert OE on fclk4, deassert OE on fclk16 + *(gpmc + displacement + GPMC_CONFIG5) = 0x000c1010; // Data valid on fclk 12, cycle time 16 fclks + + *(gpmc + displacement + GPMC_CONFIG6) = 0x00000000; // No back to back cycle restrictions + *(gpmc + displacement + GPMC_CONFIG7) = 0x00000e50; // CS0: Set base address 0x10000000, 32MB region, and enable CS + + gpmc_unmapregisters(); + } +} + +static void io_setup(void) +{ + printf("sizeof int:\t%d\n", sizeof(int)); + + /* open /dev/mem */ + if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { + printf("can't open /dev/mem \n"); + exit (-1); + } + + /* mmap GPIO */ + gpio_map = (char *)mmap( + 0, + MEMORY_SIZE, + PROT_READ|PROT_WRITE, + MAP_SHARED, + mem_fd, + 0x10000000 + ); + + if (gpio_map == MAP_FAILED) { + printf("mmap error %d\n", (int)gpio_map); + exit (-1); + } + + // Always use volatile pointer! + gpio = (volatile unsigned *)gpio_map; + gpio_char = (volatile unsigned char *)gpio_map; + + // Select a test from the following blocks of code... + +// // DEBUG ONLY +// // Clear out the mapped memory +// int i; +// for (i=0;i<0x3ff; i++) { +// *(gpio + i) = 0x00000000; +// } + + // DEBUG ONLY + // Fill the mapped memory with a test pattern +// int j; +// for (j=0;j<0x00001000; j++) { +// *(gpio + j) = j; +// } +// int j; +// for (j=0;j<0x3ff; j++) { +// *(gpio + j) = j; +// } + int j; + for (j=0;j<MEMORY_SIZE; j++) { + *(gpio_char + j) = ((unsigned char)j); + } + + // DEBUG ONLY + // Prints the contents of the mapped memory + int k; + for (k=0;k<(MEMORY_SIZE/4); k++) { + printf("0x%08x\t%08x\n", k, *(gpio + k)); + } + fflush(stdout); + +// // DEBUG ONLY +// // Excercise the memory space +// int l; +// while (1) { +// for (l=0;l<(MEMORY_SIZE/4); l++) { +// k = *(gpio + l); +// } +// } + +// while (1) { +// printf("0x%08x\t0x%08x\t0x%08x\t0x%08x\r", *(gpio + 0), *(gpio + 1), *(gpio + 2), *(gpio + 3)); +// usleep(1); +// } + +// while (1) { +// printf("0x%08x\t0x%08x\t0x%08x\t0x%08x\r", *(gpio + 3), *(gpio + 2), *(gpio + 1), *(gpio + 0)); +// usleep(1); +// } + +// printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\n\r", *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0)); +// + while (1) { +// printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\r", *(gpio_char + 0), *(gpio_char + 1), *(gpio_char + 2), *(gpio_char + 3), *(gpio_char + 4), *(gpio_char + 5), *(gpio_char + 6), *(gpio_char + 7)); +// printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\r", *(gpio_char + 0), *(gpio_char + 1), *(gpio_char + 2), *(gpio_char + 3), *(gpio_char + 0x1000), *(gpio_char + 0x1001), *(gpio_char + 0x1002), *(gpio_char + 0x1003)); + printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\r", *(gpio_char + 0), *(gpio_char + 1), *(gpio_char + 2), *(gpio_char + 3), *(gpio_char + 0x4000), *(gpio_char + 0x4001), *(gpio_char + 0x4002), *(gpio_char + 0x4003)); +// printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\r", *(gpio_char + 0x4000), *(gpio_char + 0x4001), *(gpio_char + 0x4002), *(gpio_char + 0x4003), *(gpio_char + 0x4000), *(gpio_char + 0x4001), *(gpio_char + 0x4002), *(gpio_char + 0x4003)); + usleep(10); + } +} + +static void io_shutdown(void) +{ + // +} + +/** END: Low-Level I/O Implementation **/ + +int main(int argc, char **argv) +{ + gpmc_setup(); + printf("GPMC setup complete!\n"); fflush(stdout); + io_setup(); + return 0; +} + |