32X SCI Use

Ask anything your want about the 32X Mushroom programming.

Moderator: BigEvilCorporation

Post Reply
Graz
Very interested
Posts: 81
Joined: Thu Aug 23, 2007 12:36 am
Location: Orlando, FL

32X SCI Use

Post by Graz » Sat Feb 08, 2014 2:22 am

Has anyone written any code that works with the 32X SCI interfaces in the SH2? I've been bashing on some code for a few days now and haven't gotten anywhere. I want to send data from the master to the slave. It looks like the master side of things is working (at least, it doesn't seem to be locking up), but the slave is never receiving anything. It just spins waiting for RDRF to go to 1.

Looking at the Mars test ROM, it appears that it only receives by interrupt. I'm not using interrupts - only polling. Could that be it?

Which games use the SCI? Which emulators emulate it fully?

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Sat Feb 08, 2014 11:32 am

At least the feature is not implemented in Gens as no game rely on it.
And i remember something about it, as "not fonctionnal" or "not connected" in the 32X, not 100 sure though.

ob1
Very interested
Posts: 463
Joined: Wed Dec 06, 2006 9:01 am
Location: Aix-en-Provence, France

Post by ob1 » Sat Jun 21, 2014 1:54 pm

The 32X Hardware Manual (valpocl.com/SuperVDP/32x_hardware_manual.pdf) states :
Built-in SCI (Serial Communication I/F) :
SH2 has one SCI channel. In the 32X, the master and slave are connected to each other making serial communication possible. If data receive interrupt is used, timing is effective in severe cases. Data is set in the SDRAM described below and timing can be taken by SCI. Since the 32X is not equipped with any external clock source for the SH2 SCI, an internal clock must be selected. Otherwise any setting can be done.
(japanese roughly translated in english, I guess)

The Hitachi SH2 Hardware Manual §13 will give you all the needed explainations. In particular, you won't be able to reach more than 150kb/s. If you have a large amount of data to send from one CPU to the other, you should use SCI Interrupt and transfer data via SDRAM.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Sat Jun 21, 2014 6:57 pm

I haven't played around with the SCI since it's pretty worthless. Anything you can do with the SCI can be done easier and faster in a variety of other ways. For example, exchanging words via the communication registers in the 32X IO, or using blocks of uncached sdram. About the only useful thing the SCI can do is trigger an interrupt in the other SH2... after some latency due to the serial transmission of data.

ob1
Very interested
Posts: 463
Joined: Wed Dec 06, 2006 9:01 am
Location: Aix-en-Provence, France

Post by ob1 » Mon Jun 23, 2014 7:17 am

Chilly Willy wrote:About the only useful thing the SCI can do is trigger an interrupt in the other SH2
+1

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Mon Jun 23, 2014 9:08 pm

ob1 wrote:
Chilly Willy wrote:About the only useful thing the SCI can do is trigger an interrupt in the other SH2
+1
A little more on that... if you had a fully interrupt-driven cross processor communication handler for your program, the SCI would be your way to generate an int. However, that level of multi-processor communications is not really needed to make the 32X useful. You don't gain anything by making an SH2 wait on an interrupt compared to checking a communication register in the system regs. I don't even bother making the 68000 wait on ints as I normally have it running from work ram to keep it off the bus.

It's simple and easy to make the Master SH2 watch one set of comm regs, the Slave watch another, and the 68000 yet another. The comm regs (being in the system regs) are uncached, so you don't need to worry about cache issues; they're also much faster to read than a corresponding sdram location due to burst read hardware. The 32X is hardwired to do burst reads on the sdram, and single writes. That means a read of 8 words (one cache line) is done in 12 cycles, or 1.5 cycles per word. However, even when reading a single word that is uncached, it still does a burst read - 8 words are read in 12 cycles, and the other 7 are tossed out. So reading an uncached word in sdram is the slowest thing you can do on the SH2s. You'd be better off putting the variable in vram than sdram! Keeping in mind the burst reads on the SH2 is one of the key things to remember when designing code for the 32X when trying to get as much speed as possible. Note, the DMA in the SH2 can use this burst mode when put in 16-byte mode. If you're trying to get the best speed from DMA, put the source data on 16 byte boundaries, and use the 16 byte transfer word size.

ob1
Very interested
Posts: 463
Joined: Wed Dec 06, 2006 9:01 am
Location: Aix-en-Provence, France

Re: 32X SCI Use

Post by ob1 » Wed May 19, 2021 8:46 pm

All right, by looking into Sega SDK\SEGADTS\32X\DEMO\SOJ_32X, I could achieve something (well, I sent a byte from Master to Slave on real Hardware).
Here's the stuff:

Code: Select all

initMaster:
* ...
	MOV	#$80,R4
	MOV	#74,R5
	MOV	#$20,R6    ; TE | SCK is output
	BSR	initSci
	NOP
* ...
with

Code: Select all

initSci:
* IN	R4	SMR
*	R5	BRR
*	R6	SCR
	STS.L	PR,@-R15
	MOV.L	R0,@-R15
	MOV.L	R1,@-R15

	MOV.W	!SCI_REGS,R1

	MOV	#0,R0
	MOV.B	R0,@(2,R1)	; Clear TE and RE bits in SCR to 0

	MOV	R4,R0		; C//A | CKS0
	MOV.B	R0,@R1		; Set SMR

	MOV	R5,R0
	MOV.B	R0,@(1,R1)	; Set BRR

	MOV	#0,R0
	MOV.B	R0,@(2,R1)	; Clear SCR

	MOV	R5,R0
	SHLL2	R0
!waitABit:
	NOP
	DT	R0
	BF	!waitABit

	MOV	R6,R0
	MOV.B	R0,@(2,R1)	; Set SCR

	MOV.L	@R15+,R1
	MOV.L	@R15+,R0
	LDS.L	@R15+,PR
	RTS
	NOP
!SCI_REGS	DC.W	$FE00
Then, on the slave side :

Code: Select all

initSlave:
* ...
	MOV	#$80,R4
	MOV	#74,R5
	MOV	#$12,R6    ; RE | SCK is input
	BSR	initSci
	NOP
* ...
Now, for sending, from the Master:

Code: Select all

send:
* IN	R4	data
	STS.L	PR,@-R15
	MOV.L	R0,@-R15
	MOV.L	R1,@-R15

	MOV.W	!SCI_REGS,R1

!waitForTDRESet:
	mov.b	@(4,r1),r0
	tst	#%10000000,r0	; if (TDRE == 0), 1 -> T
	bt	!waitForTDRESet

	mov	r4,r0
	mov.b	r0,@(3,r1)

!waitForTENDSet:
	mov.b	@(4,r1),r0
	tst	#%00000100,r0	; if (TEND == 0), 1 -> T
	bt	!waitForTENDSet

	mov	#0,r0
	mov.b	r0,@(4,r1)	; Clear SSR

	MOV.L	@R15+,R1
	MOV.L	@R15+,R0
	LDS.L	@R15+,PR
	RTS
	NOP
!SCI_REGS	DC.W	$FE00

Finally, for the Slave to receive :

Code: Select all

receive:
* OUT	R0	data
	STS.L	PR,@-R15
	MOV.L	R1,@-R15
	MOV.L	R2,@-R15

	MOV.W	!SCI_REGS,R1

	mov	#%00010000,r0
	mov.b	r0,@(2,r1)	; Set RE

	mov.b	@(4,r1),r0
	tst	#%01000000,r0	; if (RDRF == 0), 1 -> T
	bt	!noData
	mov.b	@(5,r1),r0	; Read RDR
	MOV	R0,R2

	mov	#0,r0
	mov.b	r0,@(4,r1)	; Clear SSR
	mov.b	r0,@(2,r1)	; Clear SCR, Reset RE

	MOV	R2,R0

!epilog:
	MOV.L	@R15+,R2
	MOV.L	@R15+,R1
	LDS.L	@R15+,PR
	RTS
	NOP
!SCI_REGS	DC.W	$FE00

!noData:
	MOV	#-2,R0
	BRA	!epilog
	NOP
As you can see, I don't bother with ORER, but it was just a quick and dirty test.
IMG_2738.jpg
CommPort.B[6] ("07") is the byte sent
CommPort.B[7] ("01") is the number of bytes received
IMG_2738.jpg (83.7 KiB) Viewed 4881 times
Truth is, it's a lot of hassle (not very well emulated, not very well documented), for not so much of a result.

Post Reply