Jump to content

    
Sign in to follow this  
kostyan1

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

Recommended Posts

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

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

Share this post


Link to post
Share on other sites

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

 

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

 

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites
Документация у филипков восхитительная - просто названия флагов написаны!!!

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

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

 

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

 

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

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

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

Share this post


Link to post
Share on other sites

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

 

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

Share this post


Link to post
Share on other sites

В 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

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Edited by IgorKossak
[code] или [codebox] для кода

Share this post


Link to post
Share on other sites

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

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

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

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

работает.

Share this post


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

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

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

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

работает.

 

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

Share this post


Link to post
Share on other sites

to prgjz: как то так повелось, что не люблю я работу по всяким таймаутам и полингам, когда можно все сделать по прерываниям, но Ваш вариант возможно таки проверю. А скажите при работе Ваш логгер как часто по таймауту вываливается? Сколько миллисекунд таймаут? Что делаете при вываливании - повторяете запись в ту же страницу?

Share this post


Link to post
Share on other sites

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

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

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this