This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/PROCESSOR-SDK-AM437X: A/D multiplexed 8-bit GPMC

Part Number: PROCESSOR-SDK-AM437X

Tool/software: Linux

Hi Forum,

I have been trying to implement 8bit address data multiplexed GPMC bus to my FPGA. There are a few problems getting it going. I hope you guys would be of help.

	gpmc_default: gpmc_default {
 	pinctrl-single,pins = < 

		0x3c ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (A11) gpmc_ad15.gpmc_ad15 */
		0x38 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (B11) gpmc_ad14.gpmc_ad14 */
		0x34 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (C11) gpmc_ad13.gpmc_ad13 */
		0x30 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (E11) gpmc_ad12.gpmc_ad12 */
		0x2c ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (D11) gpmc_ad11.gpmc_ad11 */
		0x28 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (F11) gpmc_ad10.gpmc_ad10 */
		0x24 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (A10) gpmc_ad9.gpmc_ad9 */
		0x20 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (B10) gpmc_ad8.gpmc_ad8 */
		0x1c ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (B8) gpmc_ad7.gpmc_ad7 */
		0x18 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (C8) gpmc_ad6.gpmc_ad6 */
		0x14 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (A7) gpmc_ad5.gpmc_ad5 */
		0x10 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (B7) gpmc_ad4.gpmc_ad4 */
		0xc  ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (A6) gpmc_ad3.gpmc_ad3 */
		0x8  ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (B6) gpmc_ad2.gpmc_ad2 */
		0x4  ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (A5) gpmc_ad1.gpmc_ad1 */
		0x0  ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (B5) gpmc_ad0.gpmc_ad0 */
		0x70 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (A2) gpmc_wait0.gpmc_wait0 */
		0x8c ( PIN_INPUT_PULLUP | MUX_MODE2 ) /* (A12) gpmc_clk.gpmc_wait1 */
		0x7c ( PIN_OUTPUT | MUX_MODE0 ) /* (A8) gpmc_csn0.gpmc_csn0 */
		0x88 ( PIN_OUTPUT | MUX_MODE0 ) /* (B12) gpmc_csn3.gpmc_csn3 */
		0x74 ( PIN_OUTPUT | MUX_MODE2 ) /* (B3) gpmc_wpn.gpmc_csn5 */
		0x78 ( PIN_OUTPUT | MUX_MODE2 ) /* (A3) gpmc_be1n.gpmc_csn6 */
		0x90 ( PIN_OUTPUT | MUX_MODE0 ) /* (A9) gpmc_advn_ale.gpmc_advn_ale */
		0x94 ( PIN_OUTPUT | MUX_MODE0 ) /* (E10) gpmc_oen_ren.gpmc_oen_ren */
		0x98 ( PIN_OUTPUT | MUX_MODE0 ) /* (D10) gpmc_wen.gpmc_wen */
		0x9c ( PIN_OUTPUT | MUX_MODE0 ) /* (C10) gpmc_be0n_cle.gpmc_be0n_cle */


			
		>;
	};

&gpmc {
	status = "okay"; /* Disable eMMC when enabling GPMC/NAND */
	pinctrl-names = "default";
	pinctrl-0 = <&gpmc_default>;        
        ranges = <3 0 0x02000000 0x00020000>


    sram@3,0 {
        reg = <3 0 0x00100000>;       
        bank-width = <1>;
        gpmc,async-read;        
        gpmc,async-write;       
        gpmc,clk-activation-ns = <20>;    
        gpmc,burst-length = <16>; 
        gpmc,mux-add-data = <2>;
        gpmc,sync-clk-ps = <10000>;
        gpmc,cs-on-ns = <0>;
        gpmc,cs-rd-off-ns = <141>;
        gpmc,cs-wr-off-ns = <141>;
        gpmc,adv-on-ns = <0>;     
        gpmc,adv-rd-off-ns = <75>;
        gpmc,adv-wr-off-ns = <75>;
        gpmc,we-on-ns = <85>;     
        gpmc,we-off-ns = <123>;
        gpmc,oe-on-ns = <85>;
        gpmc,oe-off-ns = <141>;
        gpmc,page-burst-access-ns = <10>; 
        gpmc,access-ns = <50>;
        gpmc,rd-cycle-ns = <150>;
        gpmc,wr-cycle-ns = <150>;
        gpmc,wr-access-ns = <0>;      
        gpmc,wr-data-mux-bus-ns = <85>;
        gpmc,bus-turnaround-ns = <10>;        
        gpmc,cycle2cycle-samecsen;      
        gpmc,cycle2cycle-delay-ns = <10>;   


    };

the above is my device tree timings.

#include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>



#define GPMC_BASE 0x02000000
static int devmemfd = -1;

//map memory of length "len" at offset "offset"
static void* util_mapmemoryblock(off_t offset, size_t len)
{
	devmemfd = open("/dev/mem", O_RDWR | O_SYNC);
	void* registers = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, devmemfd, offset);
	if (registers == MAP_FAILED) {
		printf("Map failed\n");
	}
	return registers;
}

static void util_unmapmemoryblock(void* block, size_t len)
{
	munmap((void*) block, len);
	if (devmemfd != -1) {
		close(devmemfd);
	}
}

#define REGLEN 0x00020000

static volatile uint32_t* registers = NULL;

static void gpmc_mapregisters()
{
	registers = (uint32_t*) util_mapmemoryblock(GPMC_BASE, REGLEN);
}

static void gpmc_unmapregisters()
{
	util_unmapmemoryblock((void*) registers, REGLEN);
}

void gpmc_setup(void)
{
	gpmc_mapregisters();
	gpmc_unmapregisters();
}

volatile uint8_t* extbus;

void bus_init() {
	gpmc_setup();
	extbus = (uint8_t*) util_mapmemoryblock(GPMC_BASE, REGLEN);
}

void bus_writebyte(uint8_t address, uint8_t data) {
	*(extbus + (address<<1)) = data;
}

uint8_t bus_readbyte(uint8_t address) {


	return*(extbus + (address<<1));

}

void bus_shutdown() {
	util_unmapmemoryblock((void*) extbus, 0x200);
}
int main(int argc, char const *argv[]) {
	int i,a,f;
	int array[10];
	bus_init();
/*	for (i = 0; i < 10; i++) {
		printf("byte at address %x: %X\n", i, bus_readbyte(i));
	}*/
	if (strcmp("write", argv[1]) == 0) {
		a = strtol(argv[2], NULL, 0);
		f = strtol(argv[3], NULL, 0);
		bus_writebyte(a,f);
	}
	if (strcmp("read", argv[1]) == 0) {
		a = strtol(argv[2], NULL, 0);
		printf("read value: %x \n",bus_readbyte(a));
	}
	if (strcmp("writetest", argv[1]) == 0) {
		for (i = 0; i < 10; i++) {
			bus_writebyte(i,0xaa);
			}
	}
		if (strcmp("readtest", argv[1]) == 0) {
		for (i = 0; i < 10; i++) {
			array[i]=bus_readbyte(i);
			printf("byte at address %x: %X\n", i, array[i]);
			}

	}
	bus_shutdown();
	return 0;
}

The problems I am facing right now

  • my writes work fine and I could see the address and data works fine when i do a ./main 0x00 0x03 and so on.
  • but when i do a read from the register the reads always return back the physical address of my asic instead of returning me the data.
./main write 0x02 0x04
./main write 0x03 0x05

./main read 0x02
readvalue: 0x02
./main read 0x03
readvalue: 0x03

I am expecting the reads to return back the actual value written in my case (0x04 and 0x05) I can see the data arriving at the cpu through my logic analyzer but unfortunately my returns does not corellate to the values i see on the logic analyzer.

Any suggestions would be appreciated.

Regards

