📄 power_main.c
字号:
/*
* File: main.c
* Purpose: Main process
*
* Notes: This test was created for the M5213EVB, but can
* be modified to use other platforms. Interrupt
* usage may be the only change to consider.
*/
#include "common.h"
#include "uif.h"
#include "clock/clock.h"
#include "uart/uart.h"
#include "power.h"
/********************************************************************/
/*
* Setup user interface
*/
const char BANNER[] = "\nPower Measurement Utility\n";
const char PROMPT[] = "PWR> ";
UIF_CMD UIF_CMDTAB[] =
{
UIF_CMDS_ALL
{"clk", 0,1,0,cmd_sysclk,"Set PLL output clock","<sys_clk>"},
{"stop",0,0,0,cmd_stop, "STOP low-power mode", ""},
{"wait",0,0,0,cmd_wait, "WAIT low-power mode", ""},
{"doze",0,0,0,cmd_doze, "DOZE low-power mode", ""},
{"run", 0,0,0,cmd_run, "RUN low-power mode", ""},
{"loop", 0,1,0,cmd_loop, "Enter loop", "<one|nop|tpf|poll>"},
{"rd",0,0,0,cmd_rd, "Register Disply",""},
{"ppm", 0,2,0,cmd_ppm, "Periph Pwr Mngt tests",""},
};
UIF_SETCMD UIF_SETCMDTAB[] =
{
{"sysclk", 0,1,setshow_sysclk,""},
{"clkout", 0,1,setshow_clkout,""},
{"lpd", 0,1,setshow_lpd,""},
{"stpmd", 0,1,setshow_stpmd,""},
{"lvdse", 0,1,setshow_lvdse,""},
{"xipl", 0,1,setshow_xipl,""},
{"baud", 0,1,setshow_baud,""},
{"step", 0,1,setshow_step,""},
{"pwrcfg", 0,1,setshow_pwrcfg,"min/max power config"},
};
const int UIF_NUM_CMD = UIF_CMDTAB_SIZE;
const int UIF_NUM_SETCMD = UIF_SETCMDTAB_SIZE;
/*
* Set/show and global variables
*/
int baud = TERMINAL_BAUD;
int stpmd = 0;
int lvdse = 0;
int xipl = 0;
int exit_loop = FALSE;
int clkout = ON;
int clk_step = 8000;
int tpwrcfg = PWR_MAX; /* power configuration for tests */
int cpwrcfg = PWR_MAX; /* current power configuration */
int running_in_sram;
ADDRESS old_handler;
int loop_test;
volatile int abort_flag;
/********************************************************************/
void
main (void)
{
extern char __DATA_ROM[];
extern char __DATA_RAM[];
/* Determine if execution is from Flash or SRAM */
running_in_sram = (__DATA_ROM == __DATA_RAM) ? TRUE : FALSE;
/*
* Level-sensitivity needs to be used on the IRQx pins to bring
* the processor out of stop mode
*/
MCF_EPORT_EPPAR = 0
| MCF_EPORT_EPPAR_EPPA4_RISING
| MCF_EPORT_EPPAR_EPPA5_RISING
| MCF_EPORT_EPPAR_EPPA7_LEVEL;
/* Set the interrupt handlers in the vector table */
mcf5xxx_set_handler(64 + 4, (ADDRESS)sw1_handler);
mcf5xxx_set_handler(64 + 5, (ADDRESS)sw2_handler);
mcf5xxx_set_handler(64 + 7, (ADDRESS)abort_handler);
/* Enable the "maximum" power cnofiguration by default */
max_pwr_config();
printf("\n");
printf("**************************************************\n");
printf("* *\n");
printf("* Power Measurement Utility *\n");
printf("* *\n");
printf("**************************************************\n");
printf("\nEnter all clock settings in KHz\n");
printf("SW1 increases PLL in valid increments of 8MHz\n");
printf("SW2 decreases PLL in valid increments of 8MHz\n");
printf("ABORT to exit a loop or low-power modes\n");
printf(HELPMSG);
printf("\n");
mainloop();
}
/********************************************************************/
void
mainloop (void)
{
/* Enable interrupts to the core */
mcf5xxx_irq_enable();
while (TRUE)
{
printf(PROMPT);
run_cmd();
}
}
/********************************************************************/
__interrupt__ void
abort_handler(void)
{
/* Wait for the switch to deassert */
while (!(MCF_EPORT_EPPDR & MCF_EPORT_EPPDR_EPPD7)) {};
abort_flag = TRUE;
if (exit_loop == TRUE)
{
exit_loop = FALSE;
/*
* Exit loop by jumping to mainloop()
* This leaves stack frames on the stack and could
* eventually result in stack overflow
*/
max_pwr_config();
mainloop();
}
}
/********************************************************************/
/*
* Increment the PLL output clock by the smallest valid increment
*/
__interrupt__ void
sw1_handler(void)
{
int pllclk, pwrcfg;
/* save off current power configuration setting */
pwrcfg = cpwrcfg;
/* enable the max config setting */
max_pwr_config();
/* get the current PLL clock output */
pllclk = clock_pll(REF_CLK_KHZ,0,0);
while (pllclk < MAX_FSYS)
{
/* Bump the PLL output up to the next valid clk_step increment */
pllclk = ((pllclk / clk_step) * clk_step) + clk_step;
if (clock_pll(REF_CLK_KHZ, pllclk, PLL_PRETEND) == pllclk)
break;
}
/* Set the PLL and calculate the SYS CLK based PLL and LPD settings */
sys_clk_khz = clock_pll(REF_CLK_KHZ, pllclk, 0) / clock_lpd(0);
/* Re-init the UART with the new system clock setting */
uart_init(TERMINAL_PORT, sys_clk_khz, baud, 0);
printf("System Clock: %d KHz\n", sys_clk_khz);
/* Wait for the UART to finish transmitting */
while(!(MCF_UART_UCSR(TERMINAL_PORT) & MCF_UART_USR_TXEMP)) {};
/* Clear the interrupt event */
MCF_EPORT_EPFR = MCF_EPORT_EPFR_EPF4;
/* Restore the power configuration */
set_pwr_config(pwrcfg);
}
/********************************************************************/
/*
* Decrement the PLL output clock by the smallest valid increment
*/
__interrupt__ void
sw2_handler(void)
{
int pllclk, pwrcfg;
/* save off current power configuration setting */
pwrcfg = cpwrcfg;
/* enable the max config setting */
max_pwr_config();
/* get the current PLL clock output */
pllclk = clock_pll(REF_CLK_KHZ,0,0);
while (pllclk > REF_CLK_KHZ)
{
/*
* Decrement the PLL output so that it is set to the next valid clk_step
* below the current one
*/
pllclk = ((pllclk / clk_step) * clk_step) - clk_step;
if (clock_pll(REF_CLK_KHZ, pllclk, PLL_PRETEND) == pllclk)
break;
}
/* Set the PLL and calculate the SYS CLK based PLL and LPD settings */
sys_clk_khz = clock_pll(REF_CLK_KHZ, pllclk, 0) / clock_lpd(0);
/* Re-init the UART with the new system clock setting */
uart_init(TERMINAL_PORT, sys_clk_khz, baud, 0);
printf("System Clock: %d KHz\n", sys_clk_khz);
/* Wait for the UART to finish transmitting */
while(!(MCF_UART_UCSR(TERMINAL_PORT) & MCF_UART_USR_TXEMP)) {};
/* Clear the interrupt event */
MCF_EPORT_EPFR = MCF_EPORT_EPFR_EPF5;
/* Restore the power configuration */
set_pwr_config(pwrcfg);
}
/********************************************************************/
void
enter_low_pwr_mode(void)
{
/* Make sure the UART is done transmitting */
while(!(MCF_UART_UCSR(TERMINAL_PORT) & MCF_UART_USR_TXEMP));
/* Setup the low-power interrupt control register */
MCF_PMM_LPICR = 0
| MCF_PMM_LPICR_XIPL(xipl)
| MCF_PMM_LPICR_ENBSTOP;
/* Enable the "test" power configuration */
set_pwr_config(tpwrcfg);
/* Execute the stop instruction */
stop_2000();
/* Enable the max power configuration */
max_pwr_config();
}
/********************************************************************/
void
cmd_stop(int argc, char **argv)
{
printf("Entering STOP mode\n");
printf(" STPMD = %02b\n",stpmd);
printf(" LVDSE = %b\n",lvdse);
printf(" XIPL = %03b\n",xipl);
MCF_PMM_LPCR = 0
| MCF_PMM_LPCR_LPMD_STOP
| MCF_PMM_LPCR_STPMD(stpmd);
if (lvdse)
{
MCF_PMM_LPCR |= MCF_PMM_LPCR_LVDSE;
}
enter_low_pwr_mode();
}
/********************************************************************/
void
cmd_wait(int argc, char **argv)
{
printf("Entering WAIT mode\n");
printf(" STPMD = %02b\n",stpmd);
printf(" LVDSE = %b\n",lvdse);
printf(" XIPL = %03b\n",xipl);
MCF_PMM_LPCR = 0
| MCF_PMM_LPCR_LPMD_WAIT
| MCF_PMM_LPCR_STPMD(stpmd);
if (lvdse)
{
MCF_PMM_LPCR |= MCF_PMM_LPCR_LVDSE;
}
enter_low_pwr_mode();
}
/********************************************************************/
void
cmd_doze(int argc, char **argv)
{
printf("Entering DOZE mode\n");
printf(" STPMD = %02b\n",stpmd);
printf(" LVDSE = %b\n",lvdse);
printf(" XIPL = %03b\n",xipl);
MCF_PMM_LPCR = 0
| MCF_PMM_LPCR_LPMD_DOZE
| MCF_PMM_LPCR_STPMD(stpmd);
if (lvdse)
{
MCF_PMM_LPCR |= MCF_PMM_LPCR_LVDSE;
}
enter_low_pwr_mode();
}
/********************************************************************/
void
cmd_run(int argc, char **argv)
{
printf("Entering RUN mode\n");
printf(" STPMD = %02b\n",stpmd);
printf(" LVDSE = %b\n",lvdse);
printf(" XIPL = %03b\n",xipl);
MCF_PMM_LPCR = 0
| MCF_PMM_LPCR_LPMD_RUN
| MCF_PMM_LPCR_STPMD(stpmd);
if (lvdse)
{
MCF_PMM_LPCR |= MCF_PMM_LPCR_LVDSE;
}
enter_low_pwr_mode();
}
/********************************************************************/
void
cmd_sysclk (int argc, char **argv)
{
int success, sysclk;
if (argc == 1)
{
printf("System Clock: %d KHz\n", sys_clk_khz);
}
else
{
/* Wait for the UART to finish transmitting */
while(!(MCF_UART_UCSR(TERMINAL_PORT) & MCF_UART_USR_TXEMP)) {};
/* Get user input (in KHz) */
sysclk = get_value(argv[1],&success,10);
if (success == 0)
{
printf(INVALUE,argv[1]);
return;
}
if (sysclk == 0)
{
/* Disable the PLL */
sys_clk_khz = (clock_pll(REF_CLK_KHZ, sysclk, PLL_DISABLE) /
clock_lpd(0));
}
else
{
/* Set the PLL to the desired system clock */
sys_clk_khz = (clock_pll(REF_CLK_KHZ, sysclk, 0) /
clock_lpd(0));
}
/* Re-init the UART with the new system clock setting */
uart_init(TERMINAL_PORT, sys_clk_khz, baud, 0);
printf("System Clock: %d KHz\n", sys_clk_khz);
}
}
/********************************************************************/
void
cmd_loop (int argc, char **argv)
{
if (argc == 1)
{
printf("Enter an argument:\n");
printf(" \"one\" = while(1) loop\n");
printf(" \"nop\" = nop loop\n");
printf(" \"tpf\" = tpf loop\n");
printf(" \"poll\" = poll uart\n");
}
else
{
/* Wait for the UART to finish transmitting */
while(!(MCF_UART_UCSR(TERMINAL_PORT) & MCF_UART_USR_TXEMP)) {};
set_pwr_config(tpwrcfg);
/* Enter the desired loop */
if (strcasecmp(argv[1], "one") == 0)
{
/* Tell the abort handler to go to the mainloop */
exit_loop = TRUE;
while (1)
{
/* null */
}
}
else if (strcasecmp(argv[1], "nop") == 0)
{
/* Tell the abort handler to go to the mainloop */
exit_loop = TRUE;
while (1)
{
nop();
nop();
nop();
nop();
}
}
else if (strcasecmp(argv[1], "tpf") == 0)
{
/* Tell the abort handler to go to the mainloop */
exit_loop = TRUE;
while (1)
{
tpf();
tpf();
tpf();
tpf();
}
}
else if (strcasecmp(argv[1], "poll") == 0)
{
while (!(MCF_UART_USR(TERMINAL_PORT) & MCF_UART_USR_RXRDY))
{
/* null */
}
/* Clear the UART FIFO */
uart_getchar(TERMINAL_PORT);
}
else
{
printf(INVALUE,argv[1]);
}
max_pwr_config();
}
}
/********************************************************************/
void
cmd_rd (int argc, char **argv)
{
printf("SYNCR = %#04X\n", MCF_CLOCK_SYNCR);
printf("SYNSR = %#02X\n", MCF_CLOCK_SYNSR);
printf("LPCR = %#02X\n", MCF_PMM_LPCR);
printf("LPICR = %#02X\n", MCF_PMM_LPICR);
printf("PPMRH = %#08X\n", MCF_SCM_PPMRH);
printf("PPMRL = %#08X\n", MCF_SCM_PPMRL);
}
/********************************************************************/
void
cmd_ppm (int argc, char **argv)
{
/*
* Usage:
*
* ppm <gated_clk>
*
* Reference the RM for gated clock assignments in the PPMRH/L
* The core is always active and running the same loop. Therefore,
* a baseline power measurement can be taken with all peripherals
* off and then the consumption of each peripheral can be determined
* by enabling them individually.
*
* 0 is an invalid peripheral number and should be used to
* turn off all the peripherals
*
* If no gated_clk is specified, the ABORT button can be used to
* cycle through a loop which individually enables all the valid
* gated clocks.
*
* The only valid image target is in the internal SRAM. Since this
* test will turn off the CFM (unless it is the specified peripheral).
*/
int success, i = 0;
if (!running_in_sram)
{
printf("This test is only valid if running from SRAM\n");
return;
}
/* Disable FLASHBAR */
mcf5xxx_wr_rambar0(0);
if (argc == 2)
{
i = get_value(argv[1],&success,10);
if (success == 0)
{
printf(INVALUE,argv[1]);
return;
}
}
/* Disable the CLKOUT and PST/DDATA signals */
clock_clkout_disable();
cpu_pstddata_disable();
/*
* Test with just the specified clock enabled. The INTC will be
* disabled unless it is the one specified, so the ABORT button
* will not be able to be used to exit the test.
*/
if (argc >= 2)
{
int test;
printf("Peripheral #%d\n", i);
if (argc == 3)
{
test = get_value(argv[2],&success,10);
if (!success)
{
printf(INVALUE,argv[2]);
return;
}
}
/* Wait for the UART to finish transmitting */
while(!(MCF_UART_UCSR(TERMINAL_PORT) & MCF_UART_USR_TXEMP)) {};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -