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

📄 spi.c

📁 s3c6400 ADS下官方测试程序
💻 C
📖 第 1 页 / 共 3 页
字号:

//////////
// File Name : SPI_cpuOneTxTransfer
// File Description : Transmit tx channel from power by CPU.
// Input : SPI_channel
// Output : NONE.
// Version : 
void SPI_cpuOneTxTransfer( SPI_channel *ch ) {
	int	TxWriteCnt;
	int	i;

	//  Tx buffer ready and Non-zero Tx Data size and Tx-FIFO Ready.
	if ( (ch->m_uTxBuf != NULL) && (ch->m_uTxRemainDataSize > 0) && (Inp32(&ch->m_cBase->spi_status) & (1<<0)) ) {
		TxWriteCnt = SPI_TX_FIFO_SIZE - ((Inp32(&ch->m_cBase->spi_status)>>6) & (0x7F));
		TxWriteCnt = ( ch->m_uTxRemainDataSize < TxWriteCnt ) ? ( ch->m_uTxRemainDataSize ) : (TxWriteCnt);
	}
	else {
		TxWriteCnt = 0;
	}
	
	// TX.
	if ( ch->m_eBusSize == SPI_BYTE ) {
		u8 * ptr = ch->m_uTxBuf;
		for(i=TxWriteCnt;i>0;i--) {
			Outp8(&ch->m_cBase->spi_tx_data, *ptr++);
		}
		ch->m_uTxBuf=ptr;
	}
	else if ( ch->m_eBusSize == SPI_HWORD ) {
		u16 * ptr = (u16*)ch->m_uTxBuf;
		TxWriteCnt = (TxWriteCnt & ~(0x1));	// 2 byte align.
		for(i=TxWriteCnt>>1;i>0;i--) {
			Outp16(&ch->m_cBase->spi_tx_data, *ptr++);
		}
		ch->m_uTxBuf=(u8*)ptr;
	}
	else if ( ch->m_eBusSize == SPI_WORD ) {
		u32 * ptr = (u32*)ch->m_uTxBuf;
		TxWriteCnt = (TxWriteCnt & ~(0x3));	// 4 byte align.
		for(i=TxWriteCnt>>2;i>0;i--) {
			Outp32(&ch->m_cBase->spi_tx_data, *ptr++);
		}
		ch->m_uTxBuf=(u8*)ptr;
	}
	ch->m_uTxRemainDataSize = (ch->m_uTxRemainDataSize - TxWriteCnt < 1 ) ? ( 0 ) : ( ch->m_uTxRemainDataSize - TxWriteCnt );
}

//////////
// File Name : SPI_cpuOneRxTransfer
// File Description : Transmit rx channel from power by CPU.
// Input : SPI_channel
// Output : NONE.
// Version : 
void SPI_cpuOneRxTransfer( SPI_channel *ch ) {
	int	RxReadCnt;
	int	i;

	// Rx Buffer ready and Non-zero Rx data size and Rx-FIFO Read.
//	if ( (ch->m_uRxBuf != NULL) && (ch->m_uRxRemainDataSize > 0 ) && (Inp32(&ch->m_cBase->spi_status) & (1<<1)) ) {
	if ( (ch->m_uRxBuf != NULL) && (ch->m_uRxRemainDataSize > 0 ) && ((Inp32(&ch->m_cBase->spi_status)>>13) & (0x7f)) ) {
		RxReadCnt = (Inp32(&ch->m_cBase->spi_status)>>13) & (0x7f);
		RxReadCnt = ( ch->m_uRxRemainDataSize < RxReadCnt ) ? ( ch->m_uRxRemainDataSize ) : (RxReadCnt);
	}
	else {
		RxReadCnt = 0;
	}

	// Rx.
	if ( ch->m_eBusSize == SPI_BYTE ) {
		u8 * ptr = ch->m_uRxBuf;
		for(i=RxReadCnt;i>0;i--) {
			*ptr++ = Inp8(&ch->m_cBase->spi_rx_data);
		}
		ch->m_uRxBuf=ptr;
	}
	else if ( ch->m_eBusSize == SPI_HWORD ) {
		u16 * ptr = (u16*)ch->m_uRxBuf;
		RxReadCnt = (RxReadCnt & ~(0x1));	// 1 byte align.
		for(i=RxReadCnt>>1;i>0;i--) {
			*ptr++ = Inp16(&ch->m_cBase->spi_rx_data);
		}
		ch->m_uRxBuf=(u8*)ptr;
	}
	else if ( ch->m_eBusSize == SPI_WORD ) {
		u32 * ptr = (u32*)ch->m_uRxBuf;
		RxReadCnt = (RxReadCnt & ~(0x3));	// 4 byte align.
		for(i=RxReadCnt>>2;i>0;i--) {
			*ptr++ = Inp32(&ch->m_cBase->spi_rx_data);
		}
		ch->m_uRxBuf=(u8*)ptr;
	}
	ch->m_uRxRemainDataSize = ( ch->m_uRxRemainDataSize - RxReadCnt < 1 ) ? ( 0 ) : ( ch->m_uRxRemainDataSize - RxReadCnt );
}

//////////
// File Name : SPI_pollingProcess
// File Description : Polling transmission
// Input : SPI_channel
// Output : NONE.
// Version : 
void SPI_pollingProcess( 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 ) {
		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 );
		}
	}
}

//////////
// File Name : SPI_interruptHandler
// File Description : This function is interrupt handler for transmission and error handling.
// Input : SPI_channel, SPI VIC number.
// Output : NONE.
// Version : 
void SPI_interruptHandler( SPI_channel* ch, int interruptNumber ) {
	u8 spi_status;

	if ( NUM_SPI0 == interruptNumber ) {
//		printf( "NUM_SPI0\n" );
	}
	else {
//		printf( "NUM_SPI1\n" );
	}
	// Error inspection
	spi_status = Inp8(&ch->m_cBase->spi_status);
	if( spi_status & (0xf<<2) ) {	
		if(spi_status & SPI_INT_RX_OVERRUN) {
			printf("Rx Overrun Error\n");
		}
		else if(spi_status & SPI_INT_RX_UNDERRUN) {
			printf("Rx Underrun Error\n");
		}
		else if(spi_status & SPI_INT_TX_OVERRUN) {
			printf("Tx Overrun Error\n");
		}
		else if(spi_status & SPI_INT_TX_UNDERRUN) {
	//		printf("Tx Underrun Error\n");
		}
//		ch->m_uTxRemainDataSize = 0;	// force stop.
//		ch->m_uRxRemainDataSize = 0;
	}

	// Tx under run , Over run, RX under run, Over run clear
	Outp8(&ch->m_cBase->pending_clr, Inp8(&ch->m_cBase->pending_clr)|SPI_INT_RX_UNDERRUN|
									SPI_INT_TX_OVERRUN|SPI_INT_TX_UNDERRUN|SPI_INT_RX_FIFORDY );

	if( ch->m_uRxRemainDataSize != 0 ) {
		SPI_cpuOneRxTransfer( ch );
	}
	if( ch->m_uTxRemainDataSize != 0 ) {
		SPI_cpuOneTxTransfer( ch );
	}

	if ( ch->m_uTxRemainDataSize == 0 && ch->m_uRxRemainDataSize == 0 ) {
		// transfer done.
		INTC_Disable( interruptNumber );
		if ( ch->m_pCallback != NULL ) {
			SPI_transactionDone(ch);
			ch->m_pCallback(ch);
		}
	}
	else {
		// transfer contine.
	//	INTC_Enable( interruptNumber );
	}
}

//////////
// File Name : SPI_interruptChannel0
// File Description : Interrupt Handler for channel 0
// Input : NONE
// Output : NONE.
// Version : 
void __irq SPI_interruptChannel0( void ) {
	SPI_channel * ch = &SPI_current_channel[0];

	SPI_interruptHandler( ch, NUM_SPI0);
 	INTC_ClearVectAddr();
}

//////////
// File Name : SPI_interruptChannel1
// File Description : Interrupt Handler for channel 1
// Input : NONE
// Output : NONE.
// Version : 
void __irq SPI_interruptChannel1( void ) {
	SPI_channel * ch = &SPI_current_channel[1];

	SPI_interruptHandler( ch, NUM_SPI1);
  	INTC_ClearVectAddr();
}

//////////
// File Name : SPI_DMADoneHandler
// File Description : DMA Done Interrupt Handler for channel 0
// Input : NONE
// Output : NONE.
// Version : 
void SPI_DMADoneHandler( SPI_channel *ch, DMA_CH dmaCh) {
	// which DMA channel between CH_A and CH_B
	if ( dmaCh & DMA_A ) {
		ch->m_uTxRemainDataSize = 0;
		putchar('A');		// At the CPU power mode, must remove print message for system resource.
	}
	if ( dmaCh & DMA_B ) {
		ch->m_uRxRemainDataSize = 0;
		putchar('B');		// At the CPU power mode, must remove print message for system resource.
	}
	if ( dmaCh & DMA_C ) {
		ch->m_uTxRemainDataSize = 0;
		ch->m_uRxRemainDataSize = 0;
		putchar('C');
	}
	
	// done
	if ( ch->m_uTxRemainDataSize == 0 && ch->m_uRxRemainDataSize == 0 ) {
		if ( ch->m_pCallback != NULL ) {
			SPI_transactionDone(ch);
			ch->m_pCallback(ch);
		}
//		INTC_Disable(ch->m_ucIntNum);	// disable interrupt
	}
}

//////////
// File Name : SPI_DMADoneChannel0
// File Description : DMA Done Interrupt Handler for channel 0
// Input : NONE
// Output : NONE.
// Version : 
void __irq SPI_DMADoneChannel0( void ) {
	SPI_channel* ch = &SPI_current_channel[0];
	DMA_CH rxtx = DMACH_GetChannelNumber(&ch->m_sDMA);
	DMACH_ClearIntPending(&ch->m_sDMA);
	putchar( '0' );	// At the CPU power mode, must remove print message for system resource.
	SPI_DMADoneHandler( ch, rxtx);
 	INTC_ClearVectAddr();
}

//////////
// File Name : SPI_DMADoneChannel1
// File Description : DMA Done Interrupt Handler for channel 1
// Input : NONE
// Output : NONE.
// Version : 
void __irq SPI_DMADoneChannel1( void ) {
	SPI_channel* ch = &SPI_current_channel[1];
	DMA_CH rxtx = DMACH_GetChannelNumber(&ch->m_sDMA);
	DMACH_ClearIntPending(&ch->m_sDMA);
	putchar( '1' );	// At the CPU power mode, must remove print message for system resource.
	SPI_DMADoneHandler( ch, rxtx);
 	INTC_ClearVectAddr();
}

//////////
// File Name : SPI_ErrorCheck
// File Description : Setting error interrupt handler.
// Input : NONE
// Output : NONE.
// Version : 
void SPI_ErrorCheck(SPI_channel* ch) {
	Outp8(&ch->m_cBase->int_enable, Inp8(&ch->m_cBase->int_enable)|
		(SPI_INT_TRAILING|SPI_INT_RX_OVERRUN|SPI_INT_RX_UNDERRUN|SPI_INT_TX_OVERRUN|
		SPI_INT_TX_UNDERRUN|SPI_INT_RX_FIFORDY|SPI_INT_TX_FIFORDY) );
	INTC_SetVectAddr( ch->m_ucIntNum, ch->m_fISR);
	INTC_Enable( ch->m_ucIntNum);
}

//////////
// File Name : SPI_GPIOPortSet
// File Description : This function set GPIO fit on certain channel.
// Input : NONE
// Output : NONE.
// Version : 
void SPI_GPIOPortSet(u8 channel)
{
	if ( channel == 1 ) {
		GPIO_SetFunctionEach( eGPIO_C, eGPIO_4, 0x2 );	// SPI MISO[1] - EINT2[4], GPC4
		GPIO_SetFunctionEach( eGPIO_C, eGPIO_5, 0x2 );	// SPI CLK[1] - EINT2[5], GPC5
		GPIO_SetFunctionEach( eGPIO_C, eGPIO_6, 0x2 );	// SPI MOSI[1] - EINT2[6], GPC6
		GPIO_SetFunctionEach( eGPIO_C, eGPIO_7, 0x2 );	// SPI CSn[1] - EINT2[7], GPC7
		GPIO_SetPullUpDownEach( eGPIO_C, eGPIO_4, 0 );	// SPI MISO[1] - EINT2[4], GPC4
		GPIO_SetPullUpDownEach( eGPIO_C, eGPIO_5, 0 );	// SPI CLK[1] - EINT2[5], GPC5
		GPIO_SetPullUpDownEach( eGPIO_C, eGPIO_6, 0 );	// SPI MOSI[1] - EINT2[6], GPC6
		GPIO_SetPullUpDownEach( eGPIO_C, eGPIO_7, 0 );	// SPI CSn[1] - EINT2[7], GPC7

	}
	else {	// channel 0
		GPIO_SetFunctionEach( eGPIO_C, eGPIO_0, 0x2 );	// SPI MISO[0] - ADDR_CF[0], Eint2[0], GPC0
		GPIO_SetFunctionEach( eGPIO_C, eGPIO_1, 0x2 );	// SPI CLK[0] - ADDR_CF[1], EINT2[1], GPC1
		GPIO_SetFunctionEach( eGPIO_C, eGPIO_2, 0x2 );	// SPI MOSI[0] - ADDR_CF[2], EINT2[2], GPC2
		GPIO_SetFunctionEach( eGPIO_C, eGPIO_3, 0x2 );	// SPI CSn[0] - EINT2[3], GPC3
		GPIO_SetPullUpDownEach( eGPIO_C, eGPIO_0, 0 );	// SPI MISO[0] - ADDR_CF[0], Eint2[0], GPC0
		GPIO_SetPullUpDownEach( eGPIO_C, eGPIO_1, 0 );	// SPI CLK[0] - ADDR_CF[1], EINT2[1], GPC1
		GPIO_SetPullUpDownEach( eGPIO_C, eGPIO_2, 0 );	// SPI MOSI[0] - ADDR_CF[2], EINT2[2], GPC2
		GPIO_SetPullUpDownEach( eGPIO_C, eGPIO_3, 0 );	// SPI CSn[0] - EINT2[3], GPC3
	}
}

⌨️ 快捷键说明

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