Pathfinder 0 10 февраля, 2009 Опубликовано 10 февраля, 2009 · Жалоба Пытаюсь реализовать на BF-533 чтение из SPI через DMA (до этого использовал только одиночные операции), и как-то странно оно себя ведёт. Во-первых, после окончания приёма сигнал SCK продолжает формироваться, во-вторых, в SPI_STAT выставляется бит RBSY. Может, кто-нибудь сталкивался? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Renom 0 10 февраля, 2009 Опубликовано 10 февраля, 2009 · Жалоба SPI DMA в 533 работает прекрасно, читаем datasheet и ищем ошибки в программе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bmf 0 10 февраля, 2009 Опубликовано 10 февраля, 2009 · Жалоба Да, клок для SPI в режиме DMA сделан криво. Кроме того что он не останавливается сразу, так он еще может остановиться посреди передаваемого слова и таким образом нарушить синхронизацию (для 537 битовую синхронизацию частично пофиксили, изменили бит SYNC в конфигурации DMA). Когда подключал SD карту пришлось дополнительно корретировать прием внешней логикой для прерывания потока. Ну а в остальном работает как описано в доках, ошибки в состоянии не должно возникать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Pathfinder 0 10 февраля, 2009 Опубликовано 10 февраля, 2009 · Жалоба bmf, у меня клок вообще не останавливается после чтения, если конечно порт не выключить. Это нормально? Странно, что в ерратах про это ничего нету. А в каком случае он останавливается посреди передаваемого слова? При записи смотрел, вроде клоков ровно столько, сколько нужно. 2 Rendom огромное спасибо за столь информативный и содержательный ответ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bmf 0 11 февраля, 2009 Опубликовано 11 февраля, 2009 · Жалоба У меня было примерно так, + еще процедура прерывания. static void _spiDMARead(byte *adr,int nbytes) { *pDMA5_PERIPHERAL_MAP = 0x5000; *pDMA5_CONFIG = 0; *pDMA5_IRQ_STATUS = (DMA_DONE | DMA_ERR); SSYNCA; OSSemSet0(semSPIDMAReady); unsigned long limit = SPI_TIMEOUT_LIMIT1MS; while(!(*pSPI_STAT & SPIF) && limit--) { delay100ns(); }; *pSPI_STAT=BIT_STAT_CLR; *pSPI_CTL=MSTR | RDBR_DMA/* | SIZE */; /* clear tx reg soformer data is not shifted out */ *pSPI_TDBR = 0xFFFF; /* start dma */ // dma enable irq sd_spidmaenable_interrupt(); // Configure DMA5 *pDMA5_CONFIG = WNR | WDSIZE_8 | DI_EN | RESTART; // Start address of data buffer *pDMA5_START_ADDR = (void*)adr; // DMA inner loop count (in elements) *pDMA5_X_COUNT = nbytes; // Inner loop address increment *pDMA5_X_MODIFY = 1; SSYNCA; *pDMA5_CONFIG = DMAEN | WNR | WDSIZE_8 | DI_EN | RESTART; SSYNCA; /* start SPI transfer RD */ *pSPI_CTL=SPE | MSTR | RDBR_DMA/* | SIZE*/; INT8U osErr; OSSemPend(semSPIDMAReady, 0, &osErr ); sd_spidmadisable_interrupt(); // polling variant /* // Wait for DMA to complete while (*pDMA5_IRQ_STATUS & DMA_RUN); sd_spidmastop(); limit = SPI_TIMEOUT_LIMIT1MS; while(!(*pSPI_STAT & SPIF) && limit--) { delay100ns(); }; *pSPI_CTL=MSTR | (TIMOD & 1); */ #ifdef USE_WB_CACHE FlushInvArea(adr,((byte *)adr)+nbytes); // in bytes #else dcache_invalidate_both(); #endif // restore (new) spi ctrl *pSPI_CTL=SPE | MSTR | (TIMOD & 1); //0x5C01; enable SPI, nondma tx mode, 8bit } static void sd_spidmadisable_interrupt(void) { unsigned savint; enter(savint); // disable Sport0 DMA RX interrupt *pSIC_IMASK &= (~(1<<13)); // spi (13 IVG10 ID=3) share IVG_PORTB leave(savint); SSYNCA; } static void sd_spidmastop(void) { // disable DMAs *pDMA5_CONFIG = 0; SSYNCA; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться