📄 board.c
字号:
/* The content of this file or document is CONFIDENTIAL and PROPRIETARY
* to Jade Technologies Co., Ltd. It is subjected to the terms of a
* License Agreement between Licensee and Jade Technologies Co., Ltd.
* restricting among other things, the use, reproduction, distribution
* and transfer. Each of the embodiments, including this information
* and any derivative work shall retain this copyright notice.
*
* Copyright (c) 2004 - 2005 Jade Technologies Co., Ltd.
* All rights reserved.tent permitted
* by a licensing agreement from ARM Limited.
* ----------------------------------------------------------------
* File: board.c,v
* Revision: 1.0
* ----------------------------------------------------------------
* $
*/
#include <windows.h>
#include <nkintr.h>
#include <oalfuncs.h>
#include <oalintr.h>
#include "win_plat.h" /* This includes platform.h */
#include <pl190.h> // VIC and SIC
#include <sp804.h> // timers
//#include <apcharlcd.h>
/* OS_TIMER increment for 1 ms clock time */
DWORD OEMCount1ms;
/* system tick frequency */
unsigned long OEMClockFreq; /* OEM clock frequency is used only in OAL */
/* counts per reschedule */
extern DWORD dwReschedIncrement;
extern ULONG LogIntrOpenStatus[LOGINTR_MAX];
// Internal fucntion
//void apCHARLCD_Write(unsigned char dat, unsigned char rs);
/* Codes for hexadecimal characters */
//static unsigned int alpha_codes[] =
//{
// 0x007E, 0x080C, 0x01B6, 0x011E, 0x01CC, 0x01DA, 0x01FA, 0x2802,
// 0x01FE, 0x01CE, 0x01EE, 0x01F8, 0x0072, 0x01BC, 0x00F2, 0x00E2
//};
/* Data structure used for timer-related information */
typedef struct uHALis_Timer
{
pvstTimerRegs pt; /* timer registers */
DWORD irq; /* IRQ number */
} SoftTimer_t;
/* Array timer data */
SoftTimer_t gSysTimers[] = {
{ (pvstTimerRegs)(VA_CT_BASE + TIMER0_OFFSET), LOGINTR_TIMER0 },
{ (pvstTimerRegs)(VA_CT_BASE + TIMER1_OFFSET), LOGINTR_TIMER1 }
};
static int Irq2Vic[] =
{
-1,
/*LOGINTR_WDOG */ 0 ,
/*LOGINTR_SOFTINT */ 1 ,
/*LOGINTR_CPUINT0 */ 2 ,
/*LOGINTR_CPUINT1 */ 3 ,
/*LOGINTR_TIMER0 */ 4 ,
/*LOGINTR_TIMER1 */ 5 ,
/*LOGINTR_IIC */ 7 ,
/*LOGINTR_CF */ 8 ,
/*LOGINTR_RTC */ 9 ,
/*LOGINTR_USB */ 10 ,
/*LOGINTR_UART0 */ 11 ,
/*LOGINTR_UART1 */ 12 ,
/*LOGINTR_UART2 */ 13 ,
/*LOGINTR_UART3 */ 14 ,
/*LOGINTR_SD0 */ 14 ,
/*LOGINTR_FIRI */ 14 ,
/*LOGINTR_SCI */ 15 ,
/*LOGINTR_CLCD1 */ 16 ,
/*LOGINTR_SD1 */ 16 ,
/*LOGINTR_DMA */ 17 ,
/*LOGINTR_PWRFAIL */ 18 ,
/*LOGINTR_SSP0 */ 19 ,
/*LOGINTR_IIS */ 19 ,
/*LOGINTR_KBD */ 22 ,
/*LOGINTR_AUDIO */ 23 ,
/*LOGINTR_SSP1 */ 23 ,
/*LOGINTR_CLCD0 */ 24 ,
/*LOGINTR_DMA23 */ 26 ,
/*LOGINTR_VIA */ 27 ,
/*LOGINTR_MP4D */ 28 ,
/*LOGINTR_MP4E */ 29 ,
/*LOGINTR_EXTINT0 */ 30 ,
/*LOGINTR_EXTINT1 */ 31
};
static int Vic2Irq[][4] =
{
/*0 */ { LOGINTR_WDOG , -1 , -1 , -1 } ,
/*1 */ { LOGINTR_SOFTINT , -1 , -1 , -1 } ,
/*2 */ { LOGINTR_CPUINT0 , -1 , -1 , -1 } ,
/*3 */ { LOGINTR_CPUINT1 , -1 , -1 , -1 } ,
/*4 */ { LOGINTR_TIMER0 , -1 , -1 , -1 } ,
/*5 */ { LOGINTR_TIMER1 , -1 , -1 , -1 } ,
/*6 */ { -1 , -1 , -1 , -1 , } ,
/*7 */ { LOGINTR_IIC , -1 , -1 , -1 } ,
/*8 */ { LOGINTR_CF , -1 , -1 , -1 } ,
/*9 */ { LOGINTR_RTC , -1 , -1 , -1 } ,
/*10*/ { LOGINTR_USB , -1 , -1 , -1 } ,
/*11*/ { LOGINTR_UART0 , -1 , -1 , -1 } ,
/*12*/ { LOGINTR_UART1 , -1 , -1 , -1 } ,
/*13*/ { LOGINTR_UART2 , -1 , -1 , -1 } ,
/*14*/ { LOGINTR_UART3 , LOGINTR_SD0 , LOGINTR_FIRI , -1} ,
/*15*/ { LOGINTR_SCI , -1 , -1 , -1 } ,
/*16*/ { LOGINTR_CLCD1 , LOGINTR_SD1 , -1 , -1 } ,
/*17*/ { LOGINTR_DMA , -1 , -1 , -1 } ,
/*18*/ { LOGINTR_PWRFAIL , -1 , -1 , -1 } ,
/*19*/ { LOGINTR_SSP0 , LOGINTR_IIS , -1 , -1 } ,
/*20*/ { -1 , -1 , -1 , -1 } ,
/*21*/ { -1 , -1 , -1 , -1 } ,
/*22*/ { LOGINTR_KBD , -1 , -1 , -1 } ,
/*23*/ { LOGINTR_AUDIO , LOGINTR_SSP1 , -1 , -1 } ,
/*24*/ { LOGINTR_CLCD0 , -1 , -1 , -1 } ,
/*25*/ { -1 , -1 , -1 , -1 } ,
/*26*/ { LOGINTR_DMA23, -1 , -1 , -1 } ,
/*27*/ { LOGINTR_VIA , -1 , -1 , -1 } ,
/*28*/ { LOGINTR_MP4D , -1 , -1 , -1 } ,
/*29*/ { LOGINTR_MP4E , -1 , -1 , -1 } ,
/*30*/ { LOGINTR_EXTINT0, -1 , -1 , -1 } ,
/*31*/ { LOGINTR_EXTINT1, -1 , -1 , -1 } ,
};
// Z228 Development Board- we must take into account the VIC
// and the Z228 Development Board's secondary interrupt controller.
void pHALir_DisableIrq(DWORD irq)
{
pvstVICRegs pVic;
pVic = (pvstVICRegs)(VA_VIC_BASE);
if( irq >MAXLOGINTR || irq < 1 )
{
DEBUGMSG(1, (TEXT("ERROR: attempt to DISABLE a not exist irq!\r\n")));
return;
}
pVic->IntEnClear = (1 << Irq2Vic[irq]);
return;
}
void pHALir_DisableVic(DWORD irq)
{
pvstVICRegs pVic;
pVic = (pvstVICRegs)(VA_VIC_BASE);
if( irq >MAXLOGINTR || irq < 1 )
{
DEBUGMSG(1, (TEXT("ERROR: attempt to DISABLE a not exist irq!\r\n")));
return;
}
pVic->IntEnClear = (1 << Irq2Vic[irq]);
return;
}
// Z228 Development Board - we must take into account the VIC
// and the Z228 Development Board's secondary interrupt controller.
void pHALir_EnableIrq(DWORD irq)
{
pvstVICRegs pVic;
pVic = (pvstVICRegs)(VA_VIC_BASE);
if( irq >MAXLOGINTR || irq < 1 )
{
RETAILMSG(1, (TEXT("ERROR: attempt to DISABLE a not exist irq!\r\n")));
return;
}
pVic->IntEnable = (1 << Irq2Vic[irq] );
}
/* Returns TRUE if the timer has generated an interrupt */
BOOL pHALir_HasTimerInterrupt(DWORD timer)
{
pvstTimerRegs pTimer = gSysTimers[timer].pt;
return (pTimer->MaskedInterruptStatus);
}
/* Returns TRUE if the timer can generate an interrupt */
BOOL pHALir_TimerInterruptEnabled(DWORD timer)
{
pvstTimerRegs pTimer = gSysTimers[timer].pt;
return (pTimer->Control & TimerControlEnable);
}
/* Enables the interrupt for the timer */
void pHALir_EnableTimerInterrupt(DWORD timer)
{
pvstTimerRegs pTimer = gSysTimers[timer].pt;
pTimer->Control |= TimerControlIntEnable;
}
/* Disables the interrupt for the timer */
void pHALir_DisableTimerInterrupt(DWORD timer)
{
pvstTimerRegs pTimer = gSysTimers[timer].pt;
pTimer->Control &= ~TimerControlIntEnable;
}
/* Clears the Timer interrupt */
void pHALir_ClearTimerInterrupt(DWORD timer)
{
pvstTimerRegs pTimer = gSysTimers[timer].pt;
/* clear the interrupt (if any) */
pTimer->InterruptClear = 1;
}
/* This routine stops the specified timer hardware. */
void uHALir_DisableTimer(DWORD timer)
{
pvstTimerRegs pTimer = gSysTimers[timer].pt;
/* Clear control register to disable timer */
pTimer->Control = 0;
/* clear the interrupt (if any) */
pTimer->InterruptClear = 1;
/* Disable at VIC */
pHALir_DisableIrq(gSysTimers[timer].irq);
}
/* Start-up routine to initialise the timers to a known state */
void uHALr_InitTimers(void)
{
DWORD i;
for (i = 0; i < NUMSYSTIMERS; i++)
{
uHALir_DisableTimer(i);
}
}
/* set a timer to a specific tick count */
void SetSysTimerInterval(DWORD dwTicks)
{
pvstTimerRegs pTimer = gSysTimers[OS_TIMER].pt;
pTimer->Control = 0;
/* program the new timer value */
pTimer->Load = dwTicks;
/* Set up timer control register */
pTimer->Control = TimerControlPeriodic | TimerControlEnable |
TimerControlIntEnable | TimerControlSize32;
/* Enable at IC */
pHALir_EnableIrq(gSysTimers[OS_TIMER].irq);
}
/* Put the CPU into a low-power state.
** If none is available, loop on a flag that gets set by ISRs.
*/
void CPUEnterIdle(DWORD dwIdleParam)
{
/* Wait For Interrupt */
WFI();
}
/* determine the maximum delay for a given request within the limits of
** the hardware
*/
DWORD CPUGetSysTimerCountMax(DWORD dwIdleMSecRequested)
{
if (dwIdleMSecRequested > IDLE_MAX_MS)
{
/*
** Our timer isn't capable of idling more than IDLE_MAX_MS milliseconds.
** We'll have to break the sleep time into reasonable chunks.
*/
return IDLE_MAX_MS;
}
return dwIdleMSecRequested;
}
/* set the new period for the timer */
void CPUSetSysTimerCount(DWORD dwIdleMSec)
{
DWORD dwTicks;
/* determine the number of ticks required for the number of milliseconds
* requested
*/
dwTicks = dwIdleMSec * RESCHED_INCREMENT;
/* program the new timer value */
SetSysTimerInterval(dwTicks);
}
/* return TRUE if a timer IRQ was pending, false otherwise.
** Clear the interrupt if pending.
*/
BOOL CPUClearSysTimerIRQ(void)
{
BOOL fPending;
/* This is the base address for the ADK timer block */
pvstTimerRegs pTimer = gSysTimers[OS_TIMER].pt;
/* Check if OS_TIMER interrupt is set */
if(((pTimer->RawInterruptStatus) & 0x1) != 0)
{
pHALir_ClearTimerInterrupt(OS_TIMER);
fPending = TRUE;
}
else
{
fPending = FALSE;
}
return fPending;
}
DWORD
CPUGetSysTimerCountElapsed(
DWORD dwTimerCountdownMSec,
volatile DWORD *pCurMSec,
DWORD *pPartialCurMSec,
volatile ULARGE_INTEGER *pCurTicks
)
{
pvstTimerRegs pTimer = gSysTimers[OS_TIMER].pt;
DWORD dwTick = dwTimerCountdownMSec * OEMCount1ms;
DWORD dwCount;
/* If timer IRQ pending, a full resched period elapsed */
if (CPUClearSysTimerIRQ( ))
{
*pCurMSec += dwTimerCountdownMSec;
pCurTicks->QuadPart += dwTick;
return dwTimerCountdownMSec;
}
/* No timer IRQ pending, calculate how much time has elapsed */
dwCount = pTimer->Value;
if (dwCount > dwTick)
{
/* This is an error case. Recover gracefully. */
RETAILMSG(1, (L"CPUGetSysTimerCountElapsed( ): Correcting periodic timer read error\r\n"));
dwCount = dwTick;
}
else
{
dwCount = dwTick - dwCount;
}
pCurTicks->QuadPart += dwCount;
dwCount += *pPartialCurMSec;
*pPartialCurMSec = dwCount % OEMCount1ms;
*pCurMSec += (dwCount /= OEMCount1ms);
return dwCount;
}
DWORD PerfCountFreq()
{
return(OEMClockFreq);
}
// NOTE: This only returns the clock value, since the last tick, which may
// have happened before this call and the tick you were checking
DWORD PerfCountSinceTick()
{
pvstTimerRegs pTimer = gSysTimers[OS_TIMER].pt;
return dwReschedIncrement - pTimer->Value;
}
/* EOF board.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -