|
SD card: 512 blocks limit. |
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 21)
|
May 7 2015, 21:26
|
Профессионал
    
Группа: Свой
Сообщений: 1 386
Регистрация: 5-04-05
Из: моська, RF
Пользователь №: 3 863

|
Цитата(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.
|
|
|
|
|
May 8 2015, 00:00
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(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. Спасибо за ответ.
Сообщение отредактировал pitt - May 8 2015, 00:21
--------------------
|
|
|
|
|
May 8 2015, 07:44
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(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; ; ) { начинается обработка запросов чтения и записи (многоблочных и одноблочных).
|
|
|
|
|
May 8 2015, 12:30
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(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 Код 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...
Сообщение отредактировал pitt - May 8 2015, 13:23
--------------------
|
|
|
|
|
May 8 2015, 18:31
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(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  Ой, да ладно. Понятно же, что это в целях упрощения примера. Никто не мешает включить прерывание и взводить там какой-то флаг. Цитата(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. Посмотрел у себя - я тоже не смотрю на этот флаг.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 8 2015, 19:42
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(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.
--------------------
|
|
|
|
|
May 8 2015, 19:53
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(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-битный Как раз 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();
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 8 2015, 20:22
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(AHTOXA @ May 8 2015, 15:53)  Я не совсем понял, вы пытаетесь отправить 512 блоков по 512 байт одной транзакцией DMA? Так это не выйдет, счётчик-то (DMA_SxNDTR) 16-битный Как раз 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
Сообщение отредактировал pitt - May 8 2015, 20:38
--------------------
|
|
|
|
|
May 9 2015, 06:04
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(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, так что я не вижу повторного вхождения.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 9 2015, 12:10
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Поздравляю всех с днем нашей общей Победы. Вечная память погибшим, урок для живущих. Цитата(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 - May 9 2015, 12:06
--------------------
|
|
|
|
|
May 10 2015, 14:49
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(AHTOXA @ May 8 2015, 15:53)  Я не совсем понял, вы пытаетесь отправить 512 блоков по 512 байт одной транзакцией DMA? Так это не выйдет, счётчик-то (DMA_SxNDTR) 16-битный Как раз 512*512/4 = 0x10000. Не помещается. По-видимому, Вы правы, но 512*512 = 2^9 * 2^9 = 2^18 = 2^16 * 4, т.е 2 в степени 16 32-битных значений. И это получается, а вот >512 блоков не проходит и получается правдивость Вашей гипотезы.
Сообщение отредактировал pitt - May 11 2015, 02:20
--------------------
|
|
|
|
|
May 11 2015, 02:21
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(AHTOXA @ May 10 2015, 10:58)  Да, конечно же я имел в виду, что больше 512 блоков не получится. Хорошо бы, если об этом упоминалось в мануале... А что будем с FEIF делать? И с повторными вхождениями? Терпеть не могу недодокументированность... Можно, конечно, ограничить число блоков величиной 512 и тогда, вроде, можно обойтись без FEIF, но нет документированных оснований. Скажите, а поддрежка со стороны STM в Европе такая же архипрехреновая как и в Новом Свете?
Сообщение отредактировал pitt - May 11 2015, 02:40
--------------------
|
|
|
|
|
May 11 2015, 09:40
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
они торопятся с чипами, так что их не хватает, ошибки не успевают обслуживать, а вы неточности от них ждете)... если поглядеть просторы интернета 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. дальше табличка идет запрещенных конфигураций, может с ней свериться... в ней больше запрещено чем разрешено...
|
|
|
|
|
May 11 2015, 17:02
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(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?!
Сообщение отредактировал pitt - May 12 2015, 01:29
--------------------
|
|
|
|
|
May 12 2015, 04:06
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(pitt @ May 11 2015, 07:21)  Можно, конечно, ограничить число блоков величиной 512 и тогда, вроде, можно обойтись без FEIF, но нет документированных оснований. Вот, самое оптимальное решение. Всё равно в реальной жизни вам вряд-ли потребуется передавать более 512 блоков за раз. А попытки найти истину (документальные обоснования, ответы от техподдержки) в этом случае - просто непроизводительные потери времени. ИМХО конечно.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 12 2015, 10:38
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Проблема в том, что я не могу просимулировать ошибки. Пока только одна - запись более 512 блоков - проявляется надежно и она только выявляется через FEIF. Так как пишу прямиком с камеры JPG без проблем превышает 512 блоков... Когда и при каких обстоятельствах возникают другие ошибки... С работы опубликую ВЕСЬ тестовый проект. Давайте вместе доведем до ума. Да, никаких их HAL или библиотек, все сам - за проблемы не им отвечать.
Сообщение отредактировал pitt - May 12 2015, 12:29
Прикрепленные файлы
sdio.zip ( 5.47 килобайт )
Кол-во скачиваний: 10
--------------------
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|