zutil-asm/boostc/sdcard.c

232 lines
4.9 KiB
C
Raw Permalink Normal View History

2009-06-15 13:00:32 +00:00
/*
* http://ghmicro.com/index.php/pic/13-18f4620/11-18f4620-a-sd-card
*/
#include <system.h>
#include <memory.h>
#include "sdcard.h"
#include "spi.h"
char sd_output_buffer1[256];
char sd_output_buffer2[256];
char sd_input_buffer1[256];
char sd_input_buffer2[256];
void sd_init(void){
int i,r;
CSel=1; //init chip select (active low)
SD_LED=0; //LED off
for(i=0; i<256 ;i++){ //fill the send buffers
sd_output_buffer1[i]=0;
sd_output_buffer2[i]=0;
sd_input_buffer1[i]=0; //and clear the receive buffers
sd_input_buffer2[i]=0;
}
r = sd_initMedia();
if(r){ //card init failed - 1 blink
while(1){
SD_LED = 1;
delay_ms(150);
SD_LED = 0;
delay_s(1);
}
}
}
int sd_initMedia(void){
int i,r;
CSel = 1;
spi_putc(0xff); //while card is not selected
for(i=0;i<16;i++) //send 80 clock cycles to start up
spi_putc(0xff);
CSel = 0; //then select the card
r = sd_sendCmd(0,0); //send reset command to enter SPI mode
CSel = 1;
spi_putc(0xff); //disable SD
if(r != 1) //error check - need 1
return 0x84;
i = 10000; //send init for up to 0.3s
CSel = 0;
do{
r = sd_sendCmd(1,0); //send init command
CSel = 1;
spi_putc(0xff); //disable SD
if(!r) break;
}while(--i > 0);
if(i==0) //time out error 0x85
return 0x85;
sspcon1 = 0b00010000; //speed up spi clock
sspcon1.SSPEN = 1;
return 0;
}
int sd_writeSector(LBA a, char *p1, char *p2){
unsigned r,i;
SD_LED = 1; //turn on write LED
r = sd_sendCmd(24,(a<<9));
if(r == 0){
spi_putc(0xfe); //send Data Start byte
for(i=0;i<256;i++) //first 256 bytes
spi_putc(*p1++);
for(i=0;i<256;i++) //second 256 bytes
spi_putc(*p2++);
spi_putc(0xff); //send dummy CRC
spi_putc(0xff);
if((r=spi_putc(0xff) & 0x0f) == 0x05){ //check if data accepted
for(i=10000;i>0;i--){
if(r=spi_putc(0xff))
break;
}
}
else
r=0; //fail
}
CSel = 1; spi_putc(0xff); //disable SD
SD_LED = 0; //LED off
return(r);
}
int sd_readSector(LBA a, char *p1, char *p2){
int r,i;
SD_LED = 1; //turn on read LED
r = sd_sendCmd(17,(a<<9));
if(r == 0){ //check if command was accepted
i=10000; //wait for a response
do{
r = spi_putc(0xff);
if(r==0xfe)
break;
}while(--i > 0);
if(i){ //if no timeout, read 512 byte sector
for(i=0;i<256;i++)
*p1++ = spi_putc(0xff);
for(i=0;i<256;i++)
*p2++ = spi_putc(0xff);
spi_putc(0xff); //ignore CRC
spi_putc(0xff);
}
}
CSel = 1;spi_putc(0xff); //disable SD
SD_LED = 0; //read LED off
return(r == 0xfe);
}
int sd_sendCmd(unsigned char c, LBA a){
int i,r;
CSel = 0; //send command packet (6 bytes)
spi_putc(c|0x40); //send command & frame bit
spi_putc(a>>24); //send 32-bit address
spi_putc(a>>16);
spi_putc(a>>8);
spi_putc(a);
spi_putc(0x95); //send CRC
i = 9; //wait for response
do{
r = spi_putc(0xff); //check if ready
if(r != 0xff)
break;
}while(--i > 0);
return(r);
}
/*
void main(void){
LBA addr;
int i,r;
trisd=0;
trisc=0b00010000;
CSel=1; //init chip select (active low)
LED=0; //LED off
osccon=0x72; //8MHz clock
osctune.6=0; //disable PLL
while(!osccon.IOFS); //wait for osc stable
sspstat = 0b00000000; //SMP(7)=0, CKE(6)=0 (clock edge idle to active)
sspcon1 = 0b00010010; //CKP(4)=1 clock polarity (idle high)
//SSPM3:SSPM0(3:0)=010 spi clock FOSC/64 (<400kHz)
sspcon1.SSPEN=1; //SSPEN(5)=1 enable SPI
for(i=0;i<256;i++){ //fill the send buffers
data1[i]=i;
data2[i]=i;
buffer1[i]=0; //and clear the receive buffers
buffer2[i]=0;
}
r=initMedia();
if(r){ //card init failed - 1 blink
while(1){
LED=1;
delay_ms(150);
LED=0;
delay_s(1);
}
}
else{ //write card
addr = 10000;
for(i=0;i<1000;i++){
if(!writeSector(addr+i,data1,data2)){
while(1){ //write failed - 2 blinks
LED=1;
delay_ms(150);
LED=0;
delay_ms(150);
LED=1;
delay_ms(150);
LED=0;
delay_s(1);
}
}
}
addr=10000; //verify write
for(i=0;i<1000;i++){
if(!readSector(addr+i,buffer1,buffer2)){
while(1){ //verify failed - 3 blinks
LED=1;
delay_ms(150);
LED=0;
delay_ms(150);
LED=1;
delay_ms(150);
LED=0;
delay_ms(150);
LED=1;
delay_ms(150);
LED=0;
delay_s(1);
}
}
//verify
if(memcmp(data1,buffer1,256)||memcmp(data2,buffer2,256)){
while(1){ //mismatch - 4 blinks
LED=1;
delay_ms(150);
LED=0;
delay_ms(150);
LED=1;
delay_ms(150);
LED=0;
delay_ms(150);
LED=1;
delay_ms(150);
LED=0;
delay_ms(150);
LED=1;
delay_ms(150);
LED=0;
delay_s(1);
}
}
}
}
while(1){ //success!
LED=1;
delay_s(1);
LED=0;
delay_s(1);
}
}
*/