реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Чтение блока с SD карты, не поступает Data Token
Evgenius_Alex
сообщение Jan 23 2013, 12:41
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 373
Регистрация: 6-11-07
Пользователь №: 32 103



Добрый день!

При работе с SD картой столкнулся с проблемой чтения блока.

Карта инициализацию проходит нормально.

После команды чтения одного блока CMD17, приходит корректный ответ (0x00)
Но маркера начала данных(0xFE) не поступает.

Пробовал меня скорость SPI - не помогает

Сталкивался ли кто с таким и как бороться?
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Jan 23 2013, 13:31
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



попробуйте увеличить время ожидания 0xFE
Go to the top of the page
 
+Quote Post
AndreyVN
сообщение Jan 23 2013, 16:28
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 754
Регистрация: 29-06-06
Из: Volgograd
Пользователь №: 18 458



Цитата(Evgenius_Alex @ Jan 23 2013, 15:41) *
Добрый день!
При работе с SD картой столкнулся с проблемой чтения блока.


Читаю сектора вот так:
CODE
// Прочитать содержимое буфера в переменную Sector из MMC карты
// N-номер сектора
//-----------------------------------------------------------------------------
void SDReadSector(unsigned long int N)
{
char rsp,rsp1;
short int crc;
SPCR = 0x50; //0x50 fclk/4; 0x51 fclk/16; 0x52 fclk/64
SPSR = 0x00; //
//for(i=0; i<512; i++) Sector[i]=0xEE;
if(!BlockAdressMode) Adr = N*512; //Адрес начала сектора, побайтная адресация
else Adr=N; //Блочная адресация
rsp = MMC_cmd(CMD17, (unsigned int)(Adr>>16),(unsigned int)(Adr&0x0000ffff), 0xFF); //CMD17 Read a block from specify addr
if(rsp){ SD_init(); //Если rsp!=0x00 будим карту снова
rsp = MMC_cmd(CMD17, (unsigned int)(Adr>>16),(unsigned int)(Adr&0x0000ffff), 0xFF); }
if(!rsp) rsp1 = MMC_read(512); //Заполним массив Sector[]
if(!rsp1){ StringPrepare("Block read Err."); Scroll(); ScrollUpdate(); }
PORTB |= MMC_CE_PIN; //MMC-disable
//StringPrepare("CMD17 "); HexToStr(rsp, 7); Scroll();
crc = MMC_crc16(&Sector[0], 512);
if(crc1!=(unsigned char)(crc >> 8) || crc2!=(unsigned char)(crc & 0xff) ){
StringPrepare("CRC Err ");
HexToStr(crc1, 5); HexToStr(crc2, 8); Scroll();
ScrollUpdate(); }
}


PS: Код писал около года назад, помню, что многие проблемы решились после того, как добавил расчет CRC
по спецификации CRC является обязательной только для команд иницилизации, потом может быть отключена.

Сообщение отредактировал IgorKossak - Jan 23 2013, 19:54
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Jan 23 2013, 17:11
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



В карту при этом должны вдвигаться все "1" по SPI.
Go to the top of the page
 
+Quote Post
Evgenius_Alex
сообщение Jan 23 2013, 20:28
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 373
Регистрация: 6-11-07
Пользователь №: 32 103



Цитата(Genadi Zawidowski @ Jan 23 2013, 20:11) *
В карту при этом должны вдвигаться все "1" по SPI.


не понял насчёт выдвигания "1" по SPI. Поясните, если нетрудно.

