"CHaN fatfs" initialization problem: send_cmd (CMD0) returns 0!!

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, I am working with the CHaN fatfs routines for atmega and I have a problem that is driving me crazy.

I have tested the routines with several 4gb kingnston memories, and there are memories with which they work ok and memories with which they do not. Debugging the code, I found that the error occurs in the process of initializing the memory, because "send_cmd (CMD0)" returns 0 instead of 1. Does anyone have any idea where the problem might be? This is the code of the rutine.

Thanks!!
 

DSTATUS disk_initialize (
	BYTE drv		/* Physical drive nmuber (0) */
)
{
	BYTE n, ty, cmd, buf[4];
	UINT tmr;
	DSTATUS s;


	if (drv) return RES_NOTRDY;

	dly_us(10000);			/* 10ms */
	CS_INIT(); CS_H();		/* Initialize port pin tied to CS */
	CK_INIT(); CK_L();		/* Initialize port pin tied to SCLK */
	DI_INIT();				/* Initialize port pin tied to DI */
	DO_INIT();				/* Initialize port pin tied to DO */

	for (n = 10; n; n--) rcvr_mmc(buf, 1);	/* Apply 80 dummy clocks and the card gets ready to receive command */

	ty = 0;
	if (send_cmd(CMD0, 0) == 1) {			/* Enter Idle state */
		if (send_cmd(CMD8, 0x1AA) == 1) {	/* SDv2? */
			rcvr_mmc(buf, 4);							/* Get trailing return value of R7 resp */
			if (buf[2] == 0x01 && buf[3] == 0xAA) {		/* The card can work at vdd range of 2.7-3.6V */
				for (tmr = 1000; tmr; tmr--) {			/* Wait for leaving idle state (ACMD41 with HCS bit) */
					if (send_cmd(ACMD41, 1UL << 30) == 0) break;
					dly_us(1000);
				}
				if (tmr && send_cmd(CMD58, 0) == 0) {	/* Check CCS bit in the OCR */
					rcvr_mmc(buf, 4);
					ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;	/* SDv2 */
				}
			}
		} else {							/* SDv1 or MMCv3 */
			if (send_cmd(ACMD41, 0) <= 1) 	{
				ty = CT_SD1; cmd = ACMD41;	/* SDv1 */
			} else {
				ty = CT_MMC; cmd = CMD1;	/* MMCv3 */
			}
			for (tmr = 1000; tmr; tmr--) {			/* Wait for leaving idle state */
				if (send_cmd(cmd, 0) == 0) break;
				dly_us(1000);
			}
			if (!tmr || send_cmd(CMD16, 512) != 0)	/* Set R/W block length to 512 */
				ty = 0;
		}
	}
	CardType = ty;
	s = ty ? 0 : STA_NOINIT;
	Stat = s;

	deselect();

	return s;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What version are you working with?

 

I'm using an older version.  So I thought you would be referring to the latest -- the Web site has version 13.  The disk_initialize looks nothing like yours:

DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat;
	int result;

	switch (pdrv) {
	case DEV_RAM :
		result = RAM_disk_initialize();

		// translate the reslut code here

		return stat;

	case DEV_MMC :
		result = MMC_disk_initialize();

		// translate the reslut code here

		return stat;

	case DEV_USB :
		result = USB_disk_initialize();

		// translate the reslut code here

		return stat;
	}
	return STA_NOINIT;
}

Gotta love the "reslut" typo:  "She used to be pretty loose, but then got married.  After the divorce, it was reslut time..."

 

I must be missing something -- why don't I see e.g. MMC_disk_initialize in the downloaded source?

 

That said, the disk_initialize that I use has substantially the same flow as yours.  But I do slow down the SPI clock rate for disk_initialize...

				if (disk_status(0) & STA_NOINIT)
					{
					// also add checks for PRESENT and WP
					SPCR = SPCR_SD_INIT;
					card_status = disk_initialize(0);
					SPCR = SPCR_SD_RUN;	// return to SD card setup as the default
					}

...where

#define    SPCR_SD_INIT    ((1 << SPE) | (1 << MSTR) | (1 << SPR1))
#define    SPCR_SD_RUN        ((1 << SPE) | (1 << MSTR))

 

 

So my only guess:  Try slowing down your SPI during init.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not sure if it helps but Chan has words about the init sequence under "Initialization Procedure for SPI Mode" on this page in the documentation:

 

http://elm-chan.org/docs/mmc/mmc...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
I do slow down the SPI clock rate for disk_initialize...

ISTR that's important:

clawson wrote:
Chan has words about the init sequence 

 

http://elm-chan.org/docs/mmc/mmc_e.html

On that page, Chan wrote:

Set SPI clock rate between 100 kHz and 400 kHz.