Close

SD Card Support

A project log for Retro 68000 CPU in an FPGA

Making a Retrocomputer with a 68000 CPU in an FPGA

land-boardscomland-boards.com 02/24/2022 at 13:270 Comments

Added SD Card support. The SD card VHDL code comes from MultiComp.

Memory Map

--        0x010050-0x010058F - SD Card
--            0x010051 - SDDATA        read/write data
--            0x010053 - SDSTATUS    read
--            0x010053 - SDCONTROL    write
--            0x010055 - SDLBA0        write-only
--            0x010057 - SDLBA1        write-only
--            0x010059 - SDLBA2        write-only (only bits 6:0 are valid)

C Code to Read First SD Card Block to SRAM

// SDCard.c

#define ACIASTAT    (volatile unsigned char *) 0x010041
#define ACIADATA    (volatile unsigned char *) 0x010043
#define VDUSTAT        (volatile unsigned char *) 0x010040
#define VDUDATA        (volatile unsigned char *) 0x010042
#define ACIA_TXRDYBIT 0x2

// SD Card
#define SD_SDDATA_REG    (volatile unsigned char *) 0x010051
#define SD_STATUS_REG    (volatile unsigned char *) 0x010053
#define SD_CMD_REG        (volatile unsigned char *) 0x010053
#define SD_LBA0_REG        (volatile unsigned char *) 0x010055
#define SD_LBA1_REG        (volatile unsigned char *) 0x010057
#define SD_LBA2_REG        (volatile unsigned char *) 0x010059
// SD Card Status Reg
#define SD_WR_RDY        0X80
#define SD_RD_RDY        0X40
#define SD_BLK_BUSY        0X20
#define SD_INIT_BUSY    0X10
// SD Card Control values
#define SD_RD_BLK    0x00
#define SD_WR_BLK    0x01
#define BUFFER_START 0XE000

/*
-- To read a 512-byte block from the SDCARD:
-- Wait until SDSTATUS=0x80 (ensures previous cmd has completed)
-- Write SDLBA0, SDLBA1 SDLBA2 to select block index to read from
-- Write 0 to SDCONTROL to issue read command
-- Loop 512 times:
--     Wait until SDSTATUS=0xE0 (read byte ready, block busy)
--     Read byte from SDDATA
--
-- To write a 512-byte block to the SDCARD:
-- Wait until SDSTATUS=0x80 (ensures previous cmd has completed)
-- Write SDLBA0, SDLBA1 SDLBA2 to select block index to write to
-- Write 1 to SDCONTROL to issue write command
-- Loop 512 times:
--     Wait until SDSTATUS=0xA0 (block busy)
--     Write byte to SDDATA
*/

// Prototypes
void printCharToACIA(unsigned char);
void printStringToACIA(const char *);
void printCharToVDU(unsigned char);
void printStringToVDU(const char *);
void waitUART(unsigned int waitTime);
void wait_Until_SD_CMD_Done(void);
void write_SD_LBA(unsigned long);
void readSDBlockToBuffer(void);
void wait_Until_SD_Char_RD_Rdy(void);

int main(void)
{
    asm("move.l #0x1000,%sp"); // Set up initial stack pointer

    printStringToVDU("Waiting on SD Card ready\n\r");
    wait_Until_SD_CMD_Done();
    printStringToVDU("SD Card is ready\n\r");
    printStringToVDU("Writing LBA = 0\n\r");
    write_SD_LBA(0);
    printStringToVDU("Reading block\n\r");
    readSDBlockToBuffer();
    printStringToVDU("Block was read to 0xE000\n\r");
    asm("move.b #228,%d7\n\t"
        "trap #14");
    return(0);
}

void readSDBlockToBuffer(void)
{
    unsigned short loopCount = 512;
    unsigned char readSDChar;
    unsigned char * destAddr;
    destAddr = (unsigned long) BUFFER_START;
    * SD_CMD_REG = SD_RD_BLK;
    while (loopCount > 0)
    {
        wait_Until_SD_Char_RD_Rdy();
        readSDChar = *SD_SDDATA_REG;
        *destAddr++ = readSDChar;
        loopCount--;
    }
}

