Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: SD card: 512 blocks limit.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
pitt
Sorry for using English - I don't have russian keyboard.
Here is my problem: I'm writing blocks 512 bytes each on consecutive sectors of SDHC card. Hardware is STM3240G-EVAL. No file system, no OS no interrupts except SDIO and DMA serving SDIO. The goal is to test the software and measure my access speed: average and lowest. When I'm writing 256 blocks(CMD25) at a time loop of 1000 times I don't have issues except sometimes(5%) access time is more than 10 times greater than average. Don't know why but it is. When I'm writing 512 blocks Average speed is the same but lowest is almost 20 times above average. And the last thing: as soon as I'm trying to write >512 blocks I'm getting instantly FEIF...
Please share your thoughts and knowledge.

Thank you in advance.

Google translator:
Вот моя проблема: я пишу блоки 512 байт каждый на подряд секторов SDHC карты. Аппаратное STM3240G-EVAL. Нет файловая система, нет ОС нет прерывания кроме SDIO и DMA служащая для SDIO.Целью является для тестирования программного обеспечения и измерения мою скорость доступа: средний и низкий. Когда я пишу 256 блоков (CMD25) в петле времени в 1000 раз меня нет проблем, кроме иногда(5%) время доступа более чем в 10 раз больше, чем в среднем. Не знаю почему, но это так. Когда я пишу 512 блоков Средняя скорость же, но низкая почти в 20 раз выше среднего. И последнее: как только я пытаюсь написать> 512 блоков я получаю мгновенно FEIF ...
Пожалуйста, поделитесь своими мыслями и знаниями.
Dr.Alex
Цитата(pitt @ May 7 2015, 23:44) *
sometimes(5%) access time is more than 10 times greater than average.

I guess it is normal.
I did not ever bother to test access time for each of that small blocks because I needed *highest* possible write speed which is achievable with BIG chunks only (got over 100 Mbps with regular class-10 or UHS-I cards).


Цитата(pitt @ May 7 2015, 23:44) *
And the last thing: as soon as I'm trying to write >512 blocks I'm getting instantly FEIF...

You'd better try STMcube HAL. It works (with some issues time to time discussed here).
Also you can try Chibios alone with its HAL.
pitt
Цитата(Dr.Alex @ May 7 2015, 17:26) *
You'd better try STMcube HAL. It works (with some issues time to time discussed here).
Also you can try Chibios alone with its HAL.

Подобное творение - STMcube HAL, можно рассматривать исключительно как референс, что я и делал, но ответов на многочисленные вопросы, никак не раскрытые в Reference Manual оно не дает.
Chibios тоже использую, но предпочитаю освоить "материальную часть", а не полагаться на других.
Пример:
Код
#if (defined(STM32F4XX) || defined(STM32F2XX))
  /* Wait until DMA channel enabled to be sure that all data transferred.*/

/***********************************************/  
while (sdcp->dma->stream->CR & STM32_DMA_CR_EN);
/***********************************************/

  /* DMA event flags must be manually cleared.*/
  dmaStreamClearInterrupt(sdcp->dma);

  SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS;
  SDIO->DCTRL = 0;
  osalSysUnlock();

  /* Wait until interrupt flags to be cleared.*/
  /*while (((DMA2->LISR) >> (sdcp->dma->ishift)) & STM32_DMA_ISR_TCIF)
    dmaStreamClearInterrupt(sdcp->dma);*/
#else

Ну да, прекрасный образчик лупа: пусть остальные занимаются прерываниями пока мы ждем-с...
И, кстати, а зачем флаги ошибок проверять, когда можно все почистить?
Может у меня не свежая версия или ну фантазии, например, не хватает...

Могу и другие примеры привести...


Если у Вас есть код/образчик многоблоковой записи через DMA, буду очень признателен за возможность ознакомиться: есть вопросы с очередностью операций и, особенно, с флагом FEIE.

Спасибо за ответ.
AHTOXA
Цитата(pitt @ May 8 2015, 05:00) *
Если у Вас есть код/образчик многоблоковой записи через DMA, буду очень признателен за возможность ознакомиться: есть вопросы с очередностью операций и, особенно, с флагом FEIE.

Ссылка на отличные примеры по работе с SDIO: вот. Мне они очень помогли.
jcxz
Цитата(pitt @ May 8 2015, 02:44) *
I don't have issues except sometimes(5%) access time is more than 10 times greater than average. Don't know why but it is. When I'm writing 512 blocks Average speed is the same but lowest is almost 20 times above average.

Это нормально. Многоблочная запись пишет сектора в некоторый буфер (ОЗУ) внутри карты. Когда карта решает, что в нём данных накопилось некоторое кол-во,
она выполняет физическую запись накополенного в буфере. И в конце, при получении Stop Transfer, пишет остаток. В эти моменты и получаете задержки.
Это хорошо видно на осциллограмме: после большинства блоков BUSY короткий, но после некоторых - длинный.
Либо выполняется стирание данных в тех блоках, в которые пойдёт запись. Вы команду ACMD23 перед многоблочной записью выполняете? Я вот не выполнял. Может с ней задержки будут меньше.

Насчёт 512 блоков подряд не очень понял - у меня вроде не было проблем. Хотя надо посмотреть в сторону такого параметра SD-карты как "минимальный стираемый блок" (есть в CSD).
Как я наблюдал на многих картах, он может иметь размер около 64кБ. Может быть с этим связано.

Цитата(pitt @ May 8 2015, 06:00) *
Если у Вас есть код/образчик многоблоковой записи через DMA, буду очень признателен за возможность ознакомиться: есть вопросы с очередностью операций и, особенно, с флагом FEIE.

Я писал для SPI-интерфейса. 2-3 месяца назад (LPC1788). Мой драйвер позволяет пользовательскому уровню работать либо напрямую (операции одноблочного чтения и многоблочного продолженного чтения;
однобочной записи и многоблочной продолженной записи), либо через FatFS. При этом если в ПО есть две задачи, одна из которых обращается напрямую, а другая - через FatFS, то они не будут мешать друг другу. FatFS работает через мой драйвер (он выполняет роль низкоуровневого доступа к SD).
Естественно - никаких ожиданий в глухих лупах нет - используется uCOS и её объекты синхронизации. Более того - есть поддержка работы службы снижения потребления питания
(есть нотификации в службу о периодах работы/простоя драйвера) для возможности ухода в сон устройства.
В моём драйвере передача блоков данных/команд идёт через DMA, ожидание готовности - периодическая программная посылка 0xFF в SPI с прерыванием по приёму с таймаутом.
Вряд-ли Вам чем-то поможет кусок моего исходника, но всё-таки выложу:
CODE
//Переходит сюда после успешного обнаружения и идентификации SD-карты.
//Здесь обрабатываются запросы операций от пользователей SD-сервиса
//прикладного уровня.
static FFaza FazaIdle()
{
SDact act;
u32 i, j, n;
u8 typ;
do {
ILivePing(ILIVE_SD);
act.op = act.OP_NONE;
if (!sdReq) {
IdleBegin(IDLE_READY_SD);
MboxPend(sdMbox, ms2tkt(300));
if (!Pdat(PIN_SD_INSERT)) return (FFaza)FazaIdle;
LogsCR(COL_BLACK "Card removed");
return (FFaza)FazaRestart;
}
} while (!(n = Prepare(&act)));
IdleEnd(IDLE_READY_SD);
MboxAccept(sdMbox);
while (1) {
if (act.op == act.OP_WAIT_READY) StartAct();
else if (act.op == act.OP_TRIM) {
if (cardType <= CARD_MMC) {
sdCompletes[act.user](NULL);
return (FFaza)FazaIdle;
}
#ifdef SD_ARG_CHK
SDassert(act.trim.start <= act.trim.end, REGION_SDREQ_TRIM);
#endif
StartAct();
if ((j = act.trim.start) < sdCapacity) {
j -= j % sdEraseSize;
if (cardType != CARD_SD2_BLOCK) j <<= SD_SECTOR_LEN;
if (SendCmd(CM_SET_ERASE_START, j)) FazaIdleRestart(&act);
if ((j = act.trim.end) >= sdCapacity) j = sdCapacity - 1;
j = j - j % sdEraseSize + sdEraseSize - 1;
if (cardType != CARD_SD2_BLOCK) j <<= SD_SECTOR_LEN;
if (SendCmd(CM_SET_ERASE_END, j)) FazaIdleRestart(&act);
if (SendCmd(CM_ERASE)) FazaIdleRestart(&act);
}
} else if (act.op != act.OP_NONE) break;
sdCompletes[act.user](&act.rw.buf);
SDsselOff();
OffSpi();
return (FFaza)FazaIdle;
}
#ifdef SD_ARG_CHK
SDassert(act.rw.buf && act.rw.sector < sdCapacity &&
act.rw.secOfs < SD_SECTOR_LEN, REGION_SDREQ_RW);
#endif
for (typ = 0; ; ) {
ILivePing(ILIVE_SD);
if ((uint)(act.op - act.OP_READ_1) <= act.OP_READ_N - act.OP_READ_1) {
if (sector != act.rw.sector || !sectorValid) {
while (1) {
if (!typ) if (StartAct()) break;
i = CM_READ_MULTIPLE_BLOCK;
if (n == 1 << SD_SECTOR_LEN && act.op == act.OP_READ_1)
i = CM_READ_SINGLE_BLOCK;
typ = i - CM_READ_MULTIPLE_BLOCK;
u32 jj = act.rw.sector;
if (cardType != CARD_SD2_BLOCK) jj <<= SD_SECTOR_LEN;
if (SendCmd(i, jj)) FazaIdleRestart(&act);
break;
}
if (RcvDataPacket(sh.sectorBuf, 1 << SD_SECTOR_LEN,
ms2tkt(100)) >= 0) break;
sector = act.rw.sector;
sectorValid = 1;
}
i = act.rw.secOfs;
if ((j = (1 << SD_SECTOR_LEN) - i) > n) j = n;
memcpy(act.rw.buf, &sh.sectorBuf[i], j);
if ((i = act.rw.secOfs + j) >> SD_SECTOR_LEN) {
act.rw.sector++;
i = 0;
}
act.rw.secOfs = i;
} else {
i = DataCRC(act.rw.buf, j = 1 << SD_SECTOR_LEN);
while (1) {
if (typ) WaitR1b();
else if (StartAct()) {
WaitR1b();
break;
}
typ = sectorValid = 0;
int ii = CM_WRITE_MULTIPLE_BLOCK;
if (n == 1 << SD_SECTOR_LEN && act.op == act.OP_WRITE_1) {
typ = TOKEN_DATA - TOKEN_DATA_WMB;
ii = CM_WRITE_BLOCK;
}
u32 jj = act.rw.sector;
if (cardType != CARD_SD2_BLOCK) jj <<= SD_SECTOR_LEN;
if (SendCmd(ii, jj)) FazaIdleRestart(&act);
break;
}
if (SndDataPacket(act.rw.buf, j, i, typ + TOKEN_DATA_WMB) !=
SND_PACKET_OK) break;
act.rw.sector++;
}
act.rw.buf += j;
if (n -= j) continue;
while (!(n = sdCompletes[act.user](&act.rw.buf))) {
if (!act.rw.buf) {
if (!PeripheralPowerState(concatAB(PERIPH_PCSSP, nSSP_sd)))
return (FFaza)FazaIdle;
if (!typ) {
if ((uint)(act.op - act.OP_READ_1) > 1) {
WaitR1b();
SndStopTran();
} else if (SendCmd(CM_STOP_TRANSMISSION)) FazaIdleRestart(&act);
}
#ifdef SD_SAFE_WRITE
if ((uint)(act.op - act.OP_WRITE_1) <=
act.OP_WRITE_N - act.OP_WRITE_1) {
WaitR1b();
if (SendCmd(CM_SEND_STATUS)) FazaIdleRestart(&act);
}
#endif //SD_SAFE_WRITE
SDsselOff();
OffSpi();
return (FFaza)FazaIdle;
}
if (!(AtomicSwap(&sdReq, 0) & 1 << SDREQ_START)) do {
MboxPend(sdMbox, ms2tkt(300));
ILivePing(ILIVE_SD);
} while (!sdReq);
sdReq = 1 << SDREQ_BUSY;
MboxAccept(sdMbox);
}
#ifdef SD_ARG_CHK
SDassert(act.rw.buf, REGION_SDREQ_RW);
#endif
}
FazaIdleRestart(&act);
}

