⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.c

📁 s3c6400 ADS下官方测试程序
💻 C
📖 第 1 页 / 共 3 页
字号:
//////////
// File Name : SPI_interruptTransaction
// File Description : Execute Interrupt Mode .
// Input : SPI_channel 
// Output : success or fail.
// Version : 
bool SPI_interruptTransaction( SPI_channel * ch) {
	if ( ch->m_eClockMode == SPI_MASTER ) {
		if ( ch->m_uTxBuf == NULL ) {		// master rx only.
			Outp32( &ch->m_cBase->packet_count, (1<<16)|(ch->m_uRxRemainDataSize) );
		}
	}

	if ( ch->m_eClockMode == SPI_MASTER ) {
		if ( ch->m_bIsAutoChipSelection == FALSE ) {
			Outp32( &ch->m_cBase->slave_sel, Inp32(&ch->m_cBase->slave_sel) & ~(0x3<<0) );	// Chip selection ON.- active LOW
		}
//		Outp32( &ch->m_cBase->slave_sel, Inp32(&ch->m_cBase->slave_sel) & ~(1<<0) );	// Chip selection ON.- active LOW
		Outp32( &ch->m_cBase->clk_cfg, Inp32(&ch->m_cBase->clk_cfg) | (1<<8) );		// clock On.
	}
	Outp32( &ch->m_cBase->int_enable,
		( (ch->m_uTxRemainDataSize!=0) ? (SPI_INT_TX_FIFORDY) : (0) ) |// Tx Buffer Ready
		( (ch->m_uRxRemainDataSize!=0) ? (SPI_INT_TRAILING|SPI_INT_RX_FIFORDY|SPI_INT_RX_OVERRUN|SPI_INT_RX_UNDERRUN) : (0) ) );// Rx buffer Ready.
	Outp32( &ch->m_cBase->pending_clr, 0xffffffff );	// interrupt pending clear.
	ch->m_ucIntNum = (ch->m_ucChannelNum==0)?(NUM_SPI0):(NUM_SPI1);

	if ( ch->m_uRxBuf != 0 ) {
		Outp32( &ch->m_cBase->ch_cfg, Inp32(&ch->m_cBase->ch_cfg)|(1<<1) );	// Rx channel on
	}
	if ( ch->m_uTxBuf != 0 ) {
		Outp32( &ch->m_cBase->ch_cfg, Inp32(&ch->m_cBase->ch_cfg)|(1<<0) );	// Tx channel on
	}
	INTC_SetVectAddr( ch->m_ucIntNum, ch->m_fISR);
	INTC_Enable( ch->m_ucIntNum);

	if ( ch->m_pCallback == NULL ) {
		// Until Transfer Done.
		while( ch->m_uTxRemainDataSize != 0 );
		while( ch->m_uRxRemainDataSize != 0 );
		SPI_transactionDone(ch);
	}
	return TRUE;
}

//////////
// File Name : SPI_dmaTransaction
// File Description : Execute DMA Mode .
// Input : SPI_channel 
// Output : success or fail.
// Version : 
bool SPI_dmaTransaction( SPI_channel * ch) {
	if ( ch->m_eClockMode == SPI_MASTER ) {
		if ( ch->m_uTxBuf == NULL ) {		// master rx only.
			Outp32( &ch->m_cBase->packet_count, (1<<16)|(ch->m_uRxRemainDataSize) );
		}
	}

	if ( ch->m_eClockMode == SPI_MASTER ) {
		if ( ch->m_bIsAutoChipSelection == FALSE ) {
			Outp32( &ch->m_cBase->slave_sel, Inp32(&ch->m_cBase->slave_sel) & ~(0x3<<0) );	// Chip selection ON.- active LOW
		}
		Outp32( &ch->m_cBase->clk_cfg, Inp32(&ch->m_cBase->clk_cfg) | (1<<8) );		// clock On.
	}

	if ( ch->m_uRxBuf != 0 ) {
		Outp32( &ch->m_cBase->mode_cfg, Inp32(&ch->m_cBase->mode_cfg) | (1<<2) );	// DMA mode Rx On.
		Outp32( &ch->m_cBase->ch_cfg, Inp32(&ch->m_cBase->ch_cfg)|(1<<1) );	// Rx channel on
		SPI_RxDMAInit(ch, 0, (u32)ch->m_uRxBuf, ch->m_uRxRemainDataSize );	// SPI_RX_DATA
		Outp32( &ch->m_cBase->pending_clr, 0xffffffff);
		DMACH_Start(&ch->m_sDMA);
	}
	if ( ch->m_uTxBuf != 0 ) {
		Outp32( &ch->m_cBase->mode_cfg, Inp32(&ch->m_cBase->mode_cfg) | (1<<1) );	// DMA mode Tx On.
		Outp32( &ch->m_cBase->ch_cfg, Inp32(&ch->m_cBase->ch_cfg)|(1<<0) );	// Tx channel on
		SPI_TxDMAInit(ch, (u32)ch->m_uTxBuf, 0, ch->m_uTxRemainDataSize );	// SPI_TX_DATA
		Outp32( &ch->m_cBase->pending_clr, 0xffffffff);
		DMACH_Start(&ch->m_sDMA);
	}

	// Blocking Context, when callback-function pointer is NULL
	if ( ch->m_pCallback == NULL ) {
		// Until Transfer Done.
		while( ch->m_uTxRemainDataSize != 0 );
		while( ch->m_uRxRemainDataSize != 0 );
		DMACH_Stop(&ch->m_sDMA);		 // Stop DMA
		INTC_Disable(ch->m_ucIntNum);		 // Disable DMA Interrupt
		SPI_transactionDone(ch);
	}
	return TRUE;
}

//////////
// File Name : SPI_dmaTransaction
// File Description : Execute Polling Mode .
// Input : SPI_channel 
// Output : success or fail.
// Version : 
bool SPI_pollingTransaction(SPI_channel * ch ) {
//	SPI_ErrorCheck(ch);
//	SPI_pollingProcess(ch);
	if ( ch->m_eClockMode == SPI_MASTER ) {
		if ( ch->m_uTxBuf == NULL ) {		// master rx only.
			Outp32( &ch->m_cBase->packet_count, (1<<16)|(ch->m_uRxRemainDataSize) );
		}
	}

	if ( ch->m_eClockMode == SPI_MASTER ) {
		if ( ch->m_bIsAutoChipSelection == FALSE ) {
			Outp32( &ch->m_cBase->slave_sel, Inp32(&ch->m_cBase->slave_sel) & ~(0x3<<0) );	// Chip selection ON.- active LOW
		}
//		Outp32( &ch->m_cBase->slave_sel, Inp32(&ch->m_cBase->slave_sel) & ~(1<<0) );	// Chip selection ON.- active LOW
		Outp32( &ch->m_cBase->clk_cfg, Inp32(&ch->m_cBase->clk_cfg) | (1<<8) );		// clock On.
	}
	if ( ch->m_uRxBuf != 0 ) {
		Outp32( &ch->m_cBase->ch_cfg, Inp32(&ch->m_cBase->ch_cfg)|(1<<1) );	// Rx channel on
	}
	if ( ch->m_uTxBuf != 0 ) {
		Outp32( &ch->m_cBase->ch_cfg, Inp32(&ch->m_cBase->ch_cfg)|(1<<0) );	// Tx channel on
	}

	while(ch->m_uTxRemainDataSize != 0 || ch->m_uRxRemainDataSize != 0)
	{
		// do until SPI FIFO Ready
		//while( !(Inp32(&ch->m_cBase->spi_status) & (3<<0)));
		
		if( ch->m_uRxRemainDataSize != 0 ) {
			SPI_cpuOneRxTransfer( ch );
		}
		if( ch->m_uTxRemainDataSize != 0 ) {
			SPI_cpuOneTxTransfer( ch );
		}
	}

	SPI_transactionDone(ch);
	if ( ch->m_pCallback != NULL )
		ch->m_pCallback(ch);
	return TRUE;
}

