593 lines
11 KiB
C
593 lines
11 KiB
C
/*
|
||
* sd card
|
||
*/
|
||
|
||
#include <MCF5475.h>
|
||
#include <stdint.h>
|
||
|
||
#define dspi_dtar0 0x0c
|
||
#define dspi_dsr 0x2c
|
||
#define dspi_dtfr 0x34
|
||
#define dspi_drfr 0x38
|
||
#define time1us 1320
|
||
|
||
extern void wait_10ms(void);
|
||
|
||
|
||
uint8_t sd_com(uint32_t cmd)
|
||
{
|
||
uint8_t res;
|
||
|
||
MCF_DSPI_DTFR = cmd;
|
||
while (! MCF_DSPI_DSR & (1 << 7));
|
||
|
||
res = MCF_DSPI_DRFR;
|
||
MCF_DSPI_DSR = -1L;
|
||
|
||
return res;
|
||
}
|
||
|
||
/*
|
||
* fetch status from SD controller
|
||
*/
|
||
uint8_t sd_get_status(void)
|
||
{
|
||
uint8_t res;
|
||
|
||
while ((res = sd_com(0xff)) == 0xff);
|
||
|
||
return res;
|
||
}
|
||
|
||
void sd_rcv_info(uint8_t *buf, uint32_t size)
|
||
{
|
||
uint32_t rcvd = 0;
|
||
|
||
while (sd_get_status() != 0xfe); /* loop until data available */
|
||
|
||
do {
|
||
*buf++ = sd_com(0x18);
|
||
rcvd++;
|
||
} while (rcvd <= size);
|
||
}
|
||
|
||
|
||
void sd_card_idle(void)
|
||
{
|
||
|
||
#ifdef _NOT_USED_
|
||
asm
|
||
{
|
||
// sd idle
|
||
// speed =400kHz
|
||
move.l #0x082000ff,d4 // tx vorbesetzen
|
||
lea MCF_DSPI_DMCR,a0
|
||
move.l #0x38558897,d0
|
||
move.l d0,dspi_dtar0(a0) // 400kHz
|
||
|
||
move.b #0xff,d4
|
||
bsr sd_com // clocks
|
||
move.b #0x40,d4 // cmd idle
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #0x95,d4
|
||
bsr sd_com
|
||
}
|
||
#endif
|
||
}
|
||
|
||
#ifdef _NOT_USED_
|
||
|
||
int sd_card_init(void)
|
||
{
|
||
|
||
long az_sectors;
|
||
|
||
asm
|
||
{
|
||
lea MCF_PSC0_PSCTB_8BIT,a1
|
||
move.l #'SD-C',(a1)
|
||
move.l #'ard ',(a1)
|
||
|
||
move.l buffer,a5 // basis addresse (diesen bereich brauchen wir nicht mehr!)
|
||
move.l #0x1fffffff,d0 // normal dspi
|
||
move.l d0,MCF_PAD_PAR_DSPI
|
||
lea MCF_DSPI_DMCR,a0
|
||
move.l #0x802d3c00,(a0) // 8 bit cs off clear fifo
|
||
move.l #0x38558897,d0
|
||
move.l d0,dspi_dtar0(a0) // 400kHz
|
||
move.l #0x082000ff,d4 // tx vorbesetzen
|
||
move.l d4,dspi_dtfr // und setzen
|
||
mov3q.l #-1,dspi_dsr(a0) // status register l<>schen
|
||
|
||
move.l #0xc00d3c00,(a0) // clock on cs ist on
|
||
bsr wait_10ms
|
||
move.l #0x802d3c00,(a0) // clock off cs off
|
||
bsr sd_com
|
||
bsr sd_com
|
||
bsr sd_com
|
||
bsr sd_com
|
||
bsr sd_com
|
||
bsr sd_com
|
||
bsr sd_com
|
||
bsr sd_com
|
||
bsr sd_com
|
||
bsr sd_com
|
||
move.l #0x800d3c00,(a0) // cs on
|
||
bsr sd_com
|
||
bsr sd_com
|
||
move.l #0x802d3c00,(a0) // cs off
|
||
bsr sd_com
|
||
bsr sd_com
|
||
bsr wait_10ms
|
||
|
||
// sd idle
|
||
move.l #100,d6 // 100 versuche
|
||
move.l #10,d3 // 10 versuche
|
||
sd_idle:
|
||
bsr sd_card_idle
|
||
|
||
move.l #10,d7
|
||
move.b #0xff,d4
|
||
sd_idle_leeren:
|
||
bsr sd_com
|
||
cmp.b #0x01,d5
|
||
beq idle_end
|
||
subq.l #1,d7
|
||
bne sd_idle_leeren
|
||
subq.l #1,d6
|
||
beq sd_not
|
||
bra sd_idle
|
||
idle_end:
|
||
|
||
// cdm 8
|
||
read_ic:
|
||
move.b #0xff,d4 // clocks
|
||
bsr sd_com
|
||
move.b #0x48,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #0x01,d4
|
||
bsr sd_com
|
||
move.b #0xaa,d4
|
||
bsr sd_com
|
||
move.b #0x87,d4
|
||
bsr sd_com
|
||
|
||
bsr sd_get_status
|
||
cmp.b #5,d5
|
||
beq sd_v1
|
||
cmp.b #1,d5
|
||
bne read_ic
|
||
|
||
bsr sd_com // 4byts zum wegwerfen
|
||
bsr sd_com
|
||
bsr sd_com
|
||
bsr sd_com
|
||
cmp.b #0xaa,d5 // pattern zur<75>ckgekommen?
|
||
bne sd_testd3 // nein ->
|
||
|
||
move.l #'SDHC',(a1)
|
||
move.b #' ',(a1)
|
||
sd_v1:
|
||
|
||
// cdm 58
|
||
read_ocr:
|
||
move.b #0xff,d4 // clocks
|
||
bsr sd_com
|
||
move.b #0x7a,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #0x00,d4
|
||
bsr sd_com
|
||
move.b #0x00,d4
|
||
bsr sd_com
|
||
move.b #0x01,d4
|
||
bsr sd_com
|
||
|
||
bsr sd_get_status
|
||
move.l #'Ver1',d6
|
||
cmp.b #5,d5
|
||
beq read_ocr
|
||
cmp.b #1,d5
|
||
bne read_ocr
|
||
|
||
bsr sd_com // 4 byts zum wegwerfen
|
||
bsr sd_com
|
||
bsr sd_com
|
||
bsr sd_com
|
||
|
||
// acdm 41
|
||
move.l #20000,d6 // 20000 versuche ready can bis 1 sec gehen
|
||
wait_of_aktiv:
|
||
move.b #0xff,d4 // clocks
|
||
bsr sd_com
|
||
move.b #0x77,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #0x95,d4
|
||
bsr sd_com
|
||
|
||
bsr sd_get_status
|
||
cmp.b #0x05,d5
|
||
beq wait_of_aktiv
|
||
|
||
wait_of_aktiv2:
|
||
move.b #0xff,d4 // clocks
|
||
bsr sd_com
|
||
move.b #0x69,d4
|
||
bsr sd_com
|
||
move.b #0x40,d4
|
||
bsr sd_com
|
||
move.b #0x00,d4
|
||
bsr sd_com
|
||
move.b #0x00,d4
|
||
bsr sd_com
|
||
move.b #0x00,d4
|
||
bsr sd_com
|
||
move.b #0x95,d4
|
||
bsr sd_com
|
||
|
||
bsr sd_get_status
|
||
tst.b d5
|
||
beq sd_init_ok
|
||
cmp.b #0x05,d5
|
||
beq wait_of_aktiv2
|
||
subq.l #1,d6
|
||
bne wait_of_aktiv
|
||
sd_testd3:
|
||
subq.l #1,d3
|
||
bne sd_idle
|
||
bra sd_error
|
||
|
||
sd_init_ok:
|
||
// fullspeed
|
||
move.l #0x38551120,d0 // 22Mbit/sec
|
||
move.l d0,dspi_dtar0(a0) // setzen
|
||
|
||
// cdm 10
|
||
read_cid:
|
||
move.b #0xff,d4 // clocks
|
||
bsr sd_com
|
||
move.b #0x4a,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #0x00,d4
|
||
bsr sd_com
|
||
move.b #0x00,d4
|
||
bsr sd_com
|
||
move.b #0x95,d4
|
||
bsr sd_com
|
||
|
||
move.l a5,a2 // adresse setzen
|
||
bsr sd_rcv_info
|
||
|
||
// name ausgeben
|
||
lea 1(a5),a2
|
||
moveq #7,d7
|
||
sd_nam_loop:
|
||
move.b (a2)+,(a1)
|
||
subq.l #1,d7
|
||
bne sd_nam_loop
|
||
move.b #' ',(a1)
|
||
|
||
// cdm 9
|
||
read_csd:
|
||
move.b #0xff,d4 // clocks
|
||
bsr sd_com
|
||
move.b #0x49,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #00,d4
|
||
bsr sd_com
|
||
move.b #0x00,d4
|
||
bsr sd_com
|
||
move.b #0x00,d4
|
||
bsr sd_com
|
||
move.b #0x01,d4
|
||
bsr sd_com
|
||
|
||
move.l a5,a2 // adresse setzen
|
||
bsr sd_rcv_info
|
||
|
||
mvz.b (a5),d0
|
||
lsr.l #6,d0
|
||
|
||
bne sd_csd2 // format v2
|
||
move.l 6(a5),d1
|
||
moveq #14,d0 // bit 73..62 c_size
|
||
lsr.l d0,d1 // bits extrahieren
|
||
and.l #0xfff,d1 // 12 bits
|
||
addq.l #1,d1
|
||
mvz.w 9(a5),d0
|
||
lsr.l #7,d0 // bits 49..47
|
||
and.l #0x7,d0 // 3 bits
|
||
moveq.l #8,d2 // x256 (dif v1 v2)
|
||
sub.l d0,d2
|
||
lsr.l d2,d1
|
||
bra sd_print_size
|
||
sd_csd2:
|
||
mvz.w 8(a5),d1
|
||
addq.l #1,d1
|
||
sd_print_size:
|
||
swap d1
|
||
move.l d1,d3
|
||
lsr.l #6,d3 //x65636 /64 -> anzahl sectors
|
||
move.l d3,az_sectors
|
||
lsl.l #1,d1
|
||
bcc sd_16G
|
||
move.l #'32GB',(a1)
|
||
bra sd_ok
|
||
sd_16G:
|
||
lsl.l #1,d1
|
||
bcc sd_8G
|
||
move.l #'16GB',(a1)
|
||
bra sd_ok
|
||
sd_8G:
|
||
lsl.l #1,d1
|
||
bcc sd_4G
|
||
move.l #' 8GB',(a1)
|
||
bra sd_ok
|
||
sd_4G:
|
||
lsl.l #1,d1
|
||
bcc sd_2G
|
||
move.l #' 4GB',(a1)
|
||
bra sd_ok
|
||
sd_2G:
|
||
lsl.l #1,d1
|
||
bcc sd_1G
|
||
move.l #' 2GB',(a1)
|
||
bra sd_ok
|
||
sd_1G:
|
||
lsl.l #1,d1
|
||
bcc sd_512M
|
||
move.l #' 1GB',(a1)
|
||
bra sd_ok
|
||
sd_512M:
|
||
lsl.l #1,d1
|
||
bcc sd_256M
|
||
move.b #'5',(a1)
|
||
move.l #'12MB',(a1)
|
||
bra sd_ok
|
||
sd_256M:
|
||
lsl.l #1,d1
|
||
bcc sd_128M
|
||
move.b #'2',(a1)
|
||
move.l #'56MB',(a1)
|
||
bra sd_ok
|
||
sd_128M:
|
||
lsl.l #1,d1
|
||
bcc sd_64M
|
||
move.b #'1',(a1)
|
||
move.l #'28MB',(a1)
|
||
bra sd_ok
|
||
sd_64M:
|
||
lsl.l #1,d1
|
||
bcc sd_32M
|
||
move.l #'64MB',(a1)
|
||
bra sd_ok
|
||
sd_32M:
|
||
lsl.l #1,d1
|
||
bcc sd_16M
|
||
move.l #'32MB',(a1)
|
||
bra sd_ok
|
||
sd_16M:
|
||
lsl.l #1,d1
|
||
bcc sd_8M
|
||
move.l #'16MB',(a1)
|
||
bra sd_ok
|
||
sd_8M:
|
||
move.l #'<9MB',(a1)
|
||
sd_ok:
|
||
move.l #' OK!',(a1)
|
||
move.l #0x0a0d,(a1)
|
||
bra sd_c_ok
|
||
// subs ende -------------------------------
|
||
sd_error:
|
||
move.l #'Erro',(a1)
|
||
move.l #'r!',(a1)
|
||
move.l #0x0a0d,(a1)
|
||
bra sd_c_error
|
||
sd_not:
|
||
move.l #'non!',(a1)
|
||
move.l #0x0a0d,(a1)
|
||
bra sd_c_not
|
||
buffer: dc.l 0,0,0,0,0,0,0,0
|
||
}
|
||
sd_c_ok:
|
||
return az_sectors;
|
||
sd_c_not:
|
||
return -2;
|
||
sd_c_error:
|
||
return -1;
|
||
}
|
||
|
||
void sd_rcv_sector(void) // 1 sector daten holen ----------------------------
|
||
{
|
||
if (sd_get_status() == 0xfe)
|
||
{
|
||
for (i = 0; i < 512; i++)
|
||
}
|
||
}
|
||
asm
|
||
{
|
||
bsr sd_get_status
|
||
cmp.b #0xfe,d5 // daten bereit?
|
||
bne sd_rs_end // nein-> error
|
||
move.l #512,d3 // sonst 512 byts abholen
|
||
sd_rs_loop:
|
||
bsr sd_com
|
||
move.b d5,(a2)+
|
||
subq.l #1,d3
|
||
bne sd_rs_loop
|
||
// crc holen
|
||
bsr sd_com
|
||
bsr sd_com
|
||
clr.l d5 // alles ok
|
||
sd_rs_end:
|
||
}
|
||
}
|
||
|
||
int sd_card_sector_read(long sec_nr,long buf_adr)
|
||
{
|
||
int status ;
|
||
asm
|
||
{
|
||
lea MCF_DSPI_DMCR,a0
|
||
move.l #0x082000ff,d4 // tx vorbesetzen
|
||
|
||
move.l sec_nr,d0
|
||
move.l buf_adr,a2
|
||
|
||
lsl.l #8,d0
|
||
add.l d0,d0 // x 512 !
|
||
move.l d0,d1 // byts kehren
|
||
swap d1
|
||
move.l d1,d2
|
||
lsr.l #8,d1
|
||
|
||
move.b #0xff,d4 // clocks
|
||
bsr sd_com
|
||
|
||
move.b #0x51,d4
|
||
bsr sd_com
|
||
move.b d1,d4
|
||
bsr sd_com
|
||
move.b d2,d4
|
||
bsr sd_com
|
||
move.l d0,d2
|
||
lsr.l #8,d2
|
||
move.b d2,d4
|
||
bsr sd_com
|
||
move.b d0,d4
|
||
bsr sd_com
|
||
move.b #0x01,d4
|
||
bsr sd_com
|
||
|
||
clr.l d5 // alles auf no error
|
||
clr.l status
|
||
|
||
bsr sd_get_status // status holen
|
||
tst.b d5
|
||
bne sd_csr_end // wenn nicht ok -> weg
|
||
// sector holen
|
||
bsr sd_rcv_sector
|
||
sd_csr_end:
|
||
tst.b d5
|
||
beq sd_csr_ok
|
||
neg.l d5 // wenn nicht ok status auf negativ
|
||
move.l d5,status
|
||
sd_csr_ok:
|
||
}
|
||
return status;
|
||
}
|
||
|
||
void sd_send_sector(void) // 1 sector daten senden ----------------------------
|
||
{
|
||
asm
|
||
{
|
||
move.l #512,d3
|
||
move.b #0xfe,d4 // start token
|
||
bsr sd_com // senden
|
||
sd_send_wr_wb:
|
||
move.b (a2)+,d4 // data
|
||
bsr sd_com // senden
|
||
subq.l #1,d3
|
||
bne sd_send_wr_wb
|
||
// send crc
|
||
move.b #1,d4
|
||
bsr sd_com // crc 1.byt
|
||
move.b #1,d4
|
||
bsr sd_com // crc 2.byt
|
||
sd_send_wr_ww:
|
||
bsr sd_get_status
|
||
and.l #0x1f,d5
|
||
clr.l d6 //status auf OK
|
||
cmp.b #5,d5 //data accepted?
|
||
beq sd_send_end //ja ->
|
||
move.l d5,d6 //sonst status sichern
|
||
sd_send_end:
|
||
bsr sd_com
|
||
tst.b d5 // warte auf geschrieben
|
||
beq sd_send_end
|
||
move.l d6,d5 // status zur<75>ck
|
||
}
|
||
}
|
||
|
||
int sd_card_sector_write(long sec_nr,long buf_adr)
|
||
{
|
||
int status;
|
||
asm
|
||
{
|
||
lea MCF_DSPI_DMCR,a0
|
||
move.l #0x082000ff,d4 // tx vorbesetzen
|
||
|
||
move.l sec_nr,d0
|
||
move.l buf_adr,a2
|
||
|
||
lsl.l #8,d0
|
||
add.l d0,d0 // x 512 !
|
||
move.l d0,d1 // byts kehren
|
||
swap d1
|
||
move.l d1,d2
|
||
lsr.l #8,d1
|
||
|
||
move.b #0xff,d4 // clocks
|
||
bsr sd_com
|
||
move.b #0x58,d4
|
||
bsr sd_com
|
||
move.b d1,d4
|
||
bsr sd_com
|
||
move.b d2,d4
|
||
bsr sd_com
|
||
move.l d0,d2
|
||
lsr.l #8,d2
|
||
move.b d2,d4
|
||
bsr sd_com
|
||
move.b d0,d4
|
||
bsr sd_com
|
||
move.b #0x01,d4
|
||
bsr sd_com
|
||
|
||
clr.l d5 // alles auf no error
|
||
clr.l status
|
||
bsr sd_get_status // status holen
|
||
tst.b d5
|
||
bne sd_csw_end // wenn nicht ok -> weg
|
||
// sector schreiben
|
||
bsr sd_send_sector
|
||
sd_csw_end:
|
||
tst.b d5
|
||
beq sd_csw_ok
|
||
neg.l d5 // wenn nicht ok status auf negativ
|
||
move.l d5,status
|
||
sd_csw_ok:
|
||
}
|
||
return status;
|
||
}
|
||
#endif /* _NOT_USED */
|