union SDact {
enum {
OP_NONE, //нет операции
OP_READ_1, //выполнить чтение цепочки секторов без возможности продолжения
OP_READ_N, //выполнить чтение цепочки секторов с возможностью продолжения
OP_WRITE_1, //выполнить запись цепочки секторов без возможности продолжени
OP_WRITE_N, //выполнить запись цепочки секторов с возможностью продолжения
OP_TRIM, //выполнить стирание цепочки секторов
OP_WAIT_READY, //ожидание освобождения SD-карты (снятия сигнала BUSY)
OP_n};
enum {SD_USER_TERMINAL, SD_USER_FF, SD_USER_n};
struct { //для OP_READ_.., OP_WRITE_..
u8 *buf;
u32 sector;
u16 secOfs;
} rw;
struct { //для OP_TRIM
u32 start, end;
} trim;
struct { //для всех OP_..
u32 unuse0[2];
u16 unuse1;
u8 op, user;
};
};


Данный кусок выполняет приём запросов на операции с SD от прикладных задач, их выполнение, нотификацию источников запросов о завершении
выполнения (или о возможности продолжения выполнения).
Собственно функция SndDataPacket() и выполняет отправку блока записываемых данных через SPI+DMA.
WaitR1b() - ожидание освобождения интерфейса (снятие BUSY картой).
SendCmd() - отсылка команды карте.
Функция Prepare() принимает запрос на операцю с SD от пользовательского уровня.
Собственно со строки for (typ = 0; ; ) { начинается обработка запросов чтения и записи (многоблочных и одноблочных).
pitt
Цитата(AHTOXA @ May 8 2015, 00:18) *
Ссылка на отличные примеры по работе с SDIO: вот. Мне они очень помогли.

Thank you. I've seen that but didn't find some answers:
Цитата
//Check if the DMA is disabled (SDIO disables the DMA after it is done with it)

Could you please point me where this is in RM?
Код
  //Check if the DMA is disabled (SDIO disables the DMA after it is done with it)
  while (DMA2_Stream3->CR & DMA_SxCR_EN) {};

Very nice loop wub.gif
Код
if (DMA2->LISR & (DMA_LISR_TCIF3 | DMA_LISR_TEIF3 | DMA_LISR_DMEIF3 | DMA_LISR_FEIF3)) {
      if (!(DMA2->LISR & DMA_LISR_TCIF3)) {//A DMA error has occured. Panic!

Always have FEIF set!!! Why? How to get rid of it? Keil example doesn't look at this flag at all.

Thank you for replay though.



Цитата(jcxz @ May 8 2015, 03:44) *

Thank you.



This is the snippet from my code:
Код
void DMA2_Stream3_IRQHandler (void) {
    event_dma = true;
    *(uint8_t *)&dma_isr = DMA2->LISR>>DMA_ISR_STREAM_3;
    if (_sdio->dma_isr != NULL) (*_sdio->dma_isr)(_sdio);
    DMA2->LIFCR &= (DMA_LIFCR_CTCIF3|DMA_LIFCR_CHTIF3|DMA_LIFCR_CTEIF3|DMA_LIFCR_CDMEIF3|DMA_LIF
CR_CFEIF3);
    DMA2_Stream3->CR  &= ~(DMA_SxCR_TCIE |DMA_SxCR_TEIE);
    DMA2_Stream3->FCR &= ~DMA_SxFCR_FEIE;
}

_sdio->dma_isr is NULL
When event_dma is noticed dma_isr has only FEIF set but DMA->LISR has FEIF and TCIF even they both were cleaned in the handler...
AHTOXA
Цитата(pitt @ May 8 2015, 17:30) *
Could you please point me where this is in RM?

31.3.2 SDIO APB2 interface.
Там пример транзакции DMA. Да это и логично, ведь в случае с SDIO у нас периферийный модуль является flow controller-ом.
Цитата(pitt @ May 8 2015, 17:30) *
Very nice loop wub.gif

Ой, да ладно. Понятно же, что это в целях упрощения примера. Никто не мешает включить прерывание и взводить там какой-то флаг.
Цитата(pitt @ May 8 2015, 17:30) *
Always have FEIF set!!! Why? How to get rid of it? Keil example doesn't look at this flag at all.

Посмотрел у себя - я тоже не смотрю на этот флаг.
pitt
Цитата(AHTOXA @ May 8 2015, 14:31) *
31.3.2 SDIO APB2 interface.
Там пример транзакции DMA. Да это и логично, ведь в случае с SDIO у нас периферийный модуль является flow controller-ом.

Ой, да ладно. Понятно же, что это в целях упрощения примера. Никто не мешает включить прерывание и взводить там какой-то флаг.

Посмотрел у себя - я тоже не смотрю на этот флаг.

Try this:
Код
/* SDIO Interrupt Handler */
void SDIO_IRQHandler (void) {
  sdio_sta = SDIO->STA;
//  event_sdio = true;
event_sdio++;
//  if (_sdio->dma_isr != NULL) (*_sdio->sdio_isr)(_sdio);  // call back function
  SDIO->ICR = SDIO_ICR_CLEAR_ALL;
}


Before allowed interrupt flags
SDIO->MASK |= (SDIO_MASK_DCRCFAILIE|SDIO_MASK_DTIMEOUTIE|SDIO_MASK_TXUNDERRIE|SDIO_MASK_DATAEN
DIE|SDIO_MASK_STBITERRIE);

Look what event_sdio is? In my case it is 2 and the second time it caused by the DATAEND even as you can see it was CLEARED!!!



Цитата(AHTOXA @ May 8 2015, 14:31) *
Посмотрел у себя - я тоже не смотрю на этот флаг.


This flag is the only one indicates my problem when I'm going over 512 blocks...I was ignoring it before.
AHTOXA
Цитата(pitt @ May 9 2015, 00:42) *
This flag is the only one indicates my problem when I'm going over 512 blocks...I was ignoring it before.

Я не совсем понял, вы пытаетесь отправить 512 блоков по 512 байт одной транзакцией DMA? Так это не выйдет, счётчик-то (DMA_SxNDTR) 16-битный sm.gif
Как раз 512*512/4 = 0x10000. Не помещается.

Цитата(pitt @ May 9 2015, 00:42) *
Look what event_sdio is? In my case it is 2 and the second time it caused by the DATAEND even as you can see it was CLEARED!!!

Попробуйте добавить барьер после очистки флагов:
Код
SDIO->ICR = SDIO_ICR_CLEAR_ALL;
__DSB();
pitt
Цитата(AHTOXA @ May 8 2015, 15:53) *
Я не совсем понял, вы пытаетесь отправить 512 блоков по 512 байт одной транзакцией DMA? Так это не выйдет, счётчик-то (DMA_SxNDTR) 16-битный sm.gif
Как раз 512*512/4 = 0x10000. Не помещается.


Попробуйте добавить барьер после очистки флагов:
Код
SDIO->ICR = SDIO_ICR_CLEAR_ALL;
__DSB();


Thanks for the first tip - forgot...
Wait a minute. We're using SDIO_DLEN and it is 24 bit. Please point me out where it says that DMA limits the size of transaction.

__DSB(); doesn't help the problem is a second DATAEND interrupt.

Код
/* SDIO Interrupt Handler */
void SDIO_IRQHandler (void) {
  sdio_sta = SDIO->STA;
  event_sdio = true;
  if (_sdio->dma_isr != NULL) (*_sdio->sdio_isr)(_sdio);
  SDIO->MASK &= ~SDIO_MASK_DATAENDIE;    // WTF???
  SDIO->ICR = SDIO_ICR_CLEAR_ALL;
}


That is how it works
Golikov A.
Тоже хочу делать роботов на гусенках.... даже могу сд карту осилить
AHTOXA
Цитата(pitt @ May 9 2015, 01:22) *
Wait a minute. We're using SDIO_DLEN and it is 24 bit. Please point me out where it says that DMA limits the size of transaction.

Явного указания не припоминаю, но с точки зрения здравого смысла - если периферийный модуль является flow controller-ом, то это не значит, что подконтрольный модуль DMA сможет передавать больше данных. Скорее всего, SDIO_DLEN просто как-то управляет значением DMA_SxNDTR.
Кстати, вы легко можете проверить эту теорию - запустите транзакцию на, скажем, 20 секторов, и в прерывании DMA Half-transfer посмотрите значение DMA_SxNDTR. Если там будет половина от начального значения SDIO_DLEN, то всё так и есть.
Цитата(pitt @ May 9 2015, 01:22) *
__DSB(); doesn't help the problem is a second DATAEND interrupt.

У меня там стоит запрещение прерывания от SDIO, так что я не вижу повторного вхождения.
jcxz
Цитата(Golikov A. @ May 9 2015, 02:44) *
Тоже хочу делать роботов на гусенках.... даже могу сд карту осилить

Так делайте. Кто-ж Вам мешает wink.gif
А кстати - зачем на гусенках SD???
pitt
Поздравляю всех с днем нашей общей Победы. Вечная память погибшим, урок для живущих.

Цитата(AHTOXA @ May 9 2015, 02:04) *
Явного указания не припоминаю

У меня там стоит запрещение прерывания от SDIO, так что я не вижу повторного вхождения.

Отвратительная документация.
Вы можете разрешить и убедиться. К тому же, прерывания по DMA_SxCR_EN нет, а вот, похоже, именно оно и необходимо. Если Вы в DMA разрешите прерывание по FEIE, но тоже увидете повторное вхождение.
Код
/* DMA Interrupt Handler */
#if   defined  SDIO_DMA_STREAM3
void DMA2_Stream3_IRQHandler (void) {
//  if (DMA2_Stream3->CR & DMA_SxCR_EN) DMA2->LIFCR &= (DMA_LIFCR_CTCIF3|DMA_LIFCR_CHTIF3|DMA_LIFCR_CTEIF3|DMA_LIFCR_CDMEIF3|DMA_LIF
CR_CFEIF3);
//  else {
    event_dma = true;
    *(uint8_t *)&dma_isr = DMA2->LISR>>DMA_ISR_STREAM_3;
    if (_sdio->dma_isr != NULL) (*_sdio->dma_isr)(_sdio);
    DMA2->LIFCR &= (DMA_LIFCR_CTCIF3|DMA_LIFCR_CHTIF3|DMA_LIFCR_CTEIF3|DMA_LIFCR_CDMEIF3|DMA_LIF
CR_CFEIF3);
    DMA2_Stream3->CR  &= ~(DMA_SxCR_TCIE |DMA_SxCR_TEIE);
    DMA2_Stream3->FCR &= ~DMA_SxFCR_FEIE;
//  }
}

Раскомментируйте и полюбуйтесь.

Кристалл сложный, ошибки неизбежны, но ведь можно их хорошо задокументировать, а их errata &^%$#@!

Цитата(jcxz @ May 9 2015, 07:20) *
А кстати - зачем на гусенках SD???

DVR. А само изделие(без манипулятора) 2006-2008 года на 2-3х AT90CAN64(в зависимости от комплектации) и паре AT90PWM316 именно для привода.
pitt
Цитата(AHTOXA @ May 8 2015, 15:53) *
Я не совсем понял, вы пытаетесь отправить 512 блоков по 512 байт одной транзакцией DMA? Так это не выйдет, счётчик-то (DMA_SxNDTR) 16-битный sm.gif
Как раз 512*512/4 = 0x10000. Не помещается.

По-видимому, Вы правы, но 512*512 = 2^9 * 2^9 = 2^18 = 2^16 * 4, т.е 2 в степени 16 32-битных значений. И это получается, а вот >512 блоков не проходит и получается правдивость Вашей гипотезы.
AHTOXA
Да, конечно же я имел в виду, что больше 512 блоков не получится.
pitt
Цитата(AHTOXA @ May 10 2015, 10:58) *
Да, конечно же я имел в виду, что больше 512 блоков не получится.

Хорошо бы, если об этом упоминалось в мануале...

А что будем с FEIF делать? И с повторными вхождениями? Терпеть не могу недодокументированность... Можно, конечно, ограничить число блоков величиной 512 и тогда, вроде, можно обойтись без FEIF, но нет документированных оснований.

Скажите, а поддрежка со стороны STM в Европе такая же архипрехреновая как и в Новом Свете?
Golikov A.
они торопятся с чипами, так что их не хватает, ошибки не успевают обслуживать, а вы неточности от них ждете)...

если поглядеть просторы интернета
FEIF - про этот флаг многие говорят, и многие сходятся к простому его игнорированию.

в описании я нашел вот что
Цитата
Caution is required when choosing the FIFO threshold (bits FTH[1:0] of the DMA_SxFCR
register) and the size of the memory burst (MBURST[1:0] of the DMA_SxCR register): The
content pointed by the FIFO threshold must exactly match to an integer number of memory
burst transfers. If this is not in the case, a FIFO error (flag FEIFx of the DMA_HISR or
DMA_LISR register) will be generated when the stream is enabled, then the stream will be
automatically disabled. The allowed and forbidden configurations are described in the
Table 48: FIFO threshold configurations.

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

pitt
Цитата(Golikov A. @ May 11 2015, 05:40) *
...если поглядеть просторы интернета
FEIF - про этот флаг многие говорят, и многие сходятся к простому его игнорированию.

Links please.
Цитата(Golikov A. @ May 11 2015, 05:40) *
в описании я нашел вот что
дальше табличка идет запрещенных конфигураций, может с ней свериться... в ней больше запрещено чем разрешено...


The mode we're using (the last one on the page 315) is allowed, so the question still remains: why do I get stupid FEIF?!
Why STM doesn't clarify this issue? Well, one can ask many more rhetorical questions but the main one is always: Who needs rhetorical questions?!
AHTOXA
Цитата(pitt @ May 11 2015, 07:21) *
Можно, конечно, ограничить число блоков величиной 512 и тогда, вроде, можно обойтись без FEIF, но нет документированных оснований.

Вот, самое оптимальное решение. Всё равно в реальной жизни вам вряд-ли потребуется передавать более 512 блоков за раз. А попытки найти истину (документальные обоснования, ответы от техподдержки) в этом случае - просто непроизводительные потери времени. ИМХО конечно.
Golikov A.
ссылки...
ну типа
http://forum.easyelectronics.ru/viewtopic....69&start=75


если писать в разных вариантах сочетания
STM DMA FEIF SDIO то выпадают разные темы, в каких то люди просто не так запускали и получали ошибку, но попадаются как ваша, где концов появления не нашли...
pitt
Проблема в том, что я не могу просимулировать ошибки. Пока только одна - запись более 512 блоков - проявляется надежно и она только выявляется через FEIF. Так как пишу прямиком с камеры JPG без проблем превышает 512 блоков... Когда и при каких обстоятельствах возникают другие ошибки...
С работы опубликую ВЕСЬ тестовый проект. Давайте вместе доведем до ума. Да, никаких их HAL или библиотек, все сам - за проблемы не им отвечать.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.