CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

MMC Read Block Issue

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
arunkish



Joined: 23 Dec 2008
Posts: 83

View user's profile Send private message

MMC Read Block Issue
PostPosted: Wed Feb 20, 2013 9:58 pm     Reply with quote

Hello,
I have found the following code from forum and modified to write 1024 bytes to MMC, For testing purpose I have written it within the main function calling twice to execute command 0x58. I can see that all the 1024 bytes are written to the MMC, but I do get "Write Error 2" in hyperterminal when the i call command 0x58 for the second time. Why do i get the error and what mistake am i making ?

Code:

#include <16F877.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#use fast_io(C)

#byte SSPBUF = 0x13
#byte SSPCON = 0x14
#byte SSPSTAT = 0x94
#bit  BF = SSPSTAT.0
#bit SMP = SSPSTAT.7
#bit CKE = SSPSTAT.6
#bit CKP = SSPCON.4
#bit SSPM1 = SSPCON.1
#bit SSPEN = SSPCON.5

#byte PORTC = 7
#bit CS = PORTC.2       


//int mmc_init();
int mmc_response(unsigned char response);
//int mmc_read_block(unsigned long block_number);
int mmc_write_block(unsigned long block_number);
//int mmc_get_status();


//****************************************
// This is the same as the CCS spi_read() function.

char SPI(char d)       
{             
SSPBUF=d;
while (!BF);         
return SSPBUF;         
}

//******************************************

char Command(char befF, int16 AdrH, int16 AdrL, char befH)
{             
SPI(0xFF);
SPI(befF);
SPI(AdrH >> 8);
SPI(AdrH);
SPI(AdrL >> 8);
SPI(AdrL);
SPI(befH);
SPI(0xFF);
return SPI(0xFF);      // Return with the response
}
//********************************************

char MMC_Init()
{
char i;   

// Init SPI
SMP=0;       
CKE=0;       
CKP=1;       
SSPM1=1;       
//SSPM0=1;   
SSPEN=1;     

CS=1;      // MMC-Disabled

// MMC in SPI Mode -- start and Reset.
for(i=0; i < 10; i++) SPI(0xFF);             // 10*8=80 clocks
CS=0;                                             // MMC-Enabled

// CMD0
if (Command(0x40,0,0,0x95) !=1) goto Error;    // Reset

st:
// CMD1             
if (Command(0x41,0,0,0xFF) !=0) goto st ;   // CMD1 

return 1;

Error:
return 0;
}
//*********************************************

void main(void)
{
int16 i;
char ar;           
setup_port_a(NO_ANALOGS);
set_tris_c(0b11010011);    // sck rc3-0, sdo rc5-0, CS rc2-0.
set_tris_b(0b00000010); 


puts("Start\n\r");               
if(MMC_Init())
   puts("MMC ON\n\r");       // MMC Init OK



//*****************************************


// Write Block
OUTPUT_LOW(PIN_C2);
if (Command(0x58,0,512,0xFF) !=0) puts("Write error ");
SPI(0xFF);
SPI(0xFF);
SPI(0xFE);

SPI("Begin\n\r");   // 7 characters
   
for(i=0; i < 500; i++)   // Was 512, but used 12 for text
   {
   SPI('A');
   }
SPI("\n\rEnd");   // 5 characters


SPI(255);       // Send two bytes of 0xFF at the end
SPI(255);
//i=SPI(0xFF);
//i &=0b00011111;
//if (i != 0b00000101) puts("Write Error ");
//while(SPI(0xFF) !=0xFF); // Wait for end of Busy condition

if((SPI_READ(0xFF)&0x0F)!=0x05) puts("Write ERROR\n\r");;

puts("Write Ok\n\r");










// Write Block
OUTPUT_LOW(PIN_C2);

if (Command(0x58,0,1024,0xFF) !=0) puts("Write error 2 ");
SPI(0xFF);
SPI(0xFF);
SPI(0xFE);

SPI("Begin\n\r");   // 7 characters
   
for(i=0; i < 500; i++)   // Was 512, but used 12 for text
   {
   SPI('R');
   }
SPI("\n\rEnd");   // 5 characters


SPI(255);       // Send two bytes of 0xFF at the end
SPI(255);

if((SPI_READ(0xFF)&0x0F)!=0x05) puts("Write ERROR\n\r");;
puts("Write Ok\n\r");





while(1);       // The program stops here.             
}

Ttelmah



Joined: 11 Mar 2010
Posts: 19383

View user's profile Send private message

PostPosted: Thu Feb 21, 2013 3:09 am     Reply with quote

