SDCARD Cmd8'e gelen anlamsız yanıt

Başlatan strom, 16 Haziran 2014, 16:10:31

strom

Herkese iyi günler.

STM32F429 ile sdcard'a veri yazma/okuma yapmak stiyorum. Ancak daha init aşamasında tıkandım. İnternette barış samancının ve Z hocamın dökümanlarından yola çıkarak denemelere başladım. CMD0 komutu gönderip 0x1 yanıtını alıyorum. Daha sonra;
CMD8 [0x481AA87] verisini gönderip, [0x01010000AB] verisini alıyorum.
İletişimde veya hatta sorun olup olmadığını kontrol etmek adına gönderiğim veriyi değiştiriyorum. Mesela [0x482AA87]  yapıyorum. Bu sefer 0x9 status değerini gönderiyor (yani checksum error). Yapması gerekende ztn bu. SCARD'ın tanımadığı bir komut gönderiyorum. Bu seferde 0x5 status değerini gönderiyor (illegal cmd). CMD8 komutu dışında herşey çok güzel.
Acaba sorun neyden kaynaklanıyor olabilir??? Birde bu checksum hesabı nasıl yapılıyor. CMD8 komutunun içeriğini değiştiremiyorum crc ayarlayamadığım için.

Z hocamın dökümanı: http://www.cncdesigner.com/wordpress/?p=3609

Kullandığım kodlar;
Spi init:
void SDCARD_Hal_Init()
{
	RCC_APB2PeriphClockCmd(RCC_APB2ENR_SPI1EN, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_GPIOBEN, ENABLE);
	
	GPIO_InitTypeDef gpio;
	gpio.GPIO_Mode = GPIO_Mode_AF;
	gpio.GPIO_OType = GPIO_OType_OD;
	gpio.GPIO_PuPd = GPIO_PuPd_UP;
	gpio.GPIO_Speed = GPIO_Speed_50MHz;
	gpio.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
	GPIO_Init(GPIOB, &gpio);
	gpio.GPIO_Mode = GPIO_Mode_OUT;
	gpio.GPIO_Pin = GPIO_Pin_6;
	GPIO_Init(GPIOB, &gpio);
	
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI1);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI1);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI1);
	
	SPI_InitTypeDef spi;
	spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
	spi.SPI_CPHA = SPI_CPHA_2Edge;
	spi.SPI_CPOL = SPI_CPOL_High;
	spi.SPI_DataSize = SPI_DataSize_8b;
	spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	spi.SPI_FirstBit = SPI_FirstBit_MSB;
	spi.SPI_Mode = SPI_Mode_Master;
	spi.SPI_NSS = SPI_NSS_Soft ;
	spi.SPI_CRCPolynomial = 7;
	SPI_Init(SPI1, &spi);
	SPI1->CR1 |= (1 << 6);
	//SPI_Cmd(SPI1, ENABLE);
	
}


Sdcard:
#include "sdcard.h"
#ifdef SDCARD_DEBUG
	#include <stdio.h>
#endif


#define CMD0	0x40
#define CMD8	0x48

#define SDCARD_LOW_VOLTAGE			(1 << 8)
#define SDCARD_STANDART_VOLTAGE	(2 << 8)

#define SDCARD_PATTERN					(0xaa)

void SDCARD_Cmd(uint8_t cmd, uint32_t arg, uint8_t crc);
void SDCARD_Delay(uint32_t time){ while(time--); }
int8_t SDCARD_Response(uint8_t* response, uint8_t n);


struct R1
{
	unsigned int b1:1;
	unsigned int	 :7;
};

struct R7
{
	/*
	uint8_t  Pattern;
	uint16_t VoltageRange :4;
	uint16_t Reserved;
	uint32_t CmdVersion	:4;
	struct R1	Status;
	*/
	struct R1	Status;
	uint32_t CmdVersion	:4;
	uint16_t Reserved;
	uint16_t VoltageRange :4;
	uint8_t  Pattern;
};




