Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: CMD25 на LPC17xx кто нибудь сделал?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
kostyan
Народ, кто нибудь делал на филипсах поблочную запись на SD карту. Уже неделю бьюсь, но не работает. Документация у филипков восхитительная - просто названия флагов написаны!!! Хочу сделать поблочную запись как у SAM3U: посылаем на крату CMD13 и CMD25, а потом настраиваем ДМА на записываемый блок данных и ждем в прерывании окончания передачи (DataBlockEnd). Потом натсраиваем ДМА на следующий блок и т.д. пока не подадим CMD12.
Такой код работает собственно в SAM3U. Добиться подобного на LPC1788 не могу! Все работает до первого попадания в регистре статуса флага TxFifoEmpty. Причем, если отладчиком "вставать" в коде в этом месте, то передача продолжается нормально... Такое чувство что когда встаешь отладчиком, то какието флаги успевают отработать как положено... Может кто то подсказать по флагам филиповским что то конкретное при последовательной поблочной записи???
codier
Делали, но не доделали, как-то проект заглох. MCI контроллер в LPC1788 взят родной ARM-овский (ARM PrimeCell MultiMedia Card Interface PL181), на него можно найти TRM на сайте ARM-а, хотя пользы от неё мало sm.gif

До мультиблочной записи не дошли, но вроде проблем с DMA небыло. Хочу заметить, что при настройке DMA число транзакций указывается в словах (т.е. по 4 байта) и в итоге на сектор будет 128 записей, а в регистре LPC_MCI->DATALEN указывается полная длина блока данных.

И ещё, если у вас SDHC и выше, то можно не через CMD12 делать останов, а задать заранее через CMD23 число блоков данных.
prgjz
Делал, запись работает а вот читать поблочно не получается. На LPCWare.com есть пример который я в начале взял за основу.
Но у меня примерно после 7 секунд почему то не вызывалось прерывание MCI и программка зависала не получив флаг окончания переноса данных.
_Артём_
Цитата(kostyan @ Jul 11 2012, 16:00) *
Документация у филипков восхитительная - просто названия флагов написаны!!!

Документация как у всех - нормальная.
Наверное не там смотрите (кстати, где?).

По LPC17xx надо смотреть "UM10360 LPC17xx User manual"

Цитата(kostyan @ Jul 11 2012, 16:00) *
Такое чувство что когда встаешь отладчиком, то какието флаги успевают отработать как положено...

Очень может быть...
Не используйте отладчик в течении обмена.
kostyan
to codier: спасибо про настройки дма - это я вроде правильно делаю - запись то идет по CMD24 или по CMD25 (но после каждого блока если слать CMD12).

to prgjz: в принципе мне только поблочная запись и нужна, читать можно и медленно. Пример вы имеетие ввиду который? Который китаец пишет на основе lpc177x_8x_mci.c? Так там в "мегафункции" int32_t MCI_Cmd_WriteBlock(uint32_t blockNum, uint32_t numOfBlock) параметр numOfBlock не используется sm.gif
prgjz
В MCI_Cmd_WriteBlock() numOfBlock и не нужна. Я тоже не знаю зачем они её туда передают...
В этой функции другая ошибка:
cmdIf.Argument = blockNum * BLOCK_LENGTH;
А должно что то типа
if(SDHC)
cmdIf.Argument = blockNum;
else
cmdIf.Argument = blockNum * BLOCK_LENGTH;

