/* * bbb-gpmc-test * * Copyright (C) 2014 Timothy Pearson (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 #include #include #include #include #include /** BEGIN: Low-Level I/O Implementation **/ // Beaglebone Black GPMC driver #include #include #include #include #define MEMORY_SPACE_ADDRESS_BITS 16 #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 // 50MHz compatible SRAM device *(gpmc + displacement + GPMC_CONFIG2) = 0x00001f00; // Assert CS on fclk0, deassert CS on fclk31 *(gpmc + displacement + GPMC_CONFIG3) = 0x00000400; // Assert ADV on fclk 0, deassert ADV on fclk 4 *(gpmc + displacement + GPMC_CONFIG4) = 0x1f041f04; // Assert WE on fclk4, deassert WE on fclk31, assert OE on fclk4, deassert OE on fclk31 *(gpmc + displacement + GPMC_CONFIG5) = 0x00101f1f; // Data valid on fclk 16, cycle time 31 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; // } // DEBUG ONLY // Looping memory test unsigned int test_base = (MEMORY_SIZE/2); unsigned int test_length = (MEMORY_SIZE/2); unsigned int total_errors; unsigned char error_count[MEMORY_SIZE]; int i; int loop; unsigned int overall_total_errors; overall_total_errors = 0; for (loop=0; loop<10;loop++) { printf("Memory test loop %d\n", loop); for (i=0; i 0) { printf("\t%d\terror(s) found at offset 0x%02x\n", error_count[i], i); } } printf("\tTesting all ones/zeros\n"); // Test with 0xff for (i=0;i 0) { printf("\t%d\terror(s) found at offset 0x%02x\n", error_count[i], i); } } printf("\tTest region size:\t%d\n", test_length); printf("\tTotal errors found:\t%d\n", total_errors); fflush(stdout); overall_total_errors = overall_total_errors + total_errors; } for (i=0;i