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

Blackfin BF-533 SPI DMA Rx

Пытаюсь реализовать на BF-533 чтение из SPI через DMA (до этого использовал только одиночные операции), и как-то странно оно себя ведёт. Во-первых, после окончания приёма сигнал SCK продолжает формироваться, во-вторых, в SPI_STAT выставляется бит RBSY.

Может, кто-нибудь сталкивался?

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


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

Да, клок для SPI в режиме DMA сделан криво. Кроме того что он не останавливается сразу, так он еще может остановиться посреди передаваемого слова и таким образом нарушить синхронизацию (для 537 битовую синхронизацию частично пофиксили, изменили бит SYNC в конфигурации DMA). Когда подключал SD карту пришлось дополнительно корретировать прием внешней логикой для прерывания потока. Ну а в остальном работает как описано в доках, ошибки в состоянии не должно возникать.

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


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

bmf,

у меня клок вообще не останавливается после чтения, если конечно порт не выключить. Это нормально? Странно, что в ерратах про это ничего нету. А в каком случае он останавливается посреди передаваемого слова? При записи смотрел, вроде клоков ровно столько, сколько нужно.

 

2 Rendom

огромное спасибо за столь информативный и содержательный ответ.

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


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

У меня было примерно так, + еще процедура прерывания.

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;
}

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


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

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

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

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

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

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

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

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

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

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