kostyan1 0 11 июля, 2012 Опубликовано 11 июля, 2012 · Жалоба Народ, кто нибудь делал на филипсах поблочную запись на SD карту. Уже неделю бьюсь, но не работает. Документация у филипков восхитительная - просто названия флагов написаны!!! Хочу сделать поблочную запись как у SAM3U: посылаем на крату CMD13 и CMD25, а потом настраиваем ДМА на записываемый блок данных и ждем в прерывании окончания передачи (DataBlockEnd). Потом натсраиваем ДМА на следующий блок и т.д. пока не подадим CMD12. Такой код работает собственно в SAM3U. Добиться подобного на LPC1788 не могу! Все работает до первого попадания в регистре статуса флага TxFifoEmpty. Причем, если отладчиком "вставать" в коде в этом месте, то передача продолжается нормально... Такое чувство что когда встаешь отладчиком, то какието флаги успевают отработать как положено... Может кто то подсказать по флагам филиповским что то конкретное при последовательной поблочной записи??? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
codier 0 11 июля, 2012 Опубликовано 11 июля, 2012 · Жалоба Делали, но не доделали, как-то проект заглох. MCI контроллер в LPC1788 взят родной ARM-овский (ARM PrimeCell MultiMedia Card Interface PL181), на него можно найти TRM на сайте ARM-а, хотя пользы от неё мало :) До мультиблочной записи не дошли, но вроде проблем с DMA небыло. Хочу заметить, что при настройке DMA число транзакций указывается в словах (т.е. по 4 байта) и в итоге на сектор будет 128 записей, а в регистре LPC_MCI->DATALEN указывается полная длина блока данных. И ещё, если у вас SDHC и выше, то можно не через CMD12 делать останов, а задать заранее через CMD23 число блоков данных. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prgjz 0 11 июля, 2012 Опубликовано 11 июля, 2012 · Жалоба Делал, запись работает а вот читать поблочно не получается. На LPCWare.com есть пример который я в начале взял за основу. Но у меня примерно после 7 секунд почему то не вызывалось прерывание MCI и программка зависала не получив флаг окончания переноса данных. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 11 июля, 2012 Опубликовано 11 июля, 2012 · Жалоба Документация у филипков восхитительная - просто названия флагов написаны!!! Документация как у всех - нормальная. Наверное не там смотрите (кстати, где?). По LPC17xx надо смотреть "UM10360 LPC17xx User manual" Такое чувство что когда встаешь отладчиком, то какието флаги успевают отработать как положено... Очень может быть... Не используйте отладчик в течении обмена. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kostyan1 0 12 июля, 2012 Опубликовано 12 июля, 2012 · Жалоба to codier: спасибо про настройки дма - это я вроде правильно делаю - запись то идет по CMD24 или по CMD25 (но после каждого блока если слать CMD12). to prgjz: в принципе мне только поблочная запись и нужна, читать можно и медленно. Пример вы имеетие ввиду который? Который китаец пишет на основе lpc177x_8x_mci.c? Так там в "мегафункции" int32_t MCI_Cmd_WriteBlock(uint32_t blockNum, uint32_t numOfBlock) параметр numOfBlock не используется :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prgjz 0 12 июля, 2012 Опубликовано 12 июля, 2012 · Жалоба В 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kostyan1 0 12 июля, 2012 Опубликовано 12 июля, 2012 · Жалоба Спасибо, посмотрю конечно, но это не то! Там в примерах просто передача "большого" буфера состоящего из нескольких блоков по 512 байт. У меня такой задачи нет. У меня задача: один раз перевести карточку в режим мультиблока (CMD13+CMD25), а потом раз в какое то время скидывать в неё 512 байт данных по ДМА. При этом не вызывая каждый раз при записи очередного блока данных CMD13 (и ту же CMD25). Такая логика реализована в примерах для иара для sam3u, отлично работает. На филипке не могу добиться подобного. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prgjz 0 12 июля, 2012 Опубликовано 12 июля, 2012 (изменено) · Жалоба Всё просто: сначала (CMD13+CMD25) а потом в цикле равном количеству секторов 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 Изменено 12 июля, 2012 пользователем IgorKossak [code] или [codebox] для кода Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kostyan1 0 13 июля, 2012 Опубликовано 13 июля, 2012 · Жалоба Если Вам несложно проверить, в конце вместо "Wait 2 SD clocks", поставьте паузу в 1 секунду плиз - будет ли работать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prgjz 0 13 июля, 2012 Опубликовано 13 июля, 2012 · Жалоба Сожалею но не могу секунду ждать. У меня логгер 25600Hz 32 канала записывает. Только я не совсем понимаю зачем тогда поблочная запись если секунду ждать можно? Пробовал заменить на for(volatile unsigned int i = 100; i;--i); работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 13 июля, 2012 Опубликовано 13 июля, 2012 · Жалоба Сожалею но не могу секунду ждать. У меня логгер 25600Hz 32 канала записывает. Только я не совсем понимаю зачем тогда поблочная запись если секунду ждать можно? Пробовал заменить на for(volatile unsigned int i = 100; i;--i); работает. Что-то мне эта проблема напоминает ситуацию, когда последний байт начал выдвигаться и не дожидаясь завершения передачи сняли чипселект. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kostyan1 0 16 июля, 2012 Опубликовано 16 июля, 2012 · Жалоба to prgjz: как то так повелось, что не люблю я работу по всяким таймаутам и полингам, когда можно все сделать по прерываниям, но Ваш вариант возможно таки проверю. А скажите при работе Ваш логгер как часто по таймауту вываливается? Сколько миллисекунд таймаут? Что делаете при вываливании - повторяете запись в ту же страницу? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prgjz 0 19 июля, 2012 Опубликовано 19 июля, 2012 · Жалоба #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 которую могу только порекомендовать. Без ОСи ждать действтительно не лучший вариант. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться