📄 powerdemo.c
字号:
/*********************************************************************************
Copyright(c) 2005 Analog Devices, Inc. All Rights Reserved.
This software is proprietary and confidential. By using this software you agree
to the terms of the associated Analog Devices License Agreement.
Description:
A sample program to demonstrate three aspects of the Power Management
Module:
a) Altering the core voltage level - changes core and system clock frequencies
b) Altering the power mode, including awakening from sleep and deep sleep
c) Adjusting the SDRAM refresh rates (implicitly) each time the system
clock frequency changes.
See accompanying readme for furter details.
*********************************************************************************/
#include "PowerDemo.h"
// ////////////////////
// Global Variables //
// ////////////////////
// The bit pattern of the LED display
u16 CurrentDisplay;
// The current Power state (not to be confused with the ADI_PWR_MODE enumerator).
// 0 = Full On
// 1 = Active PLL enabled
// 2 = Active PLL disabled
// 3 - Sleep
// 4 - awoken from sleep
// 5 - Deep Sleep
u32 CurrentPowerState = 0;
// Number of voltage levels to cycle through
#define NUM_VLEVS 4
// Array of voltage level values:
static ADI_PWR_VLEV VoltageLevels[NUM_VLEVS] =
{
ADI_PWR_VLEV_085,
ADI_PWR_VLEV_095,
ADI_PWR_VLEV_105,
ADI_PWR_VLEV_120
};
// Array index of current voltage level
static u32 CurrentVoltageIndex=0;
// //////////////
// Prototypes //
// //////////////
// initialization
void Init(void);
// callback for the pushButtons
void PushButtonCallback(
void *ClientHandle,
u32 Event,
void *pArg);
// Interrupt Handler for the RTC - to awaken from Sleep and Deep Sleep
ADI_INT_HANDLER(RealTimeClockHandler);
// Configures the RTC
void ConfigureRTC(void);
// Processor specific Init function
extern void Init(void);
// Generic System Services Initialization function
void InitServices(void);
// //////////////
// static data //
// //////////////
/*********************************************************************
Peripheral ID Macros
This program works on the EZ-Kits. The macros
below are used to identify which EZ-Kit we're targeting. Specifically,
the FLAG_PERIPHERAL_ID macro is set to the peripheral ID to which the
interrupt driven push buttons are mapped. See the adi_int.h file
within the system services library (blackfin/include/services) for
more information on peripheral IDs.
*********************************************************************/
#if defined(__ADSP_EDINBURGH__)
#define FLAG_PERIPHERAL_ID (ADI_INT_PFA)
#endif
#if defined(__ADSP_BRAEMAR__)
#define FLAG_PERIPHERAL_ID (ADI_INT_PORTFG_A)
#endif
#if defined(__ADSP_TETON__)
#define FLAG_PERIPHERAL_ID (ADI_INT_PF0_15_A)
#endif
// flag service
static u8 FlagServiceData[ADI_FLAG_CALLBACK_MEMORY * (EZ_NUM_BUTTONS + 1)];
// interrupt service
static u8 IntMgrData[ADI_INT_SECONDARY_MEMORY * (EZ_NUM_BUTTONS)];
/*********************************************************************
Function: main
Description: Main entry point
*********************************************************************/
void main()
{
u32 i; // loop variable
// initialize the EZ-Kit Buttoms and Flags
for (i = EZ_FIRST_LED; i < EZ_NUM_LEDS; i++){
ezInitLED(i);
}
for (i = EZ_FIRST_BUTTON; i < EZ_NUM_BUTTONS; i++){
ezInitButton(i);
}
ezTurnOffAllLEDs();
// Initialize System Services (excluding Power Management)
InitServices();
// Processor Specific Initialization (including Power Management)
Init();
// Display Full On Power mode & Lower voltage setting
ezTurnOffAllLEDs();
ezTurnOnLED(EZ_FIRST_LED+1);
ezTurnOnLED(EZ_FIRST_LED+2);
ezTurnOnLED(EZ_FIRST_LED+3);
CurrentDisplay = ezGetDisplay();
// Processing loop
while(1)
{
BlinkLEDs(1,BLINK_MASK); //Blink all but LED 4
}
}
/*********************************************************************
Function: InitServices
Description: Initializes the LED's the Push Buttons and the RTC
and hooks interrupt handlers, and configures the
Power Settings to lowest voltage level.
*********************************************************************/
void InitServices(void)
{
u32 ResponseCount, i;
// initialize the Interrupt Manager
ezErrorCheck(adi_int_Init(IntMgrData, sizeof(IntMgrData), &ResponseCount, NULL));
// initialize the flag manager because the LEDs and buttons connect via flags
ezErrorCheck(adi_flag_Init(FlagServiceData, sizeof(FlagServiceData), &ResponseCount, NULL));
// enable all pushbuttons for callbacks
adi_flag_InstallCallback(ezButtonToFlag[EZ_FIRST_BUTTON], FLAG_PERIPHERAL_ID, ADI_FLAG_TRIGGER_RISING_EDGE, TRUE, (void*)(EZ_FIRST_BUTTON), NULL, PushButtonCallback);
adi_flag_InstallCallback(ezButtonToFlag[EZ_FIRST_BUTTON+1], FLAG_PERIPHERAL_ID, ADI_FLAG_TRIGGER_RISING_EDGE, TRUE, (void*)(EZ_FIRST_BUTTON+1), NULL, PushButtonCallback);
adi_flag_InstallCallback(ezButtonToFlag[EZ_FIRST_BUTTON+2], FLAG_PERIPHERAL_ID, ADI_FLAG_TRIGGER_RISING_EDGE, TRUE, (void*)(EZ_FIRST_BUTTON+2), NULL, PushButtonCallback);
adi_flag_InstallCallback(ezButtonToFlag[EZ_FIRST_BUTTON+3], FLAG_PERIPHERAL_ID, ADI_FLAG_TRIGGER_RISING_EDGE, TRUE, (void*)(EZ_FIRST_BUTTON+3), NULL, PushButtonCallback);
ConfigureRTC();
}
/*********************************************************************
Function: ConfigureRTC
Description: Configures the RTC to interrupt every 5 secs and
hooks its interrupt handler.
*********************************************************************/
void ConfigureRTC()
{
*pRTC_PREN = 0x1;
while (!(*pRTC_ISTAT & 0x8000));
*pRTC_ISTAT = CLEAR_RTC_IRQS; // clear any pending IRQs
*pRTC_ICTL = 0x1; // set Stopwatch interrupt enable
*pRTC_SWCNT = 0x0005; // set StopWatch to 5 seconds
while (!(*pRTC_ISTAT & 0x8000));
ezErrorCheck( adi_int_CECHook(13,RealTimeClockHandler,NULL,0) ); // Hook handler to IVG level
ezErrorCheck( adi_int_SICSetIVG(ADI_INT_RTC,13) ); // set IVG level that Buttons assert
ezErrorCheck( adi_int_SICWakeup(ADI_INT_RTC,1) ); // Enable/Disable wakeup on interrupt
ezErrorCheck( adi_int_SICEnable(ADI_INT_RTC) ); // Enable interrupts
}
/*********************************************************************
Function: TogglePowerMode
Description: Toggles the power mode from Full On down to Deep Sleep
LED's 5-7 to indicate the level:
111 Full on
101 Active - enabled
011 Active - disabled
001 Sleep (returned from sleep)
000 Deep Sleep
*********************************************************************/
void TogglePowerMode()
{
u16 tmpDisplay;
ezSetDisplay(CurrentDisplay);
switch( CurrentPowerState++ )
{
case 0: // Full on -> Active
// Restore Current display - could be in blink-off state
ezSetDisplay(CurrentDisplay);
// Display Active Mode
ezTurnOffLED(EZ_FIRST_LED+1);
// Store Current display
CurrentDisplay = ezGetDisplay();
// and set Active mode
adi_pwr_SetPowerMode(ADI_PWR_MODE_ACTIVE);
break;
case 1: // Active, PLL enabled -> Pll disabled
// Restore Current display - could be in blink-off state
ezSetDisplay(CurrentDisplay);
// Display Active, PLL disabled Mode
ezTurnOffLED(EZ_FIRST_LED+2);
ezTurnOnLED(EZ_FIRST_LED+1);
// Store Current display
CurrentDisplay = ezGetDisplay();
// and set Active, PLL disabled mode
adi_pwr_SetPowerMode(ADI_PWR_MODE_ACTIVE_PLLDISABLED);
break;
case 2: // Active PLL disabled -> Sleep
// Restore Current display - could be in blink-off state
ezSetDisplay(CurrentDisplay);
// Display Sleep Mode
ezTurnOffLED(EZ_FIRST_LED+1);
// Blink once to indicate going to sleep
tmpDisplay = ezGetDisplay();
CurrentDisplay = ALL_LEDS;
BlinkLEDs(1,ALL_LEDS);
// Store Current display
CurrentDisplay = tmpDisplay;
// Go to sleep (RTC disabled during sleep)
adi_int_SICDisable(ADI_INT_RTC);
adi_pwr_SetPowerMode(ADI_PWR_MODE_SLEEP);
adi_int_SICEnable(ADI_INT_RTC);
break;
case 4: // Full on -> Sleep
// Restore Current display - could be in blink-off state
ezSetDisplay(CurrentDisplay);
// Display Deep Sleep Mode
ezTurnOffLED(EZ_FIRST_LED+3);
// Blink twice to indicate going to deep sleep
tmpDisplay = ezGetDisplay();
CurrentDisplay = ALL_LEDS;
BlinkLEDs(2,ALL_LEDS);
// Store Current display
CurrentDisplay = tmpDisplay;
// Go to deep sleep (RTC disabled during deep sleep)
adi_int_SICDisable(ADI_INT_RTC);
adi_pwr_SetPowerMode(ADI_PWR_MODE_DEEP_SLEEP);
//adi_pwr_SetPowerMode(ADI_PWR_MODE_FULL_ON);
adi_int_SICEnable(ADI_INT_RTC);
break;
}
}
/*********************************************************************
Function: SetVoltage
Description: Uses the power management module to adjust the core and
system clock frequencies to a given voltage level and
indicates the level using LED's 8 & 9:
00 - 0.85V
01 - 0.95V
10 - 1.05V
11 - 1.2V
*********************************************************************/
void SetVoltage(ADI_PWR_VLEV vlev)
{
ezErrorCheck( adi_pwr_SetMaxFreqForVolt(vlev) );
ezSetDisplay(CurrentDisplay);
switch(vlev)
{
case ADI_PWR_VLEV_085:
ezTurnOffLED(EZ_FIRST_LED+4);
ezTurnOffLED(EZ_FIRST_LED+5);
break;
case ADI_PWR_VLEV_095:
ezTurnOnLED(EZ_FIRST_LED+4);
break;
case ADI_PWR_VLEV_105:
ezTurnOffLED(EZ_FIRST_LED+4);
ezTurnOnLED(EZ_FIRST_LED+5);
break;
case ADI_PWR_VLEV_120:
ezTurnOnLED(EZ_FIRST_LED+4);
default:
break;
}
CurrentDisplay = ezGetDisplay();
}
/*********************************************************************
Function: ToggleVoltage
Description: Cycles the voltage through 4 levels (see SetVoltage)
***********************************************************************/
void ToggleVoltage()
{
CurrentVoltageIndex++;
if (CurrentVoltageIndex==NUM_VLEVS)
CurrentVoltageIndex=0;
SetVoltage( VoltageLevels[CurrentVoltageIndex] );
}
/*********************************************************************
Function: BlinkLEDs
Description: Blinks the LED's, between the current display values
and off. Only the LED's identified by the mask argument
are affected.
NB. In the Active state, the Core is clocked at CLKIN
and so, to avoid unecessary and confusing delay the
blink frequency is adjusted to be roughly half that
at the lowest voltage setting.
*********************************************************************/
#pragma optimize_off
void BlinkLEDs(u32 count, u16 mask)
{
volatile u32 i,j;
volatile u32 delay = DELAY_COUNT;
ADI_PWR_MODE mode = adi_pwr_GetPowerMode();
if (mode==ADI_PWR_MODE_ACTIVE || mode==ADI_PWR_MODE_ACTIVE_PLLDISABLED)
delay/=4;
for (j=0;j<count;j++)
{
for (i=0;i<delay;i++);
ezSetDisplay(CurrentDisplay);
for (i=0;i<delay;i++);
ezSetDisplay(CurrentDisplay&(~mask));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -