User Tools

Site Tools


spi

SPI

The SPI bus connects the gamepad storage (Flash memory) and the UIC to the CPU.

SPI controller

The gamepad uses a pretty simple SPI controller with 16-byte FIFOs for reading and writing. Due to the way this is designed, one has to be mindful to avoid FIFO overflows/underflows during a SPI transfer.

The SPI controller has the following registers:

Address Desc.
0xF0004400 SPI control/speed
0xF0004404 SPI transfer control
0xF0004408 IRQ flags
0xF000440C FIFO status
0xF0004410 Data input/output
0xF0004414 ??
0xF0004418 IRQ enable
0xF0004420 Number of bytes to read
0xF0004424 Device select

0xF0004400

Controls SPI clock speed.

Bits Desc.
0-2 Clock multiplier
3-10 Clock divider
15 SPI enable (possibly just clock enable)

The clock multiplier selects the base clock, and the clock divider divides that by a fixed value to produce the final SPI clock.

The following clock multiplier values are available:

Multiplier Clock
0 32MHz
1 12MHz
2 ???
3 ???
4 ~857MHz
5 3.38MHz
6 15.9MHz
7 3.38MHz

Not sure how these values are generated internally. I couldn't get settings 2 and 3 to produce any observable output even at the highest divider setting. Setting 4 only works at low enough divider settings, and suggests that some kind of PLL is used. Not sure if the input clock is dependent on the system clock.

The clock divider setting is a simple count-up divider. For example, setting it to 31 divides the clock by 32.

Observed settings in the stock firmware are the following:

Register value Destination Clock speed
0x808C FLASH 48MHz
0x8018 UIC 8MHz
0x835C UIC 8MHz
0x83F8 UIC 250KHz
0x8400 UIC 248KHz

0xF0004404

Controls various aspects of the SPI transfer.

Bits Desc.
0 ??
1 Transfer direction; 0=write, 1=read
2 ??
6 ?? toggled during UIC reads, not sure what the effect is
8 Chipselect mode; 0=automatic, 1=manual
9 Manual chipselect; 0=select, 1=release
10 ?? FIFO related?

Setting bit8 to 0 causes the chipselect line to be automatically activated only during a transfer. This means that during a write-then-read transfer, the chipselect line will get deactivated and activated again between the write and the read.

Setting bit8 to 1 causes the chipselect line to be directly controlled by bit9. In this mode, no transfer will be initiated until the chipselect line is activated.

Note: it is also possible to leave bit8 at 0 and manually toggle the chipselect lines via the GPIO registers. Firmware code seems to do this for UIC comm.

0xF0004408

SPI IRQ flags. Writing a 1 to a flag clears it.

Bits Desc.
6 Read IRQ (read operation finished)
7 Write IRQ (write operation finished)

The write IRQ triggers after the contents of the write FIFO have been entirely transferred.

The read IRQ triggers after the amount specified in register 0xF0004420 has been transferred.

Both IRQ conditions trigger IRQ 0x06. Not known yet which conditions would trigger IRQ 0x07.

0xF000440C

FIFO status. The read and write FIFOs can hold up to 16 bytes each.

Bits Desc.
0-4 Free space in write FIFO (16 when empty)
8-12 Occupied space in read FIFO (16 when full)

0xF0004410

Data input/output.

During a write transfer, data written to this register is queued up in the write FIFO.

During a read transfer, the desired amount of bytes is written to 0xF0004420, then received data is queued up in the read FIFO and can be retrieved by reading 0xF0004410.

WARNING: if the write FIFO is already full, writes to this register are discarded. There seems to be no error signal in this case, so you have to be mindful of this.

In a similar vein, a read transfer will halt if the read FIFO is full.

It isn't known if there are IRQs for FIFO full/empty conditions, but there doesn't seem to be any.

0xF0004414

Unknown. Bits 0-1, 4, 15 set by firmware code.

0xF0004418

SPI IRQ enable.

Bits Desc.
0 ???
1 Unknown, causes lock-up during write transfer
2 ???
3 Unknown, causes lock-up during write transfer
4 ???
5 ???
6 Enable read IRQ
7 Enable write IRQ
8 ???
9 ???

0xF0004420

Number of bytes to read.

When the transfer mode is set to read, writing to this register will initiate a transfer.

This register does not change after a transfer.

0xF0004424

Specifies which device will be selected during SPI transfers.

Bits Desc.
0 Select Flash
1 Select UIC

Setting both bits will result in both devices being selected at the same time.

Unknown if there are more devices? The diagnostics firmware accesses a third device named 'Userial' by toggling GPIO 0xF0005104. It also does not use register 0xF0004424 at all, instead manually toggling the chipselect GPIOs.

On a retail gamepad, register 0xF0004424 only has two bits.

Using with DMA

The SPI controller can be used conjointly with DMA channels 0 or 1. Due to the simplistic design of the FIFO system, using DMA is more straightforward as it will take care of keeping the FIFOs happy for you.

To write using DMA, you simply start a DMA transfer instead of writing to 0xF0004410. You should rely on the SPI write IRQ to detect transfer completion.

To read using DMA, you set 0xF0004420 to the desired read length, then start a DMA transfer instead of reading from 0xF0004410. You should rely on the DMA IRQ to detect transfer completion.

SPI commands

For Flash commands, see the Flash datasheet.

For UIC commands, see the UIC page.

spi.txt · Last modified: 2024/11/01 22:23 by arisotura

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki