Lucrarea nr. 8
 

Accesul direct la memorie

 
Introducere
Controller-ul DMA I8237
Accesul direct la memorie la calculatoarele PC/AT

 

Tema de laborator


 

1. Introducere

Accesul direct la memorie (DMA - Direct Memory Access) este folosit pentru transferurile rapide dintre dispozitivele de intrare/ieșire și memorie fară intervenția CPU. Accesul direct la memorie este folosit în driver-ele de floppy disk și de hard disk, dar poate fi folosit și la transferuri de la alte dispozitive de intrare sau ieșire (Sound Blaster, CD-ROM, plăci de rețea, etc) și memorie. Transferuri DMA se pot face în ambele direcții între memorie și porturile de intrare/ieșire precum și între două zone de memorie.

2. Controller-ul DMA I8237

Controller-ul de acces direct la memorie 8237 este un circuit de interfață cu periferia pentru sistemele cu microprocesoare. El este proiectat să îmbunătățească performanța sistemului permițând dispozitivelor externe să transfere direct informația către sau de la memoria sistemului. Circuitul oferă și posibilitatea de transfer memorie-memorie. Circuitul 8237 oferă o varietate largă de caracteristici programabile pentru a îmbunătăți viteza transferurilor, optimizarea sistemului și a permite reconfigurarea dinamică prin program. 8237 este proiectat să fie folosit împreună cu un registru extern de adrese pe 8 biți (8282). Controller-ul 8237 conține patru canale independente și poate fi extins la orice număr de canale prin conectarea în cascadă a mai multor astfel de circuite (modul de conectare în cascadă va fi prezentat mai târziu).

Diagrama de timp pentru inițierea unui transfer DMA și acceptarea lui de către procesor este prezentată în figura 8.1.

fig-08-01.gif (3404 bytes)

Figura 8.1

Dintre registrele interne al lui 8237, cele folosite în programare sunt următoarele:

fig-08-02.gif (2643 bytes)

Figura 8.2

Biții pe zero sunt nefolosiți. Fiecare canal are asociat un bit de mascare prin care dezactivează cererile DMA (DREQ). Fiecare bit de mascare este automat pus pe 1 atunci când canalul respectiv termină un transfer, dacă canalul nu este programat pentru autoinițializare. La RESET toți biții de mascare sunt puși pe 1 logic.

fig-08-03.gif (4534 bytes)

Figura 8.3

Modul de transfer DMA poate fi:

  1. transfer la cerere - în acest mod dispozitivul este programat să facă transferuri până când: contorul ajunge la 0 (TC - terminate count), sau apare o cerere externă de oprire a transferului (EOP - End of Process), sau se dezactivează DREQ. Astfel transferul poate continua până când dispozitivul de intrare/ieșire deservit de controller-ul DMA, și-a epuizat datele;
  2. transfer pe cuvânt (singular) - dispozitivul este programat a transfera doar un octet (sau cuvânt), după care cedă controlul procesorului; pentru un nou transfer trebuie să recâștige magistrala. Acest mod este folosit pentru dispozitivele care, datorită vitezei, nu pot transfera întregul bloc de date. Dispozitivul periferic va activa DREQ pentru fiecare cuvânt transferat. (Controller-ul de floppy disk folosește acest mod de transfer)
  3. trensfer pe bloc - controller-ul este activat de DREQ și efectuează transferuri până când contorul ajunge la zero (TC) sau apare o cerere externă de oprire a transferului (EOP). DREQ trebuie să rămână activ doar până controller-ul activează DACK;
  4. modul în cascadă - Este folosit pentru a cupla în cascadă mai multe circuite 8237 pentru o expandare simplă a sistemului.

În cazul transferurilor pe bloc sau la cerere, odată ce controller-ul DMA a câștigat magistrala sistem, se transferă un bloc de date de până la 64Ko. Controller-ele de hard disk mai vechi, foloseau modul de transfer la cerere, dar, crescând viteza CPU-urilor, este mai eficient a fi folosit acesta în realizarea transferurilor cu hard disk-ul.

fig-08-04.gif (4267 bytes)

Figura 8.4

Pentru a muta un bloc de date dintr-o zonă de memorie în alta, cu un minim efort din partea procesorului, controller-ul 8237 include posibilitatea realizării transferurilor memorie-memorie. Prin setarea bitului 0 din registrul de comandă, canalele 0 și 1 sunt folosite în transferul memorie-memorie, transfer inițiat prin activarea soft a lui DREQ (prin registrul de inițiere transfer) pentru canalul 0. Diagrama de timp pentru un transfer DMA este prezentată în figura de mai jos (figura 8.5):

fig-08-05.gif (3239 bytes)

Figura 8.5

Timing comprimat - pentru a obține o lățime de bandă mai mare, acolo unde caracteristicile sistemului o permit, 8237 poate comprima timpul de transfer cu două impulsuri de tact.

8237 oferă două tipuri de codificare a priorităților, selectabile prin program. Primul tip este cel cu prioritate fixă în care ordinea de tratare a cererilor DMA este în ordinea crescătoare a numărului canalului: canalul 0 are prioritatea cea mai mare, iar canalul 3 care are prioritatea cea mai mică. Un al douilea tip de codificare a priorităților este prioritatea rotativă în care ultimul canal care a fost deservit devine cel mai puțin prioritar la o următoare cerere DMA.

Generarea adreselor - pentru a reduce numărul de pini ai circuitului 8237, liniile A8-15 din magistrala de adrese sunt multiplexate cu liniile de date. Pentru a face distincția între adrese și date este folosit semnalul ADSTB generat de către controller.

fig-08-06.gif (2360 bytes)

Figura 8.6

fig-08-07.gif (2701 bytes)

Figura 8.7

3. Accesul direct la memorie la calculatoarele PC/AT

Calculatoarele compatibile IBM PC/AT folosesc pentru accesul direct la memorie două circuite 8237A conectate în cascadă (circuitul 8237A este identic cu 8237, doar că poate realiza transferuri DMA pe 16 biți). Astfel PC-ul dispune de 8 canale DMA programabile, din care unul este folosit pentru conectarea celui de-al doilea controller în cascadă. În figura de mai jos (figura 8.8), este prezentată, la nivel de bloc, schema de conectare a celor două controller-e la microprocesor. O schemă detaliată este prezentată în Anexa .

fig-08-08.gif (4740 bytes)

Figura 8.8

În tabelul următor sunt specifică utilizarea canalelor DMA.

Canalul

Folosit la AT

Controller

0

liber

1 (8 biți)

1

SDLC (Synchronous Data Link Control)

1 (8 biți)

2

diskette adapter

1 (8 biți)

3

hard disk adapter

1 (8 biți)

4

conectarea în cascadă pentru controller-ul 1

2 (16 biți)

5

liber

2 (16 biți)

6

liber

2 (16 biți)

7

liber

2 (16 biți)

Tabelul 8.1

În continuare vom prezenta modul de programare a unui chip DMA. Când programatorul dorește pornirea unui transfer DMA, trebuie să cunoască următoarele trei tipuri de informații:

Transferul DMA are două restricții de care, din nou, trebuie să ținem seama:

Prima restricție este relativ ușor de depășit: se transferă primul bloc de date, după ce acesta s-a terminat se trece la următorul bloc de date.

În continuare vom explica ce reprezintă aceste pagini de memorie. Imaginea primilor 1MB de memorie din sistem (PC/AT) este împărțită în 16 pagini a câte 64K fiecare:

Pagina

Spațiul de adrese

0

0000:0000 - 0000:FFFF

1

1000:0000 - 1000:FFFF

2

2000:0000 - 2000:FFFF

3

3000:0000 - 3000:FFFF

4

4000:0000 - 4000:FFFF

5

5000:0000 - 5000:FFFF

6

6000:0000 - 6000:FFFF

7

7000:0000 - 7000:FFFF

8

8000:0000 - 8000:FFFF

9

9000:0000 - 9000:FFFF

A

A000:0000 - A000:FFFF

B

B000:0000 - B000:FFFF

C

C000:0000 - C000:FFFF

D

D000:0000 - D000:FFFF

E

E000:0000 - E000:FFFF

F

F000:0000 - F000:FFFF

Tabelul 8.2

În tabelul 8.2 au fost trecute adresele logice ale paginilor. O adresă logică este formată din un segment și un offset (deplasament). Atât segmentul cât și deplasamentul în cadrul segmentului sunt pe 16 biți. Adresa fizică la 8086 și în modul real la 80x86 este pe 20 biți și se obține din adresa logică prin următoarea formulă:

adresa fizică (20 biți) = segment (16 biți)*16 + offset (16 biți)

sau

adresa fizică (20 biți) = segment (16 biți)<<4 + offset (16 biți)

Următoarea structură de date (definită în limbaj de asamblare) conține cele trei elemente care definesc un transfer DMA:

dma_block	STRUC
	dma_page	db	?
	dma_offset	dw	?
	dma_length	dw	?
dma_block	ENDS

Pentru calculul paginii și a deplasamentului în cadrul paginii (primii 4 biți din adresa fizică reprezintă pagina iar următorii 16 biți reprezintă deplasamentul), avem nevoie de o rutină care primește la intrare o adresă logică și returnează adresa fizică calculată din cea logică.

calc_address	PROC	NEAR
; input : ax - segment
;	  dx - offset
; output: ax - page (first 4 bits)
;	  dx - offset (next 16bits)
		...
		RET
calc_address	ENDP

Lungimea length a blocului de transferat prin DMA se specifică controller-ului DMA prin valoarea length - 1. Deci dacă trimitem controller-ului o lungime 0 el va face un transfer pe un octet, iar dacă-i trimitem valoarea 0FFFFH, transferul va fi de 64K.

Exisă trei porturi folosite pentru a programa un canal DMA:

Tabelul următor conține adresele acestor porturi pentru registrele fiecărui canal:

Canalul DMA

