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
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.