Дабы не плодить темы, пишу сюда.
Есть в наличии плата на 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.