А вот в MCI_WriteBlock(), которая в свою очередь вызывает MCI_Cmd_WriteBlock() стоит
LPC_MCI->DATALEN = BLOCK_LENGTH*numOfBlock;
Кстати сегодня вышел новый релиз в котором исправлены некоторые ошибки в lpc177x_8x_mci.c
Посмотрите на http://sw.lpcware.com/index.php
kostyan
Спасибо, посмотрю конечно, но это не то! Там в примерах просто передача "большого" буфера состоящего из нескольких блоков по 512 байт. У меня такой задачи нет. У меня задача: один раз перевести карточку в режим мультиблока (CMD13+CMD25), а потом раз в какое то время скидывать в неё 512 байт данных по ДМА. При этом не вызывая каждый раз при записи очередного блока данных CMD13 (и ту же CMD25). Такая логика реализована в примерах для иара для sam3u, отлично работает. На филипке не могу добиться подобного.
prgjz
Всё просто: сначала (CMD13+CMD25) а потом в цикле равном количеству секторов
CODE

for (j = 0; j < cnt; buf += 512, j++) {
/* Set MCI Transfer registers. */
LPC_MCI->DATATMR = DATA_WR_TOUT_VALUE;
LPC_MCI->DATALEN = 512;

/* Start DMA Memory to Peripheral transfer. */
DmaStart (DMA_WRITE, buf);
LPC_MCI->DATACTRL = 0x99;

for (i = DMA_TOUT; i; i--) {
if (LPC_GPDMA->RawIntTCStat & 0x01) {
/* Data transfer finished. */
break;
}
}

if (i == 0) {
/* DMA Data Transfer timeout. */
return (__FALSE);
}

if (cnt == 1) {
break;
}

/* Wait until Data Block sent to Card. */
while (LPC_MCI->STATUS != (MCI_DATA_END | MCI_DATA_BLK_END)) {
if (LPC_MCI->STATUS & (MCI_DATA_CRC_FAIL | MCI_DATA_TIMEOUT)) {
/* Error while Data Block sending occured. */
return (__FALSE);
}
}
/* Wait 2 SD clocks */
for (i = WAIT_2SD_CLK(__CPUCLK); i; i--);
}


И в конце CMD12
kostyan
Если Вам несложно проверить, в конце вместо "Wait 2 SD clocks", поставьте паузу в 1 секунду плиз - будет ли работать?
prgjz
Сожалею но не могу секунду ждать. У меня логгер 25600Hz 32 канала записывает.
Только я не совсем понимаю зачем тогда поблочная запись если секунду ждать можно?
Пробовал заменить на
for(volatile unsigned int i = 100; i;--i);
работает.
Genadi Zawidowski
Цитата(prgjz @ Jul 13 2012, 16:17) *
Сожалею но не могу секунду ждать. У меня логгер 25600Hz 32 канала записывает.
Только я не совсем понимаю зачем тогда поблочная запись если секунду ждать можно?
Пробовал заменить на
for(volatile unsigned int i = 100; i;--i);
работает.


Что-то мне эта проблема напоминает ситуацию, когда последний байт начал выдвигаться и не дожидаясь завершения передачи сняли чипселект.
kostyan
to prgjz: как то так повелось, что не люблю я работу по всяким таймаутам и полингам, когда можно все сделать по прерываниям, но Ваш вариант возможно таки проверю. А скажите при работе Ваш логгер как часто по таймауту вываливается? Сколько миллисекунд таймаут? Что делаете при вываливании - повторяете запись в ту же страницу?
prgjz
#define DMA_TOUT 10000000
Ещё ни разу не выалился по таймауту.
Сама запись через DMA относительно постоянна по времени.
SanDisk Extreme Pro 20Mhz CLK: 2мс ждёт в цикле для 16ти секторов (8kbyte)
for (i = DMA_TOUT; i; i--) {
if (LPC_GPDMA->RawIntTCStat & (1<<(GPDMA_MCI_WRITE_CHANNEL))) {
/* Data transfer finished. */
break;
}
}

В начале использовал прерыания чтобы не ждать. Но для поблочного переноса нужно дать для того чтоб в конце
переноса CMD12 (Stop Read or Write transm.) послать.
При использовании ОСи не проблема подождать в низко приоритетной задаче.
Я использую TNKernel которую могу только порекомендовать.
Без ОСи ждать действтительно не лучший вариант.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.