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

📄 xrompower.c

📁 GM5621原代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
	$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 + -