// youngbo.song
// This function use for periperal DMA Test.
// have to remove, Test Only.
int SPI_PtoPTransaction( SPI_channel * ch, SPI_transfer_mode mode, u32 size, void (*callbackFn)(SPI_channel *ch) ) {
	DATA_SIZE dataSize;
	ch->m_pCallback = callbackFn;
	ch->m_eTransferMode = mode;

	// Do data size alignment
	if ( ch->m_eBusSize == SPI_WORD ) {
		size = (size+3) & ~(0x3);		// word align
	}
	else if ( ch->m_eBusSize == SPI_HWORD ) {
		size = (size+1) & ~(0x1);		// half word align
	}
	
	// renew setting.
	SPI_setBasicRegister( ch );

//	Outp32( &ch->m_cBase->ch_cfg, Inp32(&ch->m_cBase->ch_cfg)&~(3<<0) );		// Tx/Rx channel Off
//	Outp32(&ch->m_cBase->slave_sel, Inp32(&ch->m_cBase->slave_sel) | (1<<0) );	// Chip selection OFF - active LOW.
//	Outp32(&ch->m_cBase->clk_cfg, Inp32(&ch->m_cBase->clk_cfg) & ~(1<<8) );	// clock Off.
	// Auto Chip Selection.
	if ( ch->m_bIsAutoChipSelection == TRUE ) {
		Outp32( &ch->m_cBase->slave_sel, (Inp32(&ch->m_cBase->slave_sel) & ~(0x3F<<4))|(0x0<<4) );
		Outp32( &ch->m_cBase->slave_sel, Inp32(&ch->m_cBase->slave_sel) | (0x1<<1) );
	}

	Outp32( &ch->m_cBase->mode_cfg, Inp32(&ch->m_cBase->mode_cfg) | (1<<2) );	// DMA mode Rx On.
	Outp32( &ch->m_cBase->ch_cfg, Inp32(&ch->m_cBase->ch_cfg)|(1<<1) );	// Rx channel on
	Outp32( &ch->m_cBase->mode_cfg, Inp32(&ch->m_cBase->mode_cfg) | (1<<1) );	// DMA mode Tx On.
	Outp32( &ch->m_cBase->ch_cfg, Inp32(&ch->m_cBase->ch_cfg)|(1<<0) );	// Tx channel on


	DMAC_InitCh((DMA_UNIT)ch->m_ucDMACon, DMA_C, &ch->m_sDMA);			//  to do.. another..
#ifdef SPI_NORMAL_DMA
	ch->m_ucIntNum = (ch->m_cChannelNum==0)?(NUM_DMA0):(NUM_DMA1);
#else
	ch->m_ucIntNum = (ch->m_cChannelNum==0)?(NUM_SDMA0):(NUM_SDMA1);
#endif
	INTC_SetVectAddr(ch->m_ucIntNum, ch->m_fDMA);
	INTC_Enable(ch->m_ucIntNum);

	// Interrupt Clear
	DMACH_ClearIntPending(&ch->m_sDMA);
	DMACH_ClearErrIntPending(&ch->m_sDMA);
	
	if ( ch->m_eBusSize == SPI_WORD ) {
		size=(size+3)>>2;
		dataSize = WORD;
	}
	else if ( ch->m_eBusSize == SPI_HWORD ) {
		size=(size+1)>>1;
		dataSize = HWORD;
	}
	else {
		dataSize = BYTE;
	}
	DMACH_Setup(DMA_C, 0x0,
		(ch->m_ucChannelNum==0)?(0x7F00B01C):(0x7F00C01C), TRUE,	// RX Fifo.
		(ch->m_ucChannelNum==0)?(0x7F00B018):(0x7F00C018), TRUE,	// Tx Fifo
		dataSize, size, HANDSHAKE,
		(ch->m_ucChannelNum==0)?(DMA0_SPI0_RX):(DMA1_SPI1_RX),
		(ch->m_ucChannelNum==0)?(DMA0_SPI0_TX):(DMA1_SPI1_TX),
		(BURST_MODE)ch->m_eDMAType, &ch->m_sDMA);

	Outp32( &ch->m_cBase->pending_clr, 0xffffffff);
	DMACH_Start(&ch->m_sDMA);

	return TRUE;
}

//////////
// File Name : SPI_transaction
// File Description : Transmit Rx/Tx Data
// Input : SPI_channel, selection DMA/Interrupt/polling mode, Tx buffer, Rx buffer, Transfer Size
//           If user want to execte non blocking mode, than set this callback function.
//           when transmission complete, call callback function by interrupt handler.
// Output : transmission size.
// Version : 
int SPI_transaction( SPI_channel * ch, SPI_transfer_mode mode, u8* tx_data, u8* rx_data, u32 size, void (*callbackFn)(SPI_channel *ch) ) {
	ch->m_pCallback = callbackFn;
	ch->m_eTransferMode = mode;

	// Do data size alignment
	if ( ch->m_eBusSize == SPI_WORD ) {
		size = (size+3) & ~(0x3);		// word align
	}
	else if ( ch->m_eBusSize == SPI_HWORD ) {
		size = (size+1) & ~(0x1);		// half word align
	}
	
	// Channel Initialization
	if( tx_data != 0 ) {
		ch->m_uTxRemainDataSize = size;	// Tx Transfer Size.
		ch->m_uTxBuf = tx_data;			// Tx buffer pointer
	}
	else {
		ch->m_uTxRemainDataSize = 0;
		ch->m_uTxBuf = NULL;
	}
	if( rx_data != 0 ) {
		ch->m_uRxRemainDataSize = size;	// Rx Transfer Size.
		ch->m_uRxBuf = rx_data;			// Rx buffer pointer
	}
	else {
		ch->m_uRxRemainDataSize = 0;
		ch->m_uRxBuf = NULL;
	}
	
	// renew setting.
	SPI_setBasicRegister( ch );

//	Outp32( &ch->m_cBase->ch_cfg, Inp32(&ch->m_cBase->ch_cfg)&~(3<<0) );		// Tx/Rx channel Off
//	Outp32(&ch->m_cBase->slave_sel, Inp32(&ch->m_cBase->slave_sel) | (1<<0) );	// Chip selection OFF - active LOW.
//	Outp32(&ch->m_cBase->clk_cfg, Inp32(&ch->m_cBase->clk_cfg) & ~(1<<8) );	// clock Off.
	// Auto Chip Selection.
	if ( ch->m_bIsAutoChipSelection == TRUE ) {
		Outp32( &ch->m_cBase->slave_sel, (Inp32(&ch->m_cBase->slave_sel) & ~(0x3F<<4))|(0x0<<4) );
		Outp32( &ch->m_cBase->slave_sel, Inp32(&ch->m_cBase->slave_sel) | (0x1<<1) );
	}
	
	if (mode == SPI_POLLING_MODE ) {
		SPI_pollingTransaction( ch );
	}
	else if ( mode == SPI_INTERRUPT_MODE ) {
		SPI_interruptTransaction( ch );
	}
	else if (mode == SPI_DMA_MODE ) {
		SPI_dmaTransaction( ch );
	}

	return size;
}

//////////
// File Name : SPI_transactionDone
// File Description : This funtion invoked by transmission routine automatically.
// Input : SPI_channel
// Output : NONE.
// Version : 
void SPI_transactionDone( SPI_channel * ch ) {
	if ( ch->m_eClockMode == SPI_MASTER && ch->m_uTxBuf != NULL ) {
//		while ( Inp32(&ch->m_cBase->spi_status) & ( 0x7F << 6) );		// wait Tx FIFO empty.
		while ( !(Inp32(&ch->m_cBase->spi_status) & ( 1<<21 ) ) );		// wait Tx done signal.
	}
//	// Tx condition only.
	if ( ch->m_eClockMode == SPI_MASTER ) {
		if ( ch->m_bIsAutoChipSelection == FALSE ) {
			Outp32(&ch->m_cBase->slave_sel, Inp32(&ch->m_cBase->slave_sel) | (1<<0) );		// Chip selection OFF - active LOW.
			Outp32(&ch->m_cBase->clk_cfg, Inp32(&ch->m_cBase->clk_cfg) & ~(1<<8) );		// clock Off.
		}
	}
//	Outp32( &ch->m_cBase->ch_cfg, Inp32(&ch->m_cBase->ch_cfg)&~(3<<0) );		// Tx/Rx channel Off
}

//////////
// File Name : SPI_close
// File Description : spi_channel close.
// Input : SPI_channel
// Output : NONE.
// Version : 
void SPI_close( SPI_channel * ch ) {
	memset( ch, 0, sizeof (SPI_channel) );
}

//////////
// File Name : SPI_printStatus
// File Description : Print status register for debugging.
// Input : SPI_channel
// Output : NONE.
// Version : 
void SPI_printStatus( SPI_channel * ch ) {
	printf ( "Tx_done : %d\n", ( Inp32(&ch->m_cBase->spi_status) & (1<<21) )>>21 );
	printf ( "Trailing byte : %d\n" , ( Inp32(&ch->m_cBase->spi_status) & (1<<20) )>>20 );
	printf ( "RxFIFOlevel : %d\n", ( Inp32(&ch->m_cBase->spi_status) & (0x7F<<13) )>>13 );
	printf ( "TxFIFOlevel : %d\n", ( Inp32(&ch->m_cBase->spi_status) & (0x7F<<6) )>>6 );
	printf ( "RxOver-run err: %d\n" , ( Inp32(&ch->m_cBase->spi_status) & (1<<5) )>>5 );
	printf ( "RxUnder-run err: %d\n" , ( Inp32(&ch->m_cBase->spi_status) & (1<<4) )>>4 );
	printf ( "TxOver-run err : %d\n" , ( Inp32(&ch->m_cBase->spi_status) & (1<<3) )>>3 );
	printf ( "TxUnder-run err: %d\n" , ( Inp32(&ch->m_cBase->spi_status) & (1<<2) )>>2 );
	printf ( "Rx FIFO Rdy : %d\n" , ( Inp32(&ch->m_cBase->spi_status) & (1<<1) )>>1 );
	printf ( "Tx FIFO Rdy : %d\n" , ( Inp32(&ch->m_cBase->spi_status) & (1<<0) ) );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -