1 | * SIMPLE UART "ECHO" CODE
|
2 |
|
3 | * Register initialization values before execution:
|
4 | *
|
5 | * PC=00030300 SR=2700
|
6 | * USP=00080000 *ISP=00004000 (Stack pointers not used)
|
7 | *
|
8 | * D1 = SCCE3 holding register
|
9 | * D3 = count of characters received
|
10 | * D4 = count of characters transmitted
|
11 | * D5 = count of BSY conditions occuring (no receive buffers available)
|
12 | * D6 = 1 or greater, if character(s) waiting to be transmitted, 0 otherwise
|
13 | * A0 = current Rx BD pointer
|
14 | * A1 = current "next TX byte" to send pointer
|
15 | * A2 = current Tx BD pointer
|
16 | * A3 = temp
|
17 |
|
18 | * SCC3 Tx Buffer Descriptors initialization:
|
19 | * 00700640 5000 0000 0003 0000
|
20 | * 00700648 7000 0000 0003 0001 (wrap bit set)
|
21 |
|
22 | * SCC3 Rx Buffer Descriptors initialization:
|
23 | * 00700600 d000 0000 0003 0002
|
24 | * 00700608 f000 0000 0003 0003 (wrap bit set)
|
25 |
|
26 | BAR EQU $0F2
|
27 | GIMR EQU $700812
|
28 | IPR EQU $700814
|
29 | IMR EQU $700816
|
30 | ISR EQU $700818
|
31 | PACNT EQU $70081e
|
32 | SIMODE EQU $7008b4
|
33 | SCON3 EQU $7008a2
|
34 | SCM3 EQU $7008a4
|
35 | SCCE3 EQU $7008a8
|
36 | SCCM3 EQU $7008aa
|
37 |
|
38 | * SCC3 initialization code:
|
39 |
|
40 | ORG $30300
|
41 |
|
42 | MOVE.W #$700,BAR ; BAR = 0700
|
43 | * Base Address = $700000, so ALL 68302 on-chip peripherals begin at
|
44 | * address $700xxx.
|
45 |
|
46 | MOVE.W #$00A0,GIMR ; GIMR = 00a0
|
47 | MOVE.W #$FFFF,IPR ; clear IPR
|
48 | MOVE.L #$30500,$2a0 ; SCC3 vector initialization
|
49 |
|
50 | MOVE.W #$0300,PACNT ; PACNT = 0300
|
51 | * Causes the SCC3 TXD3 and RXD3 pins to be enabled. TCLK3 and RCLK3
|
52 | * pins are left as parallel I/O pins.
|
53 |
|
54 | MOVE.W #$0,SIMODE ; SIMODE = 0000 (its reset value)
|
55 | * SCC3 is set up for NMSI (i.e. modem) operation. No multiplexed
|
56 | * modes are used on the other SCCs.
|
57 |
|
58 | MOVE.W #$00d8,SCON3 ; SCON3 = 00d8 for ~9600 baud at 16.67 MHz
|
59 | * Baud Rate generator is used for transmit and receive. Rate is 9556bps.
|
60 |
|
61 | MOVE.W #$171,SCM3 ; SCM3 = 0171
|
62 | * No parity. Normal UART operation. 8-bit characters. 2 Stop bits.
|
63 | * The CD* and CTS* lines not used to enable reception and transmission,
|
64 | * but do cause a status change in the SCC3 Event register.
|
65 |
|
66 | MOVE.L #$50000000,$700640 ; Set up Tx BD 0 Status and Count
|
67 | MOVE.L #$30000,$700644 ; Set up Tx BD 0 Buffer Address
|
68 | MOVE.L #$70000000,$700648 ; Set up Tx BD 1 Status and Count
|
69 | MOVE.L #$30001,$70064c ; Set up Tx BD 1 Buffer Address
|
70 | * Set up 2 Tx BDs
|
71 |
|
72 | MOVE.L #$d0000000,$700600 ; Set up Rx BD 0 Status and Count
|
73 | MOVE.L #$30002,$700604 ; Set up Rx BD 0 Buffer Address
|
74 | MOVE.L #$f0000000,$700608 ; Set up Rx BD 1 Status and Count
|
75 | MOVE.L #$30003,$70060c ; Set up Rx BD 1 Buffer Address
|
76 | * Set up 2 Rx BDs
|
77 |
|
78 | MOVE.W #$0,$700680 ; clear RFCR/TFCR (Function code setup)
|
79 | * Must be initialized to a value other than 7, or won't work with chip selects
|
80 |
|
81 | MOVE.W #$1,$700682 ; MRBLR = 0001 (one-byte receive buffers)
|
82 | * This combined with the "I" bit set in the Rx BD, gives interrupts on each
|
83 | * character received.
|
84 |
|
85 | MOVE.W #$4,$70069c ; MAX_IDL don't care since MRBLR = 1.
|
86 | * Normally set to a small value, it closes a receive buffer if a certain
|
87 | * number of idles are received without a new character. Note that 0 is the
|
88 | * maximum value. In this case the buffer will always be closed after 1
|
89 | * character, so MAX_IDL is a don't care.
|
90 |
|
91 | MOVE.W #$1,$7006A0 ; BRKCR = 1. Only one break char. sent if
|
92 | * STOP TRANSMIT command executed. The STOP TRANSMIT command is not used in
|
93 | * this code.
|
94 |
|
95 | MOVE.W #$0,$7006A2 ; PAREC = 0000
|
96 | MOVE.W #$0,$7006A4 ; FRMEC = 0000
|
97 | MOVE.W #$0,$7006A6 ; NOSEC = 0000
|
98 | MOVE.W #$0,$7006A8 ; BRKEC = 0000
|
99 | * Initialize counters to zero
|
100 |
|
101 | MOVE.W #$0,$7006aa ; UADDR1 = 0000
|
102 | MOVE.W #$0,$7006ac ; UADDR2 = 0000
|
103 | * UART Address characters not used in normal operation.
|
104 |
|
105 | MOVE.W #$8000,$7006B0 ; CHARACTER1 = 8000
|
106 | * No control characters are initialized to cause special interrupts.
|
107 | * The flow-control facility (XON-XOFF) is not used.
|
108 |
|
109 | MOVE.B #$FF,SCCE3 ; clear SCCE3
|
110 | MOVE.B #$15,SCCM3 ; SCCM3 = 15
|
111 | * Interrupts in SCCM3 are allowed only for BRK (break character
|
112 | * received), BSY (no receive buffer available), and RX (buffer
|
113 | * received). Note that buffers are 1 character in this application.
|
114 |
|
115 | MOVE.W #$0100,IMR ; IMR = 0100. Allow SCC3 interrupts only.
|
116 |
|
117 | MOVE.W #$17d,SCM3 ; SCM3 = 017d
|
118 | * Set ENR and ENT bits in SCM3.
|
119 |
|
120 | CLR.L D0 ; clear all used data registers
|
121 | CLR.L D1
|
122 | CLR.L D3
|
123 | CLR.L D4
|
124 | CLR.L D5
|
125 | CLR.L D6
|
126 |
|
127 | MOVEA.L #$700600,A0 ; Load A0 as current Rx BD pointer
|
128 | MOVEA.L #$30002,A1 ; Load A1 as current "next Tx Byte" ptr
|
129 | MOVEA.L #$700640,A2 ; Load A2 as current Tx BD pointer
|
130 |
|
131 | MOVE.W #$2000,SR ; Enable interrupts. Stay in spvr mode.
|
132 |
|
133 | ****************************************************************************
|
134 | * Transmit Code
|
135 |
|
136 | * OUTERLOOP:
|
137 | OUTLOOP CMPI.B #$0,D6 ; Something to send (is D6>=1?)
|
138 | BEQ.B OUTLOOP ; Stay in outerloop if 0
|
139 | SUBQ.B #$1,D6 ; Decrement send status by 1 (0=empty)
|
140 |
|
141 | * INNERLOOP:
|
142 | INLOOP BTST.B #$0F,(A2) ; Test Ready bit of Tx BD
|
143 | BNE.B INLOOP ; Fall thru if 0, else wait in innerloop
|
144 |
|
145 | * The following sets up and sends out the transmit buffer
|
146 | ADDQ.W #$1,D4 ; Increment number of chars transmitted
|
147 | MOVEA.L A2,A3 ; A3 will be used to find Tx data buffer
|
148 | ADDQ.W #$4,A3 ; Inc A3 to point to Tx data pointer
|
149 | MOVEA.L (A3),A3 ; A3 now points to Tx Data buffer
|
150 | MOVE.B (A1),(A3) ; Move char from Rx Buffer to Tx Buffer
|
151 | ADDQ.W #2,A2 ; Increment A2 to point to byte count
|
152 | MOVE.W #$1,(A2) ; Set Tx BD Byte count to 1
|
153 | SUBQ.W #2,A2 ; A2 now points to beginning of Tx BD
|
154 | BSET.B #$07,(A2) ; Set Ready bit of Tx BD
|
155 | * The Tx BD send data status is not checked since the only one is CTS* lost,
|
156 | * which is not applicable, since CTS is ignored in this application.
|
157 |
|
158 | * The following updates A2 to point to the next Tx BD
|
159 | BTST.B #$05,(A2) ; test Wrap bit
|
160 | BNE.B REINIT2 ; If set, reinit A2 to 700640
|
161 | ADDA.W #$08,A2 ; else inc A2 by 8 to next Tx BD
|
162 | BRA.B CONT ; Jump to Continue on
|
163 | REINIT2 MOVEA.L #$700640,A2 ; Reinitialize A2
|
164 |
|
165 | * Determine what the next byte to "echo" will be and then go to OUTERLOOP
|
166 | CONT ADDQ.W #$1,A1 ; Increment A1 to next byte to send
|
167 | CMPA.L #$30004,A1 ; Is A1 = 30004? ***
|
168 | BEQ.B NEWA1 ; If so, go to NEWA1
|
169 | BRA.B OUTLOOP ; Jump back to outerloop and wait
|
170 | NEWA1 SUBQ.W #$02,A1 ; Set A1 back to 30002 ***
|
171 | BRA.B OUTLOOP ; Jump back to outerloop and wait
|
172 | * The two lines with *** above are dependent on the number of Rx BDs used.
|
173 | * If the number is increased, these values should be increased by the same
|
174 | * amount. These are the only lines dependent on the Rx BD or Tx BD setup.
|
175 |
|
176 | ******************************************************************************
|
177 | * SCC3 interrupt routine:
|
178 |
|
179 | ORG $30500
|
180 |
|
181 | CLR.L D1 ; clear D1
|
182 | MOVE.B SCCE3,D1 ; Move SCCE3 status to D1
|
183 | MOVE.B #$15,SCCE3 ; Clear only BRK, BSY and RX in SCCE3.
|
184 |
|
185 | BTST.B #$2,D1 ; Is BSY set?
|
186 | BNE.B BUSY ; Jump to BUSY handler if set
|
187 |
|
188 | * Test Break:
|
189 | BRKTEST BTST.B #$4,D1 ; Is BRK set?
|
190 | BNE.B BREAK ; Jump to BREAK handler if set
|
191 |
|
192 | * Test Receive:
|
193 | RECTEST BTST.B #$0,D1 ; Is RX set?
|
194 | BNE.B RECEIVE ; Jump to RECEIVE handler if set
|
195 | JMP ALMDONE ; Jump to About Done (impossible)
|
196 |
|
197 | * Busy handler:
|
198 | BUSY ADDQ.B #1,D5 ; Inc Busy counter (no receive buffers)
|
199 | BSET.B #$F,(A0) ; set Empty bit of current Rx BD
|
200 | JMP BRKTEST ; Jump to test for BREAK
|
201 |
|
202 | * Break handler:
|
203 | BREAK NOP ; This code ignores received breaks
|
204 | * The UART BRKEC will record the number of breaks received
|
205 | JMP RECTEST ; Jump to test for RECEIVE
|
206 |
|
207 | * Receive handler:
|
208 | RECEIVE ADDQ.W #1,D3 ; Increment number of chars received
|
209 | ADDQ.B #1,D6 ; D6 inc by 1 (character ready to send)
|
210 |
|
211 | ADDQ.W #1,A0 ; Inc A0 to point to Rx BD byte status
|
212 | CMPI.B #$0,(A0) ; Does status = 00?
|
213 | BNE.B BSTAT ; Jump to Bad Status if not 00
|
214 | INCPTR SUBQ.W #1,A0 ; Dec A0 to point to beginning of Rx BD
|
215 | ANDI.W #$FF00,(A0) ; Clear out Rx BD status
|
216 | BSET.B #$07,(A0) ; Set Empty bit of Rx BD
|
217 | BTST.B #$05,(A0) ; test Wrap bit
|
218 | BNE.B REINIT0 ; If set, reinit A0 to 700600
|
219 | ADDA.W #$08,A0 ; else inc A0 by 8 to next Rx BD
|
220 | BRA.B ALMDONE ; Jump to Almost Done
|
221 | REINIT0 MOVEA.L #$700600,A0 ; Reinitialize A0
|
222 | BRA.B ALMDONE ; Jump to almost Done
|
223 |
|
224 | * Bad Status:
|
225 | BSTAT NOP ; Bad status handler would go here
|
226 | * Note that the UART FRMEC, NOSEC, and PAREC counters record bad status.
|
227 | BRA.B INCPTR ; Jump back to Receive handler
|
228 |
|
229 | * Almost Done:
|
230 | ALMDONE MOVE.W #$0100,ISR ; Clear SCC3 bit in the ISR
|
231 | RTE ; end of interrupt handler
|
232 | END
|