| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| arunkish 
 
 
 Joined: 23 Dec 2008
 Posts: 83
 
 
 
			    
 
 | 
			
				| MMC Read Block Issue |  
				|  Posted: Wed Feb 20, 2013 9:58 pm |   |  
				| 
 |  
				| 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: 19962
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Feb 21, 2013 3:09 am |   |  
				| 
 |  
				| 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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Feb 21, 2013 5:03 am |   |  
				| 
 |  
				| 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: 19962
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Feb 21, 2013 5:14 am |   |  
				| 
 |  
				| 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: 1660
 Location: Perth, Australia
 
 
			        
 
 | 
			
				|  |  
				|  Posted: Thu Feb 21, 2013 9:09 am |   |  
				| 
 |  
				|  	  | 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: 19962
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Feb 21, 2013 9:45 am |   |  
				| 
 |  
				| Agreed. 
 Use the 4620, if this is available, and the standard drivers.
 
 Best Wishes
 |  |  
		|  |  
		| arunkish 
 
 
 Joined: 23 Dec 2008
 Posts: 83
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Feb 21, 2013 8:04 pm |   |  
				| 
 |  
				| 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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Feb 21, 2013 8:28 pm |   |  
				| 
 |  
				| I am working with mmc_spi.c, but it is failing to initialize.  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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Feb 21, 2013 8:53 pm |   |  
				| 
 |  
				| 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: 19962
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Feb 22, 2013 2:11 am |   |  
				| 
 |  
				| 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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Feb 22, 2013 9:43 pm |   |  
				| 
 |  
				| 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: 19962
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Feb 23, 2013 2:08 am |   |  
				| 
 |  
				| 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
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |