blob: eecb74aa9820cf58c6951e13c4b2a30d6e82cb39 [file] [log] [blame]
/**
* \file
*
* \brief BPM driver.
*
* Copyright (C) 2012 - 2013 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
#ifndef BPM_H_INCLUDED
#define BPM_H_INCLUDED
#include "compiler.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup group_sam_drivers_bpm BPM - Backup Power Manager
*
* Driver for the BPM (Backup Power Manager).
* This driver provides access to the main features of the BPM controller.
* It provides functions for different power mode management.
*
* @{
*/
/** BPM unlock macro */
#define BPM_UNLOCK(reg) \
do { \
BPM->BPM_UNLOCK = BPM_UNLOCK_KEY(0xAAu) \
| BPM_UNLOCK_ADDR((uint32_t)&BPM->BPM_##reg - (uint32_t)BPM);\
} while (0)
/** \name Sleep mode definitions */
/* @{ */
#define BPM_SM_ACTIVE 0 /**< Active mode */
#define BPM_SM_SLEEP_0 1 /**< Sleep mode 0 */
#define BPM_SM_SLEEP_1 2 /**< Sleep mode 1 */
#define BPM_SM_SLEEP_2 3 /**< Sleep mode 2 */
#define BPM_SM_SLEEP_3 4 /**< Sleep mode 3 */
#define BPM_SM_WAIT 5 /**< Wait mode */
#define BPM_SM_RET 6 /**< Retention mode */
#define BPM_SM_BACKUP 7 /**< Backup mode */
/* @} */
/** \anchor power_scaling_change_mode */
/** \name Power scaling change mode */
/* @{ */
/** Power scaling change mode: halting the CPU execution */
#define BPM_PSCM_CPU_HALT 0
/** Power scaling change mode: CPU execution not halted */
#define BPM_PSCM_CPU_NOT_HALT 1
/* @} */
/** \anchor power_scaling_mode_value */
/** \name Power scaling mode value */
/* @{ */
/** Power scaling mode 0 */
#define BPM_PS_0 0
/** Power scaling mode 1 */
#define BPM_PS_1 1
/** Power scaling mode 2 */
#define BPM_PS_2 2
/* @} */
/** \anchor CLK32_32Khz_1Khz */
/** \name CLK32 32Khz-1Khz clock source selection */
/* @{ */
/** OSC32K : Low frequency crystal oscillator */
#define BPM_CLK32_SOURCE_OSC32K 0
/** RC32K : Internal Low frequency RC oscillator */
#define BPM_CLK32_SOURCE_RC32K 1
/* @} */
/** \anchor backup_wake_up_sources */
/** \name Backup wake up sources */
/* @{ */
/** EIC wake up */
#define BPM_BKUP_WAKEUP_SRC_EIC (1UL << BPM_BKUPWEN_EIC)
/** AST wake up */
#define BPM_BKUP_WAKEUP_SRC_AST (1UL << BPM_BKUPWEN_AST)
/** WDT wake up */
#define BPM_BKUP_WAKEUP_SRC_WDT (1UL << BPM_BKUPWEN_WDT)
/** BOD33 wake up */
#define BPM_BKUP_WAKEUP_SRC_BOD33 (1UL << BPM_BKUPWEN_BOD33)
/** BOD18 wake up */
#define BPM_BKUP_WAKEUP_SRC_BOD18 (1UL << BPM_BKUPWEN_BOD18)
/** PICOUART wake up */
#define BPM_BKUP_WAKEUP_SRC_PICOUART (1UL << BPM_BKUPWEN_PICOUART)
/* @} */
/** \anchor backup_pin_muxing */
/** \name Backup pin muxing */
/* @{ */
#define BPM_BKUP_PIN_PB01_EIC0 BPM_BKUPPMUX_BKUPPMUX(0)
#define BPM_BKUP_PIN_PA06_EIC1 BPM_BKUPPMUX_BKUPPMUX(1)
#define BPM_BKUP_PIN_PA04_EIC2 BPM_BKUPPMUX_BKUPPMUX(2)
#define BPM_BKUP_PIN_PA05_EIC3 BPM_BKUPPMUX_BKUPPMUX(3)
#define BPM_BKUP_PIN_PA07_EIC4 BPM_BKUPPMUX_BKUPPMUX(4)
#define BPM_BKUP_PIN_PC03_EIC5 BPM_BKUPPMUX_BKUPPMUX(5)
#define BPM_BKUP_PIN_PC04_EIC6 BPM_BKUPPMUX_BKUPPMUX(6)
#define BPM_BKUP_PIN_PC05_EIC7 BPM_BKUPPMUX_BKUPPMUX(7)
#define BPM_BKUP_PIN_PC06_EIC8 BPM_BKUPPMUX_BKUPPMUX(8)
/* @} */
/**
* \name Power management
*/
/* @{ */
/**
* \brief Change Power Scaling mode
*
* PSOK is not checked while switching PS mode.
*
* \param bpm Base address of the BPM instance.
* \param ps_value Power scaling value, see \ref power_scaling_mode_value.
*
*/
void bpm_power_scaling_cpu(Bpm *bpm, uint32_t ps_value);
/**
* \brief Change Power Scaling mode and check results
*
* Wait for a while to check if PSOK is ready.
*
* \param bpm Base address of the BPM instance.
* \param ps_value Power scaling value, see \ref power_scaling_mode_value.
*
* \param timeout Timeout, in number of processor clocks, max 0xFFFFFF.
* \return true if PSOK is ready.
*/
bool bpm_power_scaling_cpu_failsafe(Bpm *bpm, uint32_t ps_value,
uint32_t timeout);
/**
* \brief Configure power scaling mode.
*
* While checking PSOK in power safe (no halt) mode, timeout is set to
* 240000 by default, which takes 20ms when 12MHz clock is used.
*
* \param bpm Base address of the BPM instance.
* \param ps_value Power scaling value, see \ref power_scaling_mode_value.
*
* \param no_halt No halt or Fail safe, see \c bpm_power_scaling_cpu()
* and bpm_power_scaling_cpu_failsafe()
* \return true if no error.
*/
__always_inline static
bool bpm_configure_power_scaling(Bpm *bpm, uint32_t ps_value, uint32_t no_halt)
{
if (!no_halt) {
bpm_power_scaling_cpu(bpm, ps_value);
return true;
}
return bpm_power_scaling_cpu_failsafe(bpm, ps_value, 240000);
}
/**
* \brief Enable fast wakeup for analog modules.
*
* \param bpm Base address of the BPM instance.
*/
void bpm_enable_fast_wakeup(Bpm *bpm);
/**
* \brief Disable fast wakeup for analog modules.
*
* \param bpm Base address of the BPM instance.
*/
void bpm_disable_fast_wakeup(Bpm *bpm);
/**
* \brief Set clock source for 32KHz clock.
*
* \param bpm Base address of the BPM instance.
* \param source Clock source, see \ref CLK32_32Khz_1Khz.
*/
void bpm_set_clk32_source(Bpm *bpm, uint32_t source);
/**
* \brief Get wakeup cause from backup mode.
*
* \param bpm Base address of the BPM instance.
*/
uint32_t bpm_get_backup_wakeup_cause(Bpm *bpm);
/**
* \brief Enable wakeup source.
*
* \param bpm Base address of the BPM instance.
* \param sources Wakeup source mask, see \ref backup_wake_up_sources.
*/
void bpm_enable_wakeup_source(Bpm *bpm, uint32_t sources);
/**
* \brief Disable wakeup source.
*
* \param bpm Base address of the BPM instance.
* \param sources Wakeup source mask, see \ref backup_wake_up_sources.
*/
void bpm_disable_wakeup_source(Bpm *bpm, uint32_t sources);
/**
* \brief Enable backup pin for wakeup.
*
* \param bpm Base address of the BPM instance.
* \param backup_pins Backup pin mask, see \ref backup_pin_muxing.
*/
void bpm_enable_backup_pin(Bpm *bpm, uint32_t backup_pins);
/**
* \brief Disable backup pin for wakeup.
*
* \param bpm Base address of the BPM instance.
* \param backup_pins Backup pin mask, see \ref backup_pin_muxing.
*/
void bpm_disable_backup_pin(Bpm *bpm, uint32_t backup_pins);
/**
* \brief Enable IO retention for backup mode.
*
* \param bpm Base address of the BPM instance.
*/
void bpm_enable_io_retention(Bpm *bpm);
/**
* \brief Disable IO retention for backup mode.
*
* \param bpm Base address of the BPM instance.
*/
void bpm_disable_io_retention(Bpm *bpm);
/* @} */
/**
* \name Interrupt and status management
*/
/* @{ */
/**
* \brief Enable interrupt with given sources mask.
*
* \param bpm Base address of the BPM instance.
* \param sources BPM interrupt source mask.
*/
void bpm_enable_interrupt(Bpm *bpm, uint32_t sources);
/**
* \brief Disable interrupt with given sources mask.
*
* \param bpm Base address of the BPM instance.
* \param sources BPM interrupt source mask.
*/
void bpm_disable_interrupt(Bpm *bpm, uint32_t sources);
/**
* \brief Get BPM interrupt mask.
*
* \param bpm Base address of the BPM instance.
*
* \return BPM interrupt mask.
*/
uint32_t bpm_get_interrupt_mask(Bpm *bpm);
/**
* \brief Get BPM interrupt status.
*
* \param bpm Base address of the BPM instance.
*
* \return BPM interrupt status.
*/
uint32_t bpm_get_interrupt_status(Bpm *bpm);
/**
* \brief Clear BPM interrupt.
*
* \param bpm Base address of the BPM instance.
* \param sources BPM interrupt source mask.
*/
void bpm_clear_interrupt(Bpm *bpm, uint32_t sources);
/**
* \brief Get BPM status.
*
* \param bpm Base address of the BPM instance.
*
* \return BPM status.
*/
uint32_t bpm_get_status(Bpm *bpm);
/**
* \brief Get version of BPM module.
*
* \param bpm Base address of the BPM instance.
*
* \return Version of BPM module.
*/
uint32_t bpm_get_version(Bpm *bpm);
/* @} */
/* @} */
#ifdef __cplusplus
}
#endif
/**
* \page sam_bpm_quickstart Quick start guide for the SAM BPM module
*
* This is the quick start guide for the
* \ref group_sam_drivers_bpm "BPM Module", with step-by-step instructions on
* how to configure and use the driver in a selection of use cases.
*
* The use cases contain several code fragments. The code fragments in the
* steps for setup can be copied into a custom initialization function, while
* the steps for usage can be copied into, e.g., the main application function.
*
* \section bpm_use_cases BPM use cases
* - \ref bpm_use_case_1 Basic use case - Entering Sleep Modes
* - \ref bpm_use_case_2 Advanced use case - Switch Power Scaling Modes
*
* \section bpm_use_case_1 Basic use case - Entering Sleep Modes
* In this use case, the BPM module can put system into different power saving
* modes. Check the current of the system to see consumptions.
*
* \section bpm_use_case_1_setup Setup
*
* \subsection bpm_use_case_1_setup_prereq Prerequisites
* Sleep mode itself does not require any IO input, but to wakeup an interrupt
* is needed.
* -# \ref ioport_group "Common IOPORT (for GPIO)"
* -# \ref sam_drivers_eic_group "External Interrupt Controller (EIC)"
*
* \subsection bpm_use_case_1_setup_prereq_code Code
*
* \code
* #define EIC_INT5_ENABLE
* \endcode
*
* The following code needs to be added to the user application, to wakeup
* system and switch to next power mode.
* \code
* static void push_button_eic_handler()
* {
* eic_line_clear_interrupt(EIC, GPIO_PUSH_BUTTON_EIC_LINE);
* }
* \endcode
* \code
* my_eic_init()
* {
* struct eic_line_config eic_opt={
* EIC_MODE_EDGE_TRIGGERED,
* EIC_EDGE_FALLING_EDGE,
* EIC_LEVEL_LOW_LEVEL,
* EIC_FILTER_DISABLED,
* EIC_ASYNCH_MODE
* };
* eic_enable(EIC);
* eic_line_set_config(EIC, GPIO_PUSH_BUTTON_EIC_LINE, &eic_opt);
* eic_line_set_callback(EIC, GPIO_PUSH_BUTTON_EIC_LINE,
* push_button_eic_handler, EIC_5_IRQn, 1);
* eic_line_enable(EIC, GPIO_PUSH_BUTTON_EIC_LINE);
* }
* \endcode
*
* \subsection bpm_use_case_1_setup_prereq_flow Workflow
* -# Ensure that ioport and eic driver is available.
* -# Ensure that push button is configured as external interrupt in
* conf_board.h:
* \code #define CONF_BOARD_EIC \endcode
* -# Add EIC initialize to application C-file:
* \code my_eic_init(); \endcode
*
* \section bpm_use_case_1_usage Use case
*
* \subsection bpm_use_case_1_usage_code Example code
* Add to application C-file:
* \code
* // Enable wakeup by EIC
* bpm_enable_wakeup_source(BPM, 1 << BPM_BKUPWEN_EIC);
* // Enable backup wakeup by Push button EIC line
* bpm_enable_backup_pin(BPM, 1 << GPIO_PUSH_BUTTON_EIC_LINE);
* // Retain I/O lines after wakeup from backup mode
* bpm_enable_io_retention(BPM);
* // Enable fast wakeup
* bpm_enable_fast_wakeup(BPM);
* // Enter wait mode
* // critical section when going to sleep
* cpu_irq_disable();
* bpm_sleep(BPM, BPM_SM_WAIT);
* // Enter retention mode
* cpu_irq_disable();
* bpm_sleep(BPM, BPM_SM_RET);
* // Enter backup mode
* cpu_irq_disable();
* bpm_sleep(BPM, BPM_SM_BACKUP);
* while(1);
* \endcode
*
* \subsection bpm_use_case_1_usage_flow Workflow
* -# Enable wakeup by EIC:
* \code
* bpm_enable_wakeup_source(BPM, 1 << BPM_BKUPWEN_EIC);
* bpm_enable_backup_pin(BPM, 1 << GPIO_PUSH_BUTTON_EIC_LINE);
* \endcode
* -# Setup IO retention:
* \code bpm_enable_io_retention(BPM); \endcode
* -# Setup fast wakeup:
* \code bpm_enable_fast_wakeup(BPM); \endcode
* -# Enter sleep/wait/backup mode:
* \code
* // critical section when going to sleep
* cpu_irq_disable();
* bpm_sleep(BPM, BPM_SM_WAIT);
* \endcode
*/
/**
* \page bpm_use_case_2 Advanced use case - Switch Power Scaling Modes
* In this use case, the BPM module can switch the power scaling modes of the
* system. Check the current of the system to see consumptions.
*
* \section bpm_use_case_2_setup Setup
* \subsection bpm_use_case_2_setup_prereq Prerequisites
* Some power scaling modes only work on limited system clock frequency (The
* maximum CPU frequency under PS1 is 12MHz, other peripherals also have speed
* limitations), please refer to the electrical characteristics for more
* details.
* -# \ref clk_group "Clock management"
*
* \subsection bpm_use_case_2_setup_code Code
* Content of conf_clock.h
* \code
* #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RCFAST // Uses Fast RC
* #define CONFIG_RCFAST_FRANGE 2 // Fast RC is 12MHz
* \endcode
*
* \subsection bpm_use_case_2_setup_workflow Workflow
* -# Ensure that conf_clock.h is available and contains the following
* parameters which configure system clock to 12MHz fast RC:
* \code
* #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RCFAST // Uses Fast RC
* #define CONFIG_RCFAST_FRANGE 2 // Fast RC is 12MHz
* \endcode
* -# Initialize system clock with \c sysclk_init().
*
* \section bpm_use_case_2_usage Use case
*
* \subsection bpm_use_case_2_usage_code Example code
* Add to application C-file:
* \code
* bpm_power_scaling_cpu(BPM, BPM_PMCON_PS(BPM_PS_1));
* while((bpm_get_status(BPM) & BPM_SR_PSOK) == 0);
* while(1);
* \endcode
*
* \subsection bpm_use_case_2_usage_workflow Workflow
* -# Switch the power scaling mode:
* \code bpm_power_scaling_cpu(BPM, BPM_PMCON_PS(BPM_PS_1));
* \endcode
* -# Wait power scaling done:
* \code while((bpm_get_status(BPM) & BPM_SR_PSOK) == 0); \endcode
*/
#endif /* BPM_H_INCLUDED */