Проблема с SD накопителем

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить
Прорезались зубы
Аватара пользователя
Сообщения: 244
Зарегистрирован: Вс апр 17, 2011 21:38:10

Сообщение Protobear »

Уважаемые коты, кто работал с SD картами - у меня зависает мк при втором чтении или записи 512 байт, в чем может быть дело, возможно есть команда которую нужно использовать после операции, чтоб узнать готова ли карта к обмену?
PS
я считываю с карты и пишу на нее, но если я И считываю а затем И пишу, то все виснет:(
Реклама
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Сообщение mas123 »

Protobear писал(а):Уважаемые коты, кто работал с SD картами - у меня зависает мк при втором чтении или записи
В чем заключается зависание мк? Что он в это время делает?
Protobear писал(а):я считываю с карты и пишу на нее, но если я И считываю а затем И пишу, то все виснет:(
А если попробовать прочитать 2 сектора или записать сразу два сектора - работает?
Распиши алгоритм как читаешь сектор и как пишешь.
Про два байта CRC после 512 байт данных знаешь? Их нужно вычитать при чтении и передать при записи.
Реклама
Прорезались зубы
Аватара пользователя
Сообщения: 244
Зарегистрирован: Вс апр 17, 2011 21:38:10

Сообщение Protobear »

mas123 писал(а):
Protobear писал(а):Уважаемые коты, кто работал с SD картами - у меня зависает мк при втором чтении или записи
В чем заключается зависание мк? Что он в это время делает?
я считываю с карты и пишу на нее, но если я И считываю а затем И пишу, то все виснет:([/quote]А если попробовать прочитать 2 сектора или записать сразу два сектора - работает?
Распиши алгоритм как читаешь сектор и как пишешь.
Про два байта CRC после 512 байт данных знаешь? Их нужно вычитать при чтении и передать при записи.[/quote]
обалдеть! что вы хотите сказать что любой алгоритм записи заключает в себе передачу предварительно считанных байтов срс?
код прилагаю. у меня следующая картина: Если я читаю подряд то все норм, если я читаю в массив, и пишу его же , то он пишется, но если я пишу другой массив то он виснет. ну скорее код по проверке карты виснет. опишите пожалуйста про байты CRC поподробнее - я правильно понял(выше)?
-- ДА! если я считываю и пишу (буфером массив в мк является то он пишется как я написал выше)
Вложения
specialforcat.txt
(2.42 КБ) 287 скачиваний
Прорезались зубы
Аватара пользователя
Сообщения: 244
Зарегистрирован: Вс апр 17, 2011 21:38:10

Сообщение Protobear »

И ДА! - читать ИЛИ писать могу сколько угодно подряд. Но почему то прочесть из 0х00 00 00 00 сектора а затем записать в него другие 512 байт - не выходит. Если же записать то что прочел то пишется причем не только в 0 но и в N x 0x200 cектора. сколь угодно раз. идиотизм, ведь сRс то не отсылается в 512 считанных байтах...
Реклама
Эиком - электронные компоненты и радиодетали
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Сообщение mas123 »

Protobear писал(а):обалдеть! что вы хотите сказать что любой алгоритм записи заключает в себе передачу предварительно считанных байтов срс?
Ога, карточка после сектора выдает 2 байта CRC, а при записи требует 2 байта CRC от тебя.
Можно подать команду "не проверяй CRC", и тогда самому можно не считать эти два байта. Но, читать их и передавать нужно всегда.
Protobear писал(а):код прилагаю.
Код внимательнее посмотрю чуть позже, пока что-то мне уже там не нравится....
Protobear писал(а): но если я пишу другой массив то он виснет.
КАК именно виснет? в каком месте? Какая-нибудь отладочная инфа выводится хоть куда-нить?
Protobear писал(а): опишите пожалуйста про байты CRC поподробнее - я правильно понял(выше)?
По карточкам погугли спецификацию - тама расписано.
В двух словах: после передачи команды в карточку (5 байт) передаем 6-м байтом CRC этой команды. Можно отключить контроль, тогда передаем 6-й байт что угодно.
При чтении сектора читаем с карты 512 + 2 байта, пишем тоже 512 + 2

По какой схеме включена карточка? Через SPI?
Как инициализируешь SD?
Реклама
Прорезались зубы
Аватара пользователя
Сообщения: 244
Зарегистрирован: Вс апр 17, 2011 21:38:10

Сообщение Protobear »

mas123 писал(а):
Protobear писал(а):обалдеть! что вы хотите сказать что любой алгоритм записи заключает в себе передачу предварительно считанных байтов срс?
Ога, карточка после сектора выдает 2 байта CRC, а при записи требует 2 байта CRC от тебя.
Да, нет это я понял) я в коде посылаю CRC "от балды" (во многих источниках говорят что CRC нужен только для смд 0 и 8 )я то думал что CRC строится на базе 512 байт данных, а что какие 2 байта СRC требует карточка? тех что я считал или тех что оспадают с CRC моих данных подготовленных для записи?
mas123 писал(а): По какой схеме включена карточка? Через SPI?
Как инициализируешь SD?
да по SPI инициализация 0х40 ответ 0х01 ;0х41 ответ 0х00. затем то что в текст документе, да там циклы while(o==0xff); после if(o!=0x00) goto mark1; не нужны, но это не важно, главное что проблема остается.

mas123 писал(а): КАК именно виснет? в каком месте? Какая-нибудь отладочная инфа выводится хоть куда-нить?
после всех функции считывания и отправки:
o=SD_RECIVE_DATA(0x00000000);
o=SD_SEND_DATA(mass,0x00000000);
itoa(mass[2],&ho[0],16);
print(ho);
выводится ф-ей print(ho) ; на lcd содержимое mass[2](глобальный unsigned char массив ) в который пишется при чтении инфа.
а если его при записи заменить другим массивом с данными:
o=SD_RECIVE_DATA(0x00000000);
o=SD_SEND_DATA(др массив,0x00000000);
ТО до показа на дисплей не доходит дело.
PS Более того при записи карта отвечает на пацана 0xe5 что свидетельствует о "Data accepted"
Последний раз редактировалось Protobear Ср ноя 07, 2012 23:58:57, всего редактировалось 1 раз.
Реклама
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Сообщение mas123 »

Protobear писал(а):код прилагаю.

Код: Выделить всё

unsigned char SD_RECIVE_DATA(long int address)
{
unsigned char o;
PORTB&=~(1<<PB4);
_delay_us(100);
mark:
SD_transmit(0x51);
SD_transmit((address>>24)&0x000000ff);
SD_transmit((address>>16)&0x000000ff);
SD_transmit((address>>8)&0x000000ff);
SD_transmit(address&0x000000ff);
SD_transmit(0x95);
ReadByteSPI(0xff);
o=ReadByteSPI(0xff);
if(o!=0x00) goto mark;
while((ReadByteSPI(0xff))!=0xff);
while(o!=0xfe) {o=ReadByteSPI(0xff);}
	 
		for (int p=0;p<512;p++)
			{
mass[p]=ReadByteSPI(0xff);
			}
ReadByteSPI(0xff);// считываю 2 байта СРС (вникуда)
o=ReadByteSPI(0xff);//      -//-    -//-
while((ReadByteSPI(0xff))!=0xff);
   _delay_us(100);
PORTB|=(1<<PB4);
return o;
}
Суровый код :kill:
Очень понравилось goto, если 2-й байт принялся не 0x00. Даже не знаю как бы сказать...
По спецификации карточка ответит на команду не сразу. Может ответить уже в 1-м же байте (который ты выкидываешь), а может и в 10...20-м байте. Всё зависит как самой карты, а так же от скорости работы по SPI.
А гнать в SD постоянно команду, не дожидаясь ответа.... Есть мнение, что карточка на 100500 команд тебе в ответ выдает (пытается выдать) 100500 секторов.

Передал команду - жди ответа! По таймауту читай из SD, как получишь не 0xFF - это ответ.
Далее проверяем его! Да, в идеале карточка должна ответить R1_OK (те самые 0x00), а может ответить и ошибкой!
После получения R1_OK ожидаем от карты START_SBR (0xFE, пользуйся константами - удобнее читать). Опять же - стоит завести таймаут ожидания.

А ещё мне встречались карточки, которые в ответ на команду READ_SINGLE_BLOCK отвечали сразу байтом START_SBR, забив на передачу ответа R1_OK.
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Сообщение mas123 »

Protobear писал(а):Да, нет это я понял) я в коде посылаю CRC "от балды" (во многих источниках говорят что CRC нужен только для смд 0 и 8 )
Ога, я передаю "правильные" CRC для этих 2 команд.
Protobear писал(а):я то думал что CRC строится на базе 512 байт данных, а что какие 2 байта СRC требует карточка? тех что я считал или тех что оспадают с CRC моих данных подготовленных для записи?
Не разбирался с этим вопросом, ибо контроль CRC отключаю. При работе по SPI контроль вроде бы сам выключается, я даже убрал передачу команды 59
Protobear писал(а):
mas123 писал(а):Как инициализируешь SD?
да по SPI инициализация 0х40 ответ 0х01 ;0х41 ответ 0х00. затем то что в текст документе,
Не знаю по какому именно документу делаешь :)
Для побудки SD карточки нужно подавать несколько больше команд, чем для ММС. А для SDHC ещё больше....
Тебе это ничем не поможет, скорее всего... вот выстраданный код инициализации:
Спойлер

Код: Выделить всё

//************************************************************************
//*   Активизация карты:  разбудить карту
//************************************************************************
//* ВХОД
//************************************************************************
//* ВЫХОД
//*  результат
//************************************************************************
bool CDataSD::WakeUp()
{
    m_cTypeCard = _SDCARD_TYPE_NONE; // тип карты
// при выключеном CS выдать 10 байт 0xFF, затем ждать 1 мс
    LockSPI_Init();
    g_drvSPI.Transfer(&Null_Word, NULL, 10, 0, 0);
    UnlockSPI();
    VDK::Sleep(10);

    BYTE cResult;
    for(WORD i=0; i<SD_RETRY_WAKEUP; i++)
    {
        LockSPI_Init();
        cResult = SendCommandAndWait(SD_GO_IDLE_STATE, 0,
                                     _SD_TIMEOUT_COMMAND, true);
        if( cResult == SD_R1_IDLE_STATE )
        {
            DummySend(1); // Send One Byte Delay
            UnlockSPI();
            break;
        }
        UnlockSPI();
        VDK::Sleep(10); ///~~~
    }
    if( cResult != SD_R1_IDLE_STATE )
        return false;

    VDK::Sleep(80);
    bool bVersSD2 = false;
// Проверить статус питания, обязательно для SDHC карт
    for(WORD i=0; i<255; i++)
    {
        LockSPI_Init();
        DummySend(1);
        cResult = SendCommandAndWait(SD_SEND_IF_COND, 0x000001AA,
                                     _SD_TIMEOUT_COMMAND, true);
        UnlockSPI();
        if( SD_R1_IDLE_STATE == cResult  )
        { // возможно, это SDHC!
            bVersSD2 = true;
            break;
        }
        VDK::Sleep(20);
    }
// ждем, когда карта выйдет из спящего режима.

// Проверка SD карты
    for(WORD i=0; i<60; i++)
    {
        LockSPI_Init();
        DummySend(1); // Send One Byte Delay
        cResult = SendCommandAndWait(SD_APP_CMD, 0, _SD_TIMEOUT_COMMAND, true);
        if( cResult != SD_R1_OK )
        {
            cResult = SendCommandAndWait(SD_APP_CMD, 0, _SD_TIMEOUT_COMMAND, true);
            if( cResult != SD_R1_IDLE_STATE )
            {
                UnlockSPI();
                continue;
            }
        }

        cResult = SendCommandAndWait(SD_SEND_OP_COND_FOR_SD, 0x40000000,  ///~~~ было 0
                                     _SD_TIMEOUT_COMMAND, true); // ACMD41
        UnlockSPI();
        if( SD_R1_OK == cResult )
        { // нашли SD карту
            m_cTypeCard = _SDCARD_TYPE_SD_VER1; // тип карты
            if( bVersSD2 )
                CheckSDHC(); // это SD 2-й версии или SDHC
            return true;
        }
        VDK::Sleep(20);
    }

    LockSPI_Init();
    cResult = SendCommandAndWait(SD_GO_IDLE_STATE, 0,
                                 _SD_TIMEOUT_COMMAND, true);
    UnlockSPI();
    if( cResult != SD_R1_IDLE_STATE )
    {
        return false;
    }

// poll card by sending CMD1 and wait for card initialization complete
    for(short i=0; i<300; i++ )
    {
        LockSPI_Init();
        DummySend(1);  // Send One Byte Delay
        // Send CMD1
        cResult = SendCommandAndWait(SD_SEND_OP_COND_FOR_MMC, 0,
                                    _SD_TIMEOUT_COMMAND, true);
        if( SD_R1_OK == cResult )
        { // нашли MMC карту
            UnlockSPI();
            m_cTypeCard = _SDCARD_TYPE_MMC; // тип карты
            return true;
        }
        UnlockSPI();
        VDK::Sleep(20);
    }
    return false;
}
Protobear писал(а):
mas123 писал(а): КАК именно виснет? в каком месте? Какая-нибудь отладочная инфа выводится хоть куда-нить?
после всех функции считывания и отправки:
выводится ф-ей print(ho) ; .....
ТО до показа на дисплей не доходит дело.
подключаешь UART Rx/Tx на COM-порт и кидаешь в него ключевые буковки: дошел до такого-то места в коде - кинул в УАРТ нужную буковку.
И смотри себе на консоле как и где прока крутится.
Protobear писал(а):PS Более того при записи карта отвечает на пацана 0xe5 что свидетельствует о "Data accepted"
Этот ответ получаешь сразу после передачи в карточку данных?
А что возвращает ожидание окончания записи?
Прорезались зубы
Аватара пользователя
Сообщения: 244
Зарегистрирован: Вс апр 17, 2011 21:38:10

Сообщение Protobear »

mas123 писал(а): А что возвращает ожидание окончания записи?
это после записи 512 байт, т.е. все как положено.
mas123 писал(а):Правильные срс для 41 и 40
- я тоже посылаю правильные) 0х95.
Ужас вобщем) хоть транзистор ставь на питание и хард ресет ей делай пиши что хочешь, потом хард ресет и читай что хочешь)
Прорезались зубы
Аватара пользователя
Сообщения: 244
Зарегистрирован: Вс апр 17, 2011 21:38:10

Сообщение Protobear »

Хотите верьте - хотите нет - но происходит ЛАЖА какая то)), поменял массивы местами - все заработало. как будто где то есть битые еепром в памяти мк или компилятор чудит.. вобщем очень занимательно :beer: правда я еще добавил 0х41 в конец каждой из ф-ций отправки и приема, и жду пока busy не пройдет) может и из за этого.
Но! теперь у меня при отправке массива (как я думал забитого однородными хексами 0ха3 вылезает мусор )) - a3 a3 a3 a3 a3 a3 a3 a3 20 c4 04 4f 23 d5 a3 a3 a3 a3 a3 a3 a3 a3 a3 a3 a3 a3 a3 a3 a3 a3 a3 это в конце 512 байт) бред...)
PS
Частота мк 8 мгГц, частота строба SPI 62500 Гц
А ну и еще я сделал массивы не по 512 а по 514 и пихаю туда CRC байты и пишу их.
В ходе экспериментов было обнаружено, что, а именно - если проинициализировать как и все 512 байтов 513 и 514(CRC) как 0xa3 то все зависает, НО! пишется без мусора(зависает после первой записи), но если их не инициализировать то ничего не зависает но на основании какого то неведомого CRC карта походу корректирует данные. И получается "мусор".
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Сообщение mas123 »

