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);}
}