Привожу функцию чтения сектора. Что и где надо добавить?
Мучаюсь уже второй день (((

CODE
unsigned char SD_readSingleBlock(unsigned long startBlock)
{
unsigned char response;
unsigned int i, retry=0;

//передаём в карту байты 0xFF до тех пор , пока карта не начнёт
//отвечать 0xFF, т.е. будет свободна
while(1)
{
if(SPI_transmit(0xFF)==0xff)
break;
}

// эта команда выполнятеся корректно - ответ 0x00
response = SD_sendCommand(READ_SINGLE_BLOCK, startBlock<<9); //read a Block command
//block address converted to starting address of 512 byte Block
if(response != 0x00) //check for SD status: 0x00 - OK (No flags set)
return response;

SD_CS_ASSERT; // CS опускаем в ноль

// а вот тут маркера так и не поступает
while(SPI_receive() != 0xfe) //wait for start block token 0xfe (0x11111110)
if(retry++ > 0xfffe){SD_CS_DEASSERT;
return 1;} //return if time-out

for(i=0; i<512; i++) //read 512 bytes
buffer[i] = SPI_receive();

SPI_receive(); //receive incoming CRC (16-bit), CRC is ignored here
SPI_receive();

SPI_receive(); //extra 8 clock pulses

SD_CS_DEASSERT;

return 0;
}


Сообщение отредактировал IgorKossak - Jan 24 2013, 12:25
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Jan 24 2013, 07:40
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



Цитата
SD_CS_ASSERT; // CS опускаем в ноль
SD_CS_DEASSERT;
а это зачем ? CS должен быть постоянно в нуле
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Jan 24 2013, 15:13
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Цитата
не понял насчёт выдвигания "1" по SPI. Поясните, если нетрудно.
Значит, что SPI_receive() должна быть определена через SPI_transmit(0xFF) - именно FF и ничего другого.

Сообщение отредактировал Genadi Zawidowski - Jan 24 2013, 15:14
Go to the top of the page
 
+Quote Post
Evgenius_Alex
сообщение Jan 28 2013, 07:34
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 373
Регистрация: 6-11-07
Пользователь №: 32 103



Цитата(Genadi Zawidowski @ Jan 24 2013, 19:13) *
Значит, что SPI_receive() должна быть определена через SPI_transmit(0xFF) - именно FF и ничего другого.


Вы имеете ввиду посылать на карту байты 0xFF, пока не придёт маркер 0xFE?
Если так, то данный ход, к сожалению, не проходит.

Ещё такой момент. Инициализация карты не всегда проходит успешно 3 раза проходит, 1 раз - нет.

Может причину искать в инициализации?

Go to the top of the page
 
+Quote Post
Evgenius_Alex
сообщение Jan 28 2013, 10:27
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 373
Регистрация: 6-11-07
Пользователь №: 32 103



Цитата(Evgenius_Alex @ Jan 28 2013, 10:34) *
Вы имеете ввиду посылать на карту байты 0xFF, пока не придёт маркер 0xFE?
Если так, то данный ход, к сожалению, не проходит.

Ещё такой момент. Инициализация карты не всегда проходит успешно 3 раза проходит, 1 раз - нет.

Может причину искать в инициализации?


Зацикливание происходит на этапа ожидания ответа на ACMD41
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Jan 28 2013, 12:46
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Неиспользуемые линии данных карты подтянуты через резисторы к питанию?

Кроме того -
Цитата
shitch CRC check on - required before ACMD41

Это цитата из моих исходников, между прочим. Где вычитал - наверное, в спецификации... Возмите чей-нибудь (хоть мой) рабочий вариант и сравните - всё ли у Вас правильно делается.

CODE
// set MMC in Idle mode
// Вызывается, подразумевая что CS установлен
static char mmcGoIdle(void)
{
unsigned char response;
unsigned long cmd58answer, cmd8answer = 0;

SDCARD_CS_HIGH();
nvram_read_byte(targetsdcard);
SDCARD_CS_LOW();

nvram_read_byte(targetsdcard);
//Send Command 0 to put MMC in SPI mode
mmcSendCmdCRC7(MMC_GO_IDLE_STATE, 0); // CMD0 - Обязательно с правильным CRC
//Now wait for READY RESPONSE
if ((response = mmcGetResponseR1()) != 0x01)
{
return MMC_INIT_ERROR;
}

nvram_read_byte(targetsdcard);

mmcSendCmdCRC7(MMC_SEND_IF_COND, 0x000001aa); // CMD8 - Обязательно с правильным CRC. 3.3 Volt VCC
response = mmcGetResponseR7(& cmd8answer);
if ((response & 0x04) != 0) // illegal command or pattern not match
{
mmcAddressMultiplier = MMC_SECTORSIZE;
mmcCardVersion2 = 0;

// if no responce
// Ver2.00 or later SD Memory Card(voltage mismatch)
// or Ver1.X SD Memory Card
// or not SD Memory Card
debug_printf_P("Ver1.X SD Memory Card or not SD Memory Card\n");

// check voltage range here
nvram_read_byte(targetsdcard);
mmcSendCmd(0x40 + 58, 0); // CMD58
response = mmcGetResponseR3(& cmd58answer);
//debug_printf_P("CMD58 has responce %02x, value = %08lx\n", response, cmd58answer);
if (response == 0x00 || response == 0x01)
{
if ((cmd58answer & (1UL << 21)) || (cmd58answer & (1UL << 20)))
{
debug_printf_P("3.3 volt VCC suitable.\n");
}
else
{
debug_printf_P("3.3 volt VCC NOT suitable.\n");
return MMC_INIT_ERROR;
}
}

for (;;)
{
nvram_read_byte(targetsdcard);
mmcSendCmd(MMC_APP_CMD, 0); // APP_CMD
//Now wait for READY RESPONSE
response = mmcGetResponseR1();
//debug_printf_P("APP_CMD responce R1 = %02x\n", response);
if (response != 0x01 && response != 0x00)
continue;

nvram_read_byte(targetsdcard);
mmcSendCmd(MMC_ACMD41, 0); // ACMD41(0)
//Now wait for READY RESPONSE
response = mmcGetResponseR1();
//debug_printf_P("ACMD41 responce R1 = %02x\n", response);
if (response == 0x00)
break;
}
//debug_printf_P("ACMD41 has responce %02x\n", response);

//return MMC_INIT_ERROR;
}
else if ((cmd8answer & 0xff) != 0xaa)
{
debug_printf_P("Bad CMD8 answer. SD CArd unuseable\n");
return MMC_INIT_ERROR;
}
else
{
mmcCardVersion2 = 1;

// Ver2.00 or later SD Memory Card
debug_printf_P("Ver2.00 or later SD Memory Card\n");

// check voltage range here
nvram_read_byte(targetsdcard);
mmcSendCmd(0x40 + 58, 0); // CMD58
response = mmcGetResponseR3(& cmd58answer);
//debug_printf_P("CMD58 has responce %02x, value = %08lx\n", response, cmd58answer);
if (response == 0x00 || response == 0x01)
{
if ((cmd58answer & (1UL << 21)) || (cmd58answer & (1UL << 20)))
{
debug_printf_P("3.3 volt VCC suitable.\n");
}
else
{
debug_printf_P("3.3 volt VCC NOT suitable.\n");
return MMC_INIT_ERROR;
}
}

nvram_read_byte(targetsdcard);
mmcSendCmd(0x40 + 59, 1); // shitch CRC check on - required before ACMD41
response = mmcGetResponseR1();
//debug_printf_P("CMD59 has responce %02x\n", response);

for (;;)
{
nvram_read_byte(targetsdcard);
mmcSendCmdCRC7(MMC_APP_CMD, 0); // APP_CMD
//Now wait for READY RESPONSE
response = mmcGetResponseR1();
//debug_printf_P("APP_CMD responce R1 = %02x\n", response);
if (response != 0x01 && response != 0x00)
continue;

nvram_read_byte(targetsdcard);

mmcSendCmdCRC7(MMC_ACMD41, 0x40000000); // HCS (High Capacity Support)
//Now wait for READY RESPONSE
response = mmcGetResponseR1();
//debug_printf_P("ACMD41 responce R1 = %02x\n", response);
if (response == 0x00)
break;
}

nvram_read_byte(targetsdcard);
mmcSendCmdCRC7(0x40 + 59, 0); // shitch CRC check off
response = mmcGetResponseR1();
//debug_printf_P("CMD59 has responce %02x\n", response);

// Check CCS bit (capacity) bit
nvram_read_byte(targetsdcard);
mmcSendCmd(0x40 + 58, 0); // CMD58
response = mmcGetResponseR3(& cmd58answer);
//debug_printf_P("CMD58 has responce %02x, value = %08lx\n", response, cmd58answer);
if ((cmd58answer & 0x40000000) != 0) //CCS (Card Capacity Status)
{
debug_printf_P("SDHC or SDXC (High Capacity)\n");
mmcAddressMultiplier = 1; // Для SDHC (адресация идёт в 512-ти байтовых блоках)
}
else
{
debug_printf_P("SDSD - up to 2GB\n");
mmcAddressMultiplier = MMC_SECTORSIZE; // Для обычных SD карт
}

}

//debug_printf_P("mmcGoIdle() done.\n");

nvram_read_byte(targetsdcard);
return (MMC_SUCCESS);
}



Сообщение отредактировал Genadi Zawidowski - Jan 28 2013, 12:47
Go to the top of the page
 
+Quote Post
Evgenius_Alex
сообщение Jan 28 2013, 15:12
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 373
Регистрация: 6-11-07
Пользователь №: 32 103



Спасибо, Геннадий!

Неиспользуемые линии были не подтянуты. Подтянул их к "+" питания, но всё равно проблема осталась.
Всё вроде бы делаю правильно. На команду CMD0 приходит корректный ответ - 0x01.
Правда, и 1-й и 2-й байты CRC равны 0xFF.

На команду CMD8 ответ может приходить разный (0x03, 0x07, 0xC0 и т.д.)

А на связке команд CMD55+ACMD41 программа вообще зацикливается.

Ничего не могу понять. Вот мой код функции инициалзации.

CODE
//function инициализация карты памяти
//return 0 - карта инициализирована
unsigned char SD_init(void)
{
unsigned char i, response, CRC1, CRC2;
unsigned char SD_version = 2; //по умолчанию версия SD = 2

int retry=0;

delay_ms(1); //задержка 1 мс, чтобы стабилизировалось напряжение

for(i=0;i<10;i++)
SPI_transmit(0xff); // 10*8 бит = 80 пустых циклов

SD_CS_ASSERT; //вывод CS опустить в ноль

do
{
//команда CMD0
response = SD_sendCommand(GO_IDLE_STATE, 0); //send 'reset & go idle' command
retry++;

if(retry>0xfe) {
return 1;
} //time out
} while(response != 0x01);

// Эти байты всегда равны 0xFF!!!!
CRC1 = SPI_transmit(0xff); //читаем первый байт CRC
CRC2 = SPI_transmit(0xff); //читаем второй байт CRC

SD_CS_DEASSERT;

retry = 0;

//команда CMD8 - приходят разные ответы
while((response = SD_sendCommand(SEND_IF_COND,0x000001AA)) != 0x01 )
{
if(retry++>0xfe)
{
SD_version = 1;
break;
}
}

retry = 0;

// а в этом цикле программа зацикливается и не выходит по команде return 1
do
{
response = SD_sendCommand(APP_CMD,0); //команда CMD55
response = SD_sendCommand(SD_SEND_OP_COND,0x40000000); //команда ACMD41

retry++;

if(retry>0xfffe)
return 1;

} while(response != 0x00);

//читаем регистр OCR, чтобы определить тип карты
retry = 0;
SDHC = 0;
if (SD_version == 2)
{
while((response = SD_sendCommand(READ_OCR,0))!=0x00)
if(retry++>0xfe) break;
}

putchar1('O');
putchar1('K');
putchar1('!');

return 0;
}


Сообщение отредактировал IgorKossak - Jan 28 2013, 15:17
Причина редактирования: бездумное цитирование, [CODEBOX]
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Jan 28 2013, 20:50
Сообщение #12


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Ну так если у Вас карта на SDHC, не v2 - вполне может весь этот мусор приходить...
приведите весь код, или хотя бы, получение ответа.
Да, надеюсь, SPI MODE3 используете?
Поймите, весь "огород" я наворотил не зря - как раз для поддержки всех карточек. И пока не встречал тех, с чем не работает.
Судя по коду, Вы взяли за основу пример от TI? Я, во всяком случае, с него начинал - и вот во что превратилось...

Сообщение отредактировал Genadi Zawidowski - Jan 28 2013, 20:52
Go to the top of the page
 
+Quote Post
Evgenius_Alex
сообщение Jan 29 2013, 08:25
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 373
Регистрация: 6-11-07
Пользователь №: 32 103



Цитата(Genadi Zawidowski @ Jan 29 2013, 00:50) *
Ну так если у Вас карта на SDHC, не v2 - вполне может весь этот мусор приходить...
приведите весь код, или хотя бы, получение ответа.
Да, надеюсь, SPI MODE3 используете?
Поймите, весь "огород" я наворотил не зря - как раз для поддержки всех карточек. И пока не встречал тех, с чем не работает.
Судя по коду, Вы взяли за основу пример от TI? Я, во всяком случае, с него начинал - и вот во что превратилось...


Я использую SPI MODE0.... SPI CLOCK RATE - 125 кГц. Может в этом проблема?

Пример кода я брал вот по этой ссылке http://mycontroller.ru/stm32-sd-card-inits...kartyi-pamyati/

А не могли бы Вы привети полностью весь код ?

С описанием всех функций (таких как mmcSendCmdCRC7, mmcGetResponseR1, mmcGetResponseR7 и т.д.)
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Jan 29 2013, 14:28
Сообщение #14


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Насчёт описания тяжело... Вот проект.
Пока ничего не меняя смените на mode3 - но у меня выбирать можно было только из mode2 и mode3 - скорее всего, состояние MOSI вне посылки не важно, но полярность клока (по какому перепаду обновлять) важна. Как я понял, к моему работаеюему mode3 допустимая замена mode1.
Go to the top of the page
 
+Quote Post
Evgenius_Alex
сообщение Jan 29 2013, 20:47
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 373
Регистрация: 6-11-07
Пользователь №: 32 103



Цитата(Genadi Zawidowski @ Jan 29 2013, 17:28) *
Насчёт описания тяжело... Вот проект.
Пока ничего не меняя смените на mode3 - но у меня выбирать можно было только из mode2 и mode3 - скорее всего, состояние MOSI вне посылки не важно, но полярность клока (по какому перепаду обновлять) важна. Как я понял, к моему работаеюему mode3 допустимая замена mode1.


К сожалению, изменение режима SPI не помогло. Пробовал все четыре режима SPI.

Придётся адаптировать Ваш код под ATMega128.

Правда, я смотрю, у Вас в коде типы данных есть непонятные. Я с ARM-ами никогда не работал.
Например uint_fast8_t, uint_fast32_t, uint_fast64_t. Чем их можно заменить?

И ещё не могут быть такие траблы из-за электрически неправильно собранной цепи?

Правда, у меня всё стандартно.
Согласующие резисторы между картой и МК на всех линиях - 510 Ом.
Подтягивающие резисторы к плюс питания - 51 кОм.
На всех линиях, кроме MISO стоят защитные стабилитроны на 3.3В.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th June 2025 - 18:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.01516 секунд с 7
ELECTRONIX ©2004-2016