Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Снова SD/MMC
Форум разработчиков электроники ELECTRONIX.ru > Интерфейсы > Форумы по интерфейсам > IDE/ATA/SATA/SAS/SCSI/CF
Страницы: 1, 2
ISD
Проблема с microSD Kingston 1Гб. Делаю чтение блоками в 32 байта в цикле. Карта на определенном адресе очень долго не выдает Data Token (пока до 1мс задержку докрутил) . Посмотрел по докам сандиск на SD карты - а там максимум в 100мс обозначен!!!!! Это как понимать?
aaarrr
Так и понимать. Постоянную скорость Вам никто не обещает.
ISD
исходя из этого параметра можно считать, что чтение блока в 512 байт по SPI в худшем случае займет 100мс + 512*8*Fclk+команда.? Чет медлено очень 07.gif
aaarrr
Цитата(ISD @ Oct 24 2008, 17:46) *
Чет медлено очень 07.gif

Ну, не на каждом же чтении возникает такое безобразие. Буферизируйте данные, если нужна стабильная скорость.
ISD
Если работать на 2 МГц CLK, надо буфер более 25КБ держать. Причем непонятна частота возникновения этой задержки. Как же тогда народ на АВР плееры делает? Или это только SD-карт касается? В MMC вроде меньше задержка....
LCD
Цитата(ISD @ Oct 24 2008, 18:07) *
Если работать на 2 МГц CLK, надо буфер более 25КБ держать.

Зачем так много?
ISD
Потому, что при 2Мгц CLK за 100мс должно прочитаться 25000 байт (это теоретически, практически -минус команда 7 байт, минус DataToken и CRC * кол-во блоков) (конечно, если надо поток постоянным держать). Непонятно, как в MP3 плеере, сначала буферизируют столько?
Еще одна особенность всплыла - карте иногда не нравятся адреса, не выровненные к размеру блока чтения. Иногда- тоже понятие одной "магической цифры", остальные невыровненные кушает без проблем.
Angelo
На второй странице этой ветки SALOME задаёт вопрос:
Я правильно понимаю, что с ростом количества битых блоков будет уменьшаться размер памяти, выдаваемый регистром CSD?
Zltigo отвечает:
Нет. Просто пополнятся из резерва. После исчерпания резерва, битые сектора полезут наружу и будут уже маркироваться, как битые на файловой системе.

Мой вопрос.
Карта используется как большой массив памяти, данные линейно пишутся подряд, так же линейно читаются, и после прочтения все удаляются. Т.е. файловой системы нет. Как в таком случае будут выглядеть битые сектора? Т.е. предположу, что при попытке записать в битый сектор карта вернёт ошибку. Но какую именно? Как понять (по ошибке) что это именно битый сектор, и его нужно просто пропустить? Что ответит карта при прочтении битого сектора? Опять же как это понять, чтоб данные из этого сектора пропустить?
aaarrr
Маловероятно, что при такой работе вообще вылезут битые сектора. На битом секторе карта вернет Write Error в Data Response токене при записи и Card ECC Failed в Data Error токене при чтении.
forever_student
Всем доброго дня!
Столкнулся с таким непонятным явлением:
Инициализация SDHC карты для работы по SPI
CMD 0 - ответ 0х01
CMD 8 - ответ 0х01

ACMD 41 :
CMD 55 - ответ 0х01
/* хитрое место */
CMD 41 - ответ 0х00

Непонятно вот что :
4 карты (2шт. Transcend 8 Gb и 2 шт.Kingston 4 Gb) работают
если в хитром месте подать больше 7 клоков при неактивном CS
1 карта (Kingston 8 Gb) работает если в хитром месте подать более 255 клоков при неактивном CS
1 карта (Kingston 8 Gb) работает если в хитром месте подать более 511 клоков при неактивном CS
Наверное, можно нарваться на карту, где еще более широкое "хитрое место".
В Physical Layer Simplified Specification Version 2.00 ничего на этот счет не нашел.
Сколько клоков закладывать в хитрое место?
P.S. Инициализация идет при частоте клока ~250 кГц, карты новые.
zltigo
Цитата(forever_student @ Apr 11 2010, 17:40) *
Сколько клоков закладывать в хитрое место?

