📄 xrompower.c
字号:
//Setup Timer1 time out values
{
DWORD D_Tmo = D_CpuClock/40000L; // Generate 0.1ms timeout
WRITE_PCB_REG(T1CMPA, D_Tmo); // Configure timer1 value
WRITE_PCB_REG(T1CON, (INH|CONT)); // Disable timer interrupt
SET_VECTOR(TIMER1_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(IRTimerIntRAM)));
}
IRInterruptOccurred = gmd_FALSE; // Clear flag that indicates IR interrupt occurred
}
#else // RC5
static void IRInitRAM(DWORD D_CpuClock)
{
//Setup Int2 interrupt register
gm_SetRegBitsWord(IRQ_CONFIG, GPIO_IRQ_IN_EN);
WRITE_PCB_REG(I2CON, 0);
SET_PCB_REG_BITS(IMASK, I2); // First mask the interrupt
SET_VECTOR(INT2_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(IREdgeInterruptRAM)));
CLEAR_PCB_REG_BITS(IMASK, I2); // Now, enable the interrupt
//Setup Timer1 time out values
{
W_IRPeriodTImeRAM = (WORD)(D_CpuClock/4499L); // Generate 0.889ms timeout
WRITE_PCB_REG(T1CON, (INH|CONT)); // Disable timer interrupt
SET_VECTOR(TIMER1_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(IRTimerIntRAM)));
}
IRInterruptOccurred = gmd_FALSE; // Clear flag that indicates IR interrupt occurred
}
#endif // RC5
#endif // PORT_IR_USED
//*************************************************************************
// FUNCTION : SetOCMClockFreqRAM
// USAGE : SetOCMClockFreqRAM(BYTE param)
// DESCRIPTION : This function changes the OCM frequency based on the
// input flag.
// INPUT : B_High - If TRUE, CPU clock frequency is set to TCLK
// frequency. If FALSE, it is set to gmc_OCM_CLK_POWERDOWN
// frequency. All frequencies are in kHz.
// OUTPUT : None
// GLOBALS : gmc_T_CLK_KHZ and gmc_OCM_CLK_POWERDOWN
// USED_REGS : None directly.
//*************************************************************************
static void SetOCMClockFreqRAM( BYTE B_High )
{
#ifdef EXT_ROM_RD_CTRL
BYTE ws;
#endif //EXT_ROM_RD_CTRL
BYTE B_TclkDivisor = 0;
if ( !B_High )
{
// Compute the TCLK divisor based on the OCM frequency in low power.
if(gmc_OCM_CLK_POWERDOWN != 0)
{
B_TclkDivisor = (BYTE)(((gmc_T_CLK_KHZ * 10) / gmc_OCM_CLK_POWERDOWN) + 5) / 10;
}
msg("RAM - TCLK div: %d", B_TclkDivisor);
#if DEBUG_XROM_POWER_OFF && DEBUG_MSG
if ( B_TclkDivisor >= 1 )
{
#if SBAUD_IN_LOW_POWER == 115200UL
msg("Changing baud rate to 115200", 0);
#else
msg("Changing baud rate to %d", (WORD)SBAUD_IN_LOW_POWER);
#endif
}
#endif
// Configure OCM to use TCLK
gm_ClearRegBitsByte(CLOCK_CONFIG, (BIT4 | BIT5));
gm_ClearRegBitsByte(CLOCK_CONFIG, IFM_CLKSEL); // Sel TCLK to drive IFM.
// Program divisor value to operate OCM in low freq.
// The actual divisor value is (Register Value * 2).
gm_WriteRegByte(OCM_TCLK_DIV, (B_TclkDivisor / 2));
// We've changed to the slower TCLK, we can also lower the RD waitstates.
// Also, re-initialize timers, serial and IR drivers.
if ( B_TclkDivisor >= 1 )
{
#ifdef EXT_ROM_RD_CTRL
ws = (BYTE)((((DWORD)gmc_T_CLK_KHZ / (DWORD)(B_TclkDivisor)
* (DWORD)gmc_CPU_WaitStates_NS) + 999999UL)/1000000UL);
#endif //EXT_ROM_RD_CTRL
gm_TimerInit( (gmc_T_CLK_KHZ * 1000UL / (DWORD)(B_TclkDivisor)),
&UserTimers[0], Num10mstimers, Num100mstimers );
gm_UartInit( (gmc_T_CLK_KHZ * 1000UL / (DWORD)(B_TclkDivisor)),
SBAUD_IN_LOW_POWER );
#ifdef PORT_IR_USED
IRInitRAM( gmc_T_CLK_KHZ * 1000UL / (DWORD)(B_TclkDivisor) );
#endif // PORT_IR_USED
}
else
{
#ifdef EXT_ROM_RD_CTRL
ws = (BYTE)((((DWORD)gmc_T_CLK_KHZ * (DWORD)gmc_CPU_WaitStates_NS) + 999999UL)/1000000UL);
#endif //EXT_ROM_RD_CTRL
gm_TimerInit( gmc_T_CLK_KHZ * 1000UL, &UserTimers[0], Num10mstimers, Num100mstimers);
gm_UartInit(gmc_T_CLK_KHZ * 1000UL, gmc_SerialBaudRate);
#ifdef PORT_IR_USED
IRInitRAM(gmc_T_CLK_KHZ * 1000UL);
#endif // PORT_IR_USED
}
#ifdef EXT_ROM_RD_CTRL
// Make sure wait states does not exceed register limit
if ( ws > XROM_OE_WIDTH )
{
ws = XROM_OE_WIDTH;
}
// Program the wait states
gm_WriteRegByte(EXT_ROM_RD_CTRL, (ws - 1));
#endif // EXT_ROM_RD_CTRL
// Speed up the SPI clock since CPU clock is slow
gm_ClearRegBitsByte(SPI_CONTROL, SPI_CLK_SEL);
} // if ( !B_High )
else
{
// power up RCLK - Reset to avoid any sync problems.
gm_WriteRegByte(RCLK_CONFIG, RCLK_RESET );
gm_Delay1ms(1);
gm_WriteRegByte(RCLK_CONFIG, 0);
#if DEBUG_XROM_POWER_OFF && DEBUG_MSG
if ( gmc_SerialBaudRate == 115200UL )
{
msg("Restoring baud rate to 115200", 0);
}
else
{
msg("Restoring baud rate to %d", (WORD)(gmc_SerialBaudRate));
}
#endif
#ifdef EXT_ROM_RD_CTRL
ws = (BYTE)((((DWORD)gmc_T_CLK_KHZ * (DWORD)gmc_CPU_WaitStates_NS) + 999999UL)/1000000UL);
// Make sure wait states do not exceed register limit
if ( ws > XROM_OE_WIDTH )
{
ws = XROM_OE_WIDTH;
}
// Program the wait states
gm_WriteRegByte(EXT_ROM_RD_CTRL, (ws - 1));
#endif //EXT_ROM_RD_CTRL
// Configure OCM to use TCLK
gm_ClearRegBitsByte(CLOCK_CONFIG, (BIT4 | BIT5));
// Remove any TCLK divisor value that might have been used for OCM Clk.
gm_WriteRegByte(OCM_TCLK_DIV, 0);
gm_TimerInit(gmc_T_CLK_KHZ * 1000UL, &UserTimers[0], Num10mstimers, Num100mstimers);
// Reinitialize serial port for new CPU clock frequency and higher baud rate.
gm_UartInit(gmc_T_CLK_KHZ * 1000UL, gmc_SerialBaudRate);
// Program I2C Master to run on higher serial clock
#ifdef I2C_MST_CTRL
// phoenix doesn't have a hardware I2C block, so there's no need to switch
// the speed when changing to and from TCLK.
gm_I2cInit( 0, gmc_T_CLK_KHZ, gmc_I2cSclk_Khz);
#endif //I2C_MST_CTRL
// Program IR driver to use TCLK
#ifdef PORT_IR_USED
IRInit( (DWORD)gmc_T_CLK_KHZ * 1000UL );
#endif // PORT_IR_USED
} // if ( !B_High ) else
}
//*************************************************************************
// FUNCTION : RestoreSystemToROMExecution
// USAGE : RestoreSystemToROMExecution()
// DESCRIPTION : This function is executed when control returns from RAM.
// It restores the state of the system to enable execution
// from ROM.
// INPUT : none
// OUTPUT : None
// GLOBALS : None
// USED_REGS : None directly
//*************************************************************************
static void RestoreSystemForROMExecution( void )
{
// Call function to re-initialize interrupt vector
// addresses.
InitExceptionHandler();
// Let OCM run at TCLK speed
SetOCMClockFreqRAM( gmd_TRUE );
StartGetKeyISR();
}
#pragma codeseg CUSTOM_CODE
//*************************************************************************
// Code copied to RAM starts from here
// Notes about code executed in RAM.
// This code MUST be relocatable. In other words, it cannot have any long
// jumps (i.e. intersegment jumps). Also, the goal is to keep this code
// as small as possible (within 2 KBytes).
//*************************************************************************
//*************************************************************************
// FUNCTION : PowerDownXROM
// USAGE : PowerDownXROM( param );
// DESCRIPTION : This function is executed in RAM and will power down
// external ROM when called. There are two cases to consider
// (a) Power Key (soft power off mode) and (b) Input syncs
// lost (sleep mode). In case (a), the routine turns power
// off to the external ROM after a certain number of main
// loops to allow OSD and power handlers to sync up. It then
// waits for any key to be pressed. After a key press is
// detected, it turns on power to external ROM and exits.
// The key is processed by the external keypad handler. If
// it is not the power key, control returns to RAM.
// In case (b), it shuts off the flash ROM and goes to sleep
// for the period specified in W_PowerDownTime_ms (ms units).
// When this expires, it powers on the flash ROM and returns.
// INPUTS : W_PowerDownTime_ms - A word variable that contains the
// duration (ms units) to shut power off to external ROM.
// If zero, then the routine assumes we are in soft power off
// mode (case (a) above) and cycles power to the ROM.
// OUTPUTS : None
// GLOBALS : None
// USED_REGS : None
//*************************************************************************
//
// PDR#6808 In soft power off mode, we now cycle power to the external ROM with
// a duty cycle controled by compile-time options (#define's above). This is to
// eliminate the keypad handler from RAM code. When the ROM power is on, the ROM
// keypad handler monitors the power key.
//
// PDR#7007 Sometimes the power key press is missed. This was because the ROM power
// was cycled with a duty cycle of 66% (33% off time, 66% on time). The keypad
// handler runs only when the ROM is turned on. This may lead to the power key
// not being sensed, since the ROM is on only for 66% of the time. To get around
// this problem, added code to sense any key in RAM and then branch to ROM
// (after turning power on) to process the key. This way, we can keep the ROM off
// 100% of the time and still detect key presses reliably.
//
void PowerDownXROM( WORD W_PowerDownTime_ms)
{
#if (ProcessExceptions != DisableExceptions ) && (UseWatchdogTimer == 1)
// First pet the watchdog, to keep it quite
PetWatchdogRAM();
#endif // (ProcessExceptions != DisableExceptions ) && (UseWatchdogTimer == 1)
if ( W_PowerDownTime_ms == 0 ) // Soft power off mode - power key pushed
{
DisableXROMPower(); // Turn off power to external ROM
msg("ROM power removed - soft power off", 0);
while ( gmd_TRUE )
{
if ( ReadKeypadRAM() ) // If a key is pressed, turn on power to ROM and return.
{ // The external keypad handler will process the key.
msg("RAM execution - Key press detected", 0);
XROM_StateMachine_Settle_Count = XROM_STATE_MC_SETTLE_LOOPS;
break;
}
else
{
if ( IRInterruptOccurred ) // Check if IR interrupt occurred. If it did,
{ // turn on power to ROM and exit. The external
IRInterruptOccurred = gmd_FALSE;
break; // keypad handler will take care of the rest.
}
#if (ProcessExceptions != DisableExceptions ) && (UseWatchdogTimer == 1)
PetWatchdogRAM();
#endif // (ProcessExceptions != DisableExceptions ) && (UseWatchdogTimer == 1)
if ( SerialHandlerRAM() == UNKNOWN_MSG_CMD )
{
// This is a hook to execute customer appstests.
// If the internal ROM handler is unable to process
// the serial message, we enable power to external
// ROM and exit. The external ROM serial handler will
// deal with the appstests, etc.
break;
}
} // if ( ReadKeypadRAM() ) else
} // while ( gmd_TRUE )
} // if ( W_PowerDownTime_ms == 0 )
else // Sleep mode - input syncs lost
{
// We've come here because input syncs are lost. We just start the timer
// and wait till it expires. During this time, the power to external ROM
// is turned off. While we are waiting, we pet the watchdog and process
// simple serial port commands.
DisableXROMPower();
msg("ROM power removed - sleep", 0);
gm_TimerStart( XROMPowerCycle_10ms_TMR, (gmt_Timer)(W_PowerDownTime_ms/10) );
msg("ROM power OFF timer started - sleep", 0);
msg("Power OFF time %d ms", W_PowerDownTime_ms);
// Wait for the timer to time out
while ( gm_TimerCheck( XROMPowerCycle_10ms_TMR ) == gmd_TMR_ACTIVE )
{
#if (ProcessExceptions != DisableExceptions ) && (UseWatchdogTimer == 1)
PetWatchdogRAM();
#endif // (ProcessExceptions != DisableExceptions ) && (UseWatchdogTimer == 1)
if ( SerialHandlerRAM() == UNKNOWN_MSG_CMD )
{
// This is a hook to execute customer appstests.
// If the internal ROM handler is unable to process
// the serial message, we enable power to external
// ROM and exit. The external ROM serial handler will
// deal with the appstests, etc.
break;
}
}
} // if ( W_PowerDownTime_ms == 0 ) else
// Enable power to XROM
EnableXROMPower();
msg("ROM power enabled", 0);
// Delay for some time to allow power to settle.
gm_Delay1ms(XROM_POWER_ON_SETTLE_TIME_MS);
// Enable all interrupts
ENABLE_INTERRUPTS;
}
//*************************************************************************
// FUNCTION : ReadGPIOKeypadRAM
// USAGE : ReadGPIOKeypadRAM()
// DESCRIPTION : This function reads the GPIO keypad. If any key is pressed
// it returns gmd_TRUE. Otherwise, it returns gmd_FALSE.
// INPUT : None
// OUTPUT : None
// GLOBALS : None
// USED_REGS : None
//*************************************************************************
#if USE_GPIO_KEYPAD
static __near BYTE ReadGPIOKeypadRAM(void)
{
BYTE i;
for (i = 0; i < XROM_Number_of_scan_keys_RAM; i++)
{
#if KeyPolarity
if (((gm_ReadRegByte(Sta_KeyMapTbl[i].W_GpioPortAddr))
& ((BYTE)Sta_KeyMapTbl[i].W_GpioPinPos)) != 0)
#else
if (((gm_ReadRegByte(Sta_KeyMapTbl[i].W_GpioPortAddr))
& ((BYTE)Sta_KeyMapTbl[i].W_GpioPinPos)) == 0)
#endif
{
msg("RAM - GPIO key detected", 0);
return( gmd_TRUE );
}
}
return( gmd_FALSE );
}
#endif
//*************************************************************************
// FUNCTION : ScanADCKeyOnChannelRAM
// USAGE : ScanADCKeyOnChannelRAM(ChannelNum)
// DESCRIPTION : This function starts ADC conversion and reads the ADC
// result after the conversion. It returns the result to
// the caller. The ADC on the given channel is used.
// INPUT : B_Channel - Channel number of the ADC.
// OUTPUT : Result of the ADC conversion.
// GLOBALS : None
// USED_REGS : LOW_BW_ADC_CTRL, LOW_BW_ADC_STATUS, LOW_BW_ADC_RESULT
//*************************************************************************
#if LBADC_USED
static __near BYTE ScanADCKeyOnChannelRAM (BYTE B_Channel)
{
static BYTE B_Key = 0;
BYTE B_Ctrl;
//
// 1) Configure LBW ADC channel 1, 2 and then 3 to handle keyboard key input
// 2) Program the Low Bandwidth ADC control register to start conversion.
//
B_Ctrl = LBADC_EN | B_Channel | DIV_BY_1;
gm_WriteRegByte (LOW_BW_ADC_CTRL, B_Ctrl);
gm_WriteRegByte (LOW_BW_ADC_CTRL, B_Ctrl | LBADC_START_CONV);
//
// When conversion done, copy the conversion result to the BYTE pointer.
//
// LOW_BW_ADC_STATUS needs 3TCLKs to clear after a LBADC_START_CONV,
// add delay to give time for LOW_BW_ADC_STATUS to read correctly.
gm_Delay1ms(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -