Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12658 Discussions

system.h missing /dev/dma_0, but DMA device is in the top.socpinfo file

Altera_Forum
Honored Contributor II
1,384 Views

I have a working FPGA design with PCIe + DMA + JTAG_UART + NIOS II + Internal Memory. 

 

I have been asked to move to a HAL design for the the C code running on NIOS II. 

 

I have got to the point of the Eclipse Hello world free_standing application with the alt_main entry point. 

 

/* Obtain a handle for the device */ 

if ((rx = alt_dma_rxchan_open ("/dev/dma_0")) == NULL) 

 

fails to open the rx channel ... investigating , the system.h generated is missing the anything that has *DMA* in it. 

the top.socpinfo does contain the DMA device and the JTAG_UART device  

 

<instanceCount>1</instanceCount> 

<name>altera_avalon_dma</name> 

<type>com.altera.entityinterfaces.IElementClass</type> 

<subtype>com.altera.entityinterfaces.IModule</subtype> 

<displayName>DMA Controller</displayName> 

<version>13.0.1.99.2</version> 

</plugin> 

<plugin> 

<instanceCount>1</instanceCount> 

<name>altera_avalon_jtag_uart</name> 

<type>com.altera.entityinterfaces.IElementClass</type> 

<subtype>com.altera.entityinterfaces.IModule</subtype> 

<displayName>JTAG UART</displayName> 

<version>13.0.1.99.2</version> 

 

 

 

Any ideas on why the top.socpinfo device info. for the DMA controller is not getting into the system.h file ? 

 

I assume the open of the /dev/dma_0 is failing if the system.h is missing any DMA device ... however I will run debug on the code as I have seen forum entries 

indicating the device list search for the /dev/dma_0 was failing .... 

 

Any advice appreciated. Bob.
0 Kudos
10 Replies
Altera_Forum
Honored Contributor II
656 Views

Went in with debugger .. in Eclipse ... 

 

More than that, I went in with Lauterbach from the ARM system side via the PCIe link to check the device list and confirmed that the alt_llist was indeed empty .  

 

while (next != (alt_dev*) llist) ... this evaluates not true since the alt_llist is pointing to itself which defines an empty list ,,, so ..... for some reason system.h is missing any /dev/dma_0 entry  

I believe this results in an empty device list that I would expect to contain /dev/dma_0 somethere ... Since I have 100% followed the example given ... I'm not sure what went wrong. 

I suspect it is on the Eclipse side or whaterver generates the system.h file which is missing the DAM device. 

 

I could *** a more simple device like a timer to see if it gets added to the device list. 

 

DMA could be confusing since there is the plain vanilla DMA controller and the Scatter/Gather DMA Controller. 

 

Thanks in Advance ... Spent time on this Friday night after the bell and will work it this weekend .. I know it's non-trivial, but didn't excpect these road blocks . 

Need to make serious progress next week including the "thin Device Driver " on the Linux side.... 

:):):):) 

Bob Dixon
0 Kudos
Altera_Forum
Honored Contributor II
656 Views

I'm pretty sure the dev tree isn't populated in "free standing" applications. The issue of not populating system.h is an odd one. Each and every device that Nios II's read master is connected to should be "seen" there. I've seen issues when using bridges in the past. Posting your Qsys file might help a bit. 

 

Also, you might consider generating a BSP using the SBT (software build tools) from the command line. It may give you a better idea of what's happening. 

 

Cheers! 

 

slacker
0 Kudos
Altera_Forum
Honored Contributor II
656 Views

 

--- Quote Start ---  

I'm pretty sure the dev tree isn't populated in "free standing" applications. The issue of not populating system.h is an odd one. Each and every device that Nios II's read master is connected to should be "seen" there. I've seen issues when using bridges in the past. Posting your Qsys file might help a bit. 

 

Also, you might consider generating a BSP using the SBT (software build tools) from the command line. It may give you a better idea of what's happening. 

 

Cheers! 

 

slacker 

--- Quote End ---  

 

Thanks Slacker.... I can switch to the command line but went the GIU route with Exlipse since I figured that may be easier. 

 

I went to "free standing" application as I thought that was necessary to have the system.h generated and to have the alt_main as the entry point to set various things up such as the device list. 

 

It is a worry if the dev tree isn't populated in "free standing" mode since I would need it to get the open of /dev/dma_0 to work . If this is correct do I need an OS similar to go ahead with DMA and the HAL ? 

 

I would expect the DMA to have NIOS II as a read master since it has memory mapped registers. 

 

 

I will post the QSYS file since it is a sample application and has no protected IP in it yet 

When IO tried to attach top.qsys I got error "invalid file type" 

 

