📄 cfw.c
字号:
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 + -