Hi Eduard!
I am near to success with DMA. Below is sample of my program. This sample
code works except one importatnt thing.
I use DMA in 8 bit mode with old ISA DAQ card. I programmed DMA to Single
mode with No Autoinitialization. May DAQ card triggrers AD conversion on
each internal Pacer tick. After each Conversion the DAQ card generates two
succesive DMA REQUEST signals (cause it gives two bytes from each AD
conversion). After that DMA has exclusive access to data bus and transfers
two bytes to buffer in memory. Before all I initialize my buffer with 0xAAAA
(1010101010101010). After all transfers (Terminal Count is reached in DMA) I
don’t get any new value in my buffer, there are still 0xAAAA.
I use mem_offset() to get physical address of my buffer maped with mmap(). I
know that physical address is 0x099000.
ADBuffer = (short*) mmap(0, NumberOfADConversions * sizeof(short), PROT_READ
| PROT_WRITE | PROT_NOCACHE, MAP_ANON | MAP_PHYS | MAP_NOX64K |
MAP_BELOW16M, NOFD, 0);
mem_offset((void *) ADBuffer, NOFD, NumberOfADConversions * sizeof(short),
&offset, 0);
I suppose that I write wrong values to DMAPageReg (8bit) and DMAAddrReg
(16bit). I tested it and I have proper value in AddrReg. This value is
incrementing. But I cannot read DMAPageReg, I always get 0x00 from it. Maybe
because DMAPageReg is separate chip (74LSxxxx) outside DMA. I think that my
data is being transferred to unknown area of my memory, not to buffer.
I write 7-0 bits of buffer address to DMAAddrReg, then 15-8 bits of address
to DMAAddrReg, then 23-16 bits DMAPageReg.
Maybe You do know what is the problem.
regards
Darek
======================= SAMPLE OF MY PROGRAM ====================
char DMAChannels[4] = { 0 , 1 , 2 , 3 };
char DMAMaskReg[4] = { 0x0A, 0x0A, 0x0A, 0x0A};
char DMAModeReg[4] = { 0x0B, 0x0B, 0x0B, 0x0B};
char DMAClearReg[4] = { 0x0C, 0x0C, 0x0C, 0x0C};
char DMAPageReg[4] = { 0x87, 0x83, 0x81, 0x82};
char DMAAddrReg[4] = { 0x00, 0x02, 0x04, 0x06};
char DMACountReg[4] = { 0x01, 0x03, 0x05, 0x07};
…
dma = 3;
do
{
for(bufno = 0; bufno < 2 ; bufno++)
{
if(pprm → ADStatus & 0x8000) break;
printf(“Before DMA Set…”);
InterruptDisable();
out8(pprm → Port + 9, control & ~0x04);
//clears DMAE bit
out8(DMAMaskReg[dma], 0x04 | dma);
//masks channel no. dma
out8(DMAClearReg[dma], 0x00);
//stops all transfers
out8(DMAModeReg[dma], 0x50 | 0x04 | (dma & 0x03));
//sets Single mode of DMA operation
out8(DMAAddrReg[dma], offset & 0x000000FF); //writes
7 - 0 bits of phys address
out8(DMAAddrReg[dma], (offset & 0x0000FF00) >> ; //writes
15 - 8 bits of phys address
out8(DMAPageReg[dma], (offset & 0x00FF0000) >> 16); //writes
23 - 16 bits of phys address
out8(DMACountReg[dma], transfers & 0x00FF);
//sets number of transfers (bytes in buffer)
out8(DMACountReg[dma], (transfers & 0xFF00) >> ;
out8(DMAMaskReg[dma], 0x03 & dma);
//clears the mask from channel no. dma
out8(pprm → Port + 9, control | 0x04);
//sets DMAE bit
InterruptEnable();
printf(“DMA Set…\n”);
InterruptWait(NULL, NULL);
out8(pprm → Port + 8, 0x00); //clear INT bit
InterruptUnmask(InterruptLevel, isr_handler_id);
printf(“After an INTERRUPT\n”);
pthread_mutex_lock(&mutex);
ReadyADBuffer = ADBuffer;
ADWriteCount++;
pthread_mutex_unlock(&mutex);
}
} while(CyclicMode && !(ADStatus & 0x8000));
…