Pagina

Adresa

Lungime

0

087h

000h

001h

1

083h

002h

003h

2

081h

004h

005h

3

082h

006h

007h

4

08Fh

0C0h

0C2h

5

08Bh

0C4h

0C6h

6

089h

0C8h

0CAh

7

08Ah

0CCh

0CEh

Tabelul 8.3

Deoarece controller-ului DMA i se pot trimite doar cuvinte pe 8 biți, cuvintele pe 16 biți se trimit prin două scrieri succesive la același port, prima data se scrie octetul mai puțin semnificativ iar apoi octetul mai semnificativ.

În continuare vom prezenta pașii urmați pentru programarea unui transfer DMA.

Zona de date a programului va conține:

; Definirea unui tip de date structura ce contine informatiile necesare unui transfer DMA
dma_block	STRUC
	dma_page	db	?
	dma_offset	dw	?
	dma_length	dw	?
dma_block	ENDS
; Declararea a 8 variabile de tipul dma_block pentru cele 8 canale DMA
dma_data	dma_block	<,,>, <,,>, <,,>, <,,>, <,,>, <,,>, <,,>, <,,>
; Adresele de port ale registrelor de pagina pentru fiecare canal
dma_page	dw	087h, 083h, 081h, 082h, 08Fh, 08Bh, 089h, 08Ah
; Adresele de port ale registrelor de adresa pentru fiecare canal
dma_address	dw	000h, 002h, 004h, 006h, 0C0h, 0C4h, 0C8h, 0CCh
; Adresele de port ale registrelorde lungime pentru fiecare canal
dma_length	dw	001h, 003h, 005h, 007h, 0C2h, 0C6h, 0CAh, 0CEh 
; Adresele de port ale registrelor de mascare pentru fiecare controler 
dma_mask	dw	00Ah, 0D4h
; Adresele de port ale registrelor de mod pentru fiecare controler 
dma_mode	dw	00Bh, 0D6h
; Adresele de port ale registrelor de flip-flop pentru fiecare controler 
dma_flipflop	dw	00Ch, 0D8h
; Adresele de port ale registrelor de comanda pentru fiecare controler 
dma_command	dw	008h, 0D0h
; Adresele de port ale registrelor de stare pentru fiecare controler 
dma_status	dw	008h, 0D0h
; Adresele de port ale registrelor de initiere transfer pentru fiecare controler 
dma_request	dw	009h, 0D2h

Pașii necesari pentru programarea unui transfer DMA memorie-port sau port-memorie.

* rezerva spatiu in memorie pentru transfer;
* foloseste canalul DMA corespunzator dispozitivului extern cu care se lucreaza;
* dezactiveaza intreruperile;
* mascheaza canalul;
* initializeaza registrul flipflop;
* seteaza registrul de mod corespunzator transferului dorit
	- scriere in memorie: 45h
	- citire din memorie: 49h
* calculeaza adresa fizica pentru zona de memorie implicata in transfer;
* incarca registrul de pagina cu valoarea obtinuta pentru pagina;
* incarca registrul de adrese cu valoarea offset-ului;
* incarca registrul contor cu lungimea sirului de caractere;
* demascheaza canalul;
* valideaza intreruperile.

Pașii necesari pentru programarea unui transfer DMA memorie-memorie.

* rezerva spatiu in memorie pentru transfer;
* foloseste canalele DMA 0 si 1 pentru transferul memorie-memorie, canalul 0 folosit pentru citire 
  din memorie(din zona sursa) iar canalul 1 pentru scriere in memorie (in zona destinatie);
* dezactiveaza intreruperile;
* mascheaza canalele 0 si 1;
* initializeaza registrul flipflop;
* seteaza registrul de mod pentru canalul 0;
* seteaza registrul de mod pentru canalul 1;
* calculeaza adresa fizica pentru zona de memorie sursa;
* incarca registrul de pagina al canalului 0 cu valoarea obtinuta pentru pagina;
* incarca registrul de adrese al canalului 0 cu valoarea offset-ului;
* incarca registrul contor al canalului 0 cu lungimea sirului de caractere;
* calculeaza adresa fizica pentru memoria video;
* incarca registrul de pagina al canalului 1 cu valoarea obtinuta pentru pagina;
* incarca registrul de adrese al canalului 1 cu valoarea offset-ului;
* incarca registrul contor al canalului 1 cu lungimea sirului de caractere;
* seteaza registrul de comanda pentru transferul memorie-memorie;
* demascheaza canalul;
* valideaza intreruperil;
* initiaza transferul prin setarea unui bit in registrul de initiere, corespunzator canalului 0.

 

Tema de laborator

1. Să se realizeze un program în limbaj de asamblare care realizează un transfer DMA memorie-memorie. Se transferă un șir de caractere din segmentul de date al utilizatorului în memoria video.

SAU

2. Să se realizeze un program în limbaj de asamblare care realizează un transfer DMA între memorie și placa de sunet, realizându-se, astfel, un program care trimite în fundal un set de date plăcii de sunet.