Name
Power Management — Details
Synopsis
#include <cyg/hal/hal_io.h>
void hal_str7xx_clocks_setup(
int index)
;
void hal_str7xx_set_clock_speed(
int index)
;
cyg_uint32 hal_str7xx_get_clock_speed(
void)
;
cyg_bool hal_str7xx_mode_stop(
void)
;
void hal_str7xx_mode_standby(
void)
;
cyg_uint32 hal_str7xx_startup_mode(
void)
;
void hal_str7xx_uart_setbaud(
cyg_uint32 uart, cyg_uint32 baud)
;
void hal_str7xx_uart_reinit(
void)
;
void hal_str7xx_i2c_init(
cyg_uint32 bus, cyg_uint32 clock)
;
void hal_str7xx_i2c_reinit(
void)
;
void hal_str7xx_watchdog_init(
cyg_uint32 timeout)
;
void hal_str7xx_can_init(
cyg_uint32 devno, cyg_uint32 clock)
;
void hal_str7xx_can_reinit(
void)
;
void hal_str7xx_adc_init(
cyg_uint32 rate)
;
void hal_str7xx_adc_reinit(
void)
;
void hal_str7xx_rtc_init(
void)
;
void hal_str7xx_rtc_alarm_set(
cyg_uint32 secs)
;
void hal_str7xx_rtc_alarm_cancel(
void)
;
cyg_uint32 hal_str7xx_rtc_counter(
void)
;
cyg_uint32 hal_str7xx_rtc_counter_set(
cyg_uint32 secs)
;
Description
The STR7XX variant HAL provides support for managing the power consumption of the device. This consists of a collection of functions that may be used to adjust clock frequencies, system modes and other aspects of the device. These routines mainly comprise a "kit of parts" from which applications may construct their own power management policy. The reader is referred to the STR7XX hardware documentation for full details of clock and power management.
The main function is hal_str7xx_clocks_setup(index)
which controls the frequencies of the main clocks: MCLK, which
supplies the CPU and memories; PCLK1, which supplies APB1 including
the I²C, SPI and UARTs; and PCLK2, which supplies APB2 including IO
ports, Timers, RTC etc. The single argument to this function is an
index into a table of hal_str7xx_clock_params structures,
which is defined by the platform HAL. Each entry in the table has the
following structure:
typedef struct { char *name; // Name string cyg_uint8 clk2_divider; // 1, 2 cyg_uint8 pll1_multiplier; // 12, 16, 20, 24 cyg_uint8 pll1_divider; // 1..7 cyg_uint8 rclk_select; // RCLK_SELECT_* below cyg_uint8 mclk_divider; // 1, 2, 4, 8 cyg_uint8 pclk1_divider; // 1, 2, 4, 8 cyg_uint8 pclk2_divider; // 1, 2, 4, 8 } hal_str7xx_clock_params; #define RCLK_SELECT_CLK2 0 #define RCLK_SELECT_CLK2_16 1 #define RCLK_SELECT_PLL1 2 #define RCLK_SELECT_AF 3 __externC cyg_uint32 hal_str7xx_clock_param_index;
Each entry in the table corresponds to a single configuration of the clock hardware. Some care must be taken in specifying these entries, the resulting clocks will depend on the system input clock and the various multipliers and dividers; many configurations will result in out of range or otherwise illegal clock frequencies. See the manuals for the STR7XX variant and the platform for details.
It is recommended that the clk2_divider
field is always set to 2. This causes the ocillator input to be
divided by 2 and provides a more stable input to the rest of the clock
circuity. Also, some registers in the RCCU are only accessible if MCLK
is equal to RCLK, so the mclk_divider
field
should always be 1. These restrictions may be relaxed in special
circumstances.
The last entry in this table should be all zeros, to mark the end of the table. A typical table would appear as follows:
const hal_str7xx_clock_params hal_str7xx_clock_param_table[] = { // name clk/ pll1* pll1/ rclk source mclk/ pclk1/ pclk2/ { "32KHz" , 2, 0, 0, RCLK_SELECT_AF , 1, 1, 1 }, { "500KHz" , 2, 0, 0, RCLK_SELECT_CLK2_16, 1, 1, 1 }, { "8MHz" , 2, 0, 0, RCLK_SELECT_CLK2 , 1, 1, 1 }, { "24/6/3MHz" , 2, 12, 4, RCLK_SELECT_PLL1 , 1, 4, 8 }, { "32/32MHz" , 2, 16, 4, RCLK_SELECT_PLL1 , 1, 1, 1 }, { "40/10/5MHz" , 2, 20, 4, RCLK_SELECT_PLL1 , 1, 4, 8 }, { "40/40MHz" , 2, 20, 4, RCLK_SELECT_PLL1 , 1, 1, 1 }, { "48/12/6MHz" , 2, 12, 2, RCLK_SELECT_PLL1 , 1, 4, 8 }, { "48/24/12MHz" , 2, 12, 2, RCLK_SELECT_PLL1 , 1, 2, 4 }, { 0 , 0, 0, 0, 0, 0, 0, 0 } }; cyg_uint32 hal_str7xx_clock_param_index = 5;
The naming convention used above is that a single frequency implies that all 3 clocks (MCLK, PCLK1 and PCLK2) are set to the same value. Two frequencies mean that MCLK is set to the first and both PCLK1 and PCLK2 are set to the second. Three frequencies show the values for MCLK/PCLK1/PCLK2 in order.
The variable hal_str7xx_clock_param_index
indicates
the table entry of the parameter set that is currently set. This
should be initialized by the platform HAL to the index of the default
parameter set, which will be used during initialization.
hal_str7xx_clocks_setup()
also sets a number of
other global variables with the clock rates resulting from the
parameter set in use:
__externC cyg_uint32 hal_str7xx_pclk1; // PCLK1 frequency in Hz __externC cyg_uint32 hal_str7xx_pclk2; // PCLK2 frequency in Hz __externC cyg_uint32 hal_str7xx_mclk; // MCLK frequency in Hz
Functions to initialize baud rate generators or prescaler dividers for various devices are also present:
hal_str7xx_uart_setbaud(uart, baud)
sets the baud rate
generator of the given UART to the given baud rate, based on the
current value of PCLK1. UARTs are numbered 0 to 3, corresponding to
the UARTs available on the device and baud rate is given in
Hz. hal_str7xx_uart_reinit()
causes all UARTs
baud rate generators to be reinitialized using the last baud rate
setting and the current PCLK1 value. It is usually called after
changing the system clocks.
hal_str7xx_i2c_init(bus, clock)
initializes the clock
divider of the given I2C bus to the given
value based on the current value of PCLK1. The bus numbers are either
0 or 1, and the clock rate is given in Hz.
hal_str7xx_i2c_reinit()
causes all
I2C busses clock dividers to be
reinitialized using the last clock rate setting and the current PCLK1
value.
hal_str7xx_watchdog_init(timeout)
initializes the
watchdog timeout based on the current PCLK2 setting. The timeout is
given in microseconds. Some care is needed in setting this value since
the resolution of the prescaler and the width of the 16 bit counter
mean that certain timeouts may not be achievable at different PCLK2
frequencies.
hal_str7xx_can_init(devno, clock)
initializes the
clock divider of the given CAN device to the given baud rate based on
the current PCLK1 setting. This function sets the entire Bit Timing
Register, including the bit segment lengths and the synchronization
jump width as well as the clock divider. While this interface is
designed to support multiple CAN devices, the current implementation
only supports a single CAN bus. The return value from this function
indicates whether the requested clock frequency can be supported: zero
if it is, -1 if not. hal_str7xx_can_reinit()
causes the bit timings for all CAN busses to be reinitialized based on
the current value of PCLK1.
hal_str7xx_adc_init( rate )
initializes the
prescaler for the ADC device based on the current PCLK2 setting. The
rate argument gives the sample rate for each channel in samples per
second. All channels share the same sample rate and are sampled on a
round-robin basis. Therefore the combined sample rate, and hence
maximum interrupt rate, will be four times this frequency.
hal_str7xx_adc_reinit()
causes the rate to be
reinitialized based on the current value of PCLK2.
hal_str7xx_mode_stop()
puts the STR7XX into STOP
mode. Aside from entering STOP mode, all this routine does is set the
WKUP-INT bit in the XTI CTRL register so that any of the external
interrupt lines may be used to restart the system from STOP. However,
it does not configure or unmask these lines. Instead, they may be
unmasked and configured using the standard interrupt control API
(cyg_interrupt_unmask()
,
cyg_interrupt_configure()
etc.) It is also
possible to configure the RTC to wake the STR7XX from STOP mode. The
value returned from this function indicates whether STOP mode was
entered: true
if it was, false
if not. It is usually adequate to just retry in the case of failed
entry.
hal_str7xx_mode_standby()
puts the STR7XX into
STANDBY mode. As with entering STOP mode, it is the responsibility of
the caller to configure the external interrupt lines and RTC to bring
the system out of STANDBY mode. Exit from STANDBY mode causes the
STR7XX to reboot, so if this function returns, then an error has
occurred during entry to STANDBY. It is usually adequate to just retry
in this case.
Note | |
---|---|
At the time of writing, it has not been possible, at least on the STR710-EVAL board, to test RTC wakeup from STANDBY mode. It is believed that this is due to a silicon bug in the version of the STR710 present on the board. |
hal_str7xx_startup_mode()
returns the reason for
the last restart. It indicates whether the restart was as a result of
one of the following events:
STARTUP_MODE_RESET
: Standard power-on reset.STARTUP_MODE_WAKEUP
: External WAKEUP event.STARTUP_MODE_LOW_VOLTAGE
: Low voltage detected.STARTUP_MODE_RTC_ALARM
: RTC alarm.STARTUP_MODE_WATCHDOG
: Watchdog expiry.STARTUP_MODE_SOFTWARE
: Software reset.
hal_str7xx_set_clock_speed(index)
is a wrapper
function that reprograms all the clocks and baud rate generators. The
argument is the same index into the platform HAL supplied parameter
table as given to
hal_str7xx_clocks_setup()
. After calling that
function it also calls hal_str7xx_uart_reinit()
,
hal_str7xx_i2c_reinit()
,
hal_str7xx_can_reinit()
,
HAL_CLOCK_INITIALIZE()
and
hal_str7xx_watchdog_init()
. Unlike
hal_str7xx_clocks_setup()
, this function checks
that the supplied index is valid, and returns false
if it is not.
hal_str7xx_get_clock_speed()
returns the
parameter table index given to the last call to
hal_str7xx_clocks_setup()
or
hal_str7xx_set_clock_speed()
.
The HAL also contains functions to control the Real Time Clock,
RTC. These are mainly oriented towards using the RTC to resume the
system from STOP or STANDBY mode. Before making any other calls to
the RTC routines, the application must call
hal_str7xx_rtc_init()
to initialize the
device. Calling hal_str7xx_rtc_alarm_set(secs)
sets the alarm to fire after the given number of seconds. After the
alarm had fired, or to prevent it firing, call
hal_str7xx_rtc_alarm_cancel()
. Calling
hal_str7xx_rtc_counter()
returns the current
value of the RTC counter, which counts seconds. Function
hal_str7xx_rtc_counter_set( secs )
sets the RTC
counter to the given value. These last two function may be used by a
wallclock driver to provide time and date functionality.
RedBoot Support
The STR7XX HAL installs a number of RedBoot commands to allow testing of the power management support.
speed [-l] [index]
This command reports and sets the clock speed of the STR7XX. Giving the command on its own, with no arguments, lists the available speed settings:
RedBoot> speed
0 32KHz
1 500KHz
2 8MHz
3 24/6/3MHz
4 40/10/5MHz
* 5 48/12/6MHz
6 48/24/12MHz
RedBoot>
The index numbers on the left are used as arguments to the
speed command. The names on the right correspond to
the clock parameter set names described before. The parameter set
currently in force is indicated by an asterisk in the first column. If
the -l
option is given, then more details of the
parameter sets are given, together with the current settings of MCLK,
PCLK1 and PCLK2:
RedBoot> speed -l
MCLK: 48000000, PCLK1 12000000, PCLK2 6000000
C Ix Name CLK/ PLL1* PLL1/ RCLK MCLK/ PCLK1/ PCLK2/
0 32KHz 2 0 0 AF 1 1 1
1 500KHz 2 0 0 CLK2/16 1 1 1
2 8MHz 2 0 0 CLK2 1 1 1
3 24/6/3MHz 2 12 4 PLL1 1 4 8
4 40/10/5MHz 2 20 4 PLL1 1 4 8
* 5 48/12/6MHz 2 12 2 PLL1 1 4 8
6 48/24/12MHz 2 24 2 PLL1 2 4 8
RedBoot>
Supplying the speed command with the index number of a parameter set will change the STR7XX to use that set of clock parameters:
RedBoot>speed 3
Set clock speed 3, please wait... Now running at new speed RedBoot>speed -l
MCLK: 32000000, PCLK1 32000000, PCLK2 32000000 C Ix Name CLK/ PLL1* PLL1/ RCLK MCLK/ PCLK1/ PCLK2/ 0 32KHz 2 0 0 AF 1 1 1 1 500KHz 2 0 0 CLK2/16 1 1 1 2 8MHz 2 0 0 CLK2 1 1 1 3 24/6/3MHz 2 12 4 PLL1 1 4 8 * 4 32/32MHz 2 16 4 PLL1 1 1 1 5 40/10/5MHz 2 20 4 PLL1 1 4 8 6 40/40MHz 2 20 4 PLL1 1 1 1 7 48/12/6MHz 2 12 2 PLL1 1 4 8 8 48/24/12MHz 2 12 2 PLL1 1 2 4 RedBoot>
Note that setting too low a speed may result in RedBoot not being able to program the serial baud rate generator to maintain the current speed.
stop
The stop command puts the STR7XX into STOP mode. The RTC will be programmed to wake the system up after 5 seconds. The device may also be woken up before that timeout using the WAKEUP line, if it is connected to a switch (as it is on the STR710-EVAL board).
standby
The standby command puts the STR7XX into STANDBY mode. The RTC will be programmed to wake the system up after 5 seconds. The device may also be woken up before that timeout using the WAKEUP line, if it is connected to a switch (as it is on the STR710-EVAL board).
2024-03-18 | eCosPro Non-Commercial Public License |