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

📄 sdhc.c

📁 s3c6400 ADS下官方测试程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/*************************************************************************************** *	Project Name : S3C6400 Validation**	Copyright 2006 by Samsung Electronics, Inc.*	All rights reserved.**	Project Description :*		This software is only for validating functions of the S3C6400.*		Anybody can use this software without our permission.*  *--------------------------------------------------------------------------------------* *	File Name : sdhc.c*  *	File Description : This file implements the API functon for High Speed MMC.**	Author : Youngmin.Kim*	Dept. : AP Development Team*	Created Date : 08.OCT.2005*	Version : 0.2 * *	History*	 1) 1st Made*      2) add SDIO, SDHC, CE-ATA interface and code compaction by youngbo.song*  **************************************************************************************/#include <stdio.h>#include <string.h>#include <stdlib.h>#include "def.h"#include "option.h"#include "library.h"#include "sfr6400.h"#include "system.h"#include "intc.h"#include "gpio.h"#include "sdhc.h"#ifdef DBG_SDHC#define sdDbg(x) Dbg x#else#define sdDbg(x) printf x#endif// HighSpeed mode separator#define SDHC_CARD_DELAY_ON_CLOCK 35000000#define SDHC_MMC_HIGH_SPEED_CLOCK 25000000#define SDHC_SD_HIGH_SPEED_CLOCK 25000000//////////// File Name : SDHC_SetBlockCountReg (Inline Macro)// File Description : This function set block count register.// Input : SDHC, block count // Output : NONE.#define SDHC_SetBlockCountReg( sCh, uBlkCnt) \	Outp16( (sCh)->m_uBaseAddr + SDHC_BLK_COUNT, (uBlkCnt) );//////////// File Name : SDHC_SetSystemAddressReg (Inline Macro)// File Description : This function set DMA start address.// Input : SDHC, start address.// Output : NONE.#define SDHC_SetSystemAddressReg( sCh, SysAddr) \	Outp32( (sCh)->m_uBaseAddr + SDHC_SYS_ADDR, (SysAddr) );//////////// File Name : SDHC_SetBlockSizeReg (Inline Macro)// File Description : This function set block size and buffer size.// Input : SDHC, DMA buffer boundary, One block size.// Output : NONE.#define SDHC_SetBlockSizeReg( sCh, uDmaBufBoundary, uBlkSize ) \	Outp16( (sCh)->m_uBaseAddr + SDHC_BLK_SIZE, (((uDmaBufBoundary)<<12)|(uBlkSize)) );//////////// File Name : SDHC_INT_WAIT_CLEAR (Inline Macro)// File Description : Interrupt wait and clear.// Input : SDHC, interrupt bit, timeout loop count // Output : NONE.	// 0x7F000000 youngbo.song#define SDHC_INT_WAIT_CLEAR(sCh,bit,loop) \	loop=0x7F000000; \	while ( !(Inp16( (sCh)->m_uBaseAddr + SDHC_NORMAL_INT_STAT ) & (1<<bit) ) ) { \		if ( --loop == 0 ) { \			sdDbg(( "***********Time out Error : bit : %d, Line:%d \n", bit, __LINE__ )); \			break;	} } \	do { Outp32( (sCh)->m_uBaseAddr + SDHC_NORMAL_INT_STAT, (1<<bit) ); \	} while( Inp16( (sCh)->m_uBaseAddr + SDHC_NORMAL_INT_STAT ) & (1<<bit) );//// [7:6] Command Type// [5]  Data Present Select// [4] Command Index Check Enable// [3] CRC Check Enable// [1:0] Response Type Selectconst unsigned char SDHC_cmd_sfr_data[] = {	(unsigned char)((0<<4)|(0<<3)|(0<<0)),	// RES_NO_TYPE	(unsigned char)((1<<4)|(1<<3)|(2<<0)),	// RES_R1_TYPE,	(unsigned char)((1<<4)|(1<<3)|(3<<0)),	// RES_R1B_TYPE,	(unsigned char)((0<<4)|(1<<3)|(1<<0)),	// RES_R2_TYPE,	(unsigned char)((0<<4)|(0<<3)|(2<<0)),	// RES_R3_TYPE,	(unsigned char)((0<<4)|(0<<3)|(2<<0)),	// RES_R4_TYPE,	(unsigned char)((1<<4)|(1<<3)|(2<<0)),	// RES_R5_TYPE,	(unsigned char)((1<<4)|(1<<3)|(2<<0)),	// RES_R6_TYPE,	// check need.	(unsigned char)((1<<4)|(1<<3)|(2<<0)),	// RES_R7_TYPE,	// check need.};SDHC* SDHC_curr_card[SDHC_CHANNEL_CNT];//////////// File Name : SDHC_writeIntHandler// File Description : This function is interrupt service routine for common writing.// Input : SDHC channel, Interrupt Index// Output : NONE.void SDHC_writeIntHandler(SDHC* sCh, u32 intIndex) {//	if ( !( Inp16( (sCh)->m_uBaseAddr + SDHC_NORMAL_INT_STAT ) & (1<<4) ) ) {//		printf( "Interrupt Delay~!!!\n" );//	}	SDHC_WriteOneBlock( sCh, 0 );	if ( sCh->m_uRemainBlock == 0 ) {		INTC_Disable(intIndex);	}	else {		INTC_Enable(intIndex);	}}//////////// File Name : SDHC_WriteInt0// File Description : This function is interrupt service routine for writing channel 0.// Input : NONE.// Output : NONE.void __irq SDHC_WriteInt0(void) {	SDHC_writeIntHandler( SDHC_curr_card[SDHC_CHANNEL_0], NUM_HSMMC0);	INTC_ClearVectAddr();}//////////// File Name : SDHC_WriteInt1// File Description : This function is interrupt service routine for writing channel 1.// Input : NONE.// Output : NONE.void __irq SDHC_WriteInt1(void) {	SDHC_writeIntHandler( SDHC_curr_card[SDHC_CHANNEL_1], NUM_HSMMC1);	INTC_ClearVectAddr();}//////////// File Name : SDHC_WriteInt2// File Description : This function is interrupt service routine for writing channel 2.// Input : NONE.// Output : NONE.void __irq SDHC_WriteInt2(void) {	SDHC_writeIntHandler( SDHC_curr_card[SDHC_CHANNEL_2], NUM_SPI1);	INTC_ClearVectAddr();}//////////// File Name : SDHC_InterruptInspector// File Description : Print and handle the normal interrupt status register - for debugging usage.// Input : SDHC channel.// Output : NONE.void SDHC_InterruptInspector( SDHC* sCh ) {	u16 status;	int i=0;		while ( (status = Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT)) == 0 )		i++;	if ( i != 0 )		printf ( "Int Status:%4x, loop count : %dn", status, i );	if ( status & SDHC_SD_ADDRESS_INT3_EN ) {		Outp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT, SDHC_SD_ADDRESS_INT3_EN);		while( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_SD_ADDRESS_INT3_EN );		sdDbg(( "14," ));	}	if ( status & SDHC_SD_ADDRESS_INT2_EN ) {		Outp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT, SDHC_SD_ADDRESS_INT2_EN);		while( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_SD_ADDRESS_INT2_EN );		sdDbg(( "13," ));	}	if ( status & SDHC_SD_ADDRESS_INT1_EN ) {		Outp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT, SDHC_SD_ADDRESS_INT1_EN);		while( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_SD_ADDRESS_INT1_EN );		sdDbg(( "12," ));	}	if ( status & SDHC_SD_ADDRESS_INT0_EN ) {		Outp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT, SDHC_SD_ADDRESS_INT0_EN);		while( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_SD_ADDRESS_INT0_EN );		sdDbg(( "11," ));	}	if ( status & SDHC_READWAIT_SIG_INT_EN ) {		Outp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT, SDHC_READWAIT_SIG_INT_EN);		while( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_READWAIT_SIG_INT_EN );		sdDbg(( "10," ));	}	if ( status & SDHC_CCS_INTERRUPT_STATUS_EN ) {		sdDbg(( "9," ));	}	if ( status & SDHC_CARD_SIG_INT_EN ) {		Outp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT, SDHC_CARD_SIG_INT_EN);		sdDbg(( "8," ));	}	if ( status & SDHC_CARD_REMOVAL_SIG_INT_EN ) {		sdDbg(( "7," ));	}	if ( status & SDHC_CARD_INSERT_SIG_INT_EN ) {		sdDbg(( "6," ));	}	if ( status & SDHC_BUFFER_READREADY_SIG_INT_EN ) {		sdDbg(( "5," ));	}	if ( status & SDHC_BUFFER_WRITEREADY_SIG_INT_EN ) {		sdDbg(( "4," ));	}	if ( status & SDHC_DMA_SIG_INT_EN ) {		sdDbg(( "3," ));	}	if ( status & SDHC_BLOCKGAP_EVENT_SIG_INT_EN ) {		Outp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT, SDHC_BLOCKGAP_EVENT_SIG_INT_EN);//		while( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_BLOCKGAP_EVENT_SIG_INT_EN );		sdDbg(( "2," ));	}	if ( status & SDHC_TRANSFERCOMPLETE_SIG_INT_EN ) {		sdDbg(( "1," ));	}	if ( status & SDHC_COMMANDCOMPLETE_SIG_INT_EN ) {		sdDbg(( "0," ));	}	sdDbg(( ":go Inthandler\n"));}//////////// File Name : SDHC_readIntHandler// File Description : This function is interrupt service routine for common usage.// Input : NONE.// Output : NONE.void SDHC_readIntHandler( SDHC* sCh, u32 intIndex ) {//	if ( !( Inp16( (sCh)->m_uBaseAddr + SDHC_NORMAL_INT_STAT ) & (1<<5) ) ) {//		sdDbg(( "Interrupt Delay~!!!\n" );//	}	SDHC_ReadOneBlock( sCh, 0 );	if ( sCh->m_uRemainBlock == 0 ) {		INTC_Disable(intIndex);	}	else {		INTC_Enable(intIndex);	}}//////////// File Name : SDHC_ReadInt0// File Description : This function is interrupt service routine for reading channel 0.// Input : NONE.// Output : NONE.void __irq SDHC_ReadInt0(void) {	SDHC_readIntHandler(SDHC_curr_card[SDHC_CHANNEL_0], NUM_HSMMC0);	INTC_ClearVectAddr();}//////////// File Name : SDHC_ReadInt1// File Description : This function is interrupt service routine for reading channel 1.// Input : NONE.// Output : NONE.void __irq SDHC_ReadInt1(void) {	SDHC_readIntHandler(SDHC_curr_card[SDHC_CHANNEL_1], NUM_HSMMC1);	INTC_ClearVectAddr();}//////////// File Name : SDHC_ReadInt2// File Description : This function is interrupt service routine for reading channel 2.// Input : NONE.// Output : NONE.void __irq SDHC_ReadInt2(void) {	SDHC_readIntHandler(SDHC_curr_card[SDHC_CHANNEL_2], NUM_SPI1);	INTC_ClearVectAddr();}//////////// File Name : SDHC_DMAIntHandler// File Description : This function is interrupt service routine for Common DMA Handling.// Input : NONE.// Output : NONE.void SDHC_DMAIntHandler(SDHC * sCh, u32 intIndex) {	int i;	// youngbo.song//	SDHC_InterruptInspector(sCh);//	sdDbg(("\nISR rHM_NORINTSTS = %x", Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT ) ));//	sdDbg(("block size :%d \n" , Inp16( sCh->m_uBaseAddr+SDHC_BLK_COUNT ) ));	if ( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_BLOCKGAP_EVENT_SIG_INT_EN ) {		Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) = SDHC_BLOCKGAP_EVENT_SIG_INT_EN;	}	if( ( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_TRANSFERCOMPLETE_SIG_INT_EN ) )		// When SDIO suspend mode, there is transfercomplete event, but transfer not yet completed.//		&& ( Inp16( sCh->m_uBaseAddr+SDHC_BLK_COUNT) == 0 ) )	{//		sdDbg(("\nTransfer Complete\n"));//		sdDbg(("T"));		SDHC_INT_WAIT_CLEAR( sCh, 1, i);	//SDHC_TRANSFERCOMPLETE_STS_INT_EN 		sCh->m_uRemainBlock=0;		INTC_Disable(intIndex);	}	if ( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_DMA_SIG_INT_EN ) {//		sdDbg((" DMA buffer boundary is detected!\n"));//		sdDbg(("B"));		SDHC_INT_WAIT_CLEAR( sCh, 3, i);	//SDHC_TRANSFERCOMPLETE_STS_INT_EN		SDHC_SetSystemAddressReg(sCh, Inp32(sCh->m_uBaseAddr+SDHC_SYS_ADDR) );	}	if ( Inp16(sCh->m_uBaseAddr+SDHC_NORMAL_INT_STAT) & SDHC_CCS_INTERRUPT_STATUS_EN ) {		SDHC_INT_WAIT_CLEAR( sCh, 9, i);	//SDHC_CCS_INTERRUPT_STATUS_EN		sCh->m_uCCSResponse=0;//		sdDbg(("SDHC_CCS_INTERRUPT_STATUS_EN----------------\n"));//		sdDbg(("C"));	}}//////////// File Name : SDHC_DMADone// File Description : DMA done interrupt handler for channel 0// Input : NONE.// Output : NONE.void __irq SDHC_DMAInt0(void) {	SDHC_DMAIntHandler( SDHC_curr_card[SDHC_CHANNEL_0], NUM_HSMMC0);	INTC_ClearVectAddr();}//////////// File Name : SDHC_DMAInt1// File Description : DMA done interrupt handler for channel 1// Input : NONE.// Output : NONE.void __irq SDHC_DMAInt1(void) {	SDHC_DMAIntHandler( SDHC_curr_card[SDHC_CHANNEL_1], NUM_HSMMC1);	INTC_ClearVectAddr();}//////////// File Name : SDHC_DMAInt2// File Description : DMA done interrupt handler for channel 2// Input : NONE.// Output : NONE.void __irq SDHC_DMAInt2(void) {	SDHC_DMAIntHandler( SDHC_curr_card[SDHC_CHANNEL_2], NUM_SPI1);	INTC_ClearVectAddr();}//////////// File Name : SDHC_normalIntHandler// File Description : Print Normal interrupt status register.// Input : SDHC Pointer// Output : NONE.void SDHC_normalIntHandler(SDHC* sCh) {//	SDHC_InterruptInspector(sCh);	sdDbg(( "Interrupt Status : %x\n", Inp16( sCh->m_uBaseAddr + SDHC_NORMAL_INT_STAT ) ));	if ( Inp16( sCh->m_uBaseAddr + SDHC_NORMAL_INT_STAT ) & (0x3<<6) ) {		if ( Inp16( sCh->m_uBaseAddr + SDHC_NORMAL_INT_STAT ) & (1<<6) )			sdDbg(( "Insert\n" ));		if ( Inp16( sCh->m_uBaseAddr + SDHC_NORMAL_INT_STAT ) & (1<<7) )			sdDbg(( "Remove\n" ));	}		// Card Insert Remove.	do {		Outp16( sCh->m_uBaseAddr + SDHC_NORMAL_INT_STAT , Inp16( sCh->m_uBaseAddr + SDHC_NORMAL_INT_STAT ) );	} while( Inp16( sCh->m_uBaseAddr + SDHC_NORMAL_INT_STAT ) & (0x3<<6) );	INTC_ClearVectAddr();//	INTC_Disable( sCh->m_ucIntChannelNum );}//////////// File Name : SDHC_normalInt0// File Description : Normal Interrupt Handler 0// Input : NONE// Output : NONE.void __irq SDHC_normalInt0(void) {	SDHC_normalIntHandler( SDHC_curr_card[SDHC_CHANNEL_0] );	INTC_ClearVectAddr();}//////////// File Name : SDHC_normalInt1// File Description : Normal Interrupt Handler 1// Input : NONE// Output : NONE.

⌨️ 快捷键说明

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