Retch. Messy code....
Tidy code is easier for everybody.

However obvious thing is your write. It _needs_ to write the block size of the card. (512bytes). You can't change to 500, or '12bytes for testing'. The command won't complete.

Why use the CCS function in some places, and a replacement function in others?. Use one or the other.

Best Wishes
arunkish



Joined: 23 Dec 2008
Posts: 83

View user's profile Send private message

PostPosted: Thu Feb 21, 2013 5:03 am     Reply with quote

Thank you for your reply. I know that the code is a mess. I wanted to give a try on it first, anyway as you said it did not work. I am looking for an example code that would work on 16F877A or 18F4620. Write Block and Read Block would be fine. I was searching for the code for a long time and unable to find the right one that is working. Can you please help me with an example if you have.
Ttelmah



Joined: 11 Mar 2010
Posts: 19383

View user's profile Send private message

PostPosted: Thu Feb 21, 2013 5:14 am     Reply with quote

mmc_spi.c, is a complete driver.
The big problem you are going to have, is that your chip does not have enough RAM for a block buffer. MMC, _requires_ data to be read/written in blocks. You are not going to get very far, unless you have a buffer large enough to hold a block.....
The MMC driver requires a 512byte buffer.

Best Wishes
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Feb 21, 2013 9:09 am     Reply with quote

Ttelmah wrote:
mmc_spi.c, is a complete driver.
The big problem you are going to have, is that your chip does not have enough RAM for a block buffer. MMC, _requires_ data to be read/written in blocks. You are not going to get very far, unless you have a buffer large enough to hold a block.....
The MMC driver requires a 512byte buffer.

Best Wishes


Slight correction. Writes must be performed in 512 byte blocks. It is possible to read as little as a single byte at a time. When modifying even a single byte on the media, you must read the appropriate block into RAM, modify the byte of interest, then write out the 512 byte block to the media.

Don't wast you time on a PIC16F processor for this type of application, use a PIC18F4620 or similar.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19383

View user's profile Send private message

PostPosted: Thu Feb 21, 2013 9:45 am     Reply with quote

Agreed.

Use the 4620, if this is available, and the standard drivers.

Best Wishes
arunkish



Joined: 23 Dec 2008
Posts: 83

View user's profile Send private message

PostPosted: Thu Feb 21, 2013 8:04 pm     Reply with quote

Thank you all again. I am going to give a try with 18F4620 with mmc_spi.c . I will keep you updated.
arunkish



Joined: 23 Dec 2008
Posts: 83

View user's profile Send private message

PostPosted: Thu Feb 21, 2013 8:28 pm     Reply with quote

I am working with mmc_spi.c, but it is failing to initialize. Crying or Very sad Changed PIC to 18F4620.

Code:

#include <18f4620.h>

#fuses HS, NOLVP, NOPROTECT, NOWDT, BROWNOUT, NOPUT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
//#use fast_io(C)
//#use fast_io(A)

//#define MMC_CLK    PIN_C3 //o
//#define MMC_DI     PIN_C4 //i
//#define MMC_DO     PIN_C5 //o
//#define MMC_CS  PIN_C2 //o

#include "mmc_Spi.c"
#byte TRISC = 0xf94
#byte PORTC = 0xf82
#byte TRISA = 0xf92
#byte PORTA = 0xf80


void main(void)
{
  byte testchar;
  printf("\n\rStarting CARD\n\r");

  set_tris_c(0b11010011);
  output_high(MMC_CS);

  if(mmc_init()==0)puts ("all ok");
  else
  puts("error");
 
  while(1);

}
arunkish



Joined: 23 Dec 2008
Posts: 83

View user's profile Send private message

PostPosted: Thu Feb 21, 2013 8:53 pm     Reply with quote

Sorry for writing again... Still no luck with what I am trying. Kindly help on this.

Code:

#include <18f4620.h>

#fuses HS, NOLVP, NOPROTECT, NOWDT, BROWNOUT, NOPUT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use fast_io(C)
#use fast_io(A)


#define MMC_CLK     PIN_C3
#define MMC_DI      PIN_C5
#define MMC_DO      PIN_C4
#define MMC_CS      PIN_C2

#include "mmc_Spi.c"
#byte TRISC = 0xf94
#byte PORTC = 0xf82
#byte TRISA = 0xf92
#byte PORTA = 0xf80


void main(void)
{
  byte testchar;
  printf("\n\rStarting CARD\n\r");

  set_tris_c(0b11010011);
  output_high(MMC_CS);

  if(mmc_init()==0)puts ("all ok");
  else
  puts("error");
 
  while(1);

}


MMC_SPI.C declarations:

Code:

//SanDisk’s MultiMediaCards clock data in on the rising edge and out on the falling edge.
#ifndef MMC_CLK
#define MMC_CLK   PIN_C3
#endif
#ifndef MMC_DI
#define MMC_DI    PIN_C5
#endif
#ifndef MMC_DO
#define MMC_DO    PIN_C4
#endif
#ifndef MMC_CS
#define MMC_CS    PIN_C2
#endif


Connections made between PIC and MMC CARD PINS are as follows:

MMC_CLK >> PIN_C3
MMC_DI >> PIN_C5
MMC_DO >> PIN_C4
MMC_CS >> PIN_C2

Voltage Conversion from 5V to 3.3 has also been done for the required PINS.
Ttelmah



Joined: 11 Mar 2010
Posts: 19383

View user's profile Send private message

PostPosted: Fri Feb 22, 2013 2:11 am     Reply with quote

How?.....

On the 'voltage conversion'?.

This is the commonest problem. A _lot_ of the example layouts, posted on the web, _do not work_.

If using resistive dividers, these need quite low values to work successfully at SPI clock rates.
Going the other way, a lot of people show signals fed from 3.3v SPI directly into PIC inputs. This will _only_ work if you are using a pin on the PIC that supports TTL input thresholds. An increasing number of pins don't. The hardware SPI pins don't. You need a buffer chip otherwise.
Remember the pull-up connections. These are _required_ for the chip to wake up correctly (it takes more time for a PIC to wake than the SPI I/O circuitry, and the clock line in particular _must_ be high when the chip wakes).
You need a really good decoupling capacitor close to the card. The current surges from these can be 'surprising'.

Asmallri on the Brush electronics site, has some example circuit layouts.

Seriously, the 5 to 3.3v conversion, is the part that is wrong 99.9% of the time.

Best Wishes
arunkish



Joined: 23 Dec 2008
Posts: 83

View user's profile Send private message

PostPosted: Fri Feb 22, 2013 9:43 pm     Reply with quote

Agreed with you 100%. I will work accordingly. But before that, I was trying to make it work and Initialized successfully. Read and Write blocks also works without problem. But I am facing a little difficulty with the write block function. The problem is that I am able to write only up to 0 - 63 blocks. ie. 32765 bytes and cannot go more than that.

Code:

void write_block(int32 block_num)
{
unsigned long int varl,varh;
unsigned long int i,varh1,varh2,varl1,varl2;


OUTPUT_LOW(PIN_C2);

varl=((block_num & 0x003F)<<9);
varh=((block_num & 0xFFC0)>>7);
varh1=varh>>0x08;
varh2=varh &0xFF;
varl1=varl>>0x08;
varl2=varl&0xFF;

if(mmc_send_cmd(0x58, varh1,varh2,varl1, varl2, 0xFF)!=0) puts("Write Command error ");
 
SPI(0xFF);
SPI(0xFF);
SPI(0xFE);


   
for(i=0; i < 512; i++) 
   {
    SPI('Q');
   }


SPI(0xFF);       
SPI(0xFF);

i=SPI(0xFF);
i &=0b00011111;
if (i != 0b00000101) puts("Write Error ");
while(SPI(0xFF) !=0xFF); // Wait for end of Busy condition

OUTPUT_HIGH(PIN_C2);
puts("Write Ok\n\r");

}



char mmc_send_cmd(int8 cmd, int8 arg1, int8 arg2, int8 arg3, int8 arg4, int8 crc)
{
   SPI(0xFF);
   SPI(cmd);
   SPI(arg1);
   SPI(arg2);
   SPI(arg3);
   SPI(arg4);
   SPI(crc);
   SPI(0xFF);
return SPI(0xFF);
}


and the code I call to write blocks ......... If i set the max value to anything greater than 63, it never goes beyond the 63 blocks.

Code:

for(l=1;l<=127;l++)
{
write_block(l);
}


Please advice on what I am missing.....
Ttelmah



Joined: 11 Mar 2010
Posts: 19383

View user's profile Send private message

PostPosted: Sat Feb 23, 2013 2:08 am     Reply with quote

Variable size......

A 'long int', in CCS, is an int16. You need to be using int32 values to hold the address. You are in the function declaration, but then the internal variables are int16.

Always be explicit in CCS (and every other C!). It is much safer to use declarations like 'unsigned int32', rather than 'unsigned long'. The latter will have different meanings on different chips. The declaration for an int32 (if you must use the 'long' naming), is 'unsigned long long'.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group