I know the .pdf that went through the NIOS II example has a GUI section as well as a command line section ... can you give me a rough outline on what each command line step does . 

 

Thanks in Advance.
0 Kudos
Altera_Forum
Honored Contributor II
656 Views

Slacker, you may have nailed it ... 

 

I was thinking of adding soem other dev that was not dma to see it just DMA was not in the dev list . 

I checked the DMA read master port with respect to the NIOS II data port and it wasn't connected.  

I will conect it and re-try to see it I can open the /dev/dma_0 and that it appears in system.h 

BTW can you say what devices will appear in the llist of devices .. I saw an empty list as the next pointed to  

the head and the associated string was NULL. It looks like the JTAGUART , Timer etc... don't need to be opened to  

use .. does that imply that they don't show up in the dev list . 

 

Thanks for the help. 

 

Bob.
0 Kudos
Altera_Forum
Honored Contributor II
656 Views

Slacker .. you may have nailed it . 

Went back to QSYS and the DMA read master port was conected to the PCIe TX port only and  

not the NIOS II data master port. 

This may explain why it is not seen in system.h and the dev list is empty. 

 

Can you say what devices appear in the dev list as the list was empty ... ie does the hardware UART and Timer appear in the list. 

They are not in the design but I doen't see any "open" calls for them list they don't need to be opened ?? 

 

Thanks for your help ... Bob
0 Kudos
Altera_Forum
Honored Contributor II
656 Views

system.h now has this DMA infi, 

 

/* 

* dma_0 configuration 

*/ 

 

# define ALT_MODULE_CLASS_dma_0 altera_avalon_dma 

# define DMA_0_ALLOW_BYTE_TRANSACTIONS 1 

# define DMA_0_ALLOW_DOUBLEWORD_TRANSACTIONS 1 

# define DMA_0_ALLOW_HW_TRANSACTIONS 1 

# define DMA_0_ALLOW_QUADWORD_TRANSACTIONS 1 

# define DMA_0_ALLOW_WORD_TRANSACTIONS 1 

# define DMA_0_BASE 0x1000 

# define DMA_0_IRQ -1 

# define DMA_0_IRQ_INTERRUPT_CONTROLLER_ID -1 

# define DMA_0_LENGTHWIDTH 13 

# define DMA_0_MAX_BURST_SIZE 128 

# define DMA_0_NAME "/dev/dma_0" 

# define DMA_0_SPAN 64 

# define DMA_0_TYPE "altera_avalon_dma"
0 Kudos
Altera_Forum
Honored Contributor II
656 Views

Slacker and Forum members thanks form your help. 

 

Made some progress but what worked before converting to the HAL design ... now seems to hang and transfers some data but not much. 

The HAL design will help I believe in supporting both ARRIA V ( for Gen1 + Gen2 ) and STRATIX V ( for Gen1, Gen2 and Gen3 ). 

 

 

Code: mixture of example code and other code from forums. 

what is not clear is the default mode of the DMA controller ... or if everything needs to be set up via ioctl calls. 

prior to the HAL, I explicitly set up the DMA controller and polled for the end status. 

the sample code fetched data from system memory and sends the data back to system memory via PCIe link. 

If I uncomment the while ( !rx_done ); it hangs with rx_done = 0. This was the same result when moving and internal FPGA memory buffer 

to another internal memory buffer ... looks like only 4 bytes were moved. I have seen this behavior in other posts where the recommendation 

was to disable the NIOS II data cache .. The NIOS II is minimum with no caches so I don't believe that is a factor. 

Any recommendations on where to go. I may be able to display the DMA controller state for the hang. I susspect some set up 

issue where the DMA controller is stuck and can't make progress after the first 4 bytes ? the support says all different data sizes 

are supported bu maybe an alignment issue. 

 

1) How to debug ? Do I need to go to simulation or is something plain wrong. 

2) The interrupts are connected but it isn't clear how they are used with DMA and the HAL. 

3) I need to add a "generic" working register set that the host side of the PCIe link can send commands to NIOS and the  

start address of a linked list of descriptors that reside in system memory for NIOS to process. I figure I need to generate an Avalon MM 

megafunction to add these registers that are simply r/w registers to pass data ot NIOS II ... would there be any example  

or existing megafunction ? 

 

 

 

 

 

# include <stdio.h> 

# include <stdlib.h> 

# include "system.h" 

# include "sys/alt_sys_init.h" 

# include "sys/alt_irq.h" 

# include "priv/alt_file.h" 

 

 

# include "sys/alt_dma.h" 

# include "alt_types.h" 

 

 

static volatile int rx_done = 0; 

 

 