int SDCARD_Init()
{
	uint8_t i = 0, j = 0;
	
	//SDCARD haberlesmesi icin SPI ve GPIO modulu hazirlaniyor
	SDCARD_Hal_Init();
	
	//SPI Mode Enable
	SDCARD_CS_HIGH();
	for(int i = 0; i < 10; i++)
	{
		SPI_Send(0xFF);
	}
	#ifdef SDCARD_DEBUG
	printf("Sdcard SPI Mode is enabled\n");
	#endif	
	
	//SDCARD bundan sonra aktif
	SDCARD_CS_LOW();
	
	//CMD0 gönderilerek Sdcard IDLE moda aliniyor
	SDCARD_Cmd(CMD0, 0, 0x95);
	SPI_Send(0xFF);
	uint8_t data[12];
	//Sdcard'tan CMD0 komutunun cevabi aliniyor. Eger cevap gelmezse fonksiyon sonlaniriliyor
	uint8_t temp;
	j = 0;
	do
	{
		//Eger belli bir sure dogru sonuc olan 0x01 cevabini alamiyorsak init fonksiyonunundan cikiyoruz
		if(j > 6)
		{
			#ifdef SDCARD_DEBUG
			printf("Error: CMD0 not properly responded.\nResponse is: 0x%x", temp);
			#endif
			return temp;
		}
		j++;
		SDCARD_Response((uint8_t*)&temp, 1);
	}while(temp != 0x01);
	
	#ifdef SDCARD_DEBUG
	printf("CMD0 response: 0x%x\n", temp);
	#endif

	
	//CMD8 komutu gonderilerek calisma kosullari bilgisi aliniyor
	SDCARD_Cmd(CMD8, 0x1AA, 0x87);
	if(SDCARD_Response(data, 5) == -1)
	{
		#ifdef SDCARD_DEBUG	
			printf("Error: CMD8 is not responded!!!\n");
		#endif		
		//return -1;
	}
	
	do
	{
		SDCARD_Cmd(0x7a, 0, 1);
		SDCARD_Response(data, 5);
	}while(data[0] != 0);
	SPI_Send(0xFF);
	

	printf("Done\n");
}

int8_t SDCARD_Response(uint8_t* response, uint8_t n)
{
	uint16_t i = 0, j = 0;
	uint8_t temp;
	
	for(i = 0; i < n; i++)
	{
		j = 0;
		do
		{
			if(j > 1000)
			{

				break;
			}
			j++;
			temp = SPI_Send(0xFF);
		}while(temp == 0xFF);
		
		*response = (uint8_t) temp;
		response++;
	}
	SDCARD_CS_HIGH();
	SPI_Send(0xFF);
}

void SDCARD_Cmd(uint8_t cmd, uint32_t arg, uint8_t crc)
{
	SDCARD_CS_LOW();
	SPI_Send(cmd);
	//SDCARD_Delay(100);
	SPI_Send(arg >> 24);
	//SDCARD_Delay(100);
	SPI_Send(arg >> 16);
	//SDCARD_Delay(100);
	SPI_Send(arg >> 8);
	//SDCARD_Delay(100);
	SPI_Send(arg);
	//SDCARD_Delay(100);
	SPI_Send(crc);

		
}

kimlenbu

Sorun şundan mı kaynaklı bir bak :

https://www.picproje.org/index.php/topic,52012.0.html

Eğer sorun çözülmezse stm32f407 Discovery için FatFs'in çalışan proje dosyasını (KEIL) aşağıdaki başlıkta paylaşmıştım. :

https://www.picproje.org/index.php/topic,50534.0.html

strom

Hocam öncelikle çok teşekkürler malesef sorun bundan kaynaklı değil. Çünkü herhangi bir modül kullanmıyorum ve sorunum sizinkine benzemiyor. Vermiş olduğunuz örnek kodkları indirmedim ama sanırım waveshare'ın kütüphanesini paylaşmışsınız. Onlar bende var ve sdcard okumak için kullanılan protokol sdio. O da malesef işime yaramıyor. Birde standart library kullanarak yaptığı için açıklayıcı olmuyor. Yinede çok teşekkür ederim.

Şu an 2gb, 8gb ve 32gb kart var elimde. Hepsinde de CMD8 [0x48 0x00 0x01 0xAA 0x87] koduna karışılık [0x01 0x01 0x00 0x00 0xAB] alıyorum. Acaba voltaj aralıkları mı uygun değil? Bunuda deneyemiyorum çünkü CMD8 komutunun içeriğini değiştirdiğimde CRC alanını nasıl değiştirmem gerektiğini bilmiyorum. Hiç anlamadım CRC hesabından.

z

#3
CMD8 icin 0x01 0x00 0x00 0x01 0xAA cevabi almisim.

Sen CMD8 icin 0x01 0x01 0x00 0x00 0xAB cevabi almissin.

En kucuk bitin ne anlama geldigine baktinmi? Bende bu bit 0 iken sende 1 olmus.

