#include <p24HJ128GP510.h>
//#include "delay.h"
#include "diskio.h"
//extern void prints(char *str); // prints to lcd
//extern void cls(); // clear lcd
//extern void lcd_gotoxy(uint8 x, uint8 y);//goto lcd column / row
/* MMC/SD command (in SPI) */
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
#define CMD1 (0x40+1) /* SEND_OP_COND */
#define CMD8 (0x40+8) /* SEND_IF_COND */
#define CMD9 (0x40+9) /* SEND_CSD */
#define CMD10 (0x40+10) /* SEND_CID */
#define CMD12 (0x40+12) /* STOP_TRANSMISSION */
#define CMD16 (0x40+16) /* SET_BLOCKLEN */
#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
#define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
#define CMD24 (0x40+24) /* WRITE_BLOCK */
#define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
#define CMD41 (0x40+41) /* SEND_OP_COND (ACMD) */
#define CMD55 (0x40+55) /* APP_CMD */
#define CMD58 (0x40+58) /* READ_OCR */
/* Control signals (Platform dependent) */
//#define CS _LATA4
#define SELECT() LATA &= ~16 /* MMC CS = L */
#define DESELECT() LATA |= 16 /* MMC CS = H */
#define SOCKPORT PORTA /* Socket contact port */
#define SOCKWP PORTAbits.RA0 /* Write protect switch (PB5) */
#define SOCKINS PORTAbits.RA1 /* Card detect switch (PB4) */
//#define isWriteProtect() (PORTAbits.RA0 & 0x01)// _RA1 /* Write protect switch (PB5) */
//#define isCardDetect() (PORTAbits.RA1 & 0x01)//_RA0 /* Card detect switch (PB4) */
//#define WPTRIS TRISAbits.TRISA0
//#define INTRIS TRISAbits.TRISA1
static volatile
DSTATUS Stat = STA_NOINIT; /* Disk status */
static volatile
BYTE Timer1, Timer2; /* 100Hz decrement timer */
static
BYTE BlkAddr; /* 0:Byte addressing, 1:Block addressing */
//void cfgSPI1Master(void);
//BYTE wp, cd;
void cfgSpi1Master(void)
{
// SPI1CON1 Register Settings
SPI1CON1bits.DISSCK = 0; //Internal Serial Clock is Enabled.
SPI1CON1bits.DISSDO = 0; //SDOx pin is controlled by the module.
SPI1CON1bits.SSEN = 0; //SS pin not used
SPI1CON1bits.MODE16 = 0; //Communication is byte-wide (8 bits).
SPI1CON1bits.SMP = 0; //Input Data is sampled at the middle of data output time.
SPI1CON1bits.CKE = 1; //Serial output data changes on transition from Idle clock state to active clock state
SPI1CON1bits.CKP = 0; //Idle state for clock is a low level; active state is a high level
SPI1CON1bits.MSTEN = 1; //Master Mode Enabled
SPI1CON1bits.SPRE2=1; //2:1 Fcy=40MHz 312KHz
SPI1CON1bits.SPRE1=1;
SPI1CON1bits.SPRE0=0;
SPI1CON1bits.PPRE1=0; //64:1
SPI1CON1bits.PPRE0=0;
// SPI1CON2 Register Settings
SPI1CON2bits.FRMEN = 0; // Framed Mode Disabled
SPI1CON2bits.SPIFSD = 0; // Frame sync pulse output (master)
SPI1CON2bits.FRMPOL = 0; // Frame sync pulse is active-low
// SPI1CON2bits.FRMDLY = 0; // Frame sync pulse precedes first bit clock
// SPI1CON2bits.ENHBUF = 0; // FIFO buffer disabled
//SPI1STAT Register Settings
SPI1STATbits.SPISIDL = 0; //Continue module operation in Idle mode
SPI1STATbits.BUFELM = 0; //Buffer Length = 1 Word
SPI1STATbits.SPIROV =0; //No Receive Overflow Has Occurred
SPI1STATbits.SPIEN = 1; //Enable SPI Module
//Interrupt Controller Settings
IFS0bits.SPI1IF = 0; //Clear SPI1 Interrupt Flag
IEC0bits.SPI1IE = 1; //Enable SPI1 Interrupt
}
/*=============================================================================
Interrupt Service Routines.
=============================================================================*/
void __attribute__((__interrupt__)) _SPI1Interrupt(void)
{
IFS0bits.SPI1IF =0;
}
/*
*/
unsigned int SPI1_Read(void)
{
SPI1BUF=0xFF; //if SPI1BUF=0x00; as it was in the spi lib it doesn' work
while(!SPI1STATbits.SPIRBF);
SPI1STATbits.SPIROV = 0;
if(SPI1CON1bits.MODE16) {
return SPI1BUF;
}else{
return SPI1BUF&0xff;
}
}
/*
*/
void SPI1_Write(unsigned int data)
{
if(SPI1CON1bits.MODE16) {
SPI1BUF=data;
}else{
SPI1BUF=data&0xff;
}
while(SPI1STATbits.SPITBF);
data=SPI1BUF;
}
/*-----------------------------------------------------------------------*/
/* Wait for card ready */
/*-----------------------------------------------------------------------*/
static
BYTE wait_ready (void)
{
BYTE res;
Timer2 = 50; /* Wait for ready in timeout of 500ms */
SPI1_Read();
do
res = SPI1_Read();
while ((res != 0xFF) && Timer2);
return res;
}
/*
*/
void CloseSPI1(void)
{
//SELECT(); /* Wait for card ready */
//wait_ready();
//DESELECT();
//SPI1_Read();
//Disable the Interrupt bit in the Interrupt Enable Control Register
IEC0bits.SPI1IE=0;
//Disable the module. All pins controlled by PORT Functions
SPI1STATbits.SPIEN=0;
//Disable the Interrupt flag bit in the Interrupt Flag Control Register
IFS0bits.SPI1IF=0;
//Stat |= STA_NOINIT; /* Set STA_NOINIT */
}
/*-----------------------------------------------------------------------*/
/* Receive a data packet from MMC */
/*-----------------------------------------------------------------------*/
static
BOOL rcvr_datablock (
BYTE *buff, /* Data buffer to store received data */
uint16 btr /* Byte count (must be even number) */
)
{
BYTE token;
Timer1 = 10;
do { /* Wait for data packet in timeout of 100ms */
token = SPI1_Read();
} while ((token == 0xFF) && Timer1);
if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */
do { /* Receive the data block into buffer */
*buff++ = SPI1_Read();
*buff++ = SPI1_Read();
} while (btr -= 2);
SPI1_Read(); /* Discard CRC */
SPI1_Read();
return TRUE; /* Return with success */
}
/*-----------------------------------------------------------------------*/
/* Send a data packet to MMC */
/*-----------------------------------------------------------------------*/
#if _READONLY == 0
static
BOOL xmit_datablock (
const BYTE *buff, /* 512 byte data block to be transmitted */
BYTE token /* Data/Stop token */
)
{
BYTE resp, wc;
if (wait_ready() != 0xFF)return FALSE;
SPI1_Write(token); /* Xmit data token */
if (token != 0xFD) { /* Is data token */
wc = 0;
do { /* Xmit the 512 byte data block to MMC */
SPI1_Write(*buff++);
SPI1_Write(*buff++);
} while (--wc);
SPI1_Write(0xFF); /* CRC (Dummy) */
SPI1_Write(0xFF);
//resp = SPI1_Read(); /* Reveive data response */
/********************************************************************************
This is the part that's causing the trouble
I don't know yet what's the downside of commenting it
but it works for now.
********************************************************************************/
SPI1_Read();
//if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
//{
// _LATD0 = 1; //debug
// return FALSE;
//}
}
return TRUE;
}
#endif /* _READONLY */
/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC */
/*-----------------------------------------------------------------------*/
static
BYTE send_cmd (
BYTE cmd, /* Command byte */
DWORD arg /* Argument */
)
{
BYTE n, res;
if (wait_ready() != 0xFF) return 0xFF;
/* Send command packet */
SPI1_Write(cmd); /* Command */
SPI1_Write((BYTE)(arg >> 24)); /* Argument[31..24] */
SPI1_Write((BYTE)(arg >> 16)); /* Argument[23..16] */
SPI1_Write((BYTE)(arg >> 8)); /* Argument[15..8] */
SPI1_Write((BYTE)arg); /* Argument[7..0] */
n = 0;
if (cmd == CMD0) n = 0x95; /* CRC for CMD0(0) */
if (cmd == CMD8) n = 0x87; /* CRC for CMD8(0x1AA) */
SPI1_Write(n);
/* Receive command response */
if (cmd == CMD12) SPI1_Read(); /* Skip a stuff byte when stop reading */
n = 10; /* Wait for a valid response in timeout of 10 attempts */
do
res = SPI1_Read();
while ((res & 0x80) && --n);
return res; /* Return with the response value */
}
/*
static
int chk_power(void)
{
return (PORTE & 0x80) ? 0 : 1;
}
*/
/*-----------------------------------------------------------------------*/
/* Public Functions */
/*-----------------------*/
/* Initialize Disk Drive */
/* (Platform dependent) */
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0) */
)
{
BYTE n, f, ocr[4];
DESELECT(); /* CS = H */
//start with slow clk
SPI1CON1bits.SPRE2=1; //2:1 Fcy=40MHz DOZE 1:1 312KHz
SPI1CON1bits.SPRE1=1;
SPI1CON1bits.SPRE0=0;
SPI1CON1bits.PPRE1=0; //64:1
SPI1CON1bits.PPRE0=0;
IFS0bits.SPI1IF = 0; //Clear SPI1 Interrupt Flag
SPI1STATbits.SPIROV = 0; //No Receive Overflow Has Occurred
SPI1STATbits.SPIEN = 1; //Enable SPI Module
for (Timer1 = 1; Timer1; ); /* Wait for 10ms */
//Done by SPI1STAT.SPIEN
// TRISFbits.TRISF6=0; //Output RF6/SCK1
// TRISFbits.TRISF7=1; //Input RF7/SDI1_E
// TRISFbits.TRISF8=0; //Output RF8/SDO1_E
if (drv) return STA_NOINIT; /* Supports only single drive */
if (Stat & STA_NODISK) return Stat; /* No card in the socket */
for (n = 10; n; n--) /* 80 dummy clocks */
SPI1_Read();
SELECT(); /* CS = L */
f = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
Timer1 = 100; /* Initialization timeout of 1000 msec */
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
for (n = 0; n < 4; n++)
ocr[n] = SPI1_Read();
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
do {
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0)
break;
} while (Timer1);
if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit */
for (n = 0; n < 4; n++)
ocr[n] = SPI1_Read();
f = (ocr[0] & 0x40) ? 3 : 1;
}
}
} else { /* SDC Ver1 or MMC */
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) f = 4; /* SDC? */
do {
if (!f && send_cmd(CMD1, 0) == 0) break; /* for MMC */
if ( f && send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0) break; /* for SDC Ver1 */
} while (Timer1);
if (Timer1) f = 1;
}
if (f == 1 && send_cmd(CMD16, 512) != 0) /* Select R/W block length */
f = 0;
}
DESELECT(); /* CS = H */
SPI1_Read(); /* Idle (Release DO) */
if (f & 1) { /* Initialization succeded */
BlkAddr = (f & 2) ? 1 : 0; /* Get addressing mode */
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
//Stat = 0;
//speed up spi clk
SPI1CON1bits.SPRE2=1; //1:1 Fcy=40MHz DOZE 1:1 10MHz
SPI1CON1bits.SPRE1=1;
SPI1CON1bits.SPRE0=1;
SPI1CON1bits.PPRE1=1; //4:1
SPI1CON1bits.PPRE0=0;
//cls();
//prints("MMC Initialized\n");
}
else
{
//cls();
//prints("Not Found"); //power_off();
CloseSPI1();
}
return Stat;
}
/*--------------------*/
/* Return Disk Status */
DSTATUS disk_status (
BYTE drv /* Physical drive nmuber (0) */
)
{
//if (drv) return STA_NOINIT; /* Supports only single drive */
//return Stat;
return (drv) ? STA_NODISK : Stat;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
DWORD sector, /* Start sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
if (drv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (!BlkAddr) sector *= 512; /* Convert to byte address if needed */
SELECT(); /* CS = L */
if (count == 1) { /* Single block read */
if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
&& rcvr_datablock(buff, 512))
count = 0;
}
else { /* Multiple block read */
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
do {
if (!rcvr_datablock(buff, 512)) break;
buff += 512;
} while (--count);
send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
}
}
DESELECT(); /* CS = H */
SPI1_Read(); /* Idle (Release DO) */
return (count ? RES_ERROR : RES_OK);
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0) */
const BYTE *buff, /* Pointer to the data to be written */
DWORD sector, /* Start sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
if (drv || !count) return RES_PARERR;
if (Stat & STA_PROTECT) return RES_WRPRT;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (!BlkAddr) sector *= 512; /* Convert to byte address if needed */
SELECT(); /* CS = L */
if (count == 1) { /* Single block write */
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
&& xmit_datablock(buff, 0xFE))
count = 0;
}
else{ /* Multiple block write */
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
do {
if (!xmit_datablock(buff, 0xFC)) break;
buff += 512;
} while (--count);
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
count = 1;
}
}
DESELECT(); /* CS = H */
SPI1_Read(); /* Idle (Release DO) */
return (count ? RES_ERROR : RES_OK);
//return (count ? RES_OK : RES_ERROR);
}
#endif /* _READONLY */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
BYTE n, csd[16];
WORD csize;
if (drv) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
SELECT(); /* CS = L */
res = RES_ERROR;
switch (ctrl) {
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
n = csd[0] >> 6;
switch (n) {
case 0 : /* CSD ver 1.XX */
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
*(DWORD*)buff = (DWORD)csize << (n - 9);
res = RES_OK;
break;
case 1 : /* CSD ver 2.00 */
csize = csd[9] + ((WORD)csd[8] << 8) + 1;
*(DWORD*)buff = (DWORD)csize << 10;
res = RES_OK;
break;
}
}
break;
case GET_SECTOR_SIZE : /* Get sectors on the disk (WORD) */
*(WORD*)buff = 512;
res = RES_OK;
break;
case CTRL_SYNC : /* Make sure that data has been written */
if (wait_ready() == 0xFF)
res = RES_OK;
break;
case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
if ((send_cmd(CMD9, 0) == 0) /* READ_CSD */
&& rcvr_datablock(buff, 16/2))
res = RES_OK;
break;
case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
if ((send_cmd(CMD10, 0) == 0) /* READ_CID */
&& rcvr_datablock(buff, 16/2))
res = RES_OK;
break;
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
for (n = 0; n < 4; n++)
*((BYTE*)buff+n) = SPI1_Read();
res = RES_OK;
}
break;
default:
res = RES_PARERR;
}
DESELECT(); /* CS = H */
SPI1_Read(); /* Idle (Release DO) */
return res;
}
/*---------------------------------------*/
/* Device timer interrupt procedure */
/* This must be called in period of 10ms */
/* (Platform dependent) */
void disk_timerproc (void)
{
static BYTE pv;
BYTE n, s;
n = Timer1; /* 100Hz decrement timer */
if (n) Timer1 = --n;
n = Timer2;
if (n) Timer2 = --n;
n = pv;
pv = SOCKPORT & ( SOCKWP | SOCKINS); // Sample socket switch
if (n == pv) { // Have contacts stabled?
s = Stat;
if (pv & SOCKWP) // WP is H (write protected)
s |= STA_PROTECT;
else // WP is L (write enabled)
s &= ~STA_PROTECT;
if(pv & SOCKINS) // INS = H (Socket empty)
s |= (STA_NODISK | STA_NOINIT);
else // INS = L (Card inserted)
s &= ~STA_NODISK;
Stat = s;
}
}
FILINFO finfo;
BYTE linebuf[80]; /* Console input buffer */
FATFS fatfs; /* File system object for each logical drive */
BYTE Buff[512]; /* Working buffer */
int main(void)
{
uint16 i, j;
char tmp;
uint8 index;
WORD s1, size, cnt;
// DIR dir; /* Directory object */
//FATFS *fs;
FIL file1;// file2; /* File object */
setup(); //Ports, Pheriperal Configuration
prints("MMC TEST\n");//prints to LCD
(WORD) disk_initialize(0); //initialized MMC/SPI
//xprintf("\r\nSerial Comm");
//xprintf("\r\nTiny_FatFs module test monitor");
/*
for(i = 0; i<512; i++)
{
Buff[i] = 'x';
}
*/
memset(Buff,0,sizeof(Buff));
put_rc(disk_status(0));
put_rc(f_mount(0, &fatfs));
//put_rc(disk_write(0,Buff,400,1));
//put_rc(f_mkdir("FIL1"));
//put_rc(f_opendir(&dir, "DISK"));
//put_rc(f_open(&file1, "dstfile.dat", FA_CREATE_NEW));
//put_rc(f_open(&file1, "TXTFIL/tfile1.txt", FA_CREATE_NEW | FA_READ |FA_WRITE ));
//put_rc(f_write(&file1,Buff,32,&s1));
// Close all files
// f_close(&file1);
put_rc( f_stat("readme.txt", &finfo));
size = &finfo.fsize;
put_rc( f_open(&file1, "readme.txt", FA_OPEN_EXISTING | FA_READ));
for(j=1; j<1024; j++)//for(j=1; j<sizeof(size) ; j++)
{
f_read(&file1, &tmp,1, &cnt);
switch(tmp)
{
case 0x0D : xprintf("\r\n%s", Buff);
memset(Buff,0,sizeof(Buff));
index = 0;
Delay_Ms(100);
break;
default : Buff[index] = tmp;
index++; break;
}
}
f_close(&file1);
f_mount(0,NULL);
while(1)
{
//LCD Real Time Clock
if ( rtc_lcd_update )
{
Update_LCD(); rtc_lcd_update = 0;
}
}
return 0;
}//main~
size = finfo.fsize;
for(j=1; j<sizeof(size); j++)
size = finfo.fsize;
for(j=1; j<size; j++)
picnoobie said:Just wanted to let you guys know that I succesfully read
a text file. but I cant get the file size.
If I can get the file size I could read it from start to end,
right now I had it hardcoded just to get something.
heres my test main:
Code:FILINFO finfo; BYTE linebuf[80]; /* Console input buffer */ FATFS fatfs; /* File system object for each logical drive */ BYTE Buff[512]; /* Working buffer */
Code:int main(void) { uint16 i, j; char tmp; uint8 index; WORD s1, size, cnt; // DIR dir; /* Directory object */ //FATFS *fs; FIL file1;// file2; /* File object */ setup(); //Ports, Pheriperal Configuration prints("MMC TEST\n");//prints to LCD (WORD) disk_initialize(0); //initialized MMC/SPI //xprintf("\r\nSerial Comm"); //xprintf("\r\nTiny_FatFs module test monitor"); /* for(i = 0; i<512; i++) { Buff[i] = 'x'; } */ memset(Buff,0,sizeof(Buff)); put_rc(disk_status(0)); put_rc(f_mount(0, &fatfs)); //put_rc(disk_write(0,Buff,400,1)); //put_rc(f_mkdir("FIL1")); //put_rc(f_opendir(&dir, "DISK")); //put_rc(f_open(&file1, "dstfile.dat", FA_CREATE_NEW)); //put_rc(f_open(&file1, "TXTFIL/tfile1.txt", FA_CREATE_NEW | FA_READ |FA_WRITE )); //put_rc(f_write(&file1,Buff,32,&s1)); // Close all files // f_close(&file1); put_rc( f_stat("readme.txt", &finfo)); size = &finfo.fsize; put_rc( f_open(&file1, "readme.txt", FA_OPEN_EXISTING | FA_READ)); for(j=1; j<1024; j++)//for(j=1; j<sizeof(size) ; j++) { f_read(&file1, &tmp,1, &cnt); switch(tmp) { case 0x0D : xprintf("\r\n%s", Buff); memset(Buff,0,sizeof(Buff)); index = 0; Delay_Ms(100); break; default : Buff[index] = tmp; index++; break; } } f_close(&file1); f_mount(0,NULL); while(1) { //LCD Real Time Clock if ( rtc_lcd_update ) { Update_LCD(); rtc_lcd_update = 0; } } return 0; }//main~
I'd greatly appreciate any help on the file size.
(you might need to visit the link I posted above to see the files)
thanks.
[/code]
EDIT:
never mind, I figured it out.
i was doing it like:
Code:size = finfo.fsize; for(j=1; j<sizeof(size); j++)
which should be:
Code:size = finfo.fsize; for(j=1; j<size; j++)
it works nicely now.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?