232 lines
4.9 KiB
C
232 lines
4.9 KiB
C
|
|
/*
|
||
|
|
* 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);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
*/
|