It can be manufactured very inexpensively.
It's sole purpose is to transfer data between the memory and an IO device.
You have to remember that the DMA is a helper processor for the CPU. Thus: the CPU must be able to tell the DMA what data to transfer. The only way that the CPU can do that is when the DMA is accessible on the system bus
It is therefore of no surprise that the DMA is connected onto the system bus....
The structure resembles somewhat the structure of an IO device (with the command, data and status registers), but it has two additional registers that allow the DMA to perform the data transfer operation.
The registers in the DMA are used as follows:
|
|
|
So you clearly see that the DMA is a helper device to the CPU.
First, I have to make some assumptions on how the DMA is connected to the system bus:
|
The following is a assembler code fragment that will instruct the DMA to transfer 1000 bytes of data from memory at the variable buffer to the IO device:
(#buffer = starting address of the data in memory) move.l #buffer, $1408 // Setup the Address register of DMA move.l #1000, $1404 // Setup the Count register of DMA move.l #1, $1400 // Issue print command to IO device // operation code 1 means "print" |
After these 3 simple move assembler instructions, the CPU has programmed the DMA and started the DMA to perform the IO transfer operation.
The 6-million dollar (i.e., very important) question that remains is:
|
Answers:
|
xdef Start, Stop, End Start: * .... * .... Program before IO operation * .... * Print "Hello World" by programming the DMA move.l #-1, $140C ; Write a non-zero value in status register move.l #11, $1404 ; Program the count register in DMA move.l #Str,$1408 ; Program the address register in DMA move.l #1, $1400; ; Issue the Write command to DMA * Wait until the IO operation is completed wait: move.l $140C, d0 cmp.l #-1, d0 ; Test if status has changed to ready beq wait ; Repeat testing until status changes * .... * .... Program after IO operation * .... Stop: nop nop nop X: dc.b 'Hello World' End: end |
Program file: /home/cs355001/demo/Programmed-IO/m68000-print.s Compile with: /bin/cs355001/bin/as255 m68000-print Run with: /bin/cs355001/bin/m68000 (load m68000-print) |
|
|
|
Example: program that read in 1000 grade values and computes its average:
main() { int grades[1000]; int i; double sum, average; read(grades, grade-file, 1000); // Start DMA to do data transfer // The DMA will fill the grades[ ] "slowly" // Suppose program continues execution WHILE DMA is performing the IO transfer.... sum = 0; for (i = 0; i < 1000; i++) sum = sum + grades[i]; // the grades[ ] value is not yet available !!! average = sum/1000; } |
If the program preceeds without waiting with the program segment following the read() subroutine, it will use incorrect values (because the data has not yet been transfered into the "grades" array in memory) !!!
* Wait until the IO operation is completed wait: move.l $140C, d0 cmp.l #-1, d0 ; Test if status has changed to ready beq wait ; Repeat testing until status changes |
This solution is clearly unattractive:
|
In fact, the solution is dumb... why would you want to make an extra helper device (the DMA) for the CPU and then make the CPU wait for the DMA to finish ? You could just as well make the CPU do the transfer and you don't need an extra DMA device....
|
Clearly:
|
Answer:
|
More precisely:
|
|
From the point of view of the programs, the releasing and reclaiming of the CPU is the act of one program giving the control of the CPU to another program.
In Computer Science jargon, when two (or more) programs try to interact with one another, we say that the program must synchronize with one each other.
The technique to make them agree is called a synchronization method.