void write_SD_LBA(unsigned long lba)
{
    unsigned char lba0, lba1, lba2;
    lba0 = lba & 0xff;
    lba1 = (lba >> 8) & 0xff;
    lba2 = (lba >> 16) & 0xff;
    * SD_LBA0_REG = lba0;
    * SD_LBA1_REG = lba1;
    * SD_LBA2_REG = lba2;
}

void wait_Until_SD_Char_RD_Rdy(void)
{
    unsigned char charStat;
    charStat = * SD_STATUS_REG;
    while (charStat != 0xE0)
    {
        charStat = *SD_STATUS_REG;
    }
}

void wait_Until_SD_CMD_Done(void)
{
    unsigned char charStat;
    charStat = * SD_STATUS_REG;
    while (charStat != 0x80)
    {
        charStat = *SD_STATUS_REG;
    }
}

void waitUART(unsigned int waitTime)
{
    volatile unsigned int timeCount = 0;
    for (timeCount = 0; timeCount < waitTime; timeCount++);
}

void printCharToACIA(unsigned char charToPrint)
{
    while ((*ACIASTAT & ACIA_TXRDYBIT) != ACIA_TXRDYBIT);
    * ACIADATA = charToPrint;
}

void printStringToACIA(const char * strToPrint)
{
    int strOff = 0;
    while(strToPrint[strOff] != 0)
        printCharToACIA(strToPrint[strOff++]);
}

void printCharToVDU(unsigned char charToPrint)
{
    while ((*VDUSTAT & ACIA_TXRDYBIT) != ACIA_TXRDYBIT);
    * VDUDATA = charToPrint;
}

void printStringToVDU(const char * strToPrint)
{
    int strOff = 0;
    while(strToPrint[strOff] != 0)
        printCharToVDU(strToPrint[strOff++]);
}

Results

 Reading 6809 FLEX SD Card.

TUTOR  1.3 > GO 2000
PHYSICAL ADDRESS=00002000
Waiting on SD Card ready
SD Card is ready
Writing LBA = 0
Reading block
Block was read to 0xE000

TUTOR  1.3 >
WHAT

TUTOR  1.3 > MD E000
00E000    00 41 49 4E 00 00 00 00  42 4F 4F 54 47 45 4E 00  .AIN....BOOTGEN.

TUTOR  1.3 >
00E010    45 58 45 00 24 00 00 F0  00 00 00 00 00 00 00 00  EXE.$..p........
00E020    53 59 53 54 45 4D 00 00  48 45 4C 50 00 00 00 00  SYSTEM..HELP....
00E030    45 58 45 00 25 B7 00 F0  00 00 00 00 00 00 00 00  EXE.%7.p........
00E040    48 45 4C 50 00 00 00 00  53 59 53 54 45 4D 00 00  HELP....SYSTEM..
00E050    48 4C 50 00 27 20 00 F0  00 00 00 00 00 00 00 00  HLP.' .p........
00E060    53 59 53 54 45 4D 00 00  43 4F 50 59 00 00 00 00  SYSTEM..COPY....
00E070    45 58 45 00 29 00 00 F0  00 00 00 00 00 00 00 00  EXE.)..p........
00E080    53 59 53 54 45 4D 00 00  44 49 52 00 00 00 00 00  SYSTEM..DIR.....
00E090    45 58 45 00 2B 00 00 F0  00 00 00 00 00 00 00 00  EXE.+..p........
00E0A0    53 59 53 54 45 4D 00 00  43 48 4B 44 49 53 4B 00  SYSTEM..CHKDISK.
00E0B0    45 58 45 00 2D 00 00 F0  00 00 00 00 00 00 00 00  EXE.-..p........
00E0C0    53 59 53 54 45 4D 00 00  41 53 4D 00 00 00 00 00  SYSTEM..ASM.....
00E0D0    45 58 45 00 65 00 00 F0  00 00 00 00 00 00 00 00  EXE.e..p........
00E0E0    53 59 53 54 45 4D 00 00  41 53 50 00 00 00 00 00  SYSTEM..ASP.....
00E0F0    45 58 45 00 6E 00 00 F0  00 00 00 00 00 00 00 00  EXE.n..p........
00E100    53 59 53 54 45 4D 00 00  42 41 53 49 43 00 00 00  SYSTEM..BASIC...

TUTOR  1.3 >

 Works well!

Discussions