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.

DMA uses GPMC settings?

Other Parts Discussed in Thread: AM3517, OMAP3530, 4460, 4430

Hi,

I have an OMAP3530-EVM-like board with an FPGA on the GPMC bus.  I've set  CYCLE2CYCLESAMECSEN (GPMC_CONFIG6) so that chip select toggles for each transfer as the FPGA requires and I've enabled WAIT1 to signal read/write completion.  Word transfers in Linux using "value=__raw_readw(fpga_addr)" work fine.

I tried enabling DMA for reading from the FPGA, but I'm not getting any values (all 0xff).  DMA from RAM to RAM works fine, but not from the device.  Are there other DMA settings which would affect how chip select is used, or how the transfers are timed?

 

Thanks!

,

John

 

  • Hello John,

    Have you configured the external sDMA pins?  This is described in Chapter 6 section 6.2 of the OMAP35x TRM.

  • Hi Jeff,

    The transfer is only software initiated.  It seemed from the docs (chapter 9.2 in spruf98d) that since the peripheral would not request DMA that I'd not need to configure external sys_ndmareq pins.  Is this assumption correct?

     

    Thanks,

    John

     

  • Oops.  I found that the problem was a bad source address for the DMA.  Using the physical base address returned from gpmc_cs_request() did the trick.

     

    ,

    John

  • I'm working on a character device GPMC driver module to read data from an FPGA and need some advice on how to approach this. 
    So far I am able to request a chip select (2) and register my device succesfully as well as able to write and read to the
    GPMC configuration registers with raw_read and raw_write.

    (my driver code snippet)
    gpmc_base = ioremap(OMAP34XX_GPMC_BASE, SZ_4K);
    err = gpmc_cs_request(gpmc_fpga_data->cs, FPGA_IO_SIZE, &gpmc_fpga_data->phys_base);
    err = platform_device_register(&gpmc_fpga_device);


    So now that I think I can configure the GPMC to my desire, I'm  confused as to how I actually trigger a read data
    operation from my FPGA device (NOR-like).  I read earlier someone suggesting to use sDMA, Can someone give me some
    idea as to how I would go about performing a read operation with or without sDMA?  More details the better as I'm
    new to GPMC/Memory mapped world.

  • Hi Joe Joe,

    It looks like you are writing a Linux driver.  Without DMA, the driver can read a register across the GPMC with just something like:

    __raw_readw(gpmc_base + YOUR_FPGA_DATA_REGISTER_OFFSET);

     

    With DMA there's much more setup to define the transfer.  In my case, I have a single data register in our FPGA so the source address for the transfer remains the same (AMODE_CONSTANT) while the destination address in CPU RAM increments for each read.  If your FPGA appears on the GPMC bus as a memory with each location a different address, then both source and destination addresses will increment.  Also, the contiguous block of memory I use on the CPU side is reserved at the top of RAM using "mem=" kernel boot parameter set in u-boot.

     

    Here's how I did it:

     

    /* In driver probe */

    omap_request_dma(OMAP24XX_DMA_GPMC, "FPGA rcv", your_fpga_dma_cb, info, &info->dma_channel_num);


    /* DMA completion callback */

    static void your_fpga_dma_cb(int channel_num, u16 ch_status, void *data)
    {
        struct your_fpga_info *info;

        /* Wake process waiting for dma to complete */
        info = (struct your_fpga_info *)data;
        complete(&info->dma_complete);
    }

    /* Starting the DMA and waiting for its completion */

      dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
      dma_params.src_start = info->phys_base + YOUR_FPGA_DATA_REGISTER_OFFSET;
      dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT;
      dma_params.dst_start = YOUR_DEST_BUFFER_PHYS_ADDR;
      dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
      dma_params.dst_ei = 1;
      dma_params.dst_fi = 1;
       
      dma_params.elem_count = YOUR_NUMBER_OF_ELEMENTS;
      dma_params.frame_count = YOUR_NUMBER_OF_FRAMES;
      omap_set_dma_params(info->dma_channel_num, &dma_params);     
      omap_set_dma_src_burst_mode(info->dma_channel_num, OMAP_DMA_DATA_BURST_DIS);
      omap_set_dma_dest_burst_mode(info->dma_channel_num, OMAP_DMA_DATA_BURST_DIS);
      INIT_COMPLETION(info->dma_complete);
      omap_start_dma(info->dma_channel_num);

     

    I hope this helps,

    John

     

  •  

    Hi John,

    Thanks for fast response, before I jump into the DMA, I just want to trigger a simple read instruction with your first suggestion, using __raw_readw.

    #define OMAP34XX_GPMC_BASE   0x6E000074

    gpmc_base = ioremap(OMAP34XX_GPMC_BASE, SZ_4K);
    err = gpmc_cs_request(gpmc_fpga_data->cs, FPGA_IO_SIZE, &gpmc_fpga_data->phys_base);
    err = platform_device_register(&gpmc_fpga_device);

    When I try raw reading from the gpmc_base (__raw_readw(gpmc_base + offset);), I read back the configuration registers depending on my offset, what would my "YOUR_FPGA_DATA_REGISTER_OFFSET" have to be to prevent from reading my configuration GPMC registers and instead read from the FPGA?

    From reading the technical reference manual, it looks like the memory mapping, described in ch 2, is involved to perform a GPMC read.  Am I supposed to be reading the  returned phys_base address, returned by the gpmc_cs_request  instead.  BTW, I tried that too and my kernel crashed.  


    Can you just go a little more in detail on the _raw_readw approach for now?

  • Sorry, typo on my GPMC_BASE, should be the following.

    #define OMAP34XX_GPMC_BASE   0x6E000000

  • I think I figured out my problem.  I simply needed to ioremap the physical GPMC memory mapped address (0x1000000 in my case) and use the mapped address for the __raw_readw.  Next, I'll be experimenting with the DMA. 

    Thanks again for help.

  • Hi, 

    I am trying to setup a dma operation to copy memory from GPMC address space into RAM as suggested above but I end up with a DMA transaction
    error (kernel OOPS) when I start the transfer with omap_start_dma(info->dma_channel_num). Any suggestions on what I can be causing this issue?

    I still remain unsure about the src_start and dst_start parameters. In a previous comment, it was mentioned that the src_start would have to be the
    address returned by the the cs request, phys_base in my case.

    err = gpmc_cs_request(gpmc_fpga_data->cs, FPGA_IO_SIZE, &gpmc_fpga_data->phys_base);
    gpmc_phys_base = ioremap(gpmc_fpga_data->phys_base, SZ_16M);
    dma_params.src_start = gpmc_phys_base;


    Should I do the same for the dst_start address? If so, what part of RAM can I use for this? I see in spruf98k p.g. 997, they are suggesting to use
    0x80F00000 for this. Should I do something like the following then?

    dma_params.dst_start = ioremap(0x80F00000, SZ_16M);

    Is 0x80F00000 a proper RAM memory region to use? Any help would be greatly appreciated.
  • Hi Joe Joe,

    For my src_start (source=FPGA), I use the physical address returned by gpmc_cs_request(), which would be gpmc_fpga_data->phys_base in your case, not an ioremapped address as is needed for __raw_read*(), __raw_write*(), etc.

     

    For the destination start (dest=RAM), for my platform, I have 128MB of RAM with a base address of 0x80000000, and I reserve 16M at the top of RAM with the bootloader "mem=112" parameter as I mentioned before.  I calculate the address for the DMA destination start with: 0x80000000+((128-16)*1024*1024) = 0x87000000.

     

    Good luck!,

    John

  • Hi, Thanks for previous suggestion, that worked for me and I'm now able to configure and trigger a DMA transfer w/o kernel OOPS. However, I'm still having issues performing a fully successful DMA transfer either from GPMC to RAM and/or RAM to RAM. I'm trying to do a simple 1-dimensional DMA transfer with your suggested configuration. Since I have 256MB RAM, I allocated 126M from the bootloader so I'm using the remaining free memory as scratch pad for DMA testing, for now. dma_params.data_type = OMAP_DMA_DATA_TYPE_S16; dma_params.src_start = 0x87E00000; //For RAM to RAM transfer. Since mem=126M, 0x80000000+(126*1024*1024) = 0x87E00000. dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; dma_params.dst_start = 0x88100000; //Source + 3MB = 0x88100000 dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC; dma_params.dst_ei = 1; dma_params.dst_fi = 1; dma_params.elem_count = 100; dma_params.frame_count = 1; omap_set_dma_params(info->dma_channel_num, &dma_params); omap_set_dma_src_burst_mode(info->dma_channel_num, OMAP_DMA_DATA_BURST_DIS); omap_set_dma_dest_burst_mode(info->dma_channel_num, OMAP_DMA_DATA_BURST_DIS); //INIT_COMPLETION(info->dma_complete); //I commented this out since I didn't know what the "info->dma_complete" was. omap_start_dma(info->dma_channel_num); My RAM to RAM DMA test consists of loading the RAM source with some 100 16-bit words, then try to transfer these to the destination addr w/ DMA, but the transfers seem are incomplete at the destination (only see ~13 of 100 expected words). Do you see anything obvious with this configuration that would prevent me from doing my desired transfer? Do I have to wait for a DMA complete? If so, can you provide more insight on how to do this? I'm seeing a similar problem with the GPMC to RAM transfers, but I figured it's easier to start with the mem-to-mem transfer and get that to work before jumping into the GPMC DMA.
  • Hi, Thanks for previous suggestion, that worked for me and I'm now able to configure and trigger a DMA transfer w/o kernel OOPS. However, I'm still having issues performing a fully successful DMA transfer either from GPMC to RAM and/or RAM to RAM.

    I'm trying to do a simple 1-dimensional DMA transfer with your suggested configuration. Since I have 256MB RAM, I allocated 126M from the bootloader so I'm using the remaining free memory as scratch pad for DMA testing, for now.

     

    dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;

    dma_params.src_start = 0x87E00000; //For RAM to RAM transfer. Since mem=126M, 0x80000000+(126*1024*1024) = 0x87E00000.

    dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;

    dma_params.dst_start = 0x88100000; //Source + 3MB = 0x88100000

    dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;

    dma_params.dst_ei = 1; dma_params.dst_fi = 1;

    dma_params.elem_count = 100;

    dma_params.frame_count = 1;

    omap_set_dma_params(info->dma_channel_num, &dma_params);

    omap_set_dma_src_burst_mode(info->dma_channel_num, OMAP_DMA_DATA_BURST_DIS);

    omap_set_dma_dest_burst_mode(info->dma_channel_num, OMAP_DMA_DATA_BURST_DIS);

    //INIT_COMPLETION(info->dma_complete); //I commented this out since I didn't know what the "info->dma_complete" was.

    omap_start_dma(info->dma_channel_num);

     

    My RAM to RAM DMA test consists of loading the RAM source with some 100 16-bit words, then try to transfer these to the destination addr w/ DMA, but the transfers seem are incomplete at the destination (only see ~13 of 100 expected words). Do you see anything obvious with this configuration that would prevent me from doing my desired transfer? Do I have to wait for a DMA complete? If so, can you provide more insight on how to do this?

    I'm seeing a similar problem with the GPMC to RAM transfers, but I figured it's easier to start with the mem-to-mem transfer and get that to work before jumping into the GPMC DMA.

  • I figured out my problem, I was freeing the DMA right after starting it, so apparently that was happening during the transfer.  My RAM to RAM transfers work as expected now. 

    Now I'm having an issue with the GPMC to RAM DMA transfer.   Currently, I'm unable to do a 4 word burst using the DMA.  My setup consists of the following:

     

    -GPMC setup for multiple access read.

    -DMA setup

    dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;

    dma_params.src_start = 0x87E00000; //For RAM to RAM transfer. Since mem=126M, 0x80000000+(126*1024*1024) = 0x87E00000.

    dma_params.src_amode = OMAP_DMA_AMODE_CONST;

    dma_params.dst_start = 0x88100000;

    dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;

    dma_params.dst_ei = 1;

    dma_params.dst_fi = 1;

    dma_params.elem_count = 4;

    dma_params.frame_count = 1;

    omap_set_dma_params(info->dma_channel_num, &dma_params);

    omap_set_dma_src_burst_mode(info->dma_channel_num, OMAP_DMA_DATA_BURST_DIS);

    omap_set_dma_dest_burst_mode(info->dma_channel_num, OMAP_DMA_DATA_BURST_DIS);

     

    omap_start_dma(info->dma_channel_num);

     

    With this setup I get 4 independent CS assertions (active low) and 1 word return for each assertion, I was instead expecting one CS assertion with 4 returned words since my FPGA device is returning 4 words per CS assertion. I don't know if I'm triggering the DMA read incorrectly for this type of read or if the GPMC is not configured correctly. Is there anything obviously wrong with this setup for what I'm trying to do?

     

  • Hi Joe Joe,

    Are you trying to use the GPMC to the max speed? Currently How much data rate, you are able achieve with the DMA?

  • Hi

    I'm working with GPMC on OMAP3530 / AM3517 to access FPGA ( Configured chip select 3 in 16-bit  Sync NOR Burst Mode ) . I followed the above DMA read configuration for GPMC write operation and other end I am check the data signal on Logic analyzer ( FPGA is not connected) .

    But I couldnt see any data transferring , but  simple raw_write operation is successful ? Any suggestions please...

    Thanks

    Vijay

  • Hi Joe Joe,

    I do have similar interface to FPGA over GPMC.

    I think you are the best person to answer my query.

    I have a fundamental question. In my case NAND is connected on CS0 and I'll connect HPI peripheral (Same as FPGA) to CS1.

    Both CS0 and CS1 will have DMA access. As I understand, there is only 1 dedicated EDMA channel for GPMC.

    If NAND and HPI peripheral try to access EDMA simultaneously, then how this case is managed ? Will it be taken care by GPMC controller ?

    Or I need to modify the implementation such that, if DMA transfer is not complete for one peripheral, we shouldn't start other transfer.

    Your inputs will be highly appreciated.

    Thanks and Best Regards,
    Sweta

  • Not sure if it's just the terminology used, but I'm using the sDMA not the EDMA for my GPMC transactions.  As I understand, EDMA is used by the DSP side not the ARM, but that's aside.  About your question, I've asked myself the same and found this other thread that touched on that subject, comes down to the L3 interconnect handling and coordinating potential GPMC resource contingencies.

    http://e2e.ti.com/support/dsp/omap_applications_processors/f/447/t/43106.aspx#152030

    I have not tried it myself but if this info is correct, I don't believe you need to do anything in your SW, the processor HW should handle that for you.

     

  • Is it possible to reconfigure the sDMA module after its initial setup?  I am DMAing 4kB of data from an external HW device through the GPMC and would like to offset the DMA's physical destination memory address by 4kB after every DMA transfer.  Then I would handle my data sitting in this big physical memory buffer. (At some point, I would like to do this sort of thing with DMA chaining but I'm doing baby steps. )

    After each 4kB DMA transfer, I try to apply the address offset (0x1000) to the DMA destination start address (DST_ADDR) by calling the following ioctl driver routine, but it doesn't seem to get applied, because the DMA continues using the original DST_ADDR set in my initial DMA setup.  I _raw_read the CDSA reg after writing and it prints the address with my offset applied, so I don't understand why the DMA doesn't obey it.  Is this sort of thing possible? Please advice how I can do sDMA reconfigurations on the fly at runtime.

     

    static void gpmc_dma_offset_dst_addr(volatile u32 dst_addr_offset)
    {
        struct omap_dma_channel_params dma_params;
        u32 value;

        /* Configure DMA4_CDSA */
        value = DST_ADDR + dst_addr_offset;

        __raw_writel(value, dma_base + OMAP_DMA4_CDSA (info->dma_channel_num));

    }

     

     

  • Found some info in the ref manual about reprogramming an active DMA channel, the following paragraph in pg. 992 section 9.4.1.1 of the TRM suggests that I should be able to reprogram it as I'm trying to do so with the dst address register, however I still haven't had any luck getting this to work.  The DMA does not seem to obey my updated dst address re-configuration and instead keeps dumping the data in the original dst address that was programmed during my initial DMA setup.   Any comments on what I can be doing wrong?

    9.4.11 Reprogramming an Active Channel
    A currently active logical DMA channel can be disabled through the SDMA.DMA4_CCRi[7] ENABLE bit.
    When any ongoing transaction is complete and the read-active and write-active bits in the
    SDMA.DMA4_CCRi register (SDMA.DMA4_CCRi[9] RD_ACTIVE and SDMA.DMA4_CCRi[10]
    WR_ACTIVE) are reset, the channel can be reprogrammed for a new transfer.

  • Hi joe joe

    did u write the code in the kernel space or user space?..........i am building it as a module and trying to insmod.......is it correct to write the code in the kernel space and intialize the DMA transfer......

  • could you send a complete code about this driver to me in private.I am new to this area and need a fast learning.I have seen a lot of materials about burst read,how about burst write?

     

  • hi,I want to know how the call back function works,if i call the omap_request_dma(OMAP24XX_DMA_GPMC, "FPGA rcv", your_fpga_dma_cb, info, &info->dma_channel_num);,,cause its definiton, your_fpga_dma_cb is the call back function,it has three paras,what the values of thes paras?how these params are givin values.ps,is the info the data transfered?if it is,our data is a struct?what does this struct definition in common?I cant't understand the completion thing,what's the procedure it works.when we set the data to be transfered by DMA,is it a DMA read or write?

    I am looking forward to your reply.please answer me ASAP. 

  • Hi,

    Which board u r using for OMAP3530 ? And For FPGA.

    I want to use same configuration for my application for High Speed Data transfer from FPGA to ARM.

    what is the best starting platform for me for MAP3530 /4430/4460 + FPGA. 

    also suggest me the starting point for GPMC driver to connect fpga as memory device.

  • Hi Joe Joe,

    I've the overo water and tobi cards. I am trying to configure the gpmc. For the moment I want to read the memory from the peripheral attached to gpmc cs5 (s9221 ethernet lan).

    Now, in the datasheet of the s9221 it says that in the address 0x64 of the chip memory has a constant value (0x87654321).

    I'm trying to read that value since my code that value, thus:

    #define CS 5

    #define ADDR_REG          gpmc_base + 0x80 + (0x30)*CS

    #define DATA_REG          gpmc_base + 0x84 + (0x30)*CS

    gpmc_base = ioremap(OMAP34XX_GPMC_BASE, SZ_2K); // ioremap returns 0xfe000000

    __raw_writel(0x64, ADDR_REG); // write 0x64 to the address bus

    var = __raw_readl(DATA_REG);  // trying to read the 0x87654321

    It returns a value of 4 ...

    Do you have some idea? ... Thansk for your help

  • Hello,

    We have configured GPMC for Omap3530(Gumstix overo water COM). And Connected FPGA tp GPMC port.

    Now, We successfully read write the data over GPMC port to FIFO(FPGA). We referred "linux-omap-philip-e100-2.6.38" kernel. We configured GPIO pin as interrupt and on interrupt from FPGA (Data Available) we read 2KB data from GPMC to Driver.

    Now Problem is that When We reciving data continuasly at intermidiate and random condition, even intrupt generated on exact position, Omap took long time to read data and so we loss the large data.

  • Hi Nilesh,

    The main reason for the data lost in your case seems that the buffer is overflowed. I suggest you to revise the driver and enlarge the data buffer. I made this conclusion but I don't know the max bit rate of received data and how long is "Omap took long time to read data".

    BR

    Tsvetolin Shulev

  • Hi Tsvetolin,

    Thank you for your quick reply,

    I just checked the Waveforms to conclude is the processor takes long time or the isr took some time to execute.

    So i get the result that,  ISR dose not  processed on immediate of arriving the interrupt and this is happening most of the time for first interrupt only.

    Green channel is interrupt and Blue channel is ISR processed. Red Arrow shows delay to process the ISR on first interrupt its about 3.6ms.

    How can i avoid this delay ?