1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
|
; Experimental PSn00bDEBUG Mk2 debug monitor by John Wilbert Villamor
; Copyright 2020 Meido-Tek Productions (Lameguy64)
;
; These are the communication routines for the monitor. This file can be
; swapped out with a different set of routines to adapt it for other
; interfaces.
SIO_TXRX_REG_A equ 0x1F801050 ; Serial I/O port absolute addresses
SIO_MODE_REG_A equ 0x1F801058
SIO_CTRL_REG_A equ 0x1F80105A
SIO_BAUD_REG_A equ 0x1F80105E
SIO_STAT_REG_A equ 0x1F801054
SIO_BAUD equ 0x12 ; Baud rate constant
; = Function definitions of communication routines
;
comm_ReadByte equ sioReadByte
comm_ReadReg equ sioReadReg
comm_BlockRead equ sioBlockRead
comm_SendByte equ sioSendByte
comm_SendReg equ sioSendReg
comm_BlockSend equ sioBlockSend
comm_SendStr equ sioSendStr
comm_DisableListen equ sioDisableListen
comm_EnableListen equ sioEnableListen
comm_GetStatus equ sioGetStatus
; sioReadByte - Read a byte from the serial port.
;
; Arguments: none
;
; Destroys: v0, v1
;
; Returns: v0 - byte read
;
sioReadByte:
la v1, SIO_CTRL_REG_A ; Turn on RTS
lhu v0, 0(v1)
nop
ori v0, 0x22
sh v0, 0(v1)
@@rx_wait:
la v0, SIO_STAT_REG_A ; Read status register
lw v0, 0(v0)
nop
andi v0, 0x80 ; Check DSR status
beqz v0, @@cancel
addi v0, r0, -1
la v0, SIO_STAT_REG_A ; Read value register
lw v0, 0(v0)
nop
andi v0, 0x2
beqz v0, @@rx_wait
nop
la v0, SIO_TXRX_REG_A
lbu v0, 0(v0)
@@cancel:
addiu sp, -4
sw v0, 0(sp)
la v1, SIO_CTRL_REG_A ; Turn off RTS
lhu v0, 0(v1)
nop
xori v0, 0x20
sh v0, 0(v1)
lw v0, 0(sp)
jr ra
addiu sp, 4
; sioReadByte
; sioSendByte - Send a byte to the serial port
;
; Input: a0 - byte to send to serial.
;
; Destroys: v0
;
; Returns: 0 on success, -1 on drop
;
sioSendByte:
@@cts_wait: ; Wait for Clear-to-Send signal
la v0, SIO_STAT_REG_A ; Check DSR line
lhu v0, 0(v0)
nop
andi v0, 0x80
beqz v0, @@cancel
addi v0, r0, -1
la v0, SIO_STAT_REG_A ; Wait for CTS
lhu v0, 0(v0)
nop
andi v0, 0x100
beqz v0, @@cts_wait
nop
@@tx_ready: ; Wait for TX to become ready
la v0, SIO_STAT_REG_A ; Check DSR line
lhu v0, 0(v0)
nop
andi v0, 0x80
beqz v0, @@cancel
addi v0, r0, -1
la v0, SIO_STAT_REG_A
lhu v0, 0(v0)
nop
andi v0, 0x1
beqz v0, @@tx_ready
nop
la v0, SIO_TXRX_REG_A ; Send byte
sb a0, 0(v0)
@@tx_done: ; Wait for TX to finish
la v0, SIO_STAT_REG_A ; Check DSR line
lhu v0, 0(v0)
nop
andi v0, 0x80
beqz v0, @@cancel
addi v0, r0, -1
la v0, SIO_STAT_REG_A
lhu v0, 0(v0)
nop
andi v0, 0x4
beqz v0, @@tx_done
nop
move v0, r0
@@cancel:
jr ra ; Return
nop
; sioSendByte
; sioBlockSend - Send a block of data to the serial port
;
; Arguments:
; a0 - Pointer to start sending data from
; a1 - Number of bytes to send
;
sioBlockSend:
addiu sp, -4
sw ra, 0(sp)
move a2, a0
@@sendloop:
lbu a0, 0(a2) ; Read and send a byte
jal sioSendByte
addiu a2, 1
beq v0, -1, @@cancel ; Cancel if connection dropped
addiu a1, -1
bgtz a1, @@sendloop
nop
@@cancel:
lw ra, 0(sp)
addiu sp, 4
jr ra
nop
; sioBlockSend
; sioBlockRead - Read a block of data from the serial port
;
; Arguments:
; a0 - Pointer to store read data to
; a1 - Number of bytes to read
;
sioBlockRead:
addiu sp, -4
sw ra, 0(sp)
@@readloop:
jal sioReadByte
nop
beq v0, -1, @@cancel ; Check if comms got terminated
addiu a1, -1
sb v0, 0(a0)
bgtz a1, @@readloop
addiu a0, 1
@@cancel:
lw ra, 0(sp)
addiu sp, 4
jr ra
nop
; sioBlockRead
; sioSendStr - Send a string to serial port
;
; Arguments: a0 - pointer to string
;
; Destroys: a0 and a1
;
; Returns: none
;
sioSendStr:
addiu sp, -4
sw ra, 0(sp)
move a1, a0
@@send_loop:
lbu a0, 0(a1) ; Get byte
nop
jal sioSendByte ; Send byte
addiu a1, 1
bltz v0, @@send_end ; End transmission if DSR was dropped
nop
bnez a0, @@send_loop ; Loop until terminator is sent
nop
@@send_end:
lw ra, 0(sp)
addiu sp, 4
jr ra
nop
; sioSendStr
; sioSendStr - Send 4 bytes of a 32-bit register
;
; Input: a0 - Value to send.
;
; Return: none.
;
sioSendReg:
addiu sp, -24
sw ra, 0(sp)
sw v0, 4(sp)
sw v1, 8(sp)
sw a0, 12(sp)
sw a1, 16(sp)
sw a2, 20(sp)
move a1, zero
move a2, a0
@@write_loop:
andi a0, a2, 0xFF
jal sioSendByte
srl a2, 8
bltz v0, @@cancel
addiu v0, r0, -1
li at, 3
bne a1, at, @@write_loop
addiu a1, 1
@@cancel:
lw ra, 0(sp) ; Restore stack and return
lw v0, 4(sp)
lw v1, 8(sp)
lw a0, 12(sp)
lw a1, 16(sp)
lw a2, 20(sp)
jr ra
addiu sp, 24
; sioSendReg
; sioReadReg - Receives 4 bytes to a register
;
; Arguments: none.
;
; Return: v0 - Received word.
;
sioReadReg:
addiu sp, -16
sw ra, 0(sp) ; Save stuff to stack
sw a0, 4(sp)
sw a1, 8(sp)
sw a2, 12(sp)
move a0, r0 ; Clear registers
move a1, r0
move a2, r0
@@loop:
jal sioReadByte ; Receive a byte
nop
bltz v0, @@cancel ; Cancel if return value is negative
sllv v0, a0 ; Shift return value to its respective
addiu a0, 8 ; bit location in the register
slti at, a0, 32
bnez at, @@loop
or a2, v0 ; Merge it to the register
b @@done
move v0, a2
@@cancel:
addiu v0, r0, -1 ; Set return value to -1 if canceled
@@done:
lw ra, 0(sp)
lw a0, 4(sp)
lw a1, 8(sp)
lw a2, 12(sp)
jr ra
addiu sp, 16
; sioReadReg
; sioEnableListen - Enable asynchronous listening of the serial port
;
; This function simply enables SIO interrupts and sets RTS and DTR high to
; allow debug commands to be issued to the target console. This is executed
; on every interrupt to make sure the SIO interface can receive comamnds at
; any time, and when the debug monitor leaves query mode.
;
; The monitor leaves query mode with the following commands:
; - When the monitor completes a command and resumes execution (if exec
; mode is set to run).
; - When the monitor is instructed to continue execution from a paused state.
; - When a trace or run-to operation is issued while the target is stopped.
;
; Arguments: none
;
; Destroys: v0 and v1
;
; Returns: none
;
sioEnableListen:
la v1, SIO_CTRL_REG_A ; Enable RTS and DTR so PC can send
lhu v0, 0(v1)
nop
ori v0, 0x22
sh v0, 0(v1)
jr ra
nop
; sioEnableListen
; sioDisableListen - Disable asynchronous listening of the serial port
;
; This function simply disables SIO interrupts and sets RTS and DTR low
; to allow handshaking. This is executed when the debug monitor enters query
; mode, when it has received a command, told to stop the target or when a
; break/trace/unhandled exception occurs.
;
; Arguments: none
;
; Destroys: v0 and v1
;
; Returns: none
;
sioDisableListen:
la v1, SIO_CTRL_REG_A
lhu v0, 0(v1)
nop
andi v0, 0xF ; Disable interrupts and RTS
ori v0, 0x10 ; Acknowledge serial just in case
sh v0, 0(v1)
jr ra
nop
; sioDisableListen
; sioGetStatus - Get status if there's any pending data in the serial port
;
; This function checks if the SIO interface has connection with the host
; system (when CTS is set) and if there's data pending in the RX buffer of
; the SIO interface. This function is executed on every interrupt, to check
; for any commands pending in the SIO interface.
;
; Arguments: none
; Destroys: v0 and v1
; Returns: Zero if no data pending, non-zero if there's data pending.
;
sioGetStatus:
la v0, SIO_STAT_REG_A ; Check serial status
lhu v0, 0(v0)
nop
andi v1, v0, 0x80 ; Check if CTS is set
beqz v1, @@nodata
andi v0, 0x2
beqz v0, @@nodata ; Check if rx buffer is filled
nop
jr ra
li v0, 1
@@nodata:
jr ra
move v0, r0
|