Gelen cevabin anlami icin  aklimda hic bir sey yok. Son byte'in 0xAA yada 0xAB olusu kritik bir durum olmayabilir.

Edit edit edit.

http://www.cncdesigner.com/wordpress/?p=3609 deki notlarima baktimda;

Bu AA, bizim gonderdigimiz kontrol sablonuymus. Dolayisi ile bunu AA olarak geri almamiz lazim.

AB  yollasaydik AB gelmesi lazimdi.

Sorun ne anlamadim. Keske cevap yazmasaymisim.

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

strom

#4
Est. hocam ne demek. Bi yandan sizin dökümanınız, bir yandan SD physical layer specification dökümanı bir yanda keil bir yanda board'um uğraşıp duruyorum. Sizin dökümandaki aynı sıralamada gönderiyorum ama hiçbir zaman sizinkiyle aynı sonuçları elde edemiyorum.
Yalnız cevaplar çokta mantıksız olmuyor. Mesela 2gb kart taktığımda, kartın düşük kapasiteli olduğunu cevaplardan okuyabiliyorum. Ancak kartı hazırlık sürecinden bir türlü çıkartamıyrum. CMD8'de ki olay ise hala muamma

mesaj birleştirme:: 17 Haziran 2014, 01:18:06

Hatta şu kod kümesiyle aldığım kodları bir yazayım;
void SDCARD_InitSequence_v2xx()
{
	uint8_t temp;
	uint8_t data[5];
	do
	{
		SDCARD_Cmd(CMD55, 0, 1);
		SDCARD_Response(data, 5);
	}while(data[0] != 1);	
	printf("CMD55: 0x%x-0x%x-0x%x-0x%x-0x%x\n", data[0], data[1], data[2], data[3], data[4]);	
	do
	{
		SDCARD_Cmd(ACMD41, 0x40000000, 1);
		SDCARD_Response(data, 5);
	}while(data[0] != 1);
	printf("CMD41: 0x%x-0x%x-0x%x-0x%x-0x%x\n", data[0], data[1], data[2], data[3], data[4]);	
	do
	{
	SDCARD_Cmd(CMD58, 0, 1);
	SDCARD_Response(data, 5);
	}while(data[0] != 1);
	printf("CMD58: 0x%x-0x%x-0x%x-0x%x-0x%x\n", data[0], data[1], data[2], data[3], data[4]);	
	if((data[1] & 0x40) == 0x40)
	{
		#ifdef SDCARD_DEBUG
		printf("High Capacity (higher then 2gb) Sdcard\n");
		#endif
	}
	else
	{
		#ifdef SDCARD_DEBUG
		printf("Low Capacity (lower then 2gb) Sdcard\n");
		#endif			
	}
	
	
	SDCARD_Cmd(CMD16, 0x200, 1);
	SDCARD_Response(data, 5);
	
	printf("R: 0x%x-0x%x-0x%x-0x%x-0x%x\n", data[0], data[1], data[2], data[3], data[4]);	
}


CMD55: 0x01 0xFF 0xFF 0xFF 0xFF
CMD41: 0x01 0xFF 0xFF 0xFF 0xFF
CMD58: 0x01 0xC1 0xFE 0x81 0x00 (Mesela bu cevaptan kartın high capacity bir kart olduğunu anlıyorum. Ama gelen cevap sizinkiyle uyuşmuyor)
CMD16:  0x01 0xFF 0xFF 0xFF 0xFF

Görüleceği üzere kart hiçbir zaman idle state'ten çıkmıyor

z

Benim sayfadaki bilgilere cok cok guvenme.

Onlari hazirlarken mevcut dokumanlari ve 2GB kart uzerinde elde ettigim bilgileri harmanladim. Senin yasadigin bu sorundan sonra, aciklamalarimda, kullandigim SD kart markasina bagli olarak genelleme yapmis olmaktan korkuyorum.

Bu SD kartin en pis tarafi dokumantasyonlarin gizli olusu. Internette yarim yamalak bilgi var.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

strom

Hocam sorunu çözdüm. SPI Modunda pinleri config yaparken, çıkış tipini OD (open drain) yapmışım. PP (Push-Pull) yapınca şiir gibi çalıştı. Ne değiştide doğru çalışmaya başladı acaba? Sonuçta hatta Pull-up dirençleri vardı. Ayrıca veri alıp vermede kısmen çalışıyordu. Hiç çalışmasa bir nebze anlardıö