kopia lustrzana https://github.com/bristol-seds/pico-tracker
359 wiersze
10 KiB
C
359 wiersze
10 KiB
C
/**
|
|
* \file
|
|
*
|
|
* \brief SAM D20/D21/R21 System related functionality
|
|
*
|
|
* Copyright (C) 2012-2014 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 SYSTEM_H_INCLUDED
|
|
#define SYSTEM_H_INCLUDED
|
|
|
|
#include "system/clock.h"
|
|
#include "system/gclk.h"
|
|
#include "system/pinmux.h"
|
|
|
|
/**
|
|
* SAM D20/D21/R21 System Driver (SYSTEM)
|
|
*
|
|
* This driver for SAM D20/D21/R21 devices provides an interface for
|
|
* the configuration and management of the device's system relation
|
|
* functionality, necessary for the basic device operation. This is
|
|
* not limited to a single peripheral, but extends across multiple
|
|
* hardware peripherals,
|
|
*
|
|
* The following peripherals are used by this module:
|
|
*
|
|
* - SYSCTRL (System Control)
|
|
* - PM (Power Manager)
|
|
*
|
|
* Module Overview
|
|
*
|
|
* The System driver provides a collection of interfaces between the
|
|
* user application logic, and the core device functionality (such as
|
|
* clocks, reset cause determination, etc.) that is required for all
|
|
* applications.
|
|
*
|
|
* Voltage References
|
|
*
|
|
* The various analog modules within the SAM D20/D21/R21 devices (such
|
|
* as AC, ADC and DAC) require a voltage reference to be configured to
|
|
* act as a reference point for comparisons and conversions.
|
|
*
|
|
* The SAM D20/D21/R21 devices contain multiple references, including
|
|
* an internal temperature sensor, and a fixed band-gap voltage
|
|
* source. When enabled, the associated voltage reference can be
|
|
* selected within the desired peripheral where applicable.
|
|
*
|
|
* System Reset Cause
|
|
*
|
|
* In some application there may be a need to execute a different
|
|
* program flow based on how the device was reset. For example, if the
|
|
* cause of reset was the Watchdog timer (WDT), this might indicate an
|
|
* error in the application and a form of error handling or error
|
|
* logging might be needed.
|
|
*
|
|
* For this reason, an API is provided to retrieve the cause of the
|
|
* last system reset, so that appropriate action can be taken.
|
|
*
|
|
* Sleep Modes
|
|
*
|
|
* The SAM D20/D21/R21 devices have several sleep modes, where the sleep mode controls
|
|
* which clock systems on the device will remain enabled or disabled when the
|
|
* device enters a low power sleep mode.
|
|
|
|
* \ref asfdoc_sam0_system_module_sleep_mode_table "The table below" lists the
|
|
* clock settings of the different sleep modes.
|
|
*
|
|
* \anchor asfdoc_sam0_system_module_sleep_mode_table
|
|
* <table>
|
|
* <caption>SAM D20/D21/R21 Device Sleep Modes</caption>
|
|
* <tr>
|
|
* <th>Sleep mode</th>
|
|
* <th>CPU clock</th>
|
|
* <th>AHB clock</th>
|
|
* <th>APB clocks</th>
|
|
* <th>Clock sources</th>
|
|
* <th>System clock</th>
|
|
* <th>32KHz</th>
|
|
* <th>Reg mode</th>
|
|
* <th>RAM mode</th>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>IDLE 0</td>
|
|
* <td>Stop</td>
|
|
* <td>Run</td>
|
|
* <td>Run</td>
|
|
* <td>Run</td>
|
|
* <td>Run</td>
|
|
* <td>Run</td>
|
|
* <td>Normal</td>
|
|
* <td>Normal</td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>IDLE 1</td>
|
|
* <td>Stop</td>
|
|
* <td>Stop</td>
|
|
* <td>Run</td>
|
|
* <td>Run</td>
|
|
* <td>Run</td>
|
|
* <td>Run</td>
|
|
* <td>Normal</td>
|
|
* <td>Normal</td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>IDLE 2</td>
|
|
* <td>Stop</td>
|
|
* <td>Stop</td>
|
|
* <td>Stop</td>
|
|
* <td>Run</td>
|
|
* <td>Run</td>
|
|
* <td>Run</td>
|
|
* <td>Normal</td>
|
|
* <td>Normal</td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>STANDBY</td>
|
|
* <td>Stop</td>
|
|
* <td>Stop</td>
|
|
* <td>Stop</td>
|
|
* <td>Stop</td>
|
|
* <td>Stop</td>
|
|
* <td>Stop</td>
|
|
* <td>Low Power</td>
|
|
* <td>Source/Drain biasing</td>
|
|
* </tr>
|
|
* </table>
|
|
*
|
|
* To enter device sleep, one of the available sleep modes must be set, and the
|
|
* function to enter sleep called. The device will automatically wake up in
|
|
* response to an interrupt being generated or other device event.
|
|
*
|
|
* Some peripheral clocks will remain enabled during sleep, depending on their
|
|
* configuration; if desired, modules can remain clocked during sleep to allow
|
|
* them to continue to operate while other parts of the system are powered down
|
|
* to save power.
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* List of available voltage references (VREF) that may be used within
|
|
* the device.
|
|
*/
|
|
enum system_voltage_reference {
|
|
/** Temperature sensor voltage reference. */
|
|
SYSTEM_VOLTAGE_REFERENCE_TEMPSENSE,
|
|
/** Bandgap voltage reference. */
|
|
SYSTEM_VOLTAGE_REFERENCE_BANDGAP,
|
|
};
|
|
|
|
/**
|
|
* List of available sleep modes in the device. A table of clocks
|
|
* available in different sleep modes can be found in \ref
|
|
* asfdoc_sam0_system_module_overview_sleep_mode.
|
|
*/
|
|
enum system_sleepmode {
|
|
/** IDLE 0 sleep mode. */
|
|
SYSTEM_SLEEPMODE_IDLE_0,
|
|
/** IDLE 1 sleep mode. */
|
|
SYSTEM_SLEEPMODE_IDLE_1,
|
|
/** IDLE 2 sleep mode. */
|
|
SYSTEM_SLEEPMODE_IDLE_2,
|
|
/** Standby sleep mode. */
|
|
SYSTEM_SLEEPMODE_STANDBY,
|
|
};
|
|
|
|
/**
|
|
* List of possible reset causes of the system.
|
|
*/
|
|
enum system_reset_cause {
|
|
/** The system was last reset by a software reset. */
|
|
SYSTEM_RESET_CAUSE_SOFTWARE = PM_RCAUSE_SYST,
|
|
/** The system was last reset by the watchdog timer. */
|
|
SYSTEM_RESET_CAUSE_WDT = PM_RCAUSE_WDT,
|
|
/** The system was last reset because the external reset line was pulled low. */
|
|
SYSTEM_RESET_CAUSE_EXTERNAL_RESET = PM_RCAUSE_EXT,
|
|
/** The system was last reset by the BOD33. */
|
|
SYSTEM_RESET_CAUSE_BOD33 = PM_RCAUSE_BOD33,
|
|
/** The system was last reset by the BOD12. */
|
|
SYSTEM_RESET_CAUSE_BOD12 = PM_RCAUSE_BOD12,
|
|
/** The system was last reset by the POR (Power on reset). */
|
|
SYSTEM_RESET_CAUSE_POR = PM_RCAUSE_POR,
|
|
};
|
|
|
|
/**
|
|
* Retrieves the signature of the current device.
|
|
*
|
|
* \return Device ID signature as a 32-bit integer.
|
|
*/
|
|
static inline uint32_t system_get_device_id(void)
|
|
{
|
|
return DSU->DID.reg;
|
|
}
|
|
|
|
/**
|
|
* Enables the selected voltage reference source, making the voltage reference
|
|
* available on a pin as well as an input source to the analog peripherals.
|
|
*
|
|
* \param[in] vref Voltage reference to enable
|
|
*/
|
|
static inline void system_voltage_reference_enable(
|
|
const enum system_voltage_reference vref)
|
|
{
|
|
switch (vref) {
|
|
case SYSTEM_VOLTAGE_REFERENCE_TEMPSENSE:
|
|
SYSCTRL->VREF.reg |= SYSCTRL_VREF_TSEN;
|
|
break;
|
|
|
|
case SYSTEM_VOLTAGE_REFERENCE_BANDGAP:
|
|
SYSCTRL->VREF.reg |= SYSCTRL_VREF_BGOUTEN;
|
|
break;
|
|
|
|
default:
|
|
assert(false);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disables the selected voltage reference source.
|
|
*
|
|
* \param[in] vref Voltage reference to disable
|
|
*/
|
|
static inline void system_voltage_reference_disable(
|
|
const enum system_voltage_reference vref)
|
|
{
|
|
switch (vref) {
|
|
case SYSTEM_VOLTAGE_REFERENCE_TEMPSENSE:
|
|
SYSCTRL->VREF.reg &= ~SYSCTRL_VREF_TSEN;
|
|
break;
|
|
|
|
case SYSTEM_VOLTAGE_REFERENCE_BANDGAP:
|
|
SYSCTRL->VREF.reg &= ~SYSCTRL_VREF_BGOUTEN;
|
|
break;
|
|
|
|
default:
|
|
assert(false);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the sleep mode of the device
|
|
*
|
|
* Sets the sleep mode of the device; the configured sleep mode will be entered
|
|
* upon the next call of the \ref system_sleep() function.
|
|
*
|
|
* For an overview of which systems are disabled in sleep for the different
|
|
* sleep modes, see \ref asfdoc_sam0_system_module_overview_sleep_mode.
|
|
*
|
|
* \param[in] sleep_mode Sleep mode to configure for the next sleep operation
|
|
*
|
|
* \retval STATUS_OK Operation completed successfully
|
|
* \retval STATUS_ERR_INVALID_ARG The requested sleep mode was invalid or not
|
|
* available
|
|
*/
|
|
static inline void system_set_sleepmode(
|
|
const enum system_sleepmode sleep_mode)
|
|
{
|
|
switch (sleep_mode) {
|
|
case SYSTEM_SLEEPMODE_IDLE_0:
|
|
case SYSTEM_SLEEPMODE_IDLE_1:
|
|
case SYSTEM_SLEEPMODE_IDLE_2:
|
|
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
|
PM->SLEEP.reg = sleep_mode;
|
|
break;
|
|
|
|
case SYSTEM_SLEEPMODE_STANDBY:
|
|
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
// return STATUS_ERR_INVALID_ARG;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Executes a device DSB (Data Synchronization Barrier) instruction to ensure
|
|
* all ongoing memory accesses have completed, then a WFI (Wait For Interrupt)
|
|
* instruction to place the device into the sleep mode specified by
|
|
* \ref system_set_sleepmode until woken by an interrupt.
|
|
*/
|
|
static inline void system_sleep(void)
|
|
{
|
|
__DSB();
|
|
__WFI();
|
|
}
|
|
|
|
/**
|
|
* Check if debugger is connected to the onboard debug system (DAP)
|
|
*
|
|
* \return A bool identifying if a debugger is present
|
|
*
|
|
* \retval true Debugger is connected to the system
|
|
* \retval false Debugger is not connected to the system
|
|
*
|
|
*/
|
|
static inline bool system_is_debugger_present(void)
|
|
{
|
|
return DSU->STATUSB.reg & DSU_STATUSB_DBGPRES;
|
|
}
|
|
|
|
/**
|
|
* Resets the MCU and all associated peripherals and registers, except
|
|
* RTC, all 32kHz sources, WDT (if ALWAYSON is set) and GCLK (if
|
|
* WRTLOCK is set).
|
|
*
|
|
*/
|
|
static inline void system_reset(void)
|
|
{
|
|
NVIC_SystemReset();
|
|
}
|
|
|
|
/**
|
|
* Retrieves the cause of the last system reset.
|
|
*
|
|
* \return An enum value indicating the cause of the last system reset.
|
|
*/
|
|
static inline enum system_reset_cause system_get_reset_cause(void)
|
|
{
|
|
return (enum system_reset_cause)PM->RCAUSE.reg;
|
|
}
|
|
|
|
#endif /* SYSTEM_H_INCLUDED */
|