- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Anybody use the DMA HAL driver?
I need correct example for stream device and memory. I want receive from steram device through DMA(using HAL) and save stream data to memory. I have written worked code using DMA registers, but can't get right result for HAL. Studying of sourcel codes for HAL DMA indirectly specifies a mistake in HAL library, but I am not confident it.Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There was a bug in the HAL/DMA. This has been fixed and will be released very soon. I don't believe there is a workaround for it. I'll check.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Will companies that have purchased the NIOS-II eval board/kit get notice
of any bug fixes/releases of NIOS-II? We plan on using HAL/DMA extensively for a project-in-progress. John- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm sure you will get notice of updates. I will also post it here :-)
Marketing will be able to tell me if it will be a downloadable release. It looks too big right now from what I can tell.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you are an active subscriber (meaning you purchased a Nios I/II kit less than a year ago or you purchased a Nios renewal and are still under active maintenance) then you will receive updates shipped to you automatically. We generally have 2 shipped releases per year, and 2-3 downloadable service pack releases.
Check for downloads here: nios i/ii service pack downloads (https://www.altera.com/support/software/download/service_packs/nios/upd-nios_index.jsp). Warning, please do not mistake Nios I service packs for Nios II ones. The next release is a service pack, scheduled to be available for download from www.altera.com by October 15th.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- originally posted by major@Sep 7 2004, 10:35 PM anybody use the dma hal driver?
i need correct example for stream device and memory.
i want receive from steram device through dma(using hal) and save stream data to memory.
i have written worked code using dma registers, but can't get right result for hal.
studying of sourcel codes for hal dma indirectly specifies a mistake in hal library, but i am not confident it. --- Quote End --- Major. Have you looked at the example on page 4-21 of the Nios II Software Developer's Handbook, there is an example of exactly what you're trying to do and it works. If this does not answer your question then please post back. Lastly the bug that Kerri refers to is an edge case, and will not apply in the use case you have described. To explain the problem, it is important to understand the HAL DMA model. This expects a DMA device to be performing DMA transfers in one of three modes: - memory to memory - devices to memory - memory to device Which mode is used is expected to be determined at system creation time. In the case of the altera_avalon_dma driver, this is actually done through a run time ioctl call. The bug occurs if you have run the DMA in one of these modes, and then make the ioctl call to change to one of the other modes. This is in any case not an efficent way to make use of the DMA controller, since the pending transfer queues will need to be drained between the ioctl calls. It is better to provide additional DMA channels instead.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
<div class='quotetop'>QUOTE </div>
--- Quote Start --- Have you looked at the example on page 4-21 of the Nios II Software Developer's Handbook, there is an example of exactly what you're trying to do and it works. If this does not answer your question then please post back. Lastly the bug that Kerri refers to is an edge case, and will not apply in the use case you have described. To explain the problem, it is important to understand the HAL DMA model. This expects a DMA device to be performing DMA transfers in one of three modes: - memory to memory - devices to memory - memory to device Which mode is used is expected to be determined at system creation time. In the case of the altera_avalon_dma driver, this is actually done through a run time ioctl call. The bug occurs if you have run the DMA in one of these modes, and then make the ioctl call to change to one of the other modes. This is in any case not an efficent way to make use of the DMA controller, since the pending transfer queues will need to be drained between the ioctl calls. It is better to provide additional DMA channels instead.[/b] --- Quote End --- I use mode "devices to memory". I try use code on page 4-21. This code also does not work. 1. This code with small error: /* Wait for the transaction to complete */ while (!dma_done); - dma_done: void result function 2. I add to example IOCT request for RX_STREAM_ON with argumet = SPI_BASE address, before call alt_dma_rxchan_prepare. "Which mode is used is expected to be determined at system creation time" System created in "devices to memory": 1. DMA read_master connected ONLY to SPI control port 2. DMA write_master connected ONLY to SDRAM. This configuration work correctly through direct access to DMA registers, but don't work through HAL. This my worked code: IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_SPI_REC_BASE, 0);
IOWR_ALTERA_AVALON_DMA_STATUS(DMA_SPI_REC_BASE, 0);
IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_SPI_REC_BASE, SPIS_DATA_BASE);
IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_SPI_REC_BASE, (alt_u32)buffer);
IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_SPI_REC_BASE, DMA_BUFF_SIZE*2);
ch = ALTERA_AVALON_DMA_CONTROL_HW_MSK
| ALTERA_AVALON_DMA_CONTROL_GO_MSK
| ALTERA_AVALON_DMA_CONTROL_LEEN_MSK
| ALTERA_AVALON_DMA_CONTROL_RCON_MSK;
IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_SPI_REC_BASE, ch);
printf("Wait data...\n");
while(1){
ch = IORD_ALTERA_AVALON_DMA_STATUS(DMA_SPI_REC_BASE);
if( ch & (~ALTERA_AVALON_DMA_STATUS_BUSY_MSK) )
{
printf("DMA %d\n", ch);
break;
}
}
There can be you can result a correct code for HAL operations?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Could you post the HAL code that's not working for you?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
TO_BE_DONE
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The use of transmit and receive in this context is a little confusing, since they have different meanings depending on whether you view things from outside or inside the DMA. The confusion is made worse by the fact that the documentation (and apparently the comments as well) are wrong in the 1.0 version of the Nios II kit.
Try using ALT_DMA_TX_STREAM_ON rather than ALT_DMA_RX_STREAM_ON. That should fix your problem.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks. I try it check tomorrow and inform about result.
Yes, comments for alt_avalon_dma_launch_rxonly: <div class='quotetop'>QUOTE </div> --- Quote Start --- /* * alt_avalon_dma_launch_rxonly() is called to launch a new transaction when * only the receive channel is using incrementing addresses, * i.e. the transmit channel is accessing a single memory location (which is * probably a device register). */[/b] --- Quote End --- But in function code set DMA control flag RCON, and too(WCON) for alt_avalon_dma_launch_txonly. <div class='quotetop'>QUOTE </div> --- Quote Start --- The use of transmit and receive in this context is a little confusing, since they have different meanings depending on whether you view things from outside or inside the DMA.[/b] --- Quote End --- Receive or send DMA mode defined by connection WriteMaster and ReadMaster of the DMA channel (in current DMA opperation) and independet from view point (outside or inside the DMA).- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I check idea with change the ALT_DMA_RX_STREAM_ON to ALT_DMA_TX_STREAM_ON in the IOCTL request.
All init steps passed correctly. But program haalted after call "alt_dma_rxchan_prepare". Program passes to an infinite cycle of ISR from DMA (i set break point in alt_avalon_dma_irq function). The first time ISR ocurred before programm return form alt_dma_rxchan_prepare, after write to DMA_CONTROL register. In ISR apdated DMA slot information, and programm go to infinite ISR cycle, however request for data send to SHARC processor not sended and no data was sended to SPI. This is HAL bug?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can't see any obvious source of this problem. However I do notice that in your test code you use a transfer size of DMA_BUFF_SIZE*2 and in your HAL example you use a size of 1024. I don't know what value you have set for DMA_BUFF_BYTESIZE, but could it be that you have a memory overwrite here?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
<div class='quotetop'>QUOTE </div>
--- Quote Start --- However I do notice that in your test code you use a transfer size of DMA_BUFF_SIZE*2 and in your HAL example you use a size of 1024.[/b] --- Quote End --- Excuse me. In my case it is bad style. For dirrect DMA registers acsess: For DMA_BUFF_SIZE*2:# define DMA_BUFF_SIZE (1024*1024+1) // transaction word 16-bit alt_u16 *buffer=NULL; buffer = (alt_u16 *)memalign(2, DMA_BUFF_SIZE*2); // allocate memory for DMA_BUFF_SIZE 16-bit words ............... ............... IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_SPI_REC_BASE, DMA_BUFF_SIZE*2); For HAL example:# define DMA_BUFF_BYTESIZE 1024 alt_u16 buffer[DMA_BUFF_BYTESIZE]; alt_dma_rxchan_prepare (rx, &buffer[0], 1024, NULL, NULL); Memory overwritenn cann't occur, becouse: 1. In prepare call I request less bytes then allocated for buffer. 2. DMA HAL passed to infinite ISR cycle before call of function Send2Sharc(0xA5); This function initiate the transfer process.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have just tried to run your code on the Stratix 1S10ES full reference design (with RX_STREAM changed to TX_STREAM), and it seems to work fine. The important change I made is that I removed all the references to the SPI, and instead directed the DMA to read from a location in memory.
It looks like in your case you have some configuration problem relating to the SPI. From here it's difficult to determine the source of the problem beyond that...- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have not read carefully the previous posts(I will do that later). I have a problem which is simlar to the one described by rugbybloke:
I have wrote 3 subroutines, one for peripheral-to-memory, one for memeory-to-peripheral, another for memory-to-memory. If I only call a single subroutine in the main function, ereryone will work properly; but when I call them in a queue, with ioctl to switch among them, bugs emerging. For example: (the three mode will be abbreviated as P2M,M2P,M2M) When I call those 3 routines in cycle with P2M the first: P2M(1)--->M2P(1)--->M2M(1)--->P2M(2)--->M2P(2)---->M2M(2)--->......... Then the first one---P2M(1) will work properly, when it turns to M2P(1), it will do the work of P2M with the inverse destination address and start address that assigned to M2P(1);M2M will do the work of M2P(1),P2M(2) do the work of M2M(1).........It seems that the next routine will do the work of the previous one, but the addresses of P and M are its own. I do not know whether I have described clearly. I will attach my code here, anyone who interest in it can test it on your board. ******************************************************************************** ****** Note: 1: copy_1_to_range is just the P2M, range_to_1 is M2P and range_to_range is M2M. 2: Here, I use SRAM as the test memory and SDRAM as the data and program memory. And also I use a fixed memory cell in SRAM as the peripheral. The base address of SRAM is 0x00800000. 3: To anyone who has good ideas and advices for my program, I'd like to receive your email to talk about DMA or anything else about NiosII. My email is: RemyMartin@eyou.com ******************************************************************************** ******# include <stdio.h># include <stddef.h># include <stdlib.h># include "sys/alt_dma.h"# include "alt_types.h"# include "altera_avalon_dma_regs.h"# include "altera_avalon_dma.h"# include "system.h"# include "string.h" /* ************************************************************************* */ /* The following routines is for transmintting & receiving callback routines */ /* ************************************************************************* */ volatile alt_32 transmitdone=0; volatile alt_32 receivedone=0; void transmit_done() { transmitdone=1; } void receive_done() { receivedone=1; } /* ************************************************************************* */ /* The following routines is for 1-to-range processing. */ /* ************************************************************************* */ void copy_1_to_range(const char* dma_name, void* start_addr, //Here,start_addr is the "1" void* desti_addr, //and desti_addr is the "range" alt_32 transfer_count, alt_32 transfer_mode) { alt_32 flag; alt_dma_rxchan rxchan; if((rxchan=alt_dma_rxchan_open(dma_name))==NULL) { printf("\n Failed to open receive channel(1-to-range)!\n"); exit(1); } alt_dma_rxchan_ioctl(rxchan,transfer_mode,NULL); alt_dma_rxchan_ioctl(rxchan,ALT_DMA_TX_STREAM_ON,start_addr); if((flag=alt_dma_rxchan_prepare(rxchan,desti_addr,transfer_count,receive_done,NU LL))<0) { printf("\n Failed to post receive request(1-to-range)!\n"); exit(1); } while(!receivedone); receivedone=0; alt_dma_rxchan_ioctl(rxchan,ALT_DMA_TX_STREAM_OFF,NULL); alt_dma_rxchan_close(rxchan); } /* ************************************************************************* */ /* The following routines is for range-to-1 processing. */ /* ************************************************************************* */ void copy_range_to_1(const char* dma_name, void* start_addr, //Here,start_addr is the "range" void* desti_addr, //and desti_addr is the "1" alt_32 transfer_count, alt_32 transfer_mode) { alt_32 flag; alt_dma_txchan txchan; if((txchan=alt_dma_txchan_open(dma_name))==NULL) { printf("\n Failed to open transmit channel(range-to-1)!\n"); exit(1); } alt_dma_txchan_ioctl(txchan,transfer_mode,NULL); alt_dma_txchan_ioctl(txchan,ALT_DMA_RX_STREAM_ON,start_addr); if((flag=alt_dma_txchan_send(txchan,desti_addr,transfer_count,transmit_done,NULL ))<0) { printf("\n Failed to post transmit request(range-to-1)!\n"); exit(1); } while(!transmitdone); transmitdone=0; alt_dma_txchan_ioctl(txchan,ALT_DMA_RX_STREAM_OFF,NULL); //alt_dma_txchan_close(txchan); } /* ************************************************************************* */ /* The following routines is for range-to-range processing. */ /* ************************************************************************* */ void copy_range_to_range(const char* dma_name, void* start_addr, void* desti_addr, alt_32 transfer_count, alt_32 transfer_mode) { alt_32 flag; alt_dma_txchan txchan; alt_dma_rxchan rxchan; /* Creat the transmit channel */ if((txchan=alt_dma_txchan_open(dma_name))==NULL) { printf("\n Failed to open transmit channel(range-to-range)!\n"); exit(1); } /* Creat the receive channel */ if((rxchan=alt_dma_rxchan_open(dma_name))==NULL) { printf("\n Failed to open receive channel(range-to-range)\n"); exit(1); } /* Post the transmit request */ alt_dma_txchan_ioctl(txchan,transfer_mode,NULL); if((flag=alt_dma_txchan_send(txchan,start_addr,transfer_count,transmit_done,NULL ))<0) { printf("\n Failed to post transmit request, the reason is %i\n",flag); exit(1); } /* Post the receive request */ alt_dma_rxchan_ioctl(rxchan,transfer_mode,NULL); if((flag=alt_dma_rxchan_prepare(rxchan,desti_addr,transfer_count,receive_done,NU LL))<0) { printf("\n Failed to post receive request, the reason is %i\n",flag); exit(1); } while(!(transmitdone & receivedone)); transmitdone=0; receivedone=0; alt_dma_txchan_close(txchan); alt_dma_rxchan_close(rxchan); } /* ************************************************************************* */ /* The main routine */ /* ************************************************************************* */ main() { char* name="/dev/dma_no1"; while(1){ copy_1_to_range(name, (void*)0x00800000, (void*)0x00800010, 8, ALT_DMA_SET_MODE_8); copy_range_to_1(name, (void*)0x00800020, (void*)0x00800030, 12, ALT_DMA_SET_MODE_32); copy_range_to_range(name, (void*)0x00800040, (void*)0x00800050, 16, ALT_DMA_SET_MODE_8);} }- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The receive and transmit are rather complexing in Nios II.
As for the alt_dma_txchan_...and alt_dma_rxchan_....., the memory is the reference, that means: if u use alt_dma_txchan, the the memory is the transmitting one; if u use alt_dma_rxchan, the the memory is the receiving one. But when it turns to the parameters of ioctl, the meaning is the reverse: ALT_DMA_TX_STREAM means the peripheral will do the stream transmitting work, so does the ALT_DMA_RX-STREAM. It pained me so much when I use ALT_DMA_TX_STREAM_ON/OFF in alt_dma_rxchan_ioctl(). I have not fully understand the alt_avalon_dma_launch_bidir/txonly/rxonly yet, it's rather confusing. In Nios I, the programming of DMA is rather easy, only copy_1_to_range(),copy_range_to_1() and copy_range_to_range() will do almost all the work!- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's unfortunate, but it's true. The HAL DMA interface is much more complicated than the old Nios I example functions. There's two reasons for this:
1. The HAL uses a callback interface rather than blocking waiting for the DMA to complete. This allows the processor to continue execution and do something useful while a DMA is underway - this is after all the reason for using a DMA rather than memcpy(). 2. A DMA process is described in terms of two half DMA's. While this is a little unatural when looking at the altera_avalon_dma component, it provides a much more general infrastructure which should be able to support future DMA controllers. To solve your particular problem, I'd recommend providing a seperate DMA device for each peripheral you wish to communicate with - so in your case you'd have three channels. That way you only call the ioctl at most once for each channel, and you avoid this problem. Even if the bug was not there, I believe you'd find that this becomes necessary in any case once you start putting together a real system. Given that all the transfers are being processed in parallel to you main code execution, you'll find that it becomes difficult to synchronise the DMA activity so that you call the ioctls at the right time. You'll also have the problem of figuring out where incoming packets have come from. This way it's easy in that there's a one to one correspondance between DMA channel and source. I hope that makes sense, and solves your problem.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you.
But by now, I am working for a new DMA driver which is more suitable for my project. Although @ltera will fix this problem soon, I think it's a good and useful experience which will give me a indepth view into the DMA, after all DMA will be used extensively in my project.- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page