Forum Discussion
Altera_Forum
Honored Contributor
22 years agoNIOS II DMA HAL
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 ...
Altera_Forum
Honored Contributor
21 years agoI 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: [email protected] ******************************************************************************** ******# 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);} }