Edma 2channel transfer loop

478 views
Skip to first unread message

jimmy....@gmail.com

unread,
Nov 7, 2013, 10:06:53 AM11/7/13
to beagl...@googlegroups.com

Greeting again everyone!.

I am using beaglebone with angstrom.

I am trying( by writing a kernel module ) to loop two dma channels together but i cant figure out how....

Here is what i want. i want the completion of the 1st channel to trigger the final interrupt(callback1) and also channel 2.
and at the completion of channel 2 to trigger the final interrupt (callback2) and also channel 1. etc... creating a loop between ch1 and ch2.

By linking the channels it seems that i cant  link channel 2 back to channel 1. (

edma_link(ch1, ch2);
edma_link(ch2, ch1);  system fail.

i can only link ch2 on its self 

edma_link(ch1, ch2);
edma_link(ch2, ch2);  

but i dont want that.

By chaining the final interrupt is not going off. so i dont want that either.

I tried to link  edma_link(ch1, ch2) then chain ch2 with a ch3 and have edma_link(ch3, ch1);  

but then ch1 callback1 returns DMA_CC_ERROR with its paramset being NULL (so the error is from that).

Any suggestions ? 

Terrence McGuckin

unread,
Dec 12, 2013, 8:31:14 PM12/12/13
to beagl...@googlegroups.com, jimmy....@gmail.com, Andrew D Righter
I am working on EDMA ATM as well. I was curious if you could write a little bit about how you are initializing the channels and setting up the transfers. Are you writing a kernel module for this and interfacing to it in user-space? 

Appreciate any insight, having a hard time digging up info on using EDMA on the Beaglebone

Dimitris Boulougaris

unread,
Dec 13, 2013, 6:19:45 AM12/13/13
to Terrence McGuckin, beagl...@googlegroups.com, Andrew D Righter
Hi Terrence.

Yes i am writing a kernel module and interfacing with it from user space.

As i went through the same period like you do now i'll be glad to help you.

The first step is to allocate the buffers that the edma will use
 source and destination buffers as well . as edma needs special buffers.
The second step is to allocate the channels you want.
Then comes the configuration of the transfer of each channel.

As you can understand i cant describe the hole process in detail as edma and its applications are quite complicated.
if you can be more specific ill be glad to give you more specific information.

John Syne

unread,
Dec 13, 2013, 12:00:48 PM12/13/13
to beagl...@googlegroups.com


From: Terrence McGuckin <tmc...@gmail.com>
Reply-To: <beagl...@googlegroups.com>
Date: Thursday, December 12, 2013 at 5:31 PM
To: <beagl...@googlegroups.com>
Cc: <jimmy....@gmail.com>, Andrew D Righter <andrew....@gmail.com>
Subject: [beagleboard] Re: Edma 2channel transfer loop

I am working on EDMA ATM as well. I was curious if you could write a little bit about how you are initializing the channels and setting up the transfers. Are you writing a kernel module for this and interfacing to it in user-space? 

Appreciate any insight, having a hard time digging up info on using EDMA on the Beaglebone
Hi Terrence,

Best place to understand how to work with EDMA is this link:


Under C6000, look at the videos on EDMA3. Clearly this is working under SysBIOS, but the concepts are the same.  Once you understand these concepts, it will be easier for you to understand how the Linux drivers use EDMA. 

Regards,
John


On Thursday, November 7, 2013 10:06:53 AM UTC-5, jimmy....@gmail.com wrote:

Greeting again everyone!.

I am using beaglebone with angstrom.

I am trying( by writing a kernel module ) to loop two dma channels together but i cant figure out how....

Here is what i want. i want the completion of the 1st channel to trigger the final interrupt(callback1) and also channel 2.
and at the completion of channel 2 to trigger the final interrupt (callback2) and also channel 1. etc... creating a loop between ch1 and ch2.

By linking the channels it seems that i cant  link channel 2 back to channel 1. (

edma_link(ch1, ch2);
edma_link(ch2, ch1);  system fail.

i can only link ch2 on its self 

edma_link(ch1, ch2);
edma_link(ch2, ch2);  

but i dont want that.

By chaining the final interrupt is not going off. so i dont want that either.

I tried to link  edma_link(ch1, ch2) then chain ch2 with a ch3 and have edma_link(ch3, ch1);  

but then ch1 callback1 returns DMA_CC_ERROR with its paramset being NULL (so the error is from that).

Any suggestions ? 

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Andrew Righter

unread,
Dec 15, 2013, 10:34:30 PM12/15/13
to Dimitris Boulougaris, Terrence McGuckin, beagl...@googlegroups.com
Hi Dimitris,

Thanks for responding (posted this on my buddy's PC Terrence while he was logged on, apologies.)

I just got a really good environment built for compiling kernel modules right on the BeagleBone Black. Makefile setup nicely, generates KO files that load nicely using "modprobe" - all is well with the World. 

Now, to write C code. 

I have been studying the am335x TRM, specifically the Ping Pong Buffer sections - eventually the goal is to write a ping pong buffer that receives from SPI RX FIFO. 

To get me started in the right direction I am looking for simple C code to basically setup DMA how you suggested: 
- Allocating Buffers, Channels
- Configuring transfers

... and send a very simple transfer of data. 

I have been searching through EDMA.c and SPI code within the BBB code to see how they are doing it but simple C code would def. help me understand things. 

Thanks in advance for your help,

Dimitris Boulougaris

unread,
Dec 16, 2013, 4:11:03 AM12/16/13
to Andrew Righter, Terrence McGuckin, beagl...@googlegroups.com
I am attaching you a file with a test code from texas that shows the initial setup for 3 transfer techniques. Study it i think one can get the main idea from it.


I also advise you to take a look at the bare metal examples of TI for the am335x (the starterware) they have an example with edma transferring from the spi , check it out.

Dimitris.
edma_test.c

Dimitris Boulougaris

unread,
Dec 17, 2013, 4:46:34 AM12/17/13
to Q, beagl...@googlegroups.com
Greetings Andrew.

The code from the starterware is for bare metal that is correct , but it can help you greatly by using it as a guide of what need to be done to take and give data from and to the spi .

Interfacing between KERNEL DRIVER and USERLAND CODE

Firstly I don't think i am an expert, as a recently started to duel with these kind of stuff my self. so i may miss something.

The point of creating a kernel module is to access hardware that is not available to you from user space or rewrite a driver .

The kernel module and the userland api are two completely different things , that communicate with its other . And for most cases i think you can think the module as a slave and the main api as a master.

For one example of interfacing between your kernel module and your userland code check this link : http://www.linuxforu.com/2011/08/io-control-in-linux/ .
From what i know directly accesing a function is possible but its neither the correct way nor an easy one so don't do it , this is not how this works.

Check this link that provides more than enough to get you started i think 
http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html .

Virtual versus Physical 

check this out about the memory types http://www.makelinux.net/ldd3/chp-15-sect-1

An example of hwreg
#define HWREG(x) (*((volatile unsigned int *)(x)))
have in mind that the pointer has to be the same size as the register you are going to write . so you can have more than one hwreg , like a hwregL for longs and so on.
before using hwreg you will have to request the memory you want to access(the hole edma register zones in your case(if you look at the trm of am335x it says the size and everything you want))
use  request_mem_region
Then you will have to  map this region so you can play with it  via a virtual handle.
use ioremap
Then you can use HWREG with hande that ioremap returned to you

Example:

memreq = request_mem_region (0x49000000, 0x100000, DEVICE);
if ( memreq == 0 )
        {
printk(KERN_INFO "Memory Area Requested 0x%x to 0x%x is in use",0x49000000,0x49000000+0x100000);
               
        }
  
        edma_module_start = ioremap (0x49000000, 0x100000);

        if ( edma_module_start == 0 )
        {
                printk (KERN_INFO "Cannot map edma module memory \n");
                return -EIO;
        }
        else
{

            HWREG (edma_module_start + (0x284)) = (0x210u);

............
............. 
.........

after you have finished your operations you have to free and unmap the regions and memories you have used ,so you can request them again and follow the same protocol



I highly recommend reading the links and searching a bit yourself as this email is not written as a guide but its purpose is to provide some tips. 

Hope that helped
Dimitris .



On Tue, Dec 17, 2013 at 2:39 AM, Q <andrew....@gmail.com> wrote:
Thank you so much for your help Dimitris! 

Currently studying all of the EDMA code available to me, the starter ware looks useful but seems to run on bare metal HW, addressing memory directly. 

I'm stuck on two things I don't quite understand: 

Interfacing between KERNEL DRIVER and USERLAND CODE

I have a kernel module and I have userland code, is there a good example of what should be in KO and what should be in O file? 
If I define a function in the KO file, how do I address that function in the userland file?
Are there parts of this that is REQUIRED to be inside the KO file? 

and 

Virtual versus Physical 
It seems that there is Virtual Memory and Physical Memory, and Virtual DMA Channels and Physical DMA Channels.
Where can I learn about the difference, and which to use? 
How do I address PHYSICAL MEMORY ADDRESS: 0x49000000 (EDMA3CC PID Register) - tried using HWREG(<PHYMEMADDR>) but it errors, do I use VIRTUAL MEM ADDR? If so, what's the best way to write code so it always uses the virtual, rather than physical? I'm aware of Page Table data structures, they're supposed to map between PHY and VIRT but I don't see any uses of them in this EDMA code I'm looking at.



Regards,


Reply all
Reply to author
Forward
0 new messages