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

📄 cfw.c

📁 2410 Samsung3.5寸屏用BSP源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    
    ULARGE_INTEGER liBase;
    DWORD dwCurCount;

	// Make sure CurTicks is the same before and after read of counter to account for
	// possible rollover
    do {
        liBase = CurTicks;
        dwCurCount = PerfCountSinceTick();
    } while  (liBase.LowPart != CurTicks.LowPart) ;  

    lpliPerformanceCount->QuadPart = liBase.QuadPart + dwCurCount;
    
    return TRUE;
}



//------------------------------------------------------------------------------
//
//  OEMQueryPerformanceFrequency
//  
//      The OEMQueryPerformanceFrequency function retrieves the frequency of 
//      the high-resolution performance counter, if one exists. 
//  
//  BOOL OEMQueryPerformanceFrequency(
//  
//      LARGE_INTEGER  *lpliPerformanceFreq     // address of current frequency
//     );   
//  
//  Parameters
//  
//  lpliPerformanceFreq
//  
//      Points to a variable that the function sets, in counts per second, to 
//      the current performance-counter frequency. If the installed hardware 
//      does not support a high-resolution performance counter, this parameter
//      can be to zero. 
//  
//  Return Value
//  
//      If the installed hardware supports a high-resolution performance 
//      counter, the return value is TRUE.
//      If the installed hardware does not support a high-resolution 
//      performance counter, the return value is FALSE.
//  
//  If this function is implemented by the OEM, the pointer pQueryPerformanceFrequency
//  should be initialized as follows:
//  
//  BOOL (*pQueryPerformanceFrequency)(LARGE_INTEGER *lpPerformanceFrequency)=OEMQueryPerformanceFrequency;
//
//------------------------------------------------------------------------------
BOOL 
OEMQueryPerformanceFrequency(
    LARGE_INTEGER *lpliPerformanceFreq
    ) 
{
    extern DWORD PerfCountFreq();
    
    lpliPerformanceFreq->HighPart = 0;
    lpliPerformanceFreq->LowPart  = PerfCountFreq();
    return TRUE;
}

// set pointers to OEM functions
BOOL (*pQueryPerformanceCounter)(LARGE_INTEGER *lpliPerformanceCount)=OEMQueryPerformanceCounter;
BOOL (*pQueryPerformanceFrequency)(LARGE_INTEGER *lpliPerformanceFreq)=OEMQueryPerformanceFrequency;


//
// CPU-specific functions for OEMIdle
//
extern void  CPUEnterIdle(DWORD dwIdleParam);
extern DWORD CPUGetSysTimerCountMax(DWORD dwIdleMSecRequested);
extern void  CPUSetSysTimerCount(DWORD dwIdleMSec);
extern BOOL CPUClearSysTimerIRQ(void);


//
// dougfir or later
//
extern DWORD
CPUGetSysTimerCountElapsed(
    DWORD dwTimerCountdownMSec,
    volatile DWORD *pCurMSec,
    DWORD *pPartialCurMSec,
    volatile ULARGE_INTEGER *pCurTicks
    );

