Перейти к содержанию
    

CMD25 на LPC17xx кто нибудь сделал?

Народ, кто нибудь делал на филипсах поблочную запись на SD карту. Уже неделю бьюсь, но не работает. Документация у филипков восхитительная - просто названия флагов написаны!!! Хочу сделать поблочную запись как у SAM3U: посылаем на крату CMD13 и CMD25, а потом настраиваем ДМА на записываемый блок данных и ждем в прерывании окончания передачи (DataBlockEnd). Потом натсраиваем ДМА на следующий блок и т.д. пока не подадим CMD12.

Такой код работает собственно в SAM3U. Добиться подобного на LPC1788 не могу! Все работает до первого попадания в регистре статуса флага TxFifoEmpty. Причем, если отладчиком "вставать" в коде в этом месте, то передача продолжается нормально... Такое чувство что когда встаешь отладчиком, то какието флаги успевают отработать как положено... Может кто то подсказать по флагам филиповским что то конкретное при последовательной поблочной записи???

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Делали, но не доделали, как-то проект заглох. MCI контроллер в LPC1788 взят родной ARM-овский (ARM PrimeCell MultiMedia Card Interface PL181), на него можно найти TRM на сайте ARM-а, хотя пользы от неё мало :)

 

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

 

И ещё, если у вас SDHC и выше, то можно не через CMD12 делать останов, а задать заранее через CMD23 число блоков данных.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Делал, запись работает а вот читать поблочно не получается. На LPCWare.com есть пример который я в начале взял за основу.

Но у меня примерно после 7 секунд почему то не вызывалось прерывание MCI и программка зависала не получив флаг окончания переноса данных.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Документация у филипков восхитительная - просто названия флагов написаны!!!

Документация как у всех - нормальная.

Наверное не там смотрите (кстати, где?).

 

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

 

Такое чувство что когда встаешь отладчиком, то какието флаги успевают отработать как положено...

Очень может быть...

Не используйте отладчик в течении обмена.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

to prgjz: в принципе мне только поблочная запись и нужна, читать можно и медленно. Пример вы имеетие ввиду который? Который китаец пишет на основе lpc177x_8x_mci.c? Так там в "мегафункции" int32_t MCI_Cmd_WriteBlock(uint32_t blockNum, uint32_t numOfBlock) параметр numOfBlock не используется :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, посмотрю конечно, но это не то! Там в примерах просто передача "большого" буфера состоящего из нескольких блоков по 512 байт. У меня такой задачи нет. У меня задача: один раз перевести карточку в режим мультиблока (CMD13+CMD25), а потом раз в какое то время скидывать в неё 512 байт данных по ДМА. При этом не вызывая каждый раз при записи очередного блока данных CMD13 (и ту же CMD25). Такая логика реализована в примерах для иара для sam3u, отлично работает. На филипке не могу добиться подобного.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всё просто: сначала (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

Изменено пользователем IgorKossak
[code] или [codebox] для кода

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если Вам несложно проверить, в конце вместо "Wait 2 SD clocks", поставьте паузу в 1 секунду плиз - будет ли работать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сожалею но не могу секунду ждать. У меня логгер 25600Hz 32 канала записывает.

Только я не совсем понимаю зачем тогда поблочная запись если секунду ждать можно?

Пробовал заменить на

for(volatile unsigned int i = 100; i;--i);

работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сожалею но не могу секунду ждать. У меня логгер 25600Hz 32 канала записывает.

Только я не совсем понимаю зачем тогда поблочная запись если секунду ждать можно?

Пробовал заменить на

for(volatile unsigned int i = 100; i;--i);

работает.

 

Что-то мне эта проблема напоминает ситуацию, когда последний байт начал выдвигаться и не дожидаясь завершения передачи сняли чипселект.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

to 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 которую могу только порекомендовать.

Без ОСи ждать действтительно не лучший вариант.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...