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

📄 xrompower.c

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