//------------------------------------------------------------------------------
//
//  This routine is called by the kernel when there are no threads ready to
//  run. The CPU should be put into a reduced power mode and halted. It is 
//  important to be able to resume execution quickly upon receiving an interrupt.
//  Note: It is assumed that interrupts are off when OEMIdle is called.  Interrrupts
//  are turned off when OEMIdle returns.
//
//------------------------------------------------------------------------------
static DWORD dwPartialCurMSec = 0;           // Keep CPU-specific sub-millisecond leftover.
void
OEMIdle(
    DWORD dwIdleParam
    )
{
    DWORD dwIdleMSec;
    DWORD dwPrevMSec = *pCurMSec;

    // Use for 64-bit math
    ULARGE_INTEGER currIdle = {
        curridlelow,
        curridlehigh
    };

    if ((int) (dwIdleMSec = dwReschedTime - dwPrevMSec) <= 0) {
        // already time to wakeup
        return;
    }

    // just idle till tick if profiling or running iltiming
    if (bProfileTimerRunning || fIntrTime) {  // fIntrTime : Interrupt Latency timeing.

        // idle till end of 'tick'

        CPUEnterIdle(dwIdleParam);

        // Update global idle time and return
        currIdle.QuadPart += RESCHED_PERIOD;
        curridlelow = currIdle.LowPart;
        curridlehigh = currIdle.HighPart;
        
        return;
    }

    //
    // Since OEMIdle( ) is being called in the middle of a normal reschedule
    // period, CurMSec, dwPartialCurMSec, and CurTicks need to be updated accordingly.
    // Once we reach this point, we must re-program the timer (if we ever did) 
    // because dwPartialCurMSec will be modified in the next function call.
    //
    CPUGetSysTimerCountElapsed(RESCHED_PERIOD, pCurMSec, &dwPartialCurMSec, pCurTicks);

    if ((int) (dwIdleMSec -= *pCurMSec - dwPrevMSec) > 0) {

        dwPrevMSec = *pCurMSec;

        //
        // The system timer may not be capable of arbitrary timeouts. Get the
        // CPU-specific highest possible timeout available.
        //
        dwIdleMSec = CPUGetSysTimerCountMax(dwIdleMSec);
    
        //
        // Set the timer to wake up much later than usual, if needed.
        //
        CPUSetSysTimerCount(dwIdleMSec);
        CPUClearSysTimerIRQ( );
        
        //
        // Enable wakeup on any interrupt, then go to sleep.
        //
//	    DEBUGMSG(1, (TEXT("OEMIDle  \r\n")));
        CPUEnterIdle(dwIdleParam);
        INTERRUPTS_OFF( );
        
        //
        // We're awake! The wake-up ISR (or any other ISR) has already run.
        //
        if (dwPrevMSec != *pCurMSec) {
            //
            // We completed the full period we asked to sleep.  Update the counters.
            //
            *pCurMSec  += (dwIdleMSec - RESCHED_PERIOD); // Subtract resched period, because ISR also incremented.
            CurTicks.QuadPart += (dwIdleMSec - RESCHED_PERIOD) * dwReschedIncrement;

            currIdle.QuadPart += dwIdleMSec;
        } else {
            //
            // Some other interrupt woke us up before the full idle period was
            // complete.  Determine how much time has elapsed.
            //
            currIdle.QuadPart += CPUGetSysTimerCountElapsed(dwIdleMSec, pCurMSec, &dwPartialCurMSec, pCurTicks);
        }
    }

    // Re-arm counters
    CPUSetSysTimerCount(RESCHED_PERIOD);
    CPUClearSysTimerIRQ( );

    // Update global idle time
    curridlelow = currIdle.LowPart;
    curridlehigh = currIdle.HighPart;

    return;
}




//------------------------------------------------------------------------------
//
//  DWORD GetTickCount(VOID)    Return count of time since boot in milliseconds
//
//------------------------------------------------------------------------------
DWORD 
SC_GetTickCount(void) 
{
    DWORD dwInc = 0, dwPartial = dwPartialCurMSec;
	DWORD curReturnMSec;
    ULARGE_INTEGER cdummy = {0, 0};
	curReturnMSec=*pCurMSec;
    CPUGetSysTimerCountElapsed(RESCHED_PERIOD, &dwInc, &dwPartial, &cdummy);
	return (curReturnMSec==*pCurMSec)?curReturnMSec+dwInc:*pCurMSec;
}


volatile BOOL fResumeFlag;
extern void CPUEnterIdleMode(void);



//------------------------------------------------------------------------------
// Initialize SDMMC block.. 
//------------------------------------------------------------------------------
static void InitSDMMC(void) 
{
	volatile IOPreg *s2410IOP = (IOPreg *)IOP_BASE;

	/* Initialize SDMMC and Configure SDMMC Card Detect	*/
	/* ::::::::::::::::::::::::::::::::::: GPIO Configure ::::::::::::::::::::::::::::::::::::: */
	RETAILMSG(1,(TEXT("SDMMC config current rGPGCON: %x\r\n"), s2410IOP->rGPGCON));  
	/* We must need this PULL-UP routines to inialize. */
	//s2410IOP->rGPGUP = 0xF800;   
	s2410IOP->rGPGUP &= ~(1<<10);	
	s2410IOP->rGPGCON &= ~((0x3 << 20));   
	s2410IOP->rGPGCON |=  ((0x2 << 20));		/* External Interrupt #18 Enable				*/
	RETAILMSG(1,(TEXT("SDMMC config set rGPGCON: %x\r\n"), s2410IOP->rGPGCON));   

	s2410IOP->rEXTINT2 &= ~(0x7 << 8);			/* Configure EINT18 as Both Edge Mode		*/
	s2410IOP->rEXTINT2 |=  (0x7 << 8);

	/* Configure SDMMC Write Protect */
	s2410IOP->rGPHUP = 0x0;   
	s2410IOP->rGPHCON &= ~((0x3 << 16));   
	s2410IOP->rGPHCON |=  ((0x0 << 16));		/* GPH8/UCLK Write Protect Pin					*/

	/* Enable USB Device */
	s2410IOP->rGPGCON &= ~((0x3 << 18));   
	s2410IOP->rGPGCON |=  ((0x1 << 18));		/* GPG9 Output Enable				*/
	s2410IOP->rGPGDAT |= ((1 << 9));
	
	RETAILMSG(1,(TEXT("SDMMC config Init Done.\r\n")));   
}