А почему это Вас сильно волнует? При наличии контроля responce после каждого байта этот "таймаут" может заложен весьма большим.
forever_student
Цитата(zltigo @ Apr 11 2010, 19:59) *
А почему это Вас сильно волнует? При наличии контроля responce после каждого байта этот "таймаут" может заложен весьма большим.

Насколько большим?
Если он будет мЕньшим, чем нужен для конкретной карты, то после ACMD 41 я получу responce 0хFF, и буду повторять ACMD 41 до бесконечности (пробовал 255 раз, результата никакого). Поэтому хочется или знать какое-то значение, при котором любая SDHC карта, поддерживающая SPI, ответит 0х00, или понять, где я чего-то неправильно сделал
zltigo
Цитата(forever_student @ Apr 11 2010, 20:36) *
Если он будет мЕньшим, чем нужен для...

Не понимаю, что Вы там написали, но вообще бесконтрольные магические клоки на карту выдавать просто не надо. То, что перед командой, это ожидание готовности. Ожидание готовности ТОЖЕ должно быть подконтрольным и после CMD55 перед ACMD41 сначала надо дождаться готовности. Лично у меня это отсчитывает операционка, посему не с тактах sad.gif, а в ms - 750ms почему? За давностью лет не помню sad.gif все было написано лет пять назад.
forever_student
Цитата(zltigo @ Apr 11 2010, 23:09) *
... бесконтрольные магические клоки на карту выдавать просто не надо...

Sorry, неправильно выразился. Это просто байты 0хFF(т.е. 8 клоков=1 байт), передаваемые при неактивном CS (как те, что до CMD 0).
Т.е. после CMD 55 достаточно дать паузу ~800 мС, затем CMD 41?
zltigo
Цитата(forever_student @ Apr 11 2010, 21:29) *
неправильно выразился. Это просто байты 0хFF(

Я о том-же. Вот и КОНТРОЛИРУЙТЕ ответ-готовность при передаче этих 0xFF.
Цитата
Т.е. после CMD 55 достаточно дать паузу ~800 мС, затем CMD 41?

Разумеется нет. Пауза тут вообще ни сном ни духом CD надо тактировать. Считать при этом время или байт-такты, это уже конкретная реализация.
forever_student
Цитата
Вот и КОНТРОЛИРУЙТЕ ответ-готовность при передаче этих 0xFF.

Чего-то я, видимо, не понимаю. Как я могу контролировать? Responce на CMD55 я уже получил. CMD 41 еще не передавал. Только что специально все ответы на посланные 64 байта (т.е. 512 клоков) сложил в RAM, после Responce на CMD 41 посмотрел - все 0хFF. Да и как карта может отвечать, если CS неактивен?
zltigo
Цитата
все 0хFF.

Это правильная реакция карты готовой к приему команды ее и надо ждать, а вот CS должен быть активен во время всей "большой" команды ACMD.
forever_student
Передаю CMD55, жду responce 0x01, CS оставляю активным, отправляю байты 0хFF до тех пор, пока не получу ответ 0хFF, отправляю CMD 41, жду responce 0x00, если таймаут, повторяю все сначала.
Если делаю так, то всю большую ACMD 41 повторяю от 5 до 8 раз.
Если так,как раньше (т.е. отправляю 64 байта 0хFF) то повторяю 4 раза.
Самые "медленно отвечающие" карты смогу проверить завтра.
zltigo
Цитата(forever_student @ Apr 11 2010, 22:54) *
Передаю CMD55, жду responce 0x01, CS оставляю активным, отправляю байты 0хFF до тех пор, пока не получу ответ 0хFF, отправляю CMD 41, жду responce 0x00, если таймаут, повторяю все сначала.

Да. Теперь правильно. У меня, правда, один 0xFF сначала передается бесконтрольно. Почему уже не помню что там читал 4-5 лет назад, возможно просто как минимально необходимый.
Цитата
Если делаю так, то всю большую ACMD 41 повторяю от 5 до 8 раз.

А вот проходить все должно БЕЗ таймаута с первого раза. Начните внимательно разбираться по первоисточнику с самого начала инициализации. Или с железом проблемы. Успехов!
А, на счет с первого раза - у меня есть и повтор. Зачем? Опять не помню sad.gif. В ветка, первой версии SD, или MMC повтора нет, а для продвинутой есть.
Пора по первоисточникам освежать память....
Код
                // The card can work at vdd range of 2.7-3.6V
                do
                {   // ACMD41 with HCS bit
                    if( send_cmd_app( ACMD41_OPERATE, BIT30 ) == R1_OK )
                    {
                        if( send_cmd( CMD58_OCR, 0 ) == R1_OK )
                        {    // Check CCS bit
                            mmc_receiveblock( sd_buf, 4 );
                            if( sd_buf[0] & 0x40 )
                                Mds.ctype = (CARD_SD|CARD_V2X|CARD_BLOCK);
                             else
                                 Mds.ctype = (CARD_SD|CARD_V2X);
                        }
                    }
                }
                while( xIsTimeout( timer ) == FALSE );
forever_student
Цитата(zltigo @ Apr 12 2010, 01:51) *
А вот проходить все должно БЕЗ таймаута с первого раза.

Всем доброго дня.
Проверил "медленноотвечающие" карты.
Обе 8 Gb карты не работают sad.gif После >100 повторений большой ACMD 41 - таймаут.(~1 сек.)
В железе, я думаю, проблем нет - при тупой передаче 64 байт все работает
То же самое по инициализации( если по предыдущим командам получены правильные responce, значит все в норме?)
Буду разбираться...
stepper88
Дабы не плодить темы, пишу сюда.
Есть в наличии плата на LPC2378. Карта памяти подключена к модулю MCI по схеме, которую прилагаю к посту.
Модуль MCI инициализирую следующим образом:
Код
void MCI_init (void)
{
    unsigned char i=0;

    //процедура инициализации карты памяти
    PCONP |=(1<<28);                    //Включаем тактирование модуля MCI
    //На время инициализации запрещаем все прерывания
    MCI_MASK0=0;
    MCI_MASK1=MCI_MASK0;
    //PINSEL1=0x2280;                        //Активируем выводы контроллера карт памяти
    PINSEL1=0x00002A80;
    PINSEL4=0x0A800000;
    //Задаем режим тактирования по-умолчанию, сбрасываем требуемые регистры
    MCI_COMMAND=0;
    MCI_DATA_CTRL=0;
    MCI_CLEAR=0x7FF;                    //Сбрасываем все отложенные прерывания
    MCI_POWER=0x02;                        //Подаем напряжение на карту
    while (!(MCI_POWER & 0x02));  
    for (i=0;i<100;i++);
    //Во время идентификации тактовая частота не должна превышать 400 кГц.
    //После прохождения этой фазы частота тактового сигнала может быть установлена
    //25 МГц для SD и 20 МГц для MMC
    SetMCIClock(SLOW_RATE);
    MCI_POWER |=0x01;
}

Далее следует инициализация карты памяти
Код
unsigned char init_card (void)
{
    unsigned int i=0;

    if (!(MCI_Go_Idle_State()))                        //Переход в неактивное состояние
        return    0;                                        //Карта неизвестна
    else
    {
        if (MCI_Check_Ver())                                        //Проверка версии по команде CMD8
        {
            send_string2("SD v2\r\n");
            if (MCI_Send_ACMD_OP_Cond(OCR_INDEX_V2))
                return 2;
            else
                return 0;
        }
        else
        {
            if (!(MCI_Go_Idle_State()))
                return 0;
            else
            {
                send_string2("SD v1\r\n");
                MCI_Go_Idle_State();
                MCI_POWER |= (1 << 6 );        // Set Open Drain output control for MMC
                for ( i=0; i<0x3000; i++ );

                                //Посылаем команду CMD1 - если карта MCC - она инициализируется
                if ( MCI_Send_OP_Cond())
                    return 1;
                else
                                //В противном случае посылаем команду ACMD41 с параметром OCR_INDEX
                    if (MCI_Send_ACMD_OP_Cond(OCR_INDEX))
                        return 2;
                    else
                        return 0;
            }
        }
    }
}

Команда ACMD41 реализуется, как CMD55+ACMD41
Функция отправки CMD55
Код
unsigned char MCI_Send_ACMD( void )
{
    unsigned int i=0, t=0;
    unsigned long Argument=0;
    unsigned long Status=0;
    unsigned long Data[4];
    char buf[8];

    if (CardType==2)
    {
        Argument = CardRCA;                            
//Используется адрес из команду установки относительного адреса        
    }
    else                                                
    {
        Argument = 0x00000000;                        //Для ММС используется аргумент 0
    }
    for (t=0; t<0x200; t++)
    {
         MCI_SendCmd(CMD55, Argument, SHORT_RESP, 0 );
        Status=MCI_GetCmdResp(CMD55, SHORT_RESP, (unsigned long*)&Data[0]);
        if ((!(Status)) && (Data[0] & CARD_STATUS_ACMD_ENABLE))
        {
            send_string2("CMD55 good\r\n");
            return 1;
        }
        for (i=0; i<0x50; i++);    
    }
    memcpy(buf,&Status,4);
    send_mas2(buf,4);
    send_string2("CMD55 error\r\n");
    return 0;
}

Функция отправки ACMD41. В процессе своей работы вызывает предыдущую функцию
Код
unsigned char MCI_Send_ACMD_OP_Cond (unsigned long Argument)
{
    unsigned int t=0;                                //Счетчик попыток
    unsigned int i=0;                                //Счетчик задержек
    unsigned long Status=0;                            //Статус
    unsigned long Data[4];                            //Данные, возвращаемые при запросе
    //Если процедура Send_Op_Cond вылетела по таймауту (вставлена не карта ММС),
    //пробуем Send_ACMD_OP_Cond
    MCI_POWER &= ~(1 << 6 );    /* Clear Open Drain output control for SD */
    for ( i = 0; i < 0x3000; i++ );
    for (t=0; t<0x200; t++)
    {
        if (!(MCI_Send_ACMD()))
        {
            continue;
        }
        else
        {
            MCI_SendCmd( ACMD41, Argument, SHORT_RESP, 0 );
            Status=MCI_GetCmdResp(ACMD41, SHORT_RESP, (unsigned long *)&Data[0]);
            //Нулевой и второй бит должны быть в нуле иначе ошибка CRC или таймаут
            if (!(Status&MCI_CMD_TIMEOUT) && (Data[0] & 0x80000000))
            {
                return 1;
            }
            for ( i=0; i<0x20; i++);                     //Таймаут для следующей попытки
        }
    }
    return 0;
}

Карта Tranced 2Гб нормально опознается, как карта SD V2 и проходит инициализацию нормально. Карты же Tranced 256 Мб и Tranced 1 Гб опознаются, как SD V1, но при отправке CMD55 после первой попытки в регистре статуса устанавливаются флаги Command response timeout и Command sent (no response required) - биты 3 и 8 соответственно, при последующих попытках только флаг Command response timeout. Если строки в функции MCI_Send_ACMD()
Код
         MCI_SendCmd(CMD55, Argument, SHORT_RESP, 0 );
        Status=MCI_GetCmdResp(CMD55, SHORT_RESP, (unsigned long*)&Data[0]);

заменяю на

Код
         MCI_SendCmd(CMD55, Argument, NO_RESP, 0 );
        Status=MCI_GetCmdResp(CMD55, NO_RESP, (unsigned long*)&Data[0]);

в регистре статуса не устанавливается ни одного флага, но и в переменной Data тоже нули. Подскажите пожалуйста, как правильно в таком случае поступить? Можно будет при втором варианте отправки CMD55 просто проверить регистр статуса (что ни один из флагов не выставлен) и сразу переходить к отправке самой ACMD41? Или обязательно нужно получить ответ?
P.S. Использую среду Keil, функции отправки комманд, а также чтения ответа на команду и статуса взял из примера к LPC23xx для проверки модуля MCI.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.