Add driver that uses the SD card on SF2000

The current SF2000 firmware doesn't have a FIFO for communicating with
the SD card. This limits the achieved performance. This is expected to
change soon.
This commit is contained in:
Niklas Ekström 2025-03-08 18:18:57 +01:00
parent d56fbaaaf4
commit 945db7f785
7 changed files with 187 additions and 0 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
.vscode
rp2040/build

2
examples/spisd/build-sf2000.sh Executable file
View File

@ -0,0 +1,2 @@
set -x
vc +aos68k -I$NDK32/Include_H romtag.c version.c device.c sd.c timer.c ../../spi-lib-sf2000/spi.c ../../spi-lib-sf2000/interrupt.asm -I../../spi-lib-sf2000 -O2 -nostdlib -lamiga -o spisd.device

2
examples/spisd/build.sh Executable file
View File

@ -0,0 +1,2 @@
set -x
vc +aos68k -I$NDK32/Include_H romtag.c version.c device.c sd.c timer.c ../../spi-lib/spi.c ../../spi-lib/spi_low.asm -I../../spi-lib -O2 -nostdlib -lamiga -o spisd.device

9
spi-lib-sf2000/README.md Normal file
View File

@ -0,0 +1,9 @@
# spi-lib-sf2000
The [SF2000](https://github.com/jbilander/SF2000/) Amiga accelerator has an SD
card connector whose pins are routed to its FPGA. The firmware for the FPGA
contains a basic SPI controller, which is used to communicate with the SD card.
This spi-lib-sf2000 library abstracts the SPI controller using the same API
as the spi-lib for the Amiga Parallel Port to SPI Adapter. This way, the
spisd.device driver can be compiled with the spi-lib-sf2000 to build a driver
that works with an SD card connected to the SF2000.

View File

@ -0,0 +1,25 @@
XDEF _InterruptServer
CODE
;struct InterruptData
;{
; struct SF2000SDRegisters *regs;
; void (*change_isr)();
;};
; a1 points to InterruptData structure
_InterruptServer:
move.l (a1),a0
tst 14(a0) ; check int_act
beq.b .no_irq
move #0,12(a0) ; disable interrupt
move.l 4(a1),a1
jsr (a1)
.no_irq:
moveq #0,d0
rts

127
spi-lib-sf2000/spi.c Normal file
View File

@ -0,0 +1,127 @@
/*
* Written in the end of April 2020 by Niklas Ekström.
* Updated in July 2021 by Niklas Ekström to handle Card Present signal.
* Adapted in March 2025 by Niklas Ekström to work with SF2000 SD card slot.
*/
#include <exec/types.h>
#include <exec/interrupts.h>
#include <exec/libraries.h>
#include <hardware/intbits.h>
#include <proto/exec.h>
#include "spi.h"
static const char spi_lib_name[] = "spi-lib-sf2000";
struct SF2000SDRegisters
{
volatile UWORD clock_divisor;
volatile UWORD slave_select;
volatile UWORD card_detect;
volatile UWORD shift_active;
volatile UWORD shift_reg;
volatile UWORD int_req;
volatile UWORD int_ena;
volatile UWORD int_act;
};
static struct SF2000SDRegisters *regs;
#define CLK_DIV_16M 2
#define CLK_DIV_400K 124
#define IRQ_CD_CHANGED 1
struct InterruptData
{
struct SF2000SDRegisters *regs;
void (*change_isr)();
};
extern void InterruptServer();
struct InterruptData interrupt_data;
struct Interrupt ports_interrupt;
void spi_select()
{
regs->slave_select = 1;
}
void spi_deselect()
{
regs->slave_select = 0;
}
int spi_get_card_present()
{
int present = regs->card_detect;
// Clear the CD changed interrupt.
regs->int_req = IRQ_CD_CHANGED;
// Re-enable the CD changed interrupt.
regs->int_ena = IRQ_CD_CHANGED;
return present;
}
void spi_set_speed(long speed)
{
regs->clock_divisor = speed == SPI_SPEED_FAST ? CLK_DIV_16M : CLK_DIV_400K;
}
void spi_read(__reg("a0") UBYTE *buf, __reg("d0") ULONG size)
{
for (int i = size - 1; i >= 0; i--)
{
regs->shift_reg = 0xff;
while (regs->shift_active) {
}
*buf++ = (UBYTE)(regs->shift_reg);
}
}
void spi_write(__reg("a0") const UBYTE *buf, __reg("d0") ULONG size)
{
for (int i = size - 1; i >= 0; i--)
{
regs->shift_reg = *buf++;
while (regs->shift_active) {
}
}
}
int spi_initialize(void (*change_isr)())
{
// TODO: This address should not be hardcoded,
// and should be read from autoconfig/expansion.library.
regs = (struct SF2000SDRegisters *)0xEE0000;
regs->clock_divisor = CLK_DIV_400K;
regs->int_ena = 0;
regs->int_req = IRQ_CD_CHANGED;
interrupt_data.regs = regs;
interrupt_data.change_isr = change_isr;
ports_interrupt.is_Node.ln_Type = NT_INTERRUPT;
ports_interrupt.is_Node.ln_Pri = -60;
ports_interrupt.is_Node.ln_Name = (char *)spi_lib_name;
ports_interrupt.is_Data = (APTR)&interrupt_data;
ports_interrupt.is_Code = InterruptServer;
AddIntServer(INTB_PORTS, &ports_interrupt);
return spi_get_card_present();
}
void spi_shutdown()
{
regs->int_ena = 0;
regs->int_req = IRQ_CD_CHANGED;
RemIntServer(INTB_PORTS, &ports_interrupt);
}

21
spi-lib-sf2000/spi.h Normal file
View File

@ -0,0 +1,21 @@
/*
* Written in the end of April 2020 by Niklas Ekström.
* Updated in July 2021 by Niklas Ekström to handle Card Present signal.
* Adapted in March 2025 by Niklas Ekström to work with SF2000 SD card slot.
*/
#ifndef SPI_H_
#define SPI_H_
#define SPI_SPEED_SLOW 0
#define SPI_SPEED_FAST 1
int spi_initialize(void (*change_isr)());
int spi_get_card_present();
void spi_shutdown();
void spi_set_speed(long speed);
void spi_select();
void spi_deselect();
void spi_read(__reg("a0") unsigned char *buf, __reg("d0") unsigned long size);
void spi_write(__reg("a0") const unsigned char *buf, __reg("d0") unsigned long size);
#endif