//------------------------------------------------------------------------------
// Initialize and test the LCD block.. 
//------------------------------------------------------------------------------

/*
// Define some values for TFT 16bpp
#if(LCDTYPE == TFT16BPP)    // TFT 640*480 / 16bpp
#define FR_WIDTH            240
#define FR_HEIGHT           320
#define PhysicalVmemSize    FR_HEIGHT*FR_WIDTH*LCDTYPE


struct FrameBuffer {
   unsigned short pixel[FR_HEIGHT][FR_WIDTH];
};

#else if(LCDTYPE == STN8BPP)// STN 320*240 / 8bpp
#define FR_WIDTH            320
#define FR_HEIGHT           240
#define PhysicalVmemSize    FR_HEIGHT*FR_WIDTH

struct FrameBuffer {
   unsigned char pixel[FR_HEIGHT][FR_WIDTH];
};
#endif
*/

struct FrameBuffer *FBuf;

static void InitDisplay()
{
    //int i, j;
    volatile IOPreg *s2410IOP;
    volatile LCDreg *s2410LCD;    

    s2410IOP = (IOPreg *)IOP_BASE;
    s2410LCD = (LCDreg *)LCD_BASE; 

    // LCD port initialize.
    s2410IOP->rGPCUP  = 0xFFFFFFFF;
    s2410IOP->rGPCCON = 0xAAAAAAAA;


    s2410IOP->rGPDUP  = 0xFFFFFFFF;
    s2410IOP->rGPDCON = 0xAAAAAAAA;

    s2410IOP->rGPGCON &= ~(3 << 8);                 /* Set LCD_PWREN as output                          */
    s2410IOP->rGPGCON |=  (1 << 8);

    s2410IOP->rGPGDAT |=  (1 << 4);                 /* Backlight ON                                     */

	s2410LCD->rLCDCON1=(CLKVAL_TFT<<8)|(MVAL_USED<<7)|(3<<5)|(12<<1)|0;
        // TFT LCD panel,16bpp TFT,ENVID=off
	s2410LCD->rLCDCON2=(VBPD<<24)|(LINEVAL_TFT<<14)|(VFPD<<6)|(VSPW);
	s2410LCD->rLCDCON3=(HBPD<<19)|(HOZVAL_TFT<<8)|(HFPD);
	s2410LCD->rLCDCON4=(MVAL<<8)|(HSPW);
	s2410LCD->rLCDCON5=(1<<11)|(1<<9)|(1<<8)|(1<<3)|(1<<0);	//FRM5:6:5,HSYNC and VSYNC are inverted
	s2410LCD->rLCDSADDR1=((FRAMEBUF_DMA_BASE>>22)<<21)|M5D(FRAMEBUF_DMA_BASE>>1);
	s2410LCD->rLCDSADDR2=M5D( (FRAMEBUF_DMA_BASE+(LCD_XSIZE_TFT*LCD_YSIZE_TFT*2))>>1 );
	s2410LCD->rLCDSADDR3=(((LCD_XSIZE_TFT-LCD_XSIZE_TFT)/1)<<11)|(LCD_XSIZE_TFT/1);
	s2410LCD->rLCDINTMSK|=(3); // MASK LCD Sub Interrupt
	s2410LCD->rLPCSEL&=(~7); // Disable LPC3600
	s2410LCD->rTPAL=0; // Disable Temp Palette
	
	s2410LCD->rLCDCON1 |= 1;
	
}