/* 

* Callback function that obtains notification that the data has 

* been received. 

*/ 

static void done (void* handle, void* data) 

rx_done++; 

 

 

 

 

 

 

 

int main (void) __attribute__ ((weak, alias ("alt_main"))); 

 

 

int alt_main(void) 

{  

 

int rc; 

int i; 

 

int rxchan_depth; 

int txchan_depth; 

int val; 

 

alt_dma_txchan txchan; 

alt_dma_rxchan rxchan; 

 

 

void* tx_data = (void*) 0x08000000; /* system memory*/ 

 

void* rx_buffer = (void*) 0x0800200; /* system memory */ 

 

char * fill_string = "Hello From Avenger System Memory "; 

char * fill_ptr = (char *) 0x08000000; 

int fill_string_len; 

 

 

 

 

 

/*  

 

alt_irq_init (ALT_IRQ_BASE); 

 

 

 

alt_io_redirect (ALT_STDOUT, ALT_STDIN, ALT_STDERR); 

 

 

 

printf("Hello from Nios II Free-Standing! Monday \n"); 

printf("tx_data = %p \n", tx_data ); 

printf("rx_buffer = %p \n", rx_buffer ); 

 

/* Create the transmit channel */ 

if ((txchan = alt_dma_txchan_open("/dev/dma_0")) == NULL) 

printf ("Failed to open transmit channel\n"); 

exit (1); 

else 

printf ("/dev/dma_0 opened tx device ok , tx = %x....\n", txchan); 

 

/* Obtain a handle for the device */ 

if ((rxchan = alt_dma_rxchan_open ("/dev/dma_0")) == NULL) 

printf ("Error: failed to open device ....\n"); 

exit (1); 

else 

printf ("/dev/dma_0 opened rx device ok , rx = %x....\n", rxchan); 

 

// check attributes 

 

rxchan_depth = alt_dma_rxchan_depth( rxchan ); 

printf ( "rxchan_depth = %i \n" , rxchan_depth ); 

txchan_depth = alt_dma_rxchan_depth( rxchan ); 

printf ( "txchan_depth = %i \n" , txchan_depth ); 

val = alt_dma_rxchan_ioctl( rxchan, ALT_DMA_GET_MODE, 0 ); 

printf ( "rxchan mode = %x \n" , val ); 

val = alt_dma_txchan_ioctl( txchan, ALT_DMA_GET_MODE, 0 ); 

printf ( "txchan mode = %x \n" , val ); 

 

// initialize system buffer 

fill_string_len = strlen( fill_string ); 

printf ( "fill string len = %i \n", fill_string_len ); 

for ( i = 0; i++; i < fill_string_len+1 ) 

fill_ptr = fill_string

 

/* Post the transmit request */ 

if ((rc = alt_dma_txchan_send (txchan,tx_data,32,NULL,NULL)) < 0) 

printf ("Failed to post transmit request, reason = %i\n", rc); 

exit (1); 

 

/* Post the receive request */ 

if ((rc = alt_dma_rxchan_prepare (rxchan,rx_buffer,32,done,NULL)) <0 ) 

printf ("Failed to post read request, reason = %i\n", rc); 

exit (1); 

else 

printf ("Passed post read request\n"); 

 

/* wait for transfer to complete */ 

//while (!rx_done) 

printf ("Waiting on rx_done, rx_done = %i\n", rx_done); 

printf ("Transfer successful!\n"); 

 

printf ( "%s \n", tx_data ); 

printf ( "%s \n", rx_buffer ); 

 

 

 

 

 

 

printf ("Transaction complete\n"); 

alt_dma_rxchan_close (rxchan); 

alt_dma_txchan_close (txchan); 

 

 

 

exit(0); // Return code for "success!" if anyone is checking (they aren't). 

 

Ourput: I pre-conditioned the src ( tx ) buffer with ZZZefgh and only ZZZZ was transferred to the dest ( rx ) buffer. 

 

 

Hello from Nios II Free-Standing! Monday  

tx_data = 0x8000000  

rx_buffer = 0x800200  

/dev/dma_0 opened tx device ok , tx = 820e6a8.... 

/dev/dma_0 opened rx device ok , rx = 820e6c4.... 

rxchan_depth = 3  

txchan_depth = 3  

rxchan mode = ffffffe7  

txchan mode = ffffffe7  

fill string len = 35  

Passed post read request 

Waiting on rx_done, rx_done = 0 

Transfer successful! 

ZZZZhgfe  

ÀÀÀÀZZZZ  

Transaction complete 

 

 

 

Eclipse: I am a new user to it and am able to create new projects, importing an associated .socinfo file. 

When it comes time to running, something changed now there is a problem with an id at 70 and a timestamp which  

I believe checks it the FPGA design and the NIOS II code is in synch ? Anyhow I have trouble geting that check to pass and  

it use to then something changed in Eclipse.  

Is the "free standing" the correct software model for a simple design ?
0 Kudos
Altera_Forum
Honored Contributor II
656 Views

Figure I will test the DMA for the current design by having the System set up the DMA via Lauterbach script , ( system = system ARM system connected to the FPGA card via PCIe link ). 

That worked before ... assuming that works fine , I would expect some HAL issue and will go to Simulation , but I would need to set up that environment. 

 

Is there a more detailed HAL document that may cover. 

 

1) "free standing mode" and the inititial calls inserted by template . ie 

alt_irq_init (ALT_IRQ_BASE); 

alt_io_redirect (ALT_STDOUT, ALT_STDIN, ALT_STDERR); 

 

2) The call back function ... is it called by an interrupt handler where the DMA is interrupting to indicate the transfer is done. 

 

3) Better description of the DMA controller default setting with the HAL and the use of the ioctl() calls. 

 

Thanks, Bob.
0 Kudos
Altera_Forum
Honored Contributor II
656 Views

Ok nailed this one ... as I suspected the DMA controller was hung with some bus width mismatch. 

 

Everything worked fine when I added two icotl()'s to move from a default transfer of 32 bits to 64. I checked the DMA status vie the PCIe link , vie the Lauterbach on the host system. 

I must admit that is kind of convoluted but seemed easiest. The DMA was working via scripts running on the host system via scripts so possibly the transfer count of 10 in the HAL calls  

was an issue as well. 

 

Here is a question though that I can't answer, observe that the test of rx_done will report polling of that flag if it is not zero. I extended the transfer count from a small count to 256 and 1024. 

At no time do I get a polling message. I can max out the transfer count, and if I don't get a polling message, I suspect the DMA operation is somehow usurping the NIOS II execution, or the DMA has a  

very high priority on the Avalon MM fabric. Any comments there . The NIOS II is the /e which is without any caches , bells or whistles.  

 

I am implementing a consumer / producer data transfer ... if the DMA engine moves the data buffer to the host system, I am wondering the latency to get the rx_done flag back from the DMA interrupt. 

Is there any way to reduce it ? 

 

Any ideas on the "thin" Linux device driver, I need to provide that for the system running on the host with Linux. I'm thinking at a minimum, the device driver has to open , close the FPGA PCIe device and an some ioctl() calls to post the head of a descriptor linked list resident in system memory, request destination buffers on the FPGA side and some flag / status bit management routined. 

 

As a new user I am 100% impressed with the ALTERA offering and still need to get the included simulator up. 

 

Thanks in advance . Bob.  

 

 

// check attributes 

 

rxchan_depth = alt_dma_rxchan_depth( rxchan ); 

printf ( "rxchan_depth = %i \n" , rxchan_depth ); 

txchan_depth = alt_dma_rxchan_depth( rxchan ); 

printf ( "txchan_depth = %i \n" , txchan_depth ); 

val = alt_dma_rxchan_ioctl( rxchan, ALT_DMA_GET_MODE, 0 ); 

printf ( "rxchan mode = %x \n" , val ); 

val = alt_dma_txchan_ioctl( txchan, ALT_DMA_GET_MODE, 0 ); 

printf ( "txchan mode = %x \n" , val ); 

val = alt_dma_rxchan_ioctl( rxchan, ALT_DMA_SET_MODE_64, 0 ); //************************* ADDED ******************************************* 

val = alt_dma_txchan_ioctl( txchan, ALT_DMA_SET_MODE_64, 0 ); //************************* ADDED ******************************************** 

 

 

 

 

 

 

/* Post the transmit request */ 

if ((rc = alt_dma_txchan_send (txchan,tx_data,1024,NULL,NULL)) < 0) 

printf ("Failed to post transmit request, reason = %i\n", rc); 

exit (1); 

 

/* Post the receive request */ 

if ((rc = alt_dma_rxchan_prepare (rxchan,rx_buffer,1024,done,NULL)) <0 ) 

printf ("Failed to post read request, reason = %i\n", rc); 

exit (1); 

else 

// printf ("Passed post read request\n"); 

 

/* wait for transfer to complete */ 

while (!rx_done) 

printf ("Waiting on rx_done, rx_done = %i\n", rx_done); 

printf ("Transfer successful!\n");
0 Kudos
Altera_Forum
Honored Contributor II
656 Views

Ok got everything running ... working on "thin" device driver and application code for Linux side. 

 

Thanks, Bob.
0 Kudos
Reply