Protobear писал(а):Хотите верьте - хотите нет - но происходит ЛАЖА какая то)),
Т.е. мой комментарий по твоему коду проигнорирован начисто? Про постоянную передачу команды в карточку и ожидания ответа ровно на 2-й байт?

И внимательно ли было прочитано "SD/MMC карта памяти и микроконтроллер AVR"?
Где русским по серому приведен даже кусок кода отправки команды и ожидания ответа с таймаутом:

Код: Выделить всё

unsigned char sd_cmd(char b0, char b1, char b2, char b3, char b4, char b5)	
//Отправка команды карте SD|MMC
{ unsigned char res;
long int count;
spi_transmit (b0);	//Передать индекс команды
 
spi_transmit (b1);	//Передать аргумент
spi_transmit (b2);
spi_transmit (b3);
spi_transmit (b4);
 
spi_transmit (b5);	//Передать CRC
count=0;
do {	//Подождпть R1 ответа
res=spi_receive();
count=count+1;
} while ( ((res&0x80)!=0x00)&&(count<0xffff) );
return res;
}
И там же приведен код чтения сектора с карты! Опять же - с правильным ожиданием и таймаутом. Т.е. никаких "зависаний" контролера не будет.

Я даже не знаю что ещё можно добавить...:shock:
Прорезались зубы
Аватара пользователя
Сообщения: 244
Зарегистрирован: Вс апр 17, 2011 21:38:10

Сообщение Protobear »

mas123 писал(а):Т.е. мой комментарий по твоему коду проигнорирован начисто? Про постоянную передачу команды в карточку и ожидания ответа ровно на 2-й байт?
Нет, он был убран после чего сразу пошла запись(с мусором), однако код еще не до конца похож на сайтовский, как сделаю отпишу что вышло, спасибо большое за помощь! :tea:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 347
Зарегистрирован: Сб фев 07, 2009 19:21:25

Сообщение БАТАРЕЙКУС »

добро время суток мужокоты.
подскажите кто знает.
пишу прогу для работы с FAT16 какбы всё нашол, но вот не могу насчитать
Cluster_base - адрес нулевого (не 002!!!) кластера (нулевого кластера нет, но так удобнее, см. ниже)
это из http://www.gaw.ru/html.cgi/txt/app/memory/mmc.htm
там есть расчёт типо Cluster_base = Root_base + Root_dir_entry * root_entry_size - 2 * (Sectors_per_Cluster * 0x200)
но я из прошлых опытов помню он ошибочный, а вот беда найти правильный расчёт не получается.
Мечтатель - не тот, кто сидит на диване и думает о несбыточном, а тот, кто всеми силами стремится воплотить несбыточное в реальность.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 347
Зарегистрирован: Сб фев 07, 2009 19:21:25

Сообщение БАТАРЕЙКУС »

Всё разобрался вот формула.

Код: Выделить всё

Cluster_base = (Root_base + root_entry_size) - (2*Sectors_per_Cluster) ;
Мечтатель - не тот, кто сидит на диване и думает о несбыточном, а тот, кто всеми силами стремится воплотить несбыточное в реальность.
Ответить

Вернуться в «Периферия»