static void OEMInitInterrupts(void)
{
	volatile INTreg *s2410INT = (INTreg *)INT_BASE;
	volatile IOPreg *s2410IOP = (IOPreg *)IOP_BASE;

    //RETAILMSG(1, (TEXT("Clear pending interrupts...\r\n")));

	// Configure EINT9 for CS8900 interrupt.
	//
	s2410IOP->rGPGCON  = (s2410IOP->rGPGCON  & ~(0x3 << 0x2)) | (0x2 << 0x2);		// GPG1 == EINT9.
	s2410IOP->rGPGUP   = (s2410IOP->rGPGUP   |  (0x1 << 0x1));						// Disable pull-up.
	s2410IOP->rEXTINT1 = (s2410IOP->rEXTINT1 & ~(0xf << 0x4)) | (0x1 << 0x4);		// Level-high triggered.

	// Configure EINT8 for PD6710 interrupt.
	//
	s2410IOP->rGPGCON  = (s2410IOP->rGPGCON  & ~(0x3 << 0x0)) | (0x2 << 0x0);		// GPG0 == EINT8.
	s2410IOP->rGPGUP   = (s2410IOP->rGPGUP   |  (0x1 << 0x0));						// Disable pull-up.
	s2410IOP->rEXTINT1 = (s2410IOP->rEXTINT1 & ~(0xf << 0x0)) | (0x1 << 0x0);		// Level-high triggered.

	// Mask and clear all peripheral interrupts (these come through a second-level "GPIO" interrupt register).
	//
	s2410IOP->rEINTMASK = BIT_ALLMSK;	// Mask all EINT interrupts.
	s2410IOP->rEINTPEND = BIT_ALLMSK;	// Clear pending EINT interrupts.

	// Mask and clear all interrupts.
	//
    s2410INT->rINTMSK = BIT_ALLMSK;			// Mask all interrupts (reset value).
	s2410INT->rINTMSK &= ~BIT_BAT_FLT;
    s2410INT->rSRCPND = BIT_ALLMSK;			// Clear pending interrupts.
    s2410INT->rINTPND = s2410INT->rINTPND;	// S3C2410X developer notice (page 4) warns against writing a 1 to any
											//  0 bit field in the INTPND register.  Instead we'll write the INTPND value itself.
    
}

/*
static void OEMInitInterrupts(void)
{
	volatile INTreg *s2410INT = (INTreg *)INT_BASE;
	volatile IOPreg *s2410IOP = (IOPreg *)IOP_BASE;

    //RETAILMSG(1, (TEXT("Clear pending interrupts...\r\n")));

	s2410INT->rSUBSRCPND = BIT_SUB_ALLMSK;
	s2410INT->rINTSUBMSK = BIT_SUB_ALLMSK;

	s2410IOP->rEINTMASK = 0xffffff;
	s2410IOP->rEINTPEND = 0xffffff;

    s2410INT->rSRCPND = BIT_ALLMSK;     // Clear pending bit
    s2410INT->rINTPND = BIT_ALLMSK;

    s2410INT->rINTMSK = BIT_ALLMSK;			// Mask all interrupts (reset value).
	s2410INT->rINTMSK &= ~BIT_BAT_FLT;
    s2410INT->rSRCPND = BIT_ALLMSK;			// Clear pending interrupts.
    s2410INT->rINTMSK &= ~(BIT_TIMER4);    
    s2410INT->rINTPND = s2410INT->rINTPND;	
    
}
*/

/*
static void OEMInitInterrupts(void)
{
	volatile INTreg *s2410INT = (INTreg *)INT_BASE;
	volatile IOPreg *s2410IOP = (IOPreg *)IOP_BASE;

	// Configure EINT9 for CS8900 interrupt.
	//
	s2410IOP->rGPGCON  = (s2410IOP->rGPGCON  & ~(0x3 << 0x2)) | (0x2 << 0x2);		// GPG1 == EINT9.
	s2410IOP->rGPGUP   = (s2410IOP->rGPGUP   |  (0x1 << 0x1));						// Disable pull-up.
	s2410IOP->rEXTINT1 = (s2410IOP->rEXTINT1 & ~(0xf << 0x4)) | (0x1 << 0x4);		// Level-high triggered.

	// Configure EINT8 for PD6710 interrupt.
	//
	s2410IOP->rGPGCON  = (s2410IOP->rGPGCON  & ~(0x3 << 0x0)) | (0x2 << 0x0);		// GPG0 == EINT8.
	s2410IOP->rGPGUP   = (s2410IOP->rGPGUP   |  (0x1 << 0x0));						// Disable pull-up.
	s2410IOP->rEXTINT1 = (s2410IOP->rEXTINT1 & ~(0xf << 0x0)) | (0x1 << 0x0);		// Level-high triggered.

	// Mask and clear all peripheral interrupts (these come through a second-level "GPIO" interrupt register).
	//
	s2410IOP->rEINTMASK = BIT_ALLMSK;	// Mask all EINT interrupts.
	s2410IOP->rEINTPEND = BIT_ALLMSK;	// Clear pending EINT interrupts.

	// Mask and clear all interrupts.
	//
    s2410INT->rINTMSK = BIT_ALLMSK;			// Mask all interrupts (reset value).
	s2410INT->rINTMSK &= ~BIT_BAT_FLT;
    s2410INT->rSRCPND = BIT_ALLMSK;			// Clear pending interrupts.
    s2410INT->rINTPND = s2410INT->rINTPND;	// S3C2410X developer notice (page 4) warns against writing a 1 to any
											//  0 bit field in the INTPND register.  Instead we'll write the INTPND value itself.
}
*/

⌨️ 快捷键说明

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