Έλεγχος της Σειριακής Θύρας Καθ. Γεώργιος Παπακωνσταντίνου Yπ. ρ. Βουδούρης ηµήτρης ρ. Ιωάννης Παναγόπουλος Εργαστήριο Υπολογιστικών Συστηµάτων Καθ. Γεώργιος Παπακωνσταντίνου Εθνικό Μετσόβιο Πολυτεχνείο 004 Συνήθως κάθε υπολογιστής έχει δύο σειριακές θύρες. Η βασική πόρτα Ε/Ε για κάθε µία ορίζεται από το BIOS στις θέσεις 0040:0000 και 0040:000 (για την πρώτη και τη δεύτερη σειριακή αντίστοιχα). Στη γενική περίπτωση η βασική πόρτα Ε/Ε για την πρώτη σειριακή είναι η 3F8H και για τη δεύτερη η F8H. Επιπλέον αν χρησιµοποιηθεί η µέθοδος των διακοπών για την επικοινωνία µε το UART (έτσι ονοµάζεται εν συντοµία η ψηφίδα που ελέγχει τη σειριακή), η πρώτη σειριακή θύρα πυροδοτεί διακοπές τύπου 4 (IRQ 4) ενώ η δεύτερη τύπου 3 (IRQ 3). Οι ψηφίδες που χρησιµοποιούνται για τον έλεγχο της σειριακής θύρας είναι η 850 και µεταγενέστερα η 6550. Υπάρχει συµβατότητα προς τα πίσω και έτσι θα παρουσιαστούν τα χαρακτηριστικά της 850 και θα αναφέρονται διαφοροποιήσεις µε τη 6550 όπου κρίνεται απαραίτητο. Ο 850 περιέχει 9 διαφορετικούς αποµονωτές που είναι προσπελάσιµοι µέσω διαφορετικών I/O ports και επιπλέον οι οποίοι δεν είναι προσπελάσιµοι (ο TSR Transmitter Shifting Register και ο RSR Receiver Shifting Register). Για να προσπελάσουµε τους αποµονωτές αυτούς χρειάζεται να γνωρίζουµε τη βασική διεύθυνση της σειριακής θύρας και το offset του συγκεκριµένου αποµονωτή. Έτσι για παράδειγµα αν θέλαµε να προσπελάσουµε τον IID (offset ) για την πρώτη σειριακή θύρα (base address 3F8h) θα δίναµε µια εντολή ASSEMBLY της µορφής: in al, 3FAh (όπου 3FAh=3F8h+). Στον παρακάτω πίνακα δίνεται το offset όλων των αποµονωτών.
Offset Όνοµα Περιγραφή 0 DATA (TSR Transmitter εδοµένα λήψης-αποστολής από/προς το Sending Register, RHR Receiver UART Holding Register) IER (Interrupt Enable) Αποµονωτής ενεργοποίησης διακοπών IID (Interrupt Identidication) Αποµονωτής αναγνώρισης διακοπών 3 LCR (Line Control) Αποµονωτής ελέγχου γραµµής 4 MCR (Modem Control) Αποµονωτής ελέγχου modem 5 LSR (Line Status) Αποµονωτής κατάστασης γραµµής 6 MSR (Modem Status) Αποµονωτής κατάστασης modem 0 DLL Αποµονωτής ρύθµισης Baud Rate (byte (6550) (Divisor Latch Low byte) DLH (Divisor Latch High byte) FIFO Control µικρότερης σηµασίας) Αποµονωτής ρύθµισης Baud Rate (byte µεγαλύτερης σηµασίας) Αποµονωτής ελέγχου των 6-byte buffers του 6550. Το πρώτο βασικό σηµείο που πρέπει να επισηµανθεί είναι το γεγονός ότι οι αποµονωτές DATA και DLL καθώς και οι IER και DLH έχουν το ίδιο offset. Για να ξεχωρίσουµε σε πιο αναφερόµαστε κάθε φορά χρησιµοποιούµε το 7ο bit του αποµονωτή LCR το οποίο οοµάζεται Control bit ή cbit εν συντοµία. Έτσι για cbit=0 το offset αναφέρεται στους DATA και DLL ενώ για cbit= αναφερόµαστε στους IER και DLH. Θα πρέπει να προσέχουµε κατά την αναφορά σε αυτούς τους αποµονωτές να ορίζουµε αρχικά τη σωστή τιµή στο cbit. Το δεύτερο σηµείο που πρέπει να τονιστεί αναφέρεται στους αποµονωτές IID και FIFO Control οι οποίοι επίσης έχουν κοινό offset. Στη συγκεκριµένη περίπτωση όµως από τον IID µπορούµε µόνο να διαβάσουµε (µόνο εντολές ΙΝ) ενώ στον FIFO Control µπορούµε µόνο να γράψουµε (µόνο εντολές OUT) και έτσι βάσει της λειτουργίας ο υπολογιστής αυτόµατα επιλέγει τον κατάλληλο αποµονωτή. Στη συνέχεια ακολουθεί µια σύντοµη περιγραφή των πιο σηµαντικών από τους παραπάνω αποµονωτές (για πιο αναλυτική περιγραφή τους, ο αναγνώστης παραπέµπεται σε σχετική βιβλιογραφία): IΕR: Ο αποµονωτής αυτός χρησιµοποιείται όταν το UART λειτουργεί µε τη µέθοδο των διακοπών και µέσω αυτού του αποµονωτή καθορίζονται οι αιτίες που θα προκαλούν τις διακοπές. Το bit 0 ενεργοποιεί τη διακοπή άφιξης καινούργιου χαρακτήρα στο UART, το bit ενεργοποιεί τις διακοπή σε περίπτωση που το UART είναι σε θέση να στείλει χαρακτήρα (δηλ δεν µεταδίδει κάποιον εκείνη τη στιγµή). Τα bits, 3 ενεργοποιούν τις διακοπές σε περίπτωση που αλλάξει κάτι στην κατάσταση της γραµµής ή του modem αντίστοιχα.
IIR: Ο αποµονωτής αναγνώρισης διακοπής διαβάζεται συνήθως µέσα στον χειριστή διακοπών της σειριακής θύρας και χρησιµεύει για να αναγνωρίσουµε την αιτία που οδήγησε στη διακοπή. Για παράδειγµα, έστω ότι είχαµε ορίσει στον IIR ότι θα παράγονται διακοπές σε περίπτωση άφιξης καινούργιου χαρακτήρα και σε περίπτωση που το UART είναι σε θέση να στείλει καινούργιο χαρακτήρα. Έστω ακόµα ότι αυτό πυροδοτούσε µια διακοπή. Μέσω του IIR θα µπορούσαµε να καταλάβουµε ποια από τις δύο παραπάνω συνθήκες την προξένησε. Στον οδηγό της σειριακής θύρας του Micro-Empix αυτήν ακριβώς την διαδικασία επιτελεί η ρουτίνα InterruptReason. LCR: Ο συγκεκριµένος αποµονωτής ορίζει παραµέτρους µετάδοσης της γραµµής και παίρνει τιµή κατά την αρχικοποίηση της σειριακής θύρας. Πιο συγκεκριµένα µέσω αυτού ορίζονται το µήκος της λέξης που θα χρησιµοποιηθεί (bits 0-, 0 5 bits, 6 bits, 7 bits, 3 8bits), το µήκος του stop bit (bit, 0 stop bit, stop bits ή.5 stop bits για µήκος λέξης 5 bits) και η ισοτιµία (bits 3,4,5). Το 7ο bit είναι το cbit που αναφέρθηκε παραπάνω. LSR: Ο αποµονωτής κατάστασης γραµµής µας δίνει πληροφορίες για την κατάσταση της γραµµής. Είναι από τους πιο σηµαντικούς αποµονωτές. Πριν από κάθε απόπειρα διαβάσµατος ή εγγραφής χαρακτήρα στο UART, πρέπει να ελέγχεται ο LSR. Η σηµασία των bits του είναι η ακόλουθη: Bit Bit 7 Bit 6 Bit 5 Bit 4 Notes (6550) Λάθος στους καταχωρητές FIFO (πχ λάθος ισοτιµίας), αλλά όχι στον DATA. Έχουν γεµίσει οι εσωτερικοί αποµονωτές του UART και πρέπει να περιµένουµε πριν στείλουµε άλλους χαρακτήρες. Ο TSH δεν είναι άδειος, δηλ εκείνη τη στιγµή το UART µεταδίδει χαρακτήρα. Συµβαίνει όταν η γραµµή δεδοµένων είναι στο λογικό 0 για παραπάνω από όσο χρειάζεται για την αποστολή µιας λέξης (διαγνωστική λειτουργία). Bit 3 Σφάλµα µετάδοσης. Bit Λάθος ισοτιµίας. Bit Ένας χαρακτήρας γράφτηκε πάνω στον DATA αποµονονωτή πριν ο προηγούµενος διαβαστεί. Bit 0 Υπάρχουν δεδοµένα για ανάγνωση (άφιξη καινούργιου χαρακτήρα) FIFO Control: Το 6550 ολοκληρωµένο είναι πλήρως συµβατό µε το 850. Για το λόγο αυτό οι 6-byte FIFO καταχωρητές δεν είναι αρχικά ενεργοποιηµένοι. Για να τους ενεργοποιήσουµε θα πρέπει να θέσουµε το bit 0 του FIFO Control αποµονωτή. Επιπλέον µπορούµε (bits 6,7) να ρυθµίσουµε ανά πόσους χαρακτήρες που καταφθάνουν στο UART θα ενεργοποιηθεί µια διακοπή (0 char, 4 chars, 8 chars, 3 4 chars). MCR: Κανονικά αυτός ο αποµονωτής χρησιµοποιείται στην περίπτωση που στην σειριακή θύρα συνδεθεί modem, όµως για την περίπτωση που θέλουµε να 3
χρησιµοποιήσουµε την µέθοδο των διακοπών θα πρέπει να θέσουµε το bit 3 του συγκεκριµένου αποµονωτή στο ώστε το UART να παράγει διακοπές. DLL, DLH: O πίνακας που ακολουθεί δίνει τις τιµές που πρέπει να εισαχθούν στους παραπάνω καταχωρητές για κάποιες τυπικές τιµές Baud rate. Speed (BPS) Divisor (Dec) Divisor Latch High Byte Divisor Latch Low Byte 50 304 09h 00h 300 384 0h 80h 600 9 00h C0h 400 48 00h 30h 4800 4 00h 8h 9600 00h 0Ch 900 6 00h 06h 38400 3 00h 03h 57600 00h 0h 500 00h 0h Γενικά κατά τον προγραµµατισµό του UART µε χρήση διακοπών, πρέπει να έχουµε υπόψη µας τα εξής: Τόσο το UART όσο και το 859 (PIC), που χρησιµοποιείται για να µπλοκάρει (mask) ορισµένες διακοπές υλικού, µετά από κάθε διακοπή που θα στείλουν στον επεξεργαστή, περιµένουν κάποιου είδους επιβεβαίωση ότι η διακοπή που έστειλαν παραλήφθηκε. Η επιβεβαίωση για το 859 είναι απλώς η αποστολή σε αυτόν της τιµής 0Η (στην πόρτα 0Η). Για το UART αν µας στείλει διακοπή επειδή έλαβε χαρακτήρα, τότε η επιβεβαίωση από µέρους του επεξεργαστή θα είναι να διαβάσει το χαρακτήρα. Αν το UART στείλει διακοπή ότι είναι έτοιµο να αποστείλει χαρακτήρα, τότε η επιβεβαίωση πραγµατοποιείται είτε µεταφέροντας ένα χαρακτήρα στο UART ή διαβάζοντας τον αποµονωτή IIR. Σε περίπτωση που αποτύχουµε να στείλουµε επιβεβαίωση είτε στο 859 είτε στο UART τότε δεν θα ξαναπυροδοτηθούν διακοπές. Στην επόµενη σελίδα ακολουθεί ένα διάγραµµα µε τις βασικές ενέργειες που πρέπει να πραγµατοποιούνται κατά την αρχικοποίηση της σειριακής θύρας. Ο αναγνώστης παραπέµπεται στον κώδικα του Micro-Empix ο οποίος µπορεί να µελετηθεί παράλληλα µε το παρακάτω σχεδιάγραµµα για τον έλεγχο των σειριακών θυρών: 4
CLI Ανάγνωση βασικής πόρτας της σειριακής από το BIOS ιάβασµα από το BIOS από τις διευθύνσεις 0040:0000 (COM-), 0040:000 (COM-) Καθορισµός Baud Rate Καθορισµός του Baud Rate στους DLL, DLH. Οπωσδήποτε πρέπει το Cbit =. Καθορισµός µήκους λέξης, stop bit και ισοτιµίας Καθορισµός των παραµέτρων στον LCR ιάβασµα και καθαρισµός των LSR, MSR, IIR Καθαρισµός εναποµείνοντων διακοπών Ανάγνωση και απόρριψη χαρακτήρων που έχουν τυχόν αποµείνει στη σειριακή από προηγούµενη χρήση της ιάβασµα των χαρακτήρων που έχουν τυχόν ξεµείνει στους buffers (Αποµονωτής DATA). Οπωσδήποτε πρέπει το Cbit = 0. (6550) Καθαρισµός και ενεργοποίηση των FIFO buffers (FIFO Control register) OXI Χρησιµοποίηση διακοπών? NAI Εγκατάσταση καινούργιου Η διεύθυνση του interrupt vector για εξυπηρετητή διακοπών για την το COM- είναι 0000:000C, ενώ του διακοπή που αντιστοιχεί στη COM- είναι 0000:000Β συγκεκριµένη θύρα Μηδενισµός των συνθηκών ενεργοποίησης των διακοπών. Απενεργοποίηση διακοπών στον IER Ενεργοποίηση της συγκεκριµένης διακοπής σον 859 PIC (programmable interrupt controller (θέτουµε 0 το αντίστοιχο bit) Για το COM- µηδενίζουµε το bit 4, ενώ για το COM- το bit 3. Ενεργοποίηση των διακοπών στον MCR και καθορισµός συνθηκών στον IER. Στο τέλος (αν ενεργοποιήσουµε και τις THR_Empty διακοπές) πρέπει να διαβάσουµε µια φορά και τον IIR αποµονωτή για να δηλώσουµε στο UART ότι αναγνωρίσαµε την αρχική διακοπή που θα σταλεί. STI 5