Design an initialization routine in CPU32 assembly language that initializes
the DUART as follows:
Serial port A is to use a baud rate of 19200, and character frames with
8 data bits, even parity, and 2 stop bits.
Serial port B is to use a baud rate of 38400, and character frames
with 7 data bits, fixed low parity bit, and 1.5 stop bits.
Interrupts are to be enabled for the receive direction of both serial
ports, but not for the transmit direction.
Thus, receiving a new character into either port A or port B's receiver
is to trigger a hardware interrupt to the CPU.
In your code be sure to use the predefined constants that were provided to
you in laboratory exercise 2.
.comm IMR_COPY, 1 /* Copy of IMR in system RAM */
.EQU DUART, 0xA00800 /* DUART chip base address */
/* Offsets to read/write-able registers */
.EQU MR1A, 0x00 /* Mode Register 1A */
.EQU MR2A, 0x00 /* Mode Register 2A */
.EQU MR1B, 0x08 /* Mode Register 1B */
.EQU MR2B, 0x08 /* Mode Register 2B */
.EQU IVR, 0x0C /* Interrupt Vector Register */
/* Offsets to read-only registers */
.EQU SRA, 0x01 /* Status Register A */
.EQU RBA, 0x03 /* Receiver Buffer A */
.EQU IPCR, 0x04 /* Input Port Change Register */
.EQU ISR, 0x05 /* Interrupt Status Register */
.EQU CUR, 0x06 /* Counter Upper Register */
.EQU CLR, 0x07 /* Counter Lower Register */
.EQU SRB, 0x09 /* Status Register B */
.EQU RBB, 0x0B /* Receiver Buffer B */
/* Offsets to write-only registers */
.EQU CSRA, 0x01 /* Clock Select Register A */
.EQU CRA, 0x02 /* Command Register A */
.EQU TBA, 0x03 /* Transmitter Buffer A */
.EQU ACR, 0x04 /* Auxiliary Control Register */
.EQU IMR, 0x05 /* Interrupt Mask Register */
.EQU CTUR, 0x06 /* Counter/Timer Upper Register */
.EQU CTLR, 0x07 /* Counter/Timer Lower Register */
.EQU CSRB, 0x09 /* Clock Select Register B */
.EQU CRB, 0x0A /* Command Register B */
.EQU TBB, 0x0B /* Transmitter Buffer B */
.EQU OPCR, 0x0D /* Output Port Configuration Register */
.EQU OPUR, 0x0E /* Output Port Upper Register */
.EQU OPLR, 0x0F /* Output Port Lower Register */
.EQU BSET, 0x0E /* Bit Set Command */
.EQU BRST, 0x0F /* Bit Reset Command */
/* Mode Register 1A and 1B (MR1A and MR1B) Fields */
.EQU BITS_5, 0b00000000
.EQU BITS_6, 0b00000001
.EQU BITS_7, 0b00000010
.EQU BITS_8, 0b00000011
.EQU WITH_PAR, 0b00000000
.EQU PAR_EVEN, 0b00000000
.EQU PAR_ODD, 0b00000100
.EQU FORCE_PAR, 0b00001000
.EQU FP_LOW, 0b00000000
.EQU FP_HIGH, 0b00000100
.EQU NO_PAR, 0b00010000
.EQU MULTI_DROP, 0b00011000
.EQU MD_DATA, 0b00000000
.EQU MD_ADDR, 0b00000100
.EQU CHAR_MODE, 0b00000000
.EQU BLK_MODE, 0b00100000
.EQU RxRDY, 0b00000000
.EQU FFULL, 0b01000000
.EQU RTS_Rx_CTL_OFF, 0b00000000
.EQU RTS_Rx_CTL_ON, 0b10000000
/* Mode Register 2A and 2B (MR2A and MR2B) Fields */
.EQU STOP_1, 0b00000111
.EQU STOP_1_563, 0b00001000
.EQU STOP_2, 0b00001111
.EQU CTS_Tx_CTL_OFF, 0b00000000 /*Enable CTS control over Tx */
.EQU CTS_Tx_CTL_ON, 0b00010000 /*Disable CTS control over Tx */
.EQU RTS_Tx_CTL_OFF, 0b00000000 /*Enable Tx RTS output */
.EQU RTS_Tx_CTL_ON, 0b00100000 /*Disable Tx RTS output */
.EQU MD_NORM, 0b00000000 /*Normal Channel Mode */
.EQU MD_AUTO_ECHO, 0b01000000 /*Normal Channel Mode */
.EQU MD_LOCAL_LOOP, 0b10000000 /*Normal Channel Mode */
.EQU MD_REM_LOOP, 0b11000000 /*Normal Channel Mode */
/* Clock Select Register A and B (CSRA and CSRB) Fields
(Note baud rate set, 1 or 2, must be specified in ACR[7])
Transmitter Baud Rate */
.EQU TxBAUD_9600, 0b00001011 /* 9600 bps */
.EQU TxBAUD_19200, 0b00001100 /* 19200 bps (set 2 only) */
.EQU TxBAUD_38400, 0b00001100 /* 38400 bps (set 1 only) */
.EQU TxBAUD_TIMER, 0b00001101 /* Timer used as clock source */
.EQU TxBAUD_IP3_16X, 0b00001110 /* Channel A only, IP3/16 */
.EQU TxBAUD_IP3_1X, 0b00001111 /* Channel A only, IP3/1 */
.EQU TxBAUD_IP5_16X, 0b00001110 /* Channel B only, IP5/16 */
.EQU TxBAUD_IP5_1X, 0b00001111 /* Channel B only, IP5/1 */
/* Receiver Baud Rate */
.EQU RxBAUD_9600, 0b10110000 /* 9600 bps */
.EQU RxBAUD_19200, 0b11000000 /* 19200 bps (set 2 only) */
.EQU RxBAUD_38400, 0b11000000 /* 38400 bps (set 1 only) */
.EQU RxBAUD_TIMER, 0b11010000 /* Timer used as clock source */
.EQU RxBAUD_IP4_16X, 0b11100000 /* Channel A only, IP4/16 */
.EQU RxBAUD_IP4_1X, 0b11110000 /* Channel A only, IP4/1 */
.EQU RxBAUD_IP2_16X, 0b11100000 /* Channel B only, IP2/16 */
.EQU RxBAUD_IP2_1X, 0b11110000 /* Channel B only, IP2/1 */
/* Command Registers A and B (CRA and CRB) Fields
Note: registers must be cleared after a command is issued */
.EQU ENABLE_Rx, 0b00000001
.EQU DISABLE_Rx, 0b00000010
.EQU ENABLE_Tx, 0b00000100
.EQU DISABLE_Tx, 0b00001000
.EQU RESET_MR_PTR, 0b00010000
.EQU RESET_Rx, 0b00100000
.EQU RESET_Tx, 0b00110000
.EQU RESET_ERROR, 0b01000000
.EQU RESET_BK_IRQ, 0b01010000
.EQU START_BREAK, 0b01100000
.EQU STOP_BREAK, 0b01110000
.EQU NO_CMD, 0b00000000
/* Auxiliary Control Register (ACR) Fields */
.EQU BAUD_SET_1, 0b00000000 /* Use set 1 of baud rates */
.EQU BAUD_SET_2, 0b10000000 /* Use set 2 of baud rates */
/* Exception Vector offsets and values */
.EQU VEC_90, 0x168 /* User exception vector */
.EQU VEC_90_NUM, 0x5A
.EQU AUTOVEC_1, 0x64 /* offset to autovector at priority level 1 */
.EQU AUTOVEC_1_NUM, 0x19
/******************************************************************/
.macro LOCK
/* MOVE.W SR,-(SP) */
ORI.W #0x0700,SR
.endm
.macro UNLOCK
AND.W #0xF8FF, SR
/* MOVE.W (SP)+,SR */
.endm
.globl DuartInit
DuartInit:
LOCK /* lock out H/W interrupts */
MOVEM.L D0/A0,-(SP) /* save scratchpad registers */
LEA.L DUART,A0 /* set up pointer A0 to DUART base address */
CLR.L D0
ORI.B #RESET_MR_PTR,D0 /* reset the MR pointer to MR1A and MR2A */
MOVE.B D0,CRA(A0) /* send reset MR ptr command to CRA */
MOVE.B D0,CRB(A0) /* send reset MR ptr command to CRB */
MOVE.B #NO_CMD,CRA(A0) /* remove command from CRA */
MOVE.B #NO_CMD,CRB(A0) /* remove command from CRB */
CLR.L D0
ORI.B #BITS_8,D0 /* use 8 bit data words */
ORI.B #PAR_EVEN,D0 /* include even parity bit */
ORI.B #RxRDY,D0 /* interrupts when receiver ready */
MOVE.B D0,MR1A(A0) /* initialize MR1A */
CLR.L D0
ORI.B #STOP_2,D0 /* 2.000 stop bits */
ORI.B #CTS_Tx_CTL_OFF,D0 /* disable CTS H/W flow control input */
ORI.B #RTS_Tx_CTL_OFF,D0 /* disable RTS H/W flow control output */
ORI.B #MD_NORM,D0 /* enable normal duplex mode */
MOVE.B D0,MR2A(A0) /* initialize MR2A */
CLR.L D0
ORI.B #BITS_7,D0 /* use 7 bit data words */
ORI.B #FORCE_PAR,D0 /* force a constant parity bit */
ORI.B #FP_LOW,D0 /* parity bit is fixed low */
ORI.B #RxRDY,D0 /* interrupts when receiver ready */
MOVE.B D0,MR1B(A0) /* initialize MR1B */
CLR.L D0
ORI.B #STOP_1_563,D0 /* 1.563 stop bits */
/* Note: This is the closest available rate to 1.5 stop bits */
ORI.B #CTS_Tx_CTL_OFF,D0 /* disable CTS H/W flow control input */
ORI.B #RTS_Tx_CTL_OFF,D0 /* disable RTS H/W flow control output */
ORI.B #MD_NORM,D0 /* enable normal duplex mode */
MOVE.B D0,MR2B(A0) /* initialize MR2B */
/* Set baud rate for channel A to 19200 */
CLR.L D0
ORI.B #BAUD_SET_2,D0 /* select set 2 baud rates */
MOVE.B D0,ACR(A0) /* initialize ACR */
CLR.L D0
ORI.B #RxBAUD_19200,D0 /* Tx baud rate is set by TPU */
ORI.B #TxBAUD_19200,D0 /* Rx baud rate is set by TPU */
MOVE.B D0,CSRA(A0) /* initialize CSRA */
/* Set baud rate for channel B to 38400 */
CLR.L D0
ORI.B #BAUD_SET_1,D0 /* select set 1 baud rates */
MOVE.B D0,ACR(A0) /* initialize ACR */
CLR.L D0
ORI.B #RxBAUD_38400,D0 /* Tx baud rate is set by TPU */
ORI.B #TxBAUD_38400,D0 /* Rx baud rate is set by TPU */
MOVE.B D0,CSRB(A0) /* initialize CSRB */
/* NOTE: This is probably an error in the assignment. It
seems likely that the DUART cannot simultaneously use both
sets of baud rates for the different channels. */
/* ***************** START INTERRUPT MASKS *********************** */
CLR.L D0
/* ORI.B #TxRDYA,D0 enable Tx A interrupts */
/* ORI.B #RxRDYA,D0 enable Rx A interrupts */
/* ORI.B #TxRDYB,D0 enable Tx B interrupts */
/* ORI.B #RxRDYB,D0 enable Rx B interrupts */
MOVE.B D0,IMR(A0) /* initialize the IMR */
MOVE.B D0,IMR_COPY /* update copy of IMR */
/* *********************** END INTERRUPT MASKS *************************************** */
MOVE.B #VEC_90_NUM, IVR(A0) /* initialize the IVR */
CLR.L D0
ORI.B #RESET_Rx,D0 /* reset the receiver */
ORI.B #RESET_Tx,D0 /* reset the transmitter */
ORI.B #RESET_ERROR,D0 /* reset the error status */
MOVE.B D0,CRA(A0) /* send reset commands to CRA */
MOVE.B D0,CRB(A0) /* send reset commands to CRB */
MOVE.B #NO_CMD,CRA(A0) /* remove commands from CRA */
MOVE.B #NO_CMD,CRB(A0) /* remove commands from CRB */
CLR.L D0
ORI.B #ENABLE_Rx,D0 /* enable the receiver */
ORI.B #ENABLE_Tx,D0 /* enable the transmitter */
MOVE.B D0,CRA(A0) /* send enable commands to CRA */
MOVE.B D0,CRB(A0) /* send enable commands to CRB */
MOVE.B #NO_CMD,CRA(A0) /* remove commands from CRA */
MOVE.B #NO_CMD,CRB(A0) /* remove commands from CRB */
/* install the ISR vector */
MOVE.L #DuartISR, AUTOVEC_1
MOVE.B ISR(A0), D0 /* read the ISR */
MOVEM.L (SP)+,D0/A0 /* restore scratchpad registers */
UNLOCK /* re-enable H/W interrupts */
RTS
Design an CPU32 assembly language program that implements a circular queue.
The data elements in the queue are to be word-sized (16 bits wide).
Two byte-sized flags are to be used to keep track of whether the buffer
is full or empty.
Two word-sized indexes are to be used to keep track of the queue
locations where next data word is to be inserted, and where the
next data word is to be read.
Use traps to access the queue.
A TRAP #4 is called with no parameters to initialize the circular queue.
A TRAP #5 is used to read the next word in the queue.
It returns -1 in D7.B if the circular queue is empty.
It returns the data item in D0.W and has D7.B set to 0 if the circular
queue was not empty when the trap was called.
A TRAP #6 is used to write the next word in the queue.
The data word to be inserted is passed in D0.W.
This trap returns 0 in D7.B if the word was inserted successfully;
otherwise, -1 is returned in D7.B.
In your solution, be sure to include code that reserves memory locations
for all required data structures.
Express the size of the queue as a symbolic constant value.
.equ EMPTY_FLAG, 0 /* offset to empty flag */
.equ FULL_FLAG, 1 /* offset to full flag */
.equ READ_PTR, 2 /* offset to read ptr */
.equ WRITE_PTR, 4 /* offset to write ptr */
QUEUE_BASE:
.comm 2 /* space for two byte-sized flags */
.comm 8 /* space for read and write long-sized pointers */
ELEM_ARRAY:
.org ELEM_ARRAY + NUM_ELEMS
/* The following code needs to be called in the system initialization */
MOVE.L #CircQInit,0x90 /* install TRAP #4 vector */
MOVE.L #CircQRead,0x94 /* install TRAP #5 vector */
MOVE.L #CircQWrite,0x98 /* install TRAP #6 vector */
CircQInit: /* TRAP #4 exception handling routine */
MOVEM.L A1,-(SP) /* save regs */
LEA.L QUEUE_BASE,A0
CLR.B EMPTY_FLAG(A0)
CLR.B FULL_FLAG(A0)
CLR.W READ_PTR(A0)
CLR.W WRITE_PTR(A0)
MOVEM.L (SP)+,A0 /* restore regs */
RTE
CircQRead: /* TRAP #5 exception handling routine */
MOVEM.L A0-A1/D1,-(SP) /* save regs */
LEA.L QUEUE_BASE,A0
TST.B EMPTY_FLAG(A0) /* is queue empty? */
BNE CANT_READ /* yes, load error code */
/* no, read old data */
LEA.L ELEM_ARRAY,A1
MOVE.W READ_PTR(A0),D1
MOVE.W (0,A1,D1.W*2),D0 /* read data from queue */
ADDQ.W #1,D1 /* increment read ptr */
MOVE.W D1,READ_PTR(A0)
CMPI.W #NUM_ELEMS,D1 /* check for ptr wraparound */
BLT SKIP_RESET_READ_PTR
CLR.W READ_PTR(A0) /* wrap around the read ptr */
SKIP_RESET_READ_PTR:
CLR.B D7 /* load success return code */
BRA EXIT_CIRCQWrite
CANT_WRITE:
MOVE.B #-1,D7 /* load full buffer error code */
EXIT_CIRCQWrite:
MOVEM.L (SP)+,A0-A1/D1 /* restore regs */
RTE
CircQWrite: /* TRAP #6 exception handling routine */
MOVEM.L A0-A1/D1,-(SP) /* save regs */
LEA.L QUEUE_BASE,A0
TST.B FULL_FLAG(A0) /* is queue full? */
BNE CANT_WRITE /* yes, load error code */
/* no, write new data */
LEA.L ELEM_ARRAY,A1
MOVE.W WRITE_PTR(A0),D1
MOVE.W D0,(0,A1,D1.W*2) /* write the data word */
ADDQ.W #1,D1 /* increment write ptr */
MOVE.W D1,WRITE_PTR(A0)
CMPI.W #NUM_ELEMS,D1 /* check for ptr wrap-around */
BLT SKIP_RESET_WRITE_PTR
CLR.W WRITE_PTR(A0) /* wrap around the write ptr */
SKIP_RESET_WRITE_PTR:
CLR.B D7 /* load success return code */
BRA EXIT_CIRCQWrite
CANT_WRITE:
MOVE.B #-1,D7 /* load full buffer error code */
EXIT_CIRCQWrite:
MOVEM.L (SP)+,A0-A1/D1 /* restore regs */
RTE