View previous topic :: View next topic |
Author |
Message |
epideath
Joined: 07 Jun 2006 Posts: 47
|
MMC Read Token Error |
Posted: Wed Jun 14, 2006 8:30 pm |
|
|
Hi all,
I'm having a weird problem when trying to read from my MMC card.
The command is accepted without problem every time. But after the command the MMC card will respond with 0xFE normally to let you know that the data is going to be sent next. This code in CCS works randomly and not very often. It seems like some sort of timing issue, but just not sure. Initializing and writing works every time.
I've also attached a code snippet from MCC18. This code works on the same exact hardware every single time.
I'm really starting to pull my hair out over this one. I feel that I am just so blurry eyed that I'm missing something very simple.
I've looked at every code example I can find here or on the internet. It all looks basically the same as what I have.
I'm using a 18F4520 running with the internal osc set at 8MHz.
I have tried this code with or without Interrupts on and there is no difference. The MCC18 code works with the interrupts on.
Well an ideas would be greatly appreciated.
Thanks all,
Gary
This is my SPI setup call: setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_64|SPI_SAMPLE_AT_END);
and for MCC18 it is: OpenSPI(SPI_FOSC_64, MODE_00, SMPEND);
CCS Code
Code: |
r1 = MMC_Command(17, addr);
for(to=0;to<1024;to++){
r1=SPI_READ(0xFF);
if (r1==0x00) goto ReadToken; // read token $FE
}
goto ReadError;
ReadToken:
for(to=0;to<1024;to++){
r1=SPI_READ(0xFF);
//Errors here almost always
if (r1==0xFE) goto ReadData; // read token $FE
}
goto ReadError;
/*** Begins reading data here. ***/
|
MCC18 Code
Code: |
char ReadMMC(void) // send 512 bytes from the MMC via the serial port
{
unsigned int i;
char r1;
char str[5] = " ";
PORTCbits.RC7 = 0; // MMC-Enabled
// 512 byte-read-mode
r1 = Command(0x51,0,512,0xFF);
read_retry:
if(r1 != 0) {
r1 = SPI(0xFF);
LCD_putrs(0,6, NORMAL, "Read Error 1");
goto read_retry;
}
LCD_putrs(0,7, NORMAL, "Wait Read Start");
//This one never fails with the MCC18 code
while(SPI(0xFF) != 0xFE); // wait for 0xFE - start of any transmission
LCD_putrs(0,8, NORMAL, "Reading:");
|
|
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Wed Jun 14, 2006 9:15 pm |
|
|
They are implmented differently. The "working" implementaiton in MCC18 case is sloppy. If something is wrong with the card it will never return.
In your non working implementation the card is not responding fast enough. Try increasing the for loop to 10000 iterations and see what happens. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
epideath
Joined: 07 Jun 2006 Posts: 47
|
|
Posted: Wed Jun 14, 2006 10:29 pm |
|
|
I have tried implementing it the same way as the MCC18 code. with no error checking. it will never get out of the while loop. well at least after several seconds. |
|
|
Kenny
Joined: 07 Sep 2003 Posts: 173 Location: Australia
|
|
Posted: Wed Jun 14, 2006 11:29 pm |
|
|
The spi mode should be spi mode 3.
If using the CCS setup SPI_H_TO_L | SPI_XMIT_L_TO_H
Also leave out the SPI_SAMPLE_AT_END.
Did you try the PCM Programmer's translation of the code in this thread?
http://www.ccsinfo.com/forum/viewtopic.php?t=23183
It works, and there is no need to use the CCS spi setup.
Edited:
I had a problem with one card, a Sandisk RS-MMC 512MB. The response token occurred one time slot later. To get it to work I had to add another SPI(0xFF). The specification indicates that the response can be delayed from one to eight bytes, so I loop up to eight times outputting SPI(0xFF) until the response is not 0xFF.
Last edited by Kenny on Tue Sep 26, 2006 4:31 pm; edited 3 times in total |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Jun 15, 2006 2:39 am |
|
|
Quote: | The spi mode should be spi mode 3. | Both SPI mode 0 and 3 are allowed.
Quote: | Also leave out the SPI_SAMPLE_AT_END. | I agree with this. Many times in this forum I've seen code using this parameter, but the MMC specification mentions specifically that data must always be sampled on the rising edge of the clock. |
|
|
epideath
Joined: 07 Jun 2006 Posts: 47
|
|
Posted: Thu Jun 15, 2006 9:40 am |
|
|
OK I finally figured this out.
After finally discoverying where in the MMC datasheet it explains the Read Token. I noticed I was getting a code 0x08 (Out of range). So then the light went off and I took a look at my address being sent. Lo and behold it was some crazy number.
I looked at my code and noticed that I wasn't typecasting to Int32 as required for the MMC card. So fixed that and all is working.
But I also noticed something strange. This is a C issue and I guess I'm a little weak when it comes to typecasting things.
This works correctly I get 0x00 back. addr = (int32) block*512; where block is an int16.
This one responds back with a strange number (1862270976) I assume something random because addr is not getting allocated right. addr=(int32) 512*block;
Can anyone explain why it matters if I multiply a constant to the variable vs multiplying the varible to a constant.
What is the correct format for typecasting this code would it be (int32)(512*block);
Thanks for all the help,
Gary |
|
|
emresensoy
Joined: 27 Dec 2008 Posts: 2
|
Big Card read problem |
Posted: Sun Dec 28, 2008 4:28 am |
|
|
Hi to everyone,
I use this code with 18f452 with 1gb sd, 128 mb sd and 64 mb sd card,
and everything is ok,
it means with 128mb sd card
pic reads every file, address etc
But with 1gb sd card if a file data is at address like 29589000h
the open_file routine works, there is no problem, but the file_read
routine doesn't work.
Code: |
if (read_BLOCK(address,buff)==false) return(12);
|
This line returns 12 and not read.
I think the problem is at read_block command with this:
Code: | read_block(0x29589000,buff); |
buff stayed still clear, nothing is read.
Is there anyone to help me about this ?
Sorry for bad english. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Dec 28, 2008 10:59 am |
|
|
I haven't used this driver. But, I suggest that you try to find if the
problem occurs at a specific Hex address boundary. For example,
don't use an arbitrary address such as 0x29589000. Instead, test it
at 0x1FFFFFFF and then at 0x20000000. See if it fails when it crosses
that address boundary. If it fails at both those addresses, then test it
at a lower boundary. Continue testing until you find the maximum
address for successful operation. This will give you an important clue
to solve the problem. |
|
|
|