|
Чтение блока с SD карты, не поступает Data Token |
|
|
|
Jan 23 2013, 16:28
|
Знающий
   
Группа: Свой
Сообщений: 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] - для короткого!!!
|
|
|
|
|
Jan 23 2013, 20:28
|
Местный
  
Группа: Участник
Сообщений: 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] - для короткого!!!
|
|
|
|
|
Jan 28 2013, 07:34
|
Местный
  
Группа: Участник
Сообщений: 373
Регистрация: 6-11-07
Пользователь №: 32 103

|
Цитата(Genadi Zawidowski @ Jan 24 2013, 19:13)  Значит, что SPI_receive() должна быть определена через SPI_transmit(0xFF) - именно FF и ничего другого. Вы имеете ввиду посылать на карту байты 0xFF, пока не придёт маркер 0xFE? Если так, то данный ход, к сожалению, не проходит. Ещё такой момент. Инициализация карты не всегда проходит успешно 3 раза проходит, 1 раз - нет. Может причину искать в инициализации?
|
|
|
|
|
Jan 28 2013, 10:27
|
Местный
  
Группа: Участник
Сообщений: 373
Регистрация: 6-11-07
Пользователь №: 32 103

|
Цитата(Evgenius_Alex @ Jan 28 2013, 10:34)  Вы имеете ввиду посылать на карту байты 0xFF, пока не придёт маркер 0xFE? Если так, то данный ход, к сожалению, не проходит.
Ещё такой момент. Инициализация карты не всегда проходит успешно 3 раза проходит, 1 раз - нет.
Может причину искать в инициализации? Зацикливание происходит на этапа ожидания ответа на ACMD41
|
|
|
|
|
Jan 28 2013, 12:46
|

Профессионал
    
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jan 28 2013, 15:12
|
Местный
  
Группа: Участник
Сообщений: 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]
|
|
|
|
|
Jan 28 2013, 20:50
|

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

|
Ну так если у Вас карта на SDHC, не v2 - вполне может весь этот мусор приходить... приведите весь код, или хотя бы, получение ответа. Да, надеюсь, SPI MODE3 используете? Поймите, весь "огород" я наворотил не зря - как раз для поддержки всех карточек. И пока не встречал тех, с чем не работает. Судя по коду, Вы взяли за основу пример от TI? Я, во всяком случае, с него начинал - и вот во что превратилось...
Сообщение отредактировал Genadi Zawidowski - Jan 28 2013, 20:52
|
|
|
|
|
Jan 29 2013, 08:25
|
Местный
  
Группа: Участник
Сообщений: 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 и т.д.)
|
|
|
|
|
Jan 29 2013, 20:47
|
Местный
  
Группа: Участник
Сообщений: 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В.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|