-Parker

  • Hi,

    GPMC address mapping supports address/data-multiplexed 16-bit wide devices:

    • The NOR flash memory controller still supports non-multiplexed address and data memory devices.
    • Multiplexing mode can be selected through the GPMC_CONFIG1_i[9-8] MUXADDDATA bit field.
    • Asynchronous page mode is not supported for multiplexed address and data devices.
  • Hi Biser,

    form what you say:
    so from what you say i will not be able to use 8 bit address data multiplexed bus to perform a asynchronous read or write ???

    How do i access the gpmc registers from the user space ??

    are my above understandings correct ?

    Regards
    -Parker
  • See Table 9-4 from the AM437x TRM Rev. F. GPMC_AD[15:0] pins output A[16:1] and D[15:0] in A/D muxed mode. You can read/write only to/from 16-bit addresses.
  • Let me rephrase my question,

    I have the 16 address data pins and the control pins that i have specified in the dts file above.

    I have 2 bit gpmc memory map regions to 2 fpga's and 2 16 bit memory map regions to two other fpga's. how do i perform a single read and single write on the bus ?? do i have to configure my gpmc devices as a nand or nor ?? what is the procedure to write to a register and read back from the registers within the asic.

    i your previous post multiplexing "Multiplexing mode can be selected through the GPMC_CONFIG1_i[9-8] MUXADDDATA bit field" my understanding was the "gpmc,mux-add-data = <2>;" definition in my dts does the same. correct if i am wrong.

    Regards
    -Parker
  • For A/D mux mode your peripherals should behave as NOR. What I meant to say is that in this mode address bit 0 is not output on the GPMC bus, meaning that writing to address XXXXXX0b and writing to address XXXXXX1b will address the same external memory location. Same for reads.
  • Hi biser,
    If you see my c snippet you will find that i am shifting the address and data by a bit so i am not using the bit 0 at all. I still dont understand why the reads dont work. I have double checked the timings again and tried all my tests. still no positive result for reads.

    Regards
    -parker
  • What addresses do you read/write to? GPMC is memory mapped, so you should use absolute addresses.
  • Hi Biser,

    My base address is 0x02000000
    and the size of the memory mapped region ix 0x00020000
    so from the command line if i do a devmem2 0x02000000 b 0x01 ( i expect it to write to address 0 value 1 on my fpga)
    if i read the from command line devmem2 0x02000000 b (i expect to read back the 1 which i wrote in the previous command).

    read back always return me the physical address but not the value stored in the physical address.

    what do you mean by absolute address in your previous command ??

    Regards
    -Parker
  • Hi,

    if i read the from command line devmem2 0x02000000 b (i expect to read back the 1 which i wrote in the previous command).

    read back always return me the physical address but not the value stored in the physical address.


    This is quite strange behaviour. Could you copy paste your console output when you read with devmem2?
    Also can you execute cat /proc/iomem and share the output?

    Best Regards,
    Yordan
  • Also see this thread for additional info on how to interface gpmc with sram devices:
    e2e.ti.com/.../512464

    Best Regards,
    Yordan
  • Hi Yordan,

    below is my log for the questions you have asked.

    root@am437x-evm:/bin# cat /proc/iomem
    40300000-4033ffff : 40300000.ocmcram
    44000000-443fffff : /ocp
    44800000-44bfffff : /ocp
    44d00000-44d03fff : umem
    44d80000-44d81fff : dmem
    44e07000-44e07fff : /ocp/gpio@44e07000
    44e09000-44e0901f : serial
    44e0b000-44e0bfff : /ocp/i2c@44e0b000
    44e0d000-44e0dfff : /ocp/tscadc@44e0d000
    44e10650-44e10653 : gmii-sel
    44e10800-44e10b1b : pinctrl-single
    44e11324-44e11367 : /ocp/l4_wkup@44c00000/scm@210000/wkup_m3_ipc@1324
    44e35000-44e35fff : /ocp/wdt@44e35000
    44e3e000-44e3efff : /ocp/rtc@44e3e000
    4802a000-4802afff : /ocp/i2c@4802a000
    48030100-480304ff : /ocp/spi@48030000
    4804c000-4804cfff : /ocp/gpio@4804c000
    48060000-48060fff : /ocp/mmc@48060000
    48080000-48081fff : /ocp/elm@48080000
    480c8000-480c81ff : /ocp/mailbox@480C8000
    481a0100-481a04ff : /ocp/spi@481a0000
    481a6000-481a601f : serial
    481ac000-481acfff : /ocp/gpio@481ac000
    481ae000-481aefff : /ocp/gpio@481ae000
    481cc000-481cdfff : /ocp/can@481cc000
    481d0000-481d1fff : /ocp/can@481d0000
    48300000-4830000f : /ocp/epwmss@48300000
    48310000-48311fff : /ocp/rng@48310000
    48320000-48320fff : /ocp/gpio@48320000
    48322000-48322fff : /ocp/gpio@48322000
    48345100-483454ff : /ocp/spi@48345000
    48380000-4838ffff : /ocp/omap_dwc3@48380000
    483c0000-483cffff : /ocp/omap_dwc3@483c0000
    483d0000-483d7fff : /ocp/omap_dwc3@483c0000/usb@483d0000
      483d0000-483d7fff : /ocp/omap_dwc3@483c0000/usb@483d0000
    483dc100-483dffff : /ocp/omap_dwc3@483c0000/usb@483d0000
    49000000-4900ffff : /ocp/edma@49000000
    4a100000-4a1007ff : /ocp/ethernet@4a100000
    4a101000-4a1010ff : /ocp/ethernet@4a100000/mdio@4a101000
    4a101200-4a1012ff : /ocp/ethernet@4a100000
    4c000000-4cffffff : /ocp/emif@4c000000
    50000000-50001fff : /ocp/gpmc@50000000
    53100000-531002ff : /ocp/sham@53100000
    53501000-5350109f : /ocp/aes@53501000
    53701000-5370109f : /ocp/des@53701000
    80000000-bfffffff : System RAM
      80008000-808760ab : Kernel code
      808bc000-8093bd07 : Kernel data
    root@am437x-evm:/bin#

    the reads using devmem2

    root@am437x-evm:/bin# devmem2 0x02000000 b
    /dev/mem opened.
    Memory mapped at address 0xb6fa6000.
    Read at address  0x02000000 (0xb6fa6000): 0x00
    root@am437x-evm:/bin# devmem2 0x02000001 b
    /dev/mem opened.
    Memory mapped at address 0xb6f10000.
    Read at address  0x02000001 (0xb6f10001): 0x00
    root@am437x-evm:/bin# devmem2 0x02000002 b
    /dev/mem opened.
    Memory mapped at address 0xb6fa8000.
    Read at address  0x02000002 (0xb6fa8002): 0x01
    root@am437x-evm:/bin# devmem2 0x02000003 b
    /dev/mem opened.
    Memory mapped at address 0xb6fa6000.
    Read at address  0x02000003 (0xb6fa6003): 0x01
    root@am437x-evm:/bin# devmem2 0x02000004 b
    /dev/mem opened.
    Memory mapped at address 0xb6ff6000.
    Read at address  0x02000004 (0xb6ff6004): 0x02
    root@am437x-evm:/bin# devmem2 0x02000005 b
    /dev/mem opened.
    Memory mapped at address 0xb6f03000.
    Read at address  0x02000005 (0xb6f03005): 0x02
    root@am437x-evm:/bin# devmem2 0x02000006 b
    /dev/mem opened.
    Memory mapped at address 0xb6f42000.
    Read at address  0x02000006 (0xb6f42006): 0x03
    root@am437x-evm:/bin# devmem2 0x02000007 b
    /dev/mem opened.
    Memory mapped at address 0xb6f76000.
    Read at address  0x02000007 (0xb6f76007): 0x03
    root@am437x-evm:/bin# devmem2 0x02000000 b 0x01
    /dev/mem opened.
    Memory mapped at address 0xb6fb3000.
    Read at address  0x02000000 (0xb6fb3000): 0x00
    Write at address 0x02000000 (0xb6fb3000): 0x01, readback 0x01
    root@am437x-evm:/bin# devmem2 0x02000001 b 0x01
    /dev/mem opened.
    Memory mapped at address 0xb6f7a000.
    Read at address  0x02000001 (0xb6f7a001): 0x00
    Write at address 0x02000001 (0xb6f7a001): 0x01, readback 0x01
    root@am437x-evm:/bin# devmem2 0x02000002 b 0x01
    /dev/mem opened.
    Memory mapped at address 0xb6fe6000.
    Read at address  0x02000002 (0xb6fe6002): 0x01
    Write at address 0x02000002 (0xb6fe6002): 0x01, readback 0x01
    root@am437x-evm:/bin# devmem2 0x02000003 b 0x01
    /dev/mem opened.
    Memory mapped at address 0xb6f4c000.
    Read at address  0x02000003 (0xb6f4c003): 0x01
    Write at address 0x02000003 (0xb6f4c003): 0x01, readback 0x01
    root@am437x-evm:/bin# devmem2 0x02000004 b 0x01
    /dev/mem opened.
    Memory mapped at address 0xb6f55000.
    Read at address  0x02000004 (0xb6f55004): 0x02
    Write at address 0x02000004 (0xb6f55004): 0x01, readback 0x01
    root@am437x-evm:/bin# devmem2 0x02000005 b 0x01
    /dev/mem opened.
    Memory mapped at address 0xb6f23000.
    Read at address  0x02000005 (0xb6f23005): 0x02
    Write at address 0x02000005 (0xb6f23005): 0x01, readback 0x01
    root@am437x-evm:/bin# devmem2 0x02000005 h 0x01
    /dev/mem opened.
    Memory mapped at address 0xb6ff5000.
    Read at address  0x02000005 (0xb6ff5004): 0x0202
    Write at address 0x02000005 (0xb6ff5004): 0x0001, readback 0x0001
    root@am437x-evm:/bin# devmem2 0x02000005 b 0x01
    /dev/mem opened.
    Memory mapped at address 0xb6f24000.
    Read at address  0x02000005 (0xb6f24005): 0x02
    Write at address 0x02000005 (0xb6f24005): 0x01, readback 0x01
    root@am437x-evm:/bin# devmem2 0x02000005 b
    /dev/mem opened.
    Memory mapped at address 0xb6f05000.
    Read at address  0x02000005 (0xb6f05005): 0x02
    root@am437x-evm:/bin# devmem2 0x02000004 b
    /dev/mem opened.
    Memory mapped at address 0xb6fcf000.
    Read at address  0x02000004 (0xb6fcf004): 0x02
    root@am437x-evm:/bin# devmem2 0x02000002 b
    /dev/mem opened.
    Memory mapped at address 0xb6fdd000.
    Read at address  0x02000002 (0xb6fdd002): 0x01
    root@am437x-evm:/bin# devmem2 0x02000001 b
    /dev/mem opened.
    Memory mapped at address 0xb6efd000.
    Read at address  0x02000001 (0xb6efd001): 0x00
    root@am437x-evm:/bin# devmem2 0x02000000 b
    /dev/mem opened.
    Memory mapped at address 0xb6f9d000.
    Read at address  0x02000000 (0xb6f9d000): 0x00
    root@am437x-evm:/bin#

    Regards

    -Parker

  • Hi Yordan,

    i finally got the bus to read the

    gpmc,access-ns = <50>;

    was too short on the bus so the time the gpmc read was reading the address was still present on the ad lines by extending it to

    gpmc,access-ns = <123>;

    i got the read backs working

    your help is much appreciated

    Regards

    -Parker

  • Hi, 

    Thanks for updating the thread. 

    Best Regards, 
    Yordan