📄 xrompower.c
字号:
/*
$Workfile: XromPower.c $
$Revision: 1.35 $
$Date: Dec 10 2004 06:48:52 $
*/
//******************************************************************
//
// Copyright (C) 2002. GENESIS MICROCHIP INC.
// All rights reserved. No part of this program may be reproduced.
//
// Genesis Microchip Corp., 2150 Gold Street
// Alviso, CA 95002 USA
// Genesis Microchip Inc., 165 Commerce Valley Dr. West
// Thornhill, Ontario, Canada, L3T 7V8
//
//================================================================
//
// MODULE: xrompower.c
//
// USAGE : XROM power supply function
//
//******************************************************************
//******************************************************************
// Include Files
//******************************************************************
#include "inc\all.h"
#include "mem.h"
#include <embedded.h>
#include "system\Mcu186.h"
#if USE_POWERDOWN_ROM_CE
// To enable debug printing, set this to 1
// Caution: When debug printing is enabled, it takes longer for
// key presses to be detected. With this caveat in mind, this
// flag must be turned on for debug purposes only.
#define DEBUG_XROM_POWER_OFF 0
#if DEBUG_XROM_POWER_OFF && DEBUG_MSG
#define msg(a,b) gm_Print((const char far *)a,b)
#else
#define msg(a,b)
#endif
//***********************************************************************
// Local definitions
//***********************************************************************
#ifdef PORT_ADC_1_USED || PORT_ADC_2_USED || PORT_ADC_3_USED
#define LBADC_USED 1
#else
#define LBADC_USED 0
#endif
#ifdef PORT_GPIO_1_USED || PORT_GPIO_2_USED
#if GPIOKEYPAD_ALLOWED
#define USE_GPIO_KEYPAD 1
#else
#define USE_GPIO_KEYPAD 0
#endif
#else
#define USE_GPIO_KEYPAD 0
#endif
#define XROM_POWER_ON_SETTLE_TIME_MS 20 // Settle time in ms for externl ROM power
#define XROM_LBADC_NOISE_THRESHOLD 0x0a // Noise threshold for ADC input
#define WDT_ENABLE_RAM ((WORD)1 << 15)
// #define DISABLE_INTERRUPTS() asm{ CLI } // Disable all interrupts expect NMI
// #define ENABLE_INTERRUPTS() asm{ STI } // Enable all interrupts
// A certain number of main loops are required after a key press for power and OSD
// handlers to sync up to each other. When the power key is pressed, after a delay
// of this many main loops, the code branches to RAM and executes from there. This
// is only applicable to soft power down mode (with the power key press) and not
// the sleep mode (when input syncs are lost). Note: Do not set this to zero. Minimum
// value is one.
#define XROM_STATE_MC_SETTLE_LOOPS 6 // Number of loops for power and OSD handlers to sync up
typedef enum SerialMsgStatus
{
NO_MSG_PARSED,
MSG_PARSED,
UNKNOWN_MSG_CMD
} SerialMsgStatus_t;
//***********************************************************************
// Prototypes of local functions
//***********************************************************************
void PowerDownXROM( WORD W_PowerDownTime_ms );
void DummyFunc2GetCodeSize(void);
static void InitializeSystemForRAMExecution( void );
static void RestoreSystemForROMExecution( void );
static void SetOCMClockFreqRAM( BYTE B_High );
#if ProcessExceptions != DisableExceptions
static void InitializeInterruptVectorsRAM( void );
#if UseWatchdogTimer == 1
static void EnableWatchDogTimerRAM(void);
static __near void PetWatchdogRAM(void);
#endif // UseWatchdogTimer
#else
#define InitializeInterruptVectorsRAM()
#define PetWatchdogRAM()
#define EnableWatchdogTimerRAM()
#endif // ProcessExceptions != DisableExceptions
#if RESET_ON_WDT
static __near void ResetOCMRAM(void);
#endif // RESET_ON_WDT
static __near SerialMsgStatus_t SerialHandlerRAM( void );
void interrupt CommonInterruptHandlerRAM( void );
void interrupt NMIHandlerRAM( void );
void interrupt BUS_WDT_IRQHanlderRAM (void);
#if USE_GPIO_KEYPAD
static __near BYTE ReadGPIOKeypadRAM(void);
#endif
#if LBADC_USED
static __near BYTE ScanADCKeyOnChannelRAM (BYTE B_Channel);
static __near BYTE ScanADCKeyRAM( void );
#endif
#ifdef PORT_IR_USED
static void IRInitRAM(DWORD D_CpuClock);
void interrupt IREdgeInterruptRAM(void);
void interrupt IRTimerIntRAM(void);
#endif // PORT_IR_USED
static __near BYTE ReadKeypadRAM( void );
// This function is in IROM. It is directly called.
extern SerialMsgStatus_t gmi_SystemDebug( void );
//***********************************************************************
// Global variables
//***********************************************************************
static SBYTE XROM_StateMachine_Settle_Count = XROM_STATE_MC_SETTLE_LOOPS;
#if USE_GPIO_KEYPAD
static BYTE XROM_Number_of_scan_keys_RAM = 0;
#endif // USE_GPIO_KEYPAD
static BYTE IRInterruptOccurred = gmd_FALSE; // Global to tell if IR interrupt occurred
#ifdef PORT_IR_USED
extern WORD IRKey; // Use this global variable to hold the IR Key code
static BYTE IrIndexRAM;
static WORD IrLWordRAM;
volatile WORD W_IrPacketCounterRAM;
#if IR_DRIVER != USE_RC5
volatile BYTE B_IrClockCounterRAM;
#if IR_DEVICE_LENGTH
static WORD IrAddressRAM;
#endif
#else
BYTE B_EdgeStateRAM;
WORD W_IRPeriodTImeRAM;
#endif
#endif // PORT_IR_USED
#if (WB_MAJOR < 4)
extern ST_KEY_MAP_TABLE Sta_KeyMapTbl[NUMBER_OF_KEYS];
#endif
// Address where power down code is copied in SRAM
#define POWER_DOWN_RAM_CODE_ADDR 0x1800
//*************************************************************************
// FUNCTION : CopyFlashPowerDownCodeToRAM
// USAGE : CopyXromPowerDownCodeToRAM()
// DESCRIPTION : This function copies the flash ROM turn off code,
// which is in an array to the RAM location POWER_DOWN_RAM_CODE_ADDR
// INPUT : None
// OUTPUT : None
// GLOBALS : PowerDownFlashROM[]
// USED_REGS : None directly
//*************************************************************************
void CopyXromPowerDownCodeToRAM(void)
{
WORD Csize ;
// copy routine into RAM.
WORD F1_OFF = FP_OFF(PowerDownXROM) ;
WORD F2_OFF = FP_OFF(DummyFunc2GetCodeSize) ;
Csize = F2_OFF - F1_OFF ;
// Debug Only
// msg("Power down code in RAM. Size %d", Csize);
_fmemcpy((BYTE far *)POWER_DOWN_RAM_CODE_ADDR, (void far *)PowerDownXROM, Csize);
}
//*************************************************************************
// FUNCTION : InitXROMStateMachineSettleCount
// USAGE : InitXROMStateMachineSettleCount()
// DESCRIPTION : This function initializes a global loop counter, which
// provides a delay for code to branch to RAM. This will
// allow the OSD and power handlers to settle before control
// barnches to RAM code.
// INPUT : None
// OUTPUT : None
// GLOBALS : XROM_StateMachine_Settle_Count
// USED_REGS : None directly
//*************************************************************************
void InitXROMStateMachineSettleCount( void )
{
XROM_StateMachine_Settle_Count = XROM_STATE_MC_SETTLE_LOOPS;
}
//*************************************************************************
// FUNCTION : ExecuteFromRAM
// USAGE : Executes the timeout routine from RAM
// DESCRIPTION : This function jumps to RAM location POWER_DOWN_RAM_CODE_ADDR
// and executes the flash power down code from RAM
// INPUT : W_PowerDownTime_ms - A word variable which provides the amount
// amount of time (in ms units) to turn off power to ROM.
// If zero, the routine cycles power to ROM with a duty cycle
// defined internally. This mode is used during soft power off.
// This parameter is passed on to entry point function in RAM.
// OUTPUT : None
// GLOBALS : None
// USED_REGS : None directly
//*************************************************************************
void ExecuteFromRAM(WORD W_PowerDownTime_ms)
{
void (*func)(WORD);
if ( W_PowerDownTime_ms == 0 )
{
XROM_StateMachine_Settle_Count--;
if ( XROM_StateMachine_Settle_Count >= 0 )
{
return;
}
}
// Copy code to RAM.
CopyXromPowerDownCodeToRAM();
// Initialize system to enable execution from RAM. This involves
// reprogramming interrupt vector addresses, etc.
InitializeSystemForRAMExecution();
// Execute in RAM from address POWER_DOWN_RAM_CODE_ADDR.
// Note: Currently this is a fixed address defined by a constant above.
func = ((void (*)) POWER_DOWN_RAM_CODE_ADDR);
func( W_PowerDownTime_ms );
// When control returns from RAM, we come here
// At this point, the ROM is on. We need to restore
// the system to its original state (e.g. interrupt
// vectors).
RestoreSystemForROMExecution();
}
//*************************************************************************
// FUNCTION : InitializeSystemForRAMExecution
// USAGE : InitializeSystemForRAMExecution()
// DESCRIPTION : This function performs some initialization, like copying
// tables, setting up interrupt vector addresses, etc.
// before control transfers to RAM in power down mode.
// INPUT : None
// OUTPUT : None
// GLOBALS : None
// USED_REGS : None directly
//*************************************************************************
static void InitializeSystemForRAMExecution( void )
{
#if ProcessExceptions != DisableExceptions
// Initialize the interrupt vectors.
InitializeInterruptVectorsRAM();
// Enable the watchdog timer, if so desired
#if UseWatchdogTimer == 1
EnableWatchDogTimerRAM();
#endif // UseWatchdogTimer
#endif // ProcessExceptions != DisableExceptions
// Set CPU frequency to low value
SetOCMClockFreqRAM( gmd_FALSE );
#if USE_GPIO_KEYPAD
// Initialize the number of scan keys (ROM constant) to a RAM global variable
XROM_Number_of_scan_keys_RAM = NUMBER_OF_SCAN_KEY;
#endif // USE_GPIO_KEYPAD
}
#if ProcessExceptions != DisableExceptions
//*************************************************************************
// FUNCTION : InitializeInterruptVectorsRAM
// USAGE : InitializeInterruptVectorsRAM()
// DESCRIPTION : This function initializes the interrupt vectors to RAM
// locations, since the ROM is powered off.
// INPUT : None
// OUTPUT : None
// GLOBALS : None
// USED_REGS : None directly
//*************************************************************************
static void InitializeInterruptVectorsRAM( void )
{
// We need to set up the interrupt vector addresses
// to RAM locations, since the ROM is turned off.
StopGetKeyISR();
gm_DisableInterrupts(); // Disable interrupts first
SET_VECTOR(DIV0_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(CommonInterruptHandlerRAM)));
SET_VECTOR(BOUNDS_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(CommonInterruptHandlerRAM)));
SET_VECTOR(SWBP_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(CommonInterruptHandlerRAM)));
SET_VECTOR(SINGLE_STEP_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(CommonInterruptHandlerRAM)));
#if !defined(USE_ADC_CALIBRATION_ISR) || (USE_ADC_CALIBRATION_ISR == 0)
SET_VECTOR(TIMER0_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(CommonInterruptHandlerRAM)));
#endif
SET_VECTOR(UNUSED_OP_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(CommonInterruptHandlerRAM)));
SET_VECTOR(ESC_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(CommonInterruptHandlerRAM)));
SET_VECTOR(WDT_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(NMIHandlerRAM)));
// Some debug messages
// msg("Common ISR offset: 0x%x", FP_OFF(CommonInterruptHandlerRAM));
// msg("NMI ISR offset: 0x%x", FP_OFF(NMIHandlerRAM));
//
// Following are place holders for 5221 specific interrupts
// they are commented as interrupts are masked by default
// customer code that enables interrupts should provide a handler
//
#if 0
SET_VECTOR(IRQIN, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(GenericIRQHanlder)));
SET_VECTOR(IFM_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(GenericIRQHanlder)));
SET_VECTOR(INPUT_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(GenericIRQHanlder)));
SET_VECTOR(MISC_VECTOR, (POWER_DOWN_RAM_CODE_ADDR - FP_OFF(PowerDownXROM)
+ FP_OFF(GenericIRQHanlder)));
#endif
ENABLE_INTERRUPTS;
// Enable the bus watchdog timer, but not the interrupt
// Taken out, since enabling the WDT causes CPU to hang - GB, 7/9/04
// gm_WriteRegByte(OCM_BUS_CONTROL_0,ENABLE_WDT);
}
#if UseWatchdogTimer == 1
//*************************************************************************
// FUNCTION : EnableWatchDogTimerRAM
// USAGE : EnableWatchDogTimerRAM()
// DESCRIPTION : This function enables the watchdog timer in the OCM.
// INPUT : None
// OUTPUT : None
// GLOBALS : None
// USED_REGS : None directly
//*************************************************************************
static void EnableWatchDogTimerRAM(void)
{
WRITE_PCB_REG(WDTCON, 0x3333);
WRITE_PCB_REG(WDTCON, 0xCCCC);
// Enable watchdog to generate NMI after 2^21/1.023e6 seconds
WRITE_PCB_REG(WDTCON, WDT_ENABLE_RAM | 0x04) ;
}
#endif // UseWatchdogTimer
#endif // ProcessExceptions != DisableExceptions
#ifdef PORT_IR_USED
//*************************************************************************
// FUNCTION : IRInitRAM
// USAGE : IRInitRAM(DWORD param)
// DESCRIPTION : This function initializes the Infrared remote interrupt
// and timer.
// INPUT : D_CpuClock - CPU clock frequency in Hz.
// OUTPUT : None
// GLOBALS : IrIndexRAM, IrLWordRAM
// USED_REGS : IRQ_CONFIG, I2CON
//*************************************************************************
#if IR_DRIVER != USE_RC5
static void IRInitRAM(DWORD D_CpuClock)
{
//Setup Int2 interrupt register
gm_WriteRegByte(IRQ_CONFIG, GPIO_IRQ_IN_EN);
WRITE_PCB_REG(I2CON, 0);
IrIndexRAM = 0;
IrLWordRAM = 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -