Close

SD Card Assembly Language Code

A project log for OSI SD Card Operating System (OSISDOS)

Ohio Scientific / UK101 SD Card based Operating System under Multicomp FPGA Computer

land-boardscomland-boards.com 07/31/2020 at 20:280 Comments

Minimal SD card code in C:

/* OSISDOS.c - Minimal Operating System for OSI C1P/SuperBoard ][     */
/* SDHC card based disk operating system                            */
/* 8KB Microsoft BASIC-In-ROM has I/O support routines                */
/* CEGMON has various hooks to the I/O in BASIC                        */
/* Uses Banked SRAM from $E000-$EFFF to buffer SD card data.        */
/* Intended to fit within a small ROM space below CEGMON            */
/*    Target ROM space goes from $F100-$F7FF (1.75kb)                    */
/*                                                                    */
/* Compiled using CC65 toolchain                                     */

/* 
Memory Map
    $0000-$9FFF - SRAM (40KB)
    $A000-$BFFF - Microsoft BASIC-in-ROM (8KB)
        $D000-$D3FF - 1KB Display RAM
        $DC00 - PS/2 Keyboard
        $E000-$EFFF - Bank Selectable SRAM (not detectable as BASIC RAM)
        $F000-$FFFF - CEGMON Monitor ROM 4K
        $F000-$F001 - ACIA (UART) 61440-61441 dec
        $F002 - J6 I/O Connector 61442 dec
        $F003 - J8 I/O Connector 61443 dec
     $F004 - LEDS 61444 dec
        d0-d1 LEDs are on the FPGA card
     $F005 - Bank Select Register 61445 dec
        d0..d3 used for 128KB SRAMs
    $F010-$F017 - SD card
           0    SDDATA        read/write data
        1    SDSTATUS      read
        1    SDCONTROL     write
        2    SDLBA0        write-only
        3    SDLBA1        write-only
        4    SDLBA2        write-only (only bits 6:0 are valid)
*/

//#include "osic1p.h"

#define READ_BUFFER_START    0xE000    /* Banked SRAM            */
#define WRITE_BUFFER_START    0xE200    
#define BANK_SELECT_REG_ADR    0xF005
#define START_BANKED_RAM     0xE000
#define SD_DATA                0xF000
#define SD_CTRL                0xF001
#define SD_STATUS            0xF001
#define SD_LBA0                0xF002
#define SD_LBA1                0xF003
#define SD_LBA2                0xF004
#define READ_COMMMAND        0x00
#define WRITE_COMMMAND        0x01

/* issueSDCardCommand - Send read or write command to SD Card        */
void issueSDCardCommand(unsigned char rwCmd)
{
    *(unsigned char *) SD_CTRL = rwCmd;
}

/* setLBA0 - Set the least significant logical block address bits    */
void setLBA0(unsigned char lba0)
{
    *(unsigned char *) SD_LBA0 = lba0;
}

/* setLBA1 - Set the middle 8 bits of the logical block addr bits    */
void setLBA1(unsigned char lba1)
{
    *(unsigned char *) SD_LBA1 = lba1; 
}

/* setLBA2 - Set the upper 8 bits of the logical block addr bits    */
void setLBA2(unsigned char lba2)
{
    *(unsigned char *) SD_LBA2 = lba2;
}

/* waitSDCardReady - Wait for the SD Card to be ready                */
void waitSDCardReady(void)
{
    while (*(unsigned char *) SD_STATUS != 0x80);
}

/* waitSDCardRcvDataReady - Wait for the SD Card to have data ready    */
void waitSDCardRcvDataReady(void)
{
    while (*(unsigned char *) SD_STATUS != 0xE0);
}

/* waitSDCardTxDataEmpty - Wait for transmit ready from SD ctrlr    */
void waitSDCardTxDataEmpty(void)
{
    while (*(unsigned char *) SD_STATUS != 0xA0);
}

/* readByteFromSDCard - Read a byte from the SD Card                */
unsigned char readByteFromSDCard(void)
{
    char rdChar;
    waitSDCardRcvDataReady();
    rdChar = *(unsigned char *) SD_DATA;
    return(rdChar);
}

/* writeByteToSDCard - Write a byte to the SD Card                    */
void writeByteToSDCard(unsigned char outChar)
{
    waitSDCardTxDataEmpty();
    *(unsigned char *) SD_DATA = outChar;
}

/* readBlock - -Read a block from the SD Card                        */
void readBlock(void)
{
    unsigned short loopCount;
    unsigned char * inBuffer;
    inBuffer = (unsigned char *) READ_BUFFER_START;
    waitSDCardReady();
    issueSDCardCommand(READ_COMMMAND);
    for (loopCount = 0; loopCount < 512; loopCount++)
    {
        *inBuffer++ = readByteFromSDCard();
    }
}

/* writeBlock - Write a block to the SD Card                        */
void writeBlock(void)
{
    unsigned short loopCount;
    unsigned char * outBuffer;
    outBuffer = (unsigned char *) WRITE_BUFFER_START;
    waitSDCardReady();
    issueSDCardCommand(WRITE_COMMMAND);
    for (loopCount = 0; loopCount < 512; loopCount++)
    {
        writeByteToSDCard(*outBuffer++);
    }
}

/* main - Test the SD Card interface                                */
void main(void)
{
    /* Set to first bank of the banked SRAM */ 
    *(unsigned char*) BANK_SELECT_REG_ADR = 0x00;
    setLBA0(0);
    setLBA1(0);
    setLBA2(0);
    readBlock();
}

 Assembly output list file:

ca65 V2.17 - Git de519b9
Main file   : OSISDOS.s
Current file: OSISDOS.s

000000r 1               ;
000000r 1               ; File generated by cc65 v 2.17 - Git de519b9
000000r 1               ;
000000r 1                   .fopt        compiler,"cc65 v 2.17 - Git de519b9"
000000r 1                   .setcpu        "6502"
000000r 1                   .smart        on
000000r 1                   .autoimport    on
000000r 1                   .case        on
000000r 1                   .debuginfo    off
000000r 1                   .importzp    sp, sreg, regsave, regbank
000000r 1                   .importzp    tmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3, ptr4
000000r 1                   .macpack    longbranch
000000r 2               .macro  jeq     Target
000000r 2                       .if     .match(Target, 0)
000000r 2                       bne     *+5
000000r 2                       jmp     Target
000000r 2                       .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127)
000000r 2                               beq     Target
000000r 2                       .else
000000r 2                               bne     *+5
000000r 2                               jmp     Target
000000r 2                       .endif
000000r 2               .endmacro
000000r 2               .macro  jne     Target
000000r 2                       .if     .match(Target, 0)
000000r 2                               beq     *+5
000000r 2                               jmp     Target
000000r 2                       .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127)
000000r 2                               bne     Target
000000r 2                       .else
000000r 2                               beq     *+5
000000r 2                               jmp     Target
000000r 2                       .endif
000000r 2               .endmacro
000000r 2               .macro  jmi     Target
000000r 2                       .if     .match(Target, 0)
000000r 2                               bpl     *+5
000000r 2                               jmp     Target
000000r 2                       .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127)
000000r 2                               bmi     Target
000000r 2                       .else
000000r 2                               bpl     *+5
000000r 2                               jmp     Target
000000r 2                       .endif
000000r 2               .endmacro
000000r 2               .macro  jpl     Target
000000r 2                       .if     .match(Target, 0)
000000r 2                               bmi     *+5
000000r 2                               jmp     Target
000000r 2                       .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127)
000000r 2                               bpl     Target
000000r 2                       .else
000000r 2                               bmi     *+5
000000r 2                               jmp     Target
000000r 2                       .endif
000000r 2               .endmacro
000000r 2               .macro  jcs     Target
000000r 2                       .if     .match(Target, 0)
000000r 2                               bcc     *+5
000000r 2                               jmp     Target
000000r 2                       .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127)
000000r 2                               bcs     Target
000000r 2                       .else
000000r 2                               bcc     *+5
000000r 2                               jmp     Target
000000r 2                       .endif
000000r 2               .endmacro
000000r 2               .macro  jcc     Target
000000r 2                       .if     .match(Target, 0)
000000r 2                               bcs     *+5
000000r 2                               jmp     Target
000000r 2                       .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127)
000000r 2                               bcc     Target
000000r 2                       .else
000000r 2                               bcs     *+5
000000r 2                               jmp     Target
000000r 2                       .endif
000000r 2               .endmacro
000000r 2               .macro  jvs     Target
000000r 2                       .if     .match(Target, 0)
000000r 2                               bvc     *+5
000000r 2                               jmp     Target
000000r 2                       .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127)
000000r 2                               bvs     Target
000000r 2                       .else
000000r 2                               bvc     *+5
000000r 2                               jmp     Target
000000r 2                       .endif
000000r 2               .endmacro
000000r 2               .macro  jvc     Target
000000r 2                       .if     .match(Target, 0)
000000r 2                               bvs     *+5
000000r 2                               jmp     Target
000000r 2                       .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127)
000000r 2                               bvc     Target
000000r 2                       .else
000000r 2                               bvs     *+5
000000r 2                               jmp     Target
000000r 2                       .endif
000000r 2               .endmacro
000000r 2               
000000r 1                   .forceimport    __STARTUP__
000000r 1                   .export        _issueSDCardCommand
000000r 1                   .export        _setLBA0
000000r 1                   .export        _setLBA1
000000r 1                   .export        _setLBA2
000000r 1                   .export        _waitSDCardReady
000000r 1                   .export        _waitSDCardRcvDataReady
000000r 1                   .export        _waitSDCardTxDataEmpty
000000r 1                   .export        _readByteFromSDCard
000000r 1                   .export        _writeByteToSDCard
000000r 1                   .export        _readBlock
000000r 1                   .export        _writeBlock
000000r 1                   .export        _main
000000r 1               
000000r 1               ; ---------------------------------------------------------------
000000r 1               ; void __near__ issueSDCardCommand (unsigned char)
000000r 1               ; ---------------------------------------------------------------
000000r 1               
000000r 1               .segment    "CODE"
000000r 1               
000000r 1               .proc    _issueSDCardCommand: near
000000r 1               
000000r 1               .segment    "CODE"
000000r 1               
000000r 1  20 rr rr         jsr     pusha
000003r 1  A0 00            ldy     #$00
000005r 1  A2 00            ldx     #$00
000007r 1  B1 rr            lda     (sp),y
000009r 1  8D 01 F0         sta     $F001
00000Cr 1  20 rr rr         jsr     incsp1
00000Fr 1  60               rts
000010r 1               
000010r 1               .endproc
000010r 1               
000010r 1               ; ---------------------------------------------------------------
000010r 1               ; void __near__ setLBA0 (unsigned char)
000010r 1               ; ---------------------------------------------------------------
000010r 1               
000010r 1               .segment    "CODE"
000010r 1               
000010r 1               .proc    _setLBA0: near
000010r 1               
000010r 1               .segment    "CODE"
000010r 1               
000010r 1  20 rr rr         jsr     pusha
000013r 1  A0 00            ldy     #$00
000015r 1  A2 00            ldx     #$00
000017r 1  B1 rr            lda     (sp),y
000019r 1  8D 02 F0         sta     $F002
00001Cr 1  20 rr rr         jsr     incsp1
00001Fr 1  60               rts
000020r 1               
000020r 1               .endproc
000020r 1               
000020r 1               ; ---------------------------------------------------------------
000020r 1               ; void __near__ setLBA1 (unsigned char)
000020r 1               ; ---------------------------------------------------------------
000020r 1               
000020r 1               .segment    "CODE"
000020r 1               
000020r 1               .proc    _setLBA1: near
000020r 1               
000020r 1               .segment    "CODE"
000020r 1               
000020r 1  20 rr rr         jsr     pusha
000023r 1  A0 00            ldy     #$00
000025r 1  A2 00            ldx     #$00
000027r 1  B1 rr            lda     (sp),y
000029r 1  8D 03 F0         sta     $F003
00002Cr 1  20 rr rr         jsr     incsp1
00002Fr 1  60               rts
000030r 1               
000030r 1               .endproc
000030r 1               
000030r 1               ; ---------------------------------------------------------------
000030r 1               ; void __near__ setLBA2 (unsigned char)
000030r 1               ; ---------------------------------------------------------------
000030r 1               
000030r 1               .segment    "CODE"
000030r 1               
000030r 1               .proc    _setLBA2: near
000030r 1               
000030r 1               .segment    "CODE"
000030r 1               
000030r 1  20 rr rr         jsr     pusha
000033r 1  A0 00            ldy     #$00
000035r 1  A2 00            ldx     #$00
000037r 1  B1 rr            lda     (sp),y
000039r 1  8D 04 F0         sta     $F004
00003Cr 1  20 rr rr         jsr     incsp1
00003Fr 1  60               rts
000040r 1               
000040r 1               .endproc
000040r 1               
000040r 1               ; ---------------------------------------------------------------
000040r 1               ; void __near__ waitSDCardReady (void)
000040r 1               ; ---------------------------------------------------------------
000040r 1               
000040r 1               .segment    "CODE"
000040r 1               
000040r 1               .proc    _waitSDCardReady: near
000040r 1               
000040r 1               .segment    "CODE"
000040r 1               
000040r 1  4C rr rr         jmp     L000E
000043r 1  A2 00        L000E:    ldx     #$00
000045r 1  AD 01 F0         lda     $F001
000048r 1  C9 80            cmp     #$80
00004Ar 1  20 rr rr         jsr     boolne
00004Dr 1  D0 F4            jne     L000E
00004Fr 1  60               rts
000050r 1               
000050r 1               .endproc
000050r 1               
000050r 1               ; ---------------------------------------------------------------
000050r 1               ; void __near__ waitSDCardRcvDataReady (void)
000050r 1               ; ---------------------------------------------------------------
000050r 1               
000050r 1               .segment    "CODE"
000050r 1               
000050r 1               .proc    _waitSDCardRcvDataReady: near
000050r 1               
000050r 1               .segment    "CODE"
000050r 1               
000050r 1  4C rr rr         jmp     L0013
000053r 1  A2 00        L0013:    ldx     #$00
000055r 1  AD 01 F0         lda     $F001
000058r 1  C9 E0            cmp     #$E0
00005Ar 1  20 rr rr         jsr     boolne
00005Dr 1  D0 F4            jne     L0013
00005Fr 1  60               rts
000060r 1               
000060r 1               .endproc
000060r 1               
000060r 1               ; ---------------------------------------------------------------
000060r 1               ; void __near__ waitSDCardTxDataEmpty (void)
000060r 1               ; ---------------------------------------------------------------
000060r 1               
000060r 1               .segment    "CODE"
000060r 1               
000060r 1               .proc    _waitSDCardTxDataEmpty: near
000060r 1               
000060r 1               .segment    "CODE"
000060r 1               
000060r 1  4C rr rr         jmp     L0018
000063r 1  A2 00        L0018:    ldx     #$00
000065r 1  AD 01 F0         lda     $F001
000068r 1  C9 A0            cmp     #$A0
00006Ar 1  20 rr rr         jsr     boolne
00006Dr 1  D0 F4            jne     L0018
00006Fr 1  60               rts
000070r 1               
000070r 1               .endproc
000070r 1               
000070r 1               ; ---------------------------------------------------------------
000070r 1               ; unsigned char __near__ readByteFromSDCard (void)
000070r 1               ; ---------------------------------------------------------------
000070r 1               
000070r 1               .segment    "CODE"
000070r 1               
000070r 1               .proc    _readByteFromSDCard: near
000070r 1               
000070r 1               .segment    "CODE"
000070r 1               
000070r 1  20 rr rr         jsr     decsp1
000073r 1  20 rr rr         jsr     _waitSDCardRcvDataReady
000076r 1  A2 00            ldx     #$00
000078r 1  AD 00 F0         lda     $F000
00007Br 1  A0 00            ldy     #$00
00007Dr 1  91 rr            sta     (sp),y
00007Fr 1  A0 00            ldy     #$00
000081r 1  A2 00            ldx     #$00
000083r 1  B1 rr            lda     (sp),y
000085r 1  4C rr rr         jmp     L001C
000088r 1  20 rr rr     L001C:    jsr     incsp1
00008Br 1  60               rts
00008Cr 1               
00008Cr 1               .endproc
00008Cr 1               
00008Cr 1               ; ---------------------------------------------------------------
00008Cr 1               ; void __near__ writeByteToSDCard (unsigned char)
00008Cr 1               ; ---------------------------------------------------------------
00008Cr 1               
00008Cr 1               .segment    "CODE"
00008Cr 1               
00008Cr 1               .proc    _writeByteToSDCard: near
00008Cr 1               
00008Cr 1               .segment    "CODE"
00008Cr 1               
00008Cr 1  20 rr rr         jsr     pusha
00008Fr 1  20 rr rr         jsr     _waitSDCardTxDataEmpty
000092r 1  A0 00            ldy     #$00
000094r 1  A2 00            ldx     #$00
000096r 1  B1 rr            lda     (sp),y
000098r 1  8D 00 F0         sta     $F000
00009Br 1  20 rr rr         jsr     incsp1
00009Er 1  60               rts
00009Fr 1               
00009Fr 1               .endproc
00009Fr 1               
00009Fr 1               ; ---------------------------------------------------------------
00009Fr 1               ; void __near__ readBlock (void)
00009Fr 1               ; ---------------------------------------------------------------
00009Fr 1               
00009Fr 1               .segment    "CODE"
00009Fr 1               
00009Fr 1               .proc    _readBlock: near
00009Fr 1               
00009Fr 1               .segment    "CODE"
00009Fr 1               
00009Fr 1  20 rr rr         jsr     decsp4
0000A2r 1  A2 E0            ldx     #$E0
0000A4r 1  A9 00            lda     #$00
0000A6r 1  A0 00            ldy     #$00
0000A8r 1  20 rr rr         jsr     staxysp
0000ABr 1  20 rr rr         jsr     _waitSDCardReady
0000AEr 1  A9 00            lda     #$00
0000B0r 1  20 rr rr         jsr     _issueSDCardCommand
0000B3r 1  A2 00            ldx     #$00
0000B5r 1  A9 00            lda     #$00
0000B7r 1  A0 02            ldy     #$02
0000B9r 1  20 rr rr         jsr     staxysp
0000BCr 1  A0 03        L002C:    ldy     #$03
0000BEr 1  20 rr rr         jsr     ldaxysp
0000C1r 1  E0 02            cpx     #$02
0000C3r 1  20 rr rr         jsr     boolult
0000C6r 1  F0 03 4C rr      jne     L002F
0000CAr 1  rr           
0000CBr 1  4C rr rr         jmp     L002D
0000CEr 1  A0 01        L002F:    ldy     #$01
0000D0r 1  20 rr rr         jsr     ldaxysp
0000D3r 1  85 rr            sta     regsave
0000D5r 1  86 rr            stx     regsave+1
0000D7r 1  20 rr rr         jsr     incax1
0000DAr 1  A0 00            ldy     #$00
0000DCr 1  20 rr rr         jsr     staxysp
0000DFr 1  A5 rr            lda     regsave
0000E1r 1  A6 rr            ldx     regsave+1
0000E3r 1  20 rr rr         jsr     pushax
0000E6r 1  20 rr rr         jsr     _readByteFromSDCard
0000E9r 1  A0 00            ldy     #$00
0000EBr 1  20 rr rr         jsr     staspidx
0000EEr 1  A0 03            ldy     #$03
0000F0r 1  20 rr rr         jsr     ldaxysp
0000F3r 1  85 rr            sta     regsave
0000F5r 1  86 rr            stx     regsave+1
0000F7r 1  20 rr rr         jsr     incax1
0000FAr 1  A0 02            ldy     #$02
0000FCr 1  20 rr rr         jsr     staxysp
0000FFr 1  A5 rr            lda     regsave
000101r 1  A6 rr            ldx     regsave+1
000103r 1  4C rr rr         jmp     L002C
000106r 1  20 rr rr     L002D:    jsr     incsp4
000109r 1  60               rts
00010Ar 1               
00010Ar 1               .endproc
00010Ar 1               
00010Ar 1               ; ---------------------------------------------------------------
00010Ar 1               ; void __near__ writeBlock (void)
00010Ar 1               ; ---------------------------------------------------------------
00010Ar 1               
00010Ar 1               .segment    "CODE"
00010Ar 1               
00010Ar 1               .proc    _writeBlock: near
00010Ar 1               
00010Ar 1               .segment    "CODE"
00010Ar 1               
00010Ar 1  20 rr rr         jsr     decsp4
00010Dr 1  A2 E2            ldx     #$E2
00010Fr 1  A9 00            lda     #$00
000111r 1  A0 00            ldy     #$00
000113r 1  20 rr rr         jsr     staxysp
000116r 1  20 rr rr         jsr     _waitSDCardReady
000119r 1  A9 01            lda     #$01
00011Br 1  20 rr rr         jsr     _issueSDCardCommand
00011Er 1  A2 00            ldx     #$00
000120r 1  A9 00            lda     #$00
000122r 1  A0 02            ldy     #$02
000124r 1  20 rr rr         jsr     staxysp
000127r 1  A0 03        L003C:    ldy     #$03
000129r 1  20 rr rr         jsr     ldaxysp
00012Cr 1  E0 02            cpx     #$02
00012Er 1  20 rr rr         jsr     boolult
000131r 1  F0 03 4C rr      jne     L003F
000135r 1  rr           
000136r 1  4C rr rr         jmp     L003D
000139r 1  A0 01        L003F:    ldy     #$01
00013Br 1  20 rr rr         jsr     ldaxysp
00013Er 1  85 rr            sta     regsave
000140r 1  86 rr            stx     regsave+1
000142r 1  20 rr rr         jsr     incax1
000145r 1  A0 00            ldy     #$00
000147r 1  20 rr rr         jsr     staxysp
00014Ar 1  A5 rr            lda     regsave
00014Cr 1  A6 rr            ldx     regsave+1
00014Er 1  A0 00            ldy     #$00
000150r 1  20 rr rr         jsr     ldauidx
000153r 1  20 rr rr         jsr     _writeByteToSDCard
000156r 1  A0 03            ldy     #$03
000158r 1  20 rr rr         jsr     ldaxysp
00015Br 1  85 rr            sta     regsave
00015Dr 1  86 rr            stx     regsave+1
00015Fr 1  20 rr rr         jsr     incax1
000162r 1  A0 02            ldy     #$02
000164r 1  20 rr rr         jsr     staxysp
000167r 1  A5 rr            lda     regsave
000169r 1  A6 rr            ldx     regsave+1
00016Br 1  4C rr rr         jmp     L003C
00016Er 1  20 rr rr     L003D:    jsr     incsp4
000171r 1  60               rts
000172r 1               
000172r 1               .endproc
000172r 1               
000172r 1               ; ---------------------------------------------------------------
000172r 1               ; void __near__ main (void)
000172r 1               ; ---------------------------------------------------------------
000172r 1               
000172r 1               .segment    "CODE"
000172r 1               
000172r 1               .proc    _main: near
000172r 1               
000172r 1               .segment    "CODE"
000172r 1               
000172r 1  A2 00            ldx     #$00
000174r 1  A9 00            lda     #$00
000176r 1  8D 05 F0         sta     $F005
000179r 1  A9 00            lda     #$00
00017Br 1  20 rr rr         jsr     _setLBA0
00017Er 1  A9 00            lda     #$00
000180r 1  20 rr rr         jsr     _setLBA1
000183r 1  A9 00            lda     #$00
000185r 1  20 rr rr         jsr     _setLBA2
000188r 1  20 rr rr         jsr     _readBlock
00018Br 1  60               rts
00018Cr 1               
00018Cr 1               .endproc
00018Cr 1               
00018Cr 1               

main() starts at 0x172 from 0x300 or 0x472. 

Nice!

Discussions