diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h index cb86101f69..d27ba5b5ea 100644 --- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h +++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h @@ -38,7 +38,7 @@ #define DEVICE_CAN 0 -#define DEVICE_RTC 0 +#define DEVICE_RTC 1 #define DEVICE_ETHERNET 0 diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_calendar.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_calendar.h deleted file mode 100644 index a4c91918bf..0000000000 --- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_calendar.h +++ /dev/null @@ -1,1254 +0,0 @@ -/** - * \file - * - * \brief SAM RTC Driver (Calendar Mode) - * - * 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 - * - */ -/** -* Support and FAQ: visit Atmel Support -*/ -#ifndef RTC_CALENDAR_H_INCLUDED -#define RTC_CALENDAR_H_INCLUDED - -/** - * \defgroup asfdoc_sam0_rtc_calendar_group SAM RTC Calendar Driver (RTC CAL) - * - * This driver for Atmel庐 | SMART SAM devices provides an interface for the configuration - * and management of the device's Real Time Clock functionality in Calendar - * operating mode, for the configuration and retrieval of the current time and - * date as maintained by the RTC module. The following driver API modes are - * covered by this manual: - * - * - Polled APIs - * \if RTC_CALENDAR_CALLBACK_MODE - * - Callback APIs - * \endif - * - * The following peripherals are used by this module: - * - RTC (Real Time Clock) - * - * The following devices can use this module: - * - Atmel | SMART SAM D20/D21 - * - Atmel | SMART SAM R21 - * - Atmel | SMART SAM D10/D11 - * - Atmel | SMART SAM L21 - * - * The outline of this documentation is as follows: - * - \ref asfdoc_sam0_rtc_calendar_prerequisites - * - \ref asfdoc_sam0_rtc_calendar_module_overview - * - \ref asfdoc_sam0_rtc_calendar_special_considerations - * - \ref asfdoc_sam0_rtc_calendar_extra_info - * - \ref asfdoc_sam0_rtc_calendar_examples - * - \ref asfdoc_sam0_rtc_calendar_api_overview - * - * - * \section asfdoc_sam0_rtc_calendar_prerequisites Prerequisites - * - * There are no prerequisites for this module. - * - * - * \section asfdoc_sam0_rtc_calendar_module_overview Module Overview - * - * The RTC module in the SAM devices is a 32-bit counter, with a 10-bit - * programmable prescaler. Typically, the RTC clock is run continuously, - * including in the device's low-power sleep modes, to track the current time - * and date information. The RTC can be used as a source to wake up the system - * at a scheduled time or periodically using the alarm functions. - * - * In this driver, the RTC is operated in Calendar mode. This allows for an - * easy integration of a real time clock and calendar into a user application - * to track the passing of time and/or perform scheduled tasks. - * - * Whilst operating in Calendar mode, the RTC features: - * - Time tracking in seconds, minutes, and hours - * - 12 or 24 hour mode - * - Date tracking in day, month, and year - * - Automatic leap year correction - * - * \subsection asfdoc_sam0_rtc_calendar_features Driver Feature Macro Definition - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Driver Feature MacroSupported devices
FEATURE_RTC_PERIODIC_INTSAML21
FEATURE_RTC_PRESCALER_OFFSAML21
FEATURE_RTC_CLOCK_SELECTIONSAML21
FEATURE_RTC_GENERAL_PURPOSE_REGSAML21
FEATURE_RTC_CONTINUOUSLY_UPDATEDSAMD20, SAMD21, SAMR21, SAMD10, SAMD11
- * \note The specific features are only available in the driver when the - * selected device supports those features. - * - * \subsection asfdoc_sam0_rtc_calendar_module_overview_alarms Alarms and Overflow - * The RTC has four independent hardware alarms that can be configured by the user - * application. These alarms will be will triggered on match with the current - * clock value, and can be set up to trigger an interrupt, event, or both. The - * RTC can also be configured to clear the clock value on alarm match, resetting - * the clock to the original start time. - * - * If the RTC is operated in clock-only mode (i.e. with calendar disabled), the - * RTC counter value will instead be cleared on overflow once the maximum count - * value has been reached: - * - * \f[ COUNT_{MAX} = 2^{32}-1 \f] - * - * When the RTC is operated with the calendar enabled and run using a nominal - * 1Hz input clock frequency, a register overflow will occur after 64 years. - * - * \subsection asfdoc_sam0_rtc_calendar_module_overview_periodic Periodic Events - * The RTC can generate events at periodic intervals, allowing for direct - * peripheral actions without CPU intervention. The periodic events can be - * generated on the upper eight bits of the RTC prescaler, and will be generated on - * the rising edge transition of the specified bit. The resulting periodic - * frequency can be calculated by the following formula: - * - * \f[ f_{PERIODIC}=\frac{f_{ASY}}{2^{n+3}} \f] - * - * Where \f$f_{ASY}\f$ refers to the \e asynchronous clock set up in the RTC - * module configuration. For the RTC to operate correctly in calendar mode, this - * frequency must be 1KHz, while the RTC's internal prescaler should be set to - * divide by 1024. The \b n parameter is the event source generator index of the - * RTC module. If the asynchronous clock is operated at the recommended 1KHz, - * the formula results in the values shown in - * \ref asfdoc_sam0_rtc_calendar_module_rtc_hz "the table below". - * - * \anchor asfdoc_sam0_rtc_calendar_module_rtc_hz - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
RTC Event Frequencies for Each Prescaler Bit Using a 1KHz Clock
n Periodic event
7 1Hz
6 2Hz
5 4Hz
4 8Hz
3 16Hz
2 32Hz
1 64Hz
0 128Hz
- * - * \note The connection of events between modules requires the use of the - * \ref asfdoc_sam0_events_group "SAM Event System Driver (EVENTS)" - * to route output event of one module to the the input event of another. - * For more information on event routing, refer to the event driver - * documentation. - * - * \subsection asfdoc_sam0_rtc_calendar_module_overview_correction Digital Frequency Correction - * The RTC module contains Digital Frequency Correction logic to compensate for - * inaccurate source clock frequencies which would otherwise result in skewed - * time measurements. The correction scheme requires that at least two bits - * in the RTC module prescaler are reserved by the correction logic. As a - * result of this implementation, frequency correction is only available when - * the RTC is running from a 1Hz reference clock. - * - * The correction procedure is implemented by subtracting or adding a single - * cycle from the RTC prescaler every 1024 RTC GCLK cycles. The adjustment is - * applied the specified number of time (maximum 127) over 976 of these periods. The - * corresponding correction in PPM will be given by: - * - * \f[ Correction(PPM) = \frac{VALUE}{999424}10^6 \f] - * - * The RTC clock will tick faster if provided with a positive correction value, - * and slower when given a negative correction value. - * - * - * \section asfdoc_sam0_rtc_calendar_special_considerations Special Considerations - * - * \subsection asfdoc_sam0_rtc_calendar_special_considerations_year Year Limit - * The RTC module has a year range of 63 years from the starting year configured - * when the module is initialized. Dates outside the start to end year range - * described below will need software adjustment: - * - * \f[ [YEAR_{START}, YEAR_{START}+64) \f] - * - * \subsection asfdoc_sam0_rtc_calendar_special_considerations_clock Clock Setup - * \subsubsection asfdoc_sam0_rtc_calendar_clock_samd_r SAM D20/D21/R21/D10/D11 Clock Setup - * The RTC is typically clocked by a specialized GCLK generator that has a - * smaller prescaler than the others. By default the RTC clock is on, selected - * to use the internal 32KHz RC-oscillator with a prescaler of 32, giving a - * resulting clock frequency of 1024Hz to the RTC. When the internal RTC - * prescaler is set to 1024, this yields an end-frequency of 1Hz for correct - * time keeping operations. - * - * The implementer also has the option to set other end-frequencies. - * \ref asfdoc_sam0_rtc_calendar_rtc_out_freq "The table below" lists the - * available RTC frequencies for each possible GCLK and RTC input prescaler - * options. - * - * \anchor asfdoc_sam0_rtc_calendar_rtc_out_freq - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
RTC Output Frequencies from Allowable Input Clocks
End-frequencyGCLK prescalerRTC prescaler
32KHz11
1KHz321
1Hz321024
- * - * The overall RTC module clocking scheme is shown in - * \ref asfdoc_sam0_rtc_calendar_rtc_clock_fig "the figure below". - * - * \anchor asfdoc_sam0_rtc_calendar_rtc_clock_fig - * \dot - * digraph clocking_scheme { - * rankdir=LR; - * GCLK [shape="record", label=" GCLK | RTC_GCLK", - * bgcolor="lightgray", style="filled"]; - * RTCPRE [shape="record" label=" RTC | RTC PRESCALER"]; - * RTC [shape="record", label=" RTC | RTC CLOCK"]; - * - * GCLK:f1 -> RTCPRE:f1; - * RTCPRE:f1 -> RTC:f1; - * } - * \enddot - * - * \note For the calendar to operate correctly, an asynchronous clock of 1Hz - * should be used. - * - * \subsubsection asfdoc_sam0_rtc_calendar_clock_saml SAM L21 Clock Setup - * The RTC clock can be selected from OSC32K,XOSC32K or OSCULP32K , and a 32KHz - * or 1KHz oscillator clock frequency is required. This clock must be - * configured and enabled in the 32KHz oscillator controller before using the RTC. - * - * The table below lists the available RTC clock \ref asfdoc_sam0_rtc_calendar_rtc_clk - * - * \anchor asfdoc_sam0_rtc_calendar_rtc_clk - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
RTC clocks source
RTC clock frequencyClock sourceDescription
1.024KHzULP1K1.024KHz from 32KHz internal ULP oscillator
32.768KHzULP32K32.768KHz from 32KHz internal ULP oscillator
1.024KHzOSC1K1.024KHz from 32KHz internal oscillator
32.768KHzOSC32K32.768KHz from 32KHz internal oscillator
1.024KHzXOSC1K1.024KHz from 32KHz internal oscillator
32.768KHzXOSC32K32.768KHz from 32KHz external crystal oscillator
- * - * \note For the calendar to operate correctly, an asynchronous clock of 1Hz - * should be used. - * - * \section asfdoc_sam0_rtc_calendar_extra_info Extra Information - * - * For extra information, see \ref asfdoc_sam0_rtc_calendar_extra. This includes: - * - \ref asfdoc_sam0_rtc_calendar_extra_acronyms - * - \ref asfdoc_sam0_rtc_calendar_extra_dependencies - * - \ref asfdoc_sam0_rtc_calendar_extra_errata - * - \ref asfdoc_sam0_rtc_calendar_extra_history - * - * - * \section asfdoc_sam0_rtc_calendar_examples Examples - * - * For a list of examples related to this driver, see - * \ref asfdoc_sam0_rtc_calendar_exqsg. - * - * - * \section asfdoc_sam0_rtc_calendar_api_overview API Overview - * @{ - */ - -#include - -#if RTC_CALENDAR_ASYNC == true -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Define port features set according to different device family - * @{ -*/ -#if (SAML21) || defined(__DOXYGEN__) -/** RTC periodic interval interrupt. */ -# define FEATURE_RTC_PERIODIC_INT -/** RTC prescaler is off. */ -# define FEATURE_RTC_PRESCALER_OFF -/** RTC clock selection. */ -# define FEATURE_RTC_CLOCK_SELECTION -/** General purpose registers. */ -# define FEATURE_RTC_GENERAL_PURPOSE_REG -#else -/** RTC continuously updated. */ -# define FEATURE_RTC_CONTINUOUSLY_UPDATED -#endif -/*@}*/ - -#ifdef FEATURE_RTC_CLOCK_SELECTION -/** - * \brief Available clock source for RTC. - * RTC clock source. - */ -enum rtc_clock_sel { - /** 1.024KHz from 32KHz internal ULP oscillator. */ - RTC_CLOCK_SELECTION_ULP1K = OSC32KCTRL_RTCCTRL_RTCSEL_ULP1K_Val, - /** 32.768KHz from 32KHz internal ULP oscillator. */ - RTC_CLOCK_SELECTION_ULP32K = OSC32KCTRL_RTCCTRL_RTCSEL_ULP32K_Val, - /** 1.024KHz from 32KHz internal oscillator. */ - RTC_CLOCK_SELECTION_OSC1K = OSC32KCTRL_RTCCTRL_RTCSEL_OSC1K_Val, - /** 32.768KHz from 32KHz internal oscillator. */ - RTC_CLOCK_SELECTION_OSC32K = OSC32KCTRL_RTCCTRL_RTCSEL_OSC32K_Val, - /** 1.024KHz from 32KHz internal oscillator. */ - RTC_CLOCK_SELECTION_XOSC1K = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC1K_Val, - /** 32.768KHz from 32.768KHz external crystal oscillator. */ - RTC_CLOCK_SELECTION_XOSC32K = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC32K_Val, -}; -#endif - -#if !defined (RTC_NUM_OF_ALARMS) && defined(RTC_ALARM_NUM) -#define RTC_NUM_OF_ALARMS RTC_ALARM_NUM -#endif - -/** - * \brief Available alarm channels. - * - * Available alarm channels. - * - * \note Not all alarm channels are available on all devices. - */ -enum rtc_calendar_alarm { - /** Alarm channel 0. */ - RTC_CALENDAR_ALARM_0 = 0, -#if (RTC_NUM_OF_ALARMS > 1) || defined(__DOXYGEN__) - /** Alarm channel 1. */ - RTC_CALENDAR_ALARM_1 = 1, -#endif -#if (RTC_NUM_OF_ALARMS > 2) || defined(__DOXYGEN__) - /** Alarm channel 2. */ - RTC_CALENDAR_ALARM_2 = 2, -#endif -#if (RTC_NUM_OF_ALARMS > 3) || defined(__DOXYGEN__) - /** Alarm channel 3. */ - RTC_CALENDAR_ALARM_3 = 3, -#endif -}; - -#if RTC_CALENDAR_ASYNC == true -#ifdef FEATURE_RTC_PERIODIC_INT -/** - * \brief Callback types. - * - * The available callback types for the RTC calendar module. - */ -enum rtc_calendar_callback { - /** Callback for Periodic Interval 0 Interrupt. */ - RTC_CALENDAR_CALLBACK_PERIODIC_INTERVAL_0 = 0, - /** Callback for Periodic Interval 1 Interrupt. */ - RTC_CALENDAR_CALLBACK_PERIODIC_INTERVAL_1, - /** Callback for Periodic Interval 2 Interrupt. */ - RTC_CALENDAR_CALLBACK_PERIODIC_INTERVAL_2, - /** Callback for Periodic Interval 3 Interrupt. */ - RTC_CALENDAR_CALLBACK_PERIODIC_INTERVAL_3, - /** Callback for Periodic Interval 4 Interrupt. */ - RTC_CALENDAR_CALLBACK_PERIODIC_INTERVAL_4, - /** Callback for Periodic Interval 5 Interrupt. */ - RTC_CALENDAR_CALLBACK_PERIODIC_INTERVAL_5, - /** Callback for Periodic Interval 6 Interrupt. */ - RTC_CALENDAR_CALLBACK_PERIODIC_INTERVAL_6, - /** Callback for Periodic Interval 7 Interrupt. */ - RTC_CALENDAR_CALLBACK_PERIODIC_INTERVAL_7, - /** Callback for alarm 0. */ - RTC_CALENDAR_CALLBACK_ALARM_0, -# if (RTC_NUM_OF_ALARMS > 1) || defined(__DOXYGEN__) - /** Callback for alarm 1. */ - RTC_CALENDAR_CALLBACK_ALARM_1, -# endif -# if (RTC_NUM_OF_ALARMS > 2) || defined(__DOXYGEN__) - /** Callback for alarm 2. */ - RTC_CALENDAR_CALLBACK_ALARM_2, -# endif -# if (RTC_NUM_OF_ALARMS > 3) || defined(__DOXYGEN__) - /** Callback for alarm 3. */ - RTC_CALENDAR_CALLBACK_ALARM_3, -# endif - /** Callback for overflow. */ - RTC_CALENDAR_CALLBACK_OVERFLOW, -# if !defined(__DOXYGEN__) - /** Total number of callbacks. */ - _RTC_CALENDAR_CALLBACK_N -# endif -}; -#else -/** - * \brief Callback types. - * - * The available callback types for the RTC calendar module. - */ -enum rtc_calendar_callback { - /** Callback for alarm 0. */ - RTC_CALENDAR_CALLBACK_ALARM_0 = 0, -# if (RTC_NUM_OF_ALARMS > 1) || defined(__DOXYGEN__) - /** Callback for alarm 1. */ - RTC_CALENDAR_CALLBACK_ALARM_1, -# endif -# if (RTC_NUM_OF_ALARMS > 2) || defined(__DOXYGEN__) - /** Callback for alarm 2. */ - RTC_CALENDAR_CALLBACK_ALARM_2, -# endif -# if (RTC_NUM_OF_ALARMS > 3) || defined(__DOXYGEN__) - /** Callback for alarm 3. */ - RTC_CALENDAR_CALLBACK_ALARM_3, -# endif - /** Callback for overflow. */ - RTC_CALENDAR_CALLBACK_OVERFLOW, -# if !defined(__DOXYGEN__) - /** Total number of callbacks. */ - _RTC_CALENDAR_CALLBACK_N -# endif -}; -#endif - -# if !defined(__DOXYGEN__) -typedef void (*rtc_calendar_callback_t)(void); -# endif -#endif - -#ifdef FEATURE_RTC_PRESCALER_OFF -/** - * \brief RTC input clock prescaler settings. - * - * The available input clock prescaler values for the RTC calendar module. - */ -enum rtc_calendar_prescaler { - /** RTC prescaler is off, and the input clock frequency is - prescaled by a factor of 1. */ - RTC_CALENDAR_PRESCALER_OFF = RTC_MODE2_CTRLA_PRESCALER_OFF, - /** RTC input clock frequency is prescaled by a factor of 1. */ - RTC_CALENDAR_PRESCALER_DIV_1 = RTC_MODE2_CTRLA_PRESCALER_DIV1, - /** RTC input clock frequency is prescaled by a factor of 2. */ - RTC_CALENDAR_PRESCALER_DIV_2 = RTC_MODE2_CTRLA_PRESCALER_DIV2, - /** RTC input clock frequency is prescaled by a factor of 4. */ - RTC_CALENDAR_PRESCALER_DIV_4 = RTC_MODE2_CTRLA_PRESCALER_DIV4, - /** RTC input clock frequency is prescaled by a factor of 8. */ - RTC_CALENDAR_PRESCALER_DIV_8 = RTC_MODE2_CTRLA_PRESCALER_DIV8, - /** RTC input clock frequency is prescaled by a factor of 16. */ - RTC_CALENDAR_PRESCALER_DIV_16 = RTC_MODE2_CTRLA_PRESCALER_DIV16, - /** RTC input clock frequency is prescaled by a factor of 32. */ - RTC_CALENDAR_PRESCALER_DIV_32 = RTC_MODE2_CTRLA_PRESCALER_DIV32, - /** RTC input clock frequency is prescaled by a factor of 64. */ - RTC_CALENDAR_PRESCALER_DIV_64 = RTC_MODE2_CTRLA_PRESCALER_DIV64, - /** RTC input clock frequency is prescaled by a factor of 128. */ - RTC_CALENDAR_PRESCALER_DIV_128 = RTC_MODE2_CTRLA_PRESCALER_DIV128, - /** RTC input clock frequency is prescaled by a factor of 256. */ - RTC_CALENDAR_PRESCALER_DIV_256 = RTC_MODE2_CTRLA_PRESCALER_DIV256, - /** RTC input clock frequency is prescaled by a factor of 512. */ - RTC_CALENDAR_PRESCALER_DIV_512 = RTC_MODE2_CTRLA_PRESCALER_DIV512, - /** RTC input clock frequency is prescaled by a factor of 1024. */ - RTC_CALENDAR_PRESCALER_DIV_1024 = RTC_MODE2_CTRLA_PRESCALER_DIV1024, -}; - -#else -/** - * \brief RTC input clock prescaler settings. - * - * The available input clock prescaler values for the RTC calendar module. - */ -enum rtc_calendar_prescaler { - /** RTC input clock frequency is prescaled by a factor of 1. */ - RTC_CALENDAR_PRESCALER_DIV_1 = RTC_MODE2_CTRL_PRESCALER_DIV1, - /** RTC input clock frequency is prescaled by a factor of 2. */ - RTC_CALENDAR_PRESCALER_DIV_2 = RTC_MODE2_CTRL_PRESCALER_DIV2, - /** RTC input clock frequency is prescaled by a factor of 4. */ - RTC_CALENDAR_PRESCALER_DIV_4 = RTC_MODE2_CTRL_PRESCALER_DIV4, - /** RTC input clock frequency is prescaled by a factor of 8. */ - RTC_CALENDAR_PRESCALER_DIV_8 = RTC_MODE2_CTRL_PRESCALER_DIV8, - /** RTC input clock frequency is prescaled by a factor of 16. */ - RTC_CALENDAR_PRESCALER_DIV_16 = RTC_MODE2_CTRL_PRESCALER_DIV16, - /** RTC input clock frequency is prescaled by a factor of 32. */ - RTC_CALENDAR_PRESCALER_DIV_32 = RTC_MODE2_CTRL_PRESCALER_DIV32, - /** RTC input clock frequency is prescaled by a factor of 64. */ - RTC_CALENDAR_PRESCALER_DIV_64 = RTC_MODE2_CTRL_PRESCALER_DIV64, - /** RTC input clock frequency is prescaled by a factor of 128. */ - RTC_CALENDAR_PRESCALER_DIV_128 = RTC_MODE2_CTRL_PRESCALER_DIV128, - /** RTC input clock frequency is prescaled by a factor of 256. */ - RTC_CALENDAR_PRESCALER_DIV_256 = RTC_MODE2_CTRL_PRESCALER_DIV256, - /** RTC input clock frequency is prescaled by a factor of 512. */ - RTC_CALENDAR_PRESCALER_DIV_512 = RTC_MODE2_CTRL_PRESCALER_DIV512, - /** RTC input clock frequency is prescaled by a factor of 1024. */ - RTC_CALENDAR_PRESCALER_DIV_1024 = RTC_MODE2_CTRL_PRESCALER_DIV1024, -}; -#endif - -#if !defined(__DOXYGEN__) -/** - * \brief Device structure. - */ -struct rtc_module { - /** RTC hardware module. */ - Rtc *hw; - /** If clock mode 24h. */ - bool clock_24h; -#ifdef FEATURE_RTC_CONTINUOUSLY_UPDATED - /** If continuously update clock register. */ - bool continuously_update; -#endif - /** Initial year for counter value 0. */ - uint16_t year_init_value; -# if RTC_CALENDAR_ASYNC == true - /** Pointers to callback functions. */ - volatile rtc_calendar_callback_t callbacks[_RTC_CALENDAR_CALLBACK_N]; - /** Mask for registered callbacks. */ - volatile uint16_t registered_callback; - /** Mask for enabled callbacks. */ - volatile uint16_t enabled_callback; -# endif -}; -#endif - -/** - * \brief Available mask options for alarms. - * - * Available mask options for alarms. - */ -enum rtc_calendar_alarm_mask { - /** Alarm disabled. */ - RTC_CALENDAR_ALARM_MASK_DISABLED = RTC_MODE2_MASK_SEL_OFF, - /** Alarm match on second. */ - RTC_CALENDAR_ALARM_MASK_SEC = RTC_MODE2_MASK_SEL_SS, - /** Alarm match on second and minute. */ - RTC_CALENDAR_ALARM_MASK_MIN = RTC_MODE2_MASK_SEL_MMSS, - /** Alarm match on second, minute, and hour. */ - RTC_CALENDAR_ALARM_MASK_HOUR = RTC_MODE2_MASK_SEL_HHMMSS, - /** Alarm match on second, minute, hour, and day. */ - RTC_CALENDAR_ALARM_MASK_DAY = RTC_MODE2_MASK_SEL_DDHHMMSS, - /** Alarm match on second, minute, hour, day, and month. */ - RTC_CALENDAR_ALARM_MASK_MONTH = RTC_MODE2_MASK_SEL_MMDDHHMMSS, - /** Alarm match on second, minute, hour, day, month, and year. */ - RTC_CALENDAR_ALARM_MASK_YEAR = RTC_MODE2_MASK_SEL_YYMMDDHHMMSS, -}; - -/** - * \brief RTC Calendar event enable/disable structure. - * - * Event flags for the \ref rtc_calendar_enable_events() and - * \ref rtc_calendar_disable_events(). - */ -struct rtc_calendar_events { - /** Generate an output event on each overflow of the RTC count. */ - bool generate_event_on_overflow; - /** Generate an output event on a alarm channel match against the RTC - * count. */ - bool generate_event_on_alarm[RTC_NUM_OF_ALARMS]; - /** Generate an output event periodically at a binary division of the RTC - * counter frequency. - */ - bool generate_event_on_periodic[8]; -}; - -/** - * \brief Time structure. - * - * Time structure containing the time given by or set to the RTC calendar. - * The structure uses seven values to give second, minute, hour, PM/AM, day, - * month, and year. It should be initialized via the - * \ref rtc_calendar_get_time_defaults() function before use. - */ -struct rtc_calendar_time { - /** Second value. */ - uint8_t second; - /** Minute value. */ - uint8_t minute; - /** Hour value. */ - uint8_t hour; - /** PM/AM value, \c true for PM, or \c false for AM. */ - bool pm; - /** Day value, where day 1 is the first day of the month. */ - uint8_t day; - /** Month value, where month 1 is January. */ - uint8_t month; - /** Year value.*/ - uint16_t year; -}; - -/** - * \brief Alarm structure. - * - * Alarm structure containing time of the alarm and a mask to determine when - * the alarm will trigger. - */ -struct rtc_calendar_alarm_time { - /** Alarm time. */ - struct rtc_calendar_time time; - /** Alarm mask to determine on what precision the alarm will match. */ - enum rtc_calendar_alarm_mask mask; -}; - -/** - * \brief RTC configuration structure. - * - * Configuration structure for the RTC instance. This structure should - * be initialized using the \ref rtc_calendar_get_config_defaults() before any - * user configurations are set. - */ -struct rtc_calendar_config { - /** Input clock prescaler for the RTC module. */ - enum rtc_calendar_prescaler prescaler; - /** If \c true, clears the clock on alarm match. */ - bool clear_on_match; -#ifdef FEATURE_RTC_CONTINUOUSLY_UPDATED - /** If \c true, the digital counter registers will be continuously updated - * so that internal synchronization is not needed when reading the current - * count. */ - bool continuously_update; -#endif - /** If \c true, time is represented in 24 hour mode. */ - bool clock_24h; - /** Initial year for counter value 0. */ - uint16_t year_init_value; - /** Alarm values. */ - struct rtc_calendar_alarm_time alarm[RTC_NUM_OF_ALARMS]; -}; - - -/** - * \name Configuration and Initialization - * @{ - */ - -/** - * \brief Initialize a \c time structure. - * - * This will initialize a given time structure to the time 00:00:00 (hh:mm:ss) - * and date 2000-01-01 (YYYY-MM-DD). - * - * \param[out] time Time structure to initialize - */ -static inline void rtc_calendar_get_time_defaults( - struct rtc_calendar_time *const time) -{ - time->second = 0; - time->minute = 0; - time->hour = 0; - time->pm = 0; - time->day = 1; - time->month = 1; - time->year = 2000; -} - -/** - * \brief Gets the RTC default settings. - * - * Initializes the configuration structure to the known default values. This - * function should be called at the start of any RTC initiation. - * - * The default configuration is as follows: - * - Input clock divided by a factor of 1024 - * - Clear on alarm match off - * - Continuously sync clock off - * - 12 hour calendar - * - Start year 2000 (Year 0 in the counter will be year 2000) - * - Events off - * - Alarms set to January 1. 2000, 00:00:00 - * - Alarm will match on second, minute, hour, day, month, and year - * - * \param[out] config Configuration structure to be initialized to default - * values. - */ -static inline void rtc_calendar_get_config_defaults( - struct rtc_calendar_config *const config) -{ - /* Sanity check argument */ - Assert(config); - - /* Initialize and set time structure to default. */ - struct rtc_calendar_time time; - rtc_calendar_get_time_defaults(&time); - - /* Set defaults into configuration structure */ - config->prescaler = RTC_CALENDAR_PRESCALER_DIV_1024; - config->clear_on_match = false; -#ifdef FEATURE_RTC_CONTINUOUSLY_UPDATED - config->continuously_update = false; -#endif - config->clock_24h = false; - config->year_init_value = 2000; - for (uint8_t i = 0; i < RTC_NUM_OF_ALARMS; i++) { - config->alarm[i].time = time; - config->alarm[i].mask = RTC_CALENDAR_ALARM_MASK_YEAR; - } -} - -void rtc_calendar_reset(struct rtc_module *const module); -void rtc_calendar_enable(struct rtc_module *const module); -void rtc_calendar_disable(struct rtc_module *const module); - -#if (RTC_INST_NUM > 1) && !defined(__DOXYGEN__) -/** - * \internal Find the index of given RTC module instance. - * - * \param[in] hw RTC module instance pointer - * - * \return Index of the given RTC module instance. - */ -uint8_t _rtc_get_inst_index( - Rtc *const hw) -{ - /* List of available RTC modules. */ - static Rtc *const rtc_modules[RTC_INST_NUM] = RTC_INSTS; - - /* Find index for RTC instance. */ - for (uint32_t i = 0; i < RTC_INST_NUM; i++) { - if (hw == rtc_modules[i]) { - return i; - } - } - - /* Invalid data given. */ - Assert(false); - return 0; -} -#endif /* (RTC_INST_NUM > 1) && !defined(__DOXYGEN__) */ - -void rtc_calendar_init( - struct rtc_module *const module, - Rtc *const hw, - const struct rtc_calendar_config *const config); - -void rtc_calendar_swap_time_mode(struct rtc_module *const module); - -enum status_code rtc_calendar_frequency_correction( - struct rtc_module *const module, - const int8_t value); - -/** @} */ - - -/** \name Time and Alarm Management - * @{ - */ - -void rtc_calendar_set_time( - struct rtc_module *const module, - const struct rtc_calendar_time *const time); - -void rtc_calendar_get_time( - struct rtc_module *const module, - struct rtc_calendar_time *const time); - -enum status_code rtc_calendar_set_alarm( - struct rtc_module *const module, - const struct rtc_calendar_alarm_time *const alarm, - const enum rtc_calendar_alarm alarm_index); - -enum status_code rtc_calendar_get_alarm( - struct rtc_module *const module, - struct rtc_calendar_alarm_time *const alarm, - const enum rtc_calendar_alarm alarm_index); - -/** @} */ - - -/** \name Status Flag Management - * @{ - */ - -/** - * \brief Check if an RTC overflow has occurred. - * - * Checks the overflow flag in the RTC. The flag is set when there - * is an overflow in the clock. - * - * \param[in,out] module Pointer to the software instance struct - * - * \return Overflow state of the RTC module. - * - * \retval true If the RTC count value has overflowed - * \retval false If the RTC count value has not overflowed - */ -static inline bool rtc_calendar_is_overflow(struct rtc_module *const module) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - /* Return status of flag. */ - return (rtc_module->MODE2.INTFLAG.reg & RTC_MODE2_INTFLAG_OVF); -} - -/** - * \brief Clears the RTC overflow flag. - * - * \param[in,out] module Pointer to the software instance struct - * - * Clears the RTC module counter overflow flag, so that new overflow conditions - * can be detected. - */ -static inline void rtc_calendar_clear_overflow(struct rtc_module *const module) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - /* Clear flag. */ - rtc_module->MODE2.INTFLAG.reg = RTC_MODE2_INTFLAG_OVF; -} - -/** - * \brief Check the RTC alarm flag. - * - * Check if the specified alarm flag is set. The flag is set when there - * is an compare match between the alarm value and the clock. - * - * \param[in,out] module Pointer to the software instance struct - * \param[in] alarm_index Index of the alarm to check - * - * \returns Match status of the specified alarm. - * - * \retval true If the specified alarm has matched the current time - * \retval false If the specified alarm has not matched the current time - */ -static inline bool rtc_calendar_is_alarm_match( - struct rtc_module *const module, - const enum rtc_calendar_alarm alarm_index) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - /* Sanity check. */ - if ((uint32_t)alarm_index > RTC_NUM_OF_ALARMS) { - Assert(false); - return false; - } - - /* Return int flag status. */ - return (rtc_module->MODE2.INTFLAG.reg & RTC_MODE2_INTFLAG_ALARM(1 << alarm_index)); -} - -/** - * \brief Clears the RTC alarm match flag. - * - * Clear the requested alarm match flag, so that future alarm matches can be - * determined. - * - * \param[in,out] module Pointer to the software instance struct - * \param[in] alarm_index The index of the alarm match to clear - * - * \return Status of the alarm match clear operation. - * - * \retval STATUS_OK If flag was cleared correctly - * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided - */ -static inline enum status_code rtc_calendar_clear_alarm_match( - struct rtc_module *const module, - const enum rtc_calendar_alarm alarm_index) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - /* Sanity check. */ - if ((uint32_t)alarm_index > RTC_NUM_OF_ALARMS) { - Assert(false); - return STATUS_ERR_INVALID_ARG; - } - - /* Clear flag. */ - rtc_module->MODE2.INTFLAG.reg = RTC_MODE2_INTFLAG_ALARM(1 << alarm_index); - - return STATUS_OK; -} - -/** @} */ - - -/** - * \name Event Management - * @{ - */ - -/** - * \brief Enables a RTC event output. - * - * Enables one or more output events from the RTC module. See - * \ref rtc_calendar_events for a list of events this module supports. - * - * \note Events cannot be altered while the module is enabled. - * - * \param[in,out] module Pointer to the software instance struct - * \param[in] events Struct containing flags of events to enable - */ -static inline void rtc_calendar_enable_events( - struct rtc_module *const module, - struct rtc_calendar_events *const events) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - uint32_t event_mask = 0; - - /* Check if the user has requested an overflow event. */ - if (events->generate_event_on_overflow) { - event_mask |= RTC_MODE2_EVCTRL_OVFEO; - } - - /* Check if the user has requested any alarm events. */ - for (uint8_t i = 0; i < RTC_NUM_OF_ALARMS; i++) { - if (events->generate_event_on_alarm[i]) { - event_mask |= RTC_MODE2_EVCTRL_ALARMEO(1 << i); - } - } - - /* Check if the user has requested any periodic events. */ - for (uint8_t i = 0; i < 8; i++) { - if (events->generate_event_on_periodic[i]) { - event_mask |= RTC_MODE2_EVCTRL_PEREO(1 << i); - } - } - - /* Enable given event(s). */ - rtc_module->MODE2.EVCTRL.reg |= event_mask; -} - -/** - * \brief Disables a RTC event output. - * - * Disabled one or more output events from the RTC module. See - * \ref rtc_calendar_events for a list of events this module supports. - * - * \note Events cannot be altered while the module is enabled. - * - * \param[in,out] module Pointer to the software instance struct - * \param[in] events Struct containing flags of events to disable - */ -static inline void rtc_calendar_disable_events( - struct rtc_module *const module, - struct rtc_calendar_events *const events) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - uint32_t event_mask = 0; - - /* Check if the user has requested an overflow event. */ - if (events->generate_event_on_overflow) { - event_mask |= RTC_MODE2_EVCTRL_OVFEO; - } - - /* Check if the user has requested any alarm events. */ - for (uint8_t i = 0; i < RTC_NUM_OF_ALARMS; i++) { - if (events->generate_event_on_alarm[i]) { - event_mask |= RTC_MODE2_EVCTRL_ALARMEO(1 << i); - } - } - - /* Check if the user has requested any periodic events. */ - for (uint8_t i = 0; i < 8; i++) { - if (events->generate_event_on_periodic[i]) { - event_mask |= RTC_MODE2_EVCTRL_PEREO(1 << i); - } - } - - /* Disable given event(s). */ - rtc_module->MODE2.EVCTRL.reg &= ~event_mask; -} - -/** @} */ - -#ifdef FEATURE_RTC_GENERAL_PURPOSE_REG -/** - * \name RTC General Purpose Registers - * @{ - */ - -/** - * \brief Write a value into general purpose register. - * - * \param[in] module Pointer to the software instance struct - * \param[in] n General purpose type - * \param[in] index General purpose register index (0..3) - * - */ -static inline void rtc_write_general_purpose_reg( - struct rtc_module *const module, - const uint8_t index, - uint32_t value) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - Assert(index <= 3); - - Rtc *const rtc_module = module->hw; - - rtc_module->MODE0.GP[index].reg = value; -} - -/** - * \brief Read the value from general purpose register. - * - * \param[in] module Pointer to the software instance struct - * \param[in] index General purpose register index (0..3) - * - * \retval Value of general purpose register - */ -static inline uint32_t rtc_read_general_purpose_reg( - struct rtc_module *const module, - const uint8_t index) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - Assert(index <= 3); - - Rtc *const rtc_module = module->hw; - - return rtc_module->MODE0.GP[index].reg; -} - -/** @} */ -#endif - -/** @} */ - -#ifdef __cplusplus -} -#endif - - -/** - * \page asfdoc_sam0_rtc_calendar_extra Extra Information for RTC (CAL) Driver - * - * \section asfdoc_sam0_rtc_calendar_extra_acronyms Acronyms - * Below is a table listing the acronyms used in this module, along with their - * intended meanings. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Acronym - * Description - *
RTCReal Time Counter
PPMPart Per Million
RCResistor/Capacitor
- * - * - * \section asfdoc_sam0_rtc_calendar_extra_dependencies Dependencies - * This driver has the following dependencies: - * - * - None - * - * - * \section asfdoc_sam0_rtc_calendar_extra_errata Errata - * There are no errata related to this driver. - * - * - * \section asfdoc_sam0_rtc_calendar_extra_history Module History - * An overview of the module history is presented in the table below, with - * details on the enhancements and fixes made to the module since its first - * release. The current version of this corresponds to the newest version in - * the table. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Changelog
Added support for SAML21.
- * Added support for SAMD21 and added driver instance parameter to all - * API function calls, except get_config_defaults - *
Updated initialization function to also enable the digital interface - * clock to the module if it is disabled
Initial Release
- */ - -/** - * \page asfdoc_sam0_rtc_calendar_exqsg Examples for RTC CAL Driver - * - * This is a list of the available Quick Start guides (QSGs) and example - * applications for \ref asfdoc_sam0_rtc_calendar_group. QSGs are simple - * examples with step-by-step instructions to configure and use this driver in a - * selection of use cases. Note that QSGs can be compiled as a standalone - * application or be added to the user application. - * - * - \subpage asfdoc_sam0_rtc_calendar_basic_use_case - * \if RTC_CALENDAR_CALLBACK_MODE - * - \subpage asfdoc_sam0_rtc_calendar_callback_use_case - * \endif - * - * \page asfdoc_sam0_rtc_calendar_document_revision_history Document Revision History - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Doc. Rev. - * Date - * Comments - *
E11/2014Added support for SAML21.
D12/2014Added support for SAMR21 and SAMD10/D11.
C01/2014Added support for SAMD21.
B06/2013Added additional documentation on the event system. Corrected - * documentation typos.
A06/2013Initial release
- */ - -#endif /* RTC_CALENDAR_H_INCLUDED */ - diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_count.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_count.h new file mode 100644 index 0000000000..bcbeb461f1 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_count.h @@ -0,0 +1,1201 @@ +/** + * \file + * + * \brief SAM RTC Driver (Count Mode) + * + * 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 + * + */ + /** + * Support and FAQ: visit Atmel Support + */ + +#ifndef RTC_COUNT_H_INCLUDED +#define RTC_COUNT_H_INCLUDED + +/** + * \defgroup asfdoc_sam0_rtc_count_group SAM RTC Count Driver (RTC COUNT) + * + * This driver for Atmel庐 | SMART SAM devices provides an interface for the configuration + * and management of the device's Real Time Clock functionality in Count + * operating mode, for the configuration and retrieval of the current RTC + * counter value. The following driver API modes are covered by this + * manual: + * + * - Polled APIs + * \if RTC_COUNT_CALLBACK_MODE + * - Callback APIs + * \endif + * + * The following peripherals are used by this module: + * - RTC (Real Time Clock) + * + * The following devices can use this module: + * - Atmel | SMART SAM D20/D21 + * - Atmel | SMART SAM R21 + * - Atmel | SMART SAM D10/D11 + * - Atmel | SMART SAM L21 + * + * The outline of this documentation is as follows: + * - \ref asfdoc_sam0_rtc_count_prerequisites + * - \ref asfdoc_sam0_rtc_count_module_overview + * - \ref asfdoc_sam0_rtc_count_special_considerations + * - \ref asfdoc_sam0_rtc_count_extra_info + * - \ref asfdoc_sam0_rtc_count_examples + * - \ref asfdoc_sam0_rtc_count_api_overview + * + * + * \section asfdoc_sam0_rtc_count_prerequisites Prerequisites + * + * There are no prerequisites for this module. + * + * + * \section asfdoc_sam0_rtc_count_module_overview Module Overview + * + * The RTC module in the SAM devices is a 32-bit counter, with a 10-bit + * programmable prescaler. Typically, the RTC clock is run continuously, + * including in the device's low-power sleep modes, to track the current time + * and date information. The RTC can be used as a source to wake up the system + * at a scheduled time or periodically using the alarm functions. + * + * In this driver, the RTC is operated in Count mode. This allows for an + * easy integration of an asynchronous counter into a user application, which is + * capable of operating while the device is in sleep mode. + * + * Whilst operating in Count mode, the RTC features: + * - 16-bit counter mode + * - Selectable counter period + * - Up to six configurable compare values + * - 32-bit counter mode + * - Clear counter value on match + * - Up to four configurable compare values + * + * \subsection asfdoc_sam0_rtc_count_features Driver Feature Macro Definition + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Driver Feature MacroSupported devices
FEATURE_RTC_PERIODIC_INTSAML21
FEATURE_RTC_PRESCALER_OFFSAML21
FEATURE_RTC_CLOCK_SELECTIONSAML21
FEATURE_RTC_GENERAL_PURPOSE_REGSAML21
FEATURE_RTC_CONTINUOUSLY_UPDATEDSAMD20,SAMD21,SAMR21,SAMD10,SAMD11
+ * \note The specific features are only available in the driver when the + * selected device supports those features. + * + * \section asfdoc_sam0_rtc_count_module_overview_compares Compare and Overflow + * The RTC can be used with up to 4/6 compare values (depending on selected + * operation mode). These compare values will trigger on match with the current + * RTC counter value, and can be set up to trigger an interrupt, event, or both. + * The RTC can also be configured to clear the counter value on compare match + * in 32-bit mode, resetting the count value back to zero. + * + * If the RTC is operated without the Clear on Match option enabled, or in + * 16-bit mode, the RTC counter value will instead be cleared on overflow once + * the maximum count value has been reached: + * + * \f[ COUNT_{MAX} = 2^{32}-1 \f] for 32-bit counter mode, and + * \f[ COUNT_{MAX} = 2^{16}-1 \f] for 16-bit counter mode. + * + * When running in 16-bit mode, the overflow value is selectable with a period + * value. The counter overflow will then occur when the counter value reaches + * the specified period value. + * + * \subsection asfdoc_sam0_rtc_count_module_overview_periodic Periodic Events + * The RTC can generate events at periodic intervals, allowing for direct + * peripheral actions without CPU intervention. The periodic events can be + * generated on the upper eight bits of the RTC prescaler, and will be generated on + * the rising edge transition of the specified bit. The resulting periodic + * frequency can be calculated by the following formula: + * + * \f[ f_{PERIODIC}=\frac{f_{ASY}}{2^{n+3}} \f] + * + * Where \f$f_{ASY}\f$ refers to the \e asynchronous clock set up in the RTC + * module configuration. The \b n parameter is the event source generator index + * of the RTC module. If the asynchronous clock is operated at the recommended + * frequency of 1KHz, the formula results in the values shown in + * \ref asfdoc_sam0_rtc_count_module_rtc_hz "the table below". + * + * \anchor asfdoc_sam0_rtc_count_module_rtc_hz + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
RTC Event Frequencies for Each Prescaler Bit Using a 1KHz Clock
n Periodic event
7 1Hz
6 2Hz
5 4Hz
4 8Hz
3 16Hz
2 32Hz
1 64Hz
0 128Hz
+ * + * \note The connection of events between modules requires the use of the + * \ref asfdoc_sam0_events_group "SAM Event System Driver (EVENTS)" + * to route output event of one module to the the input event of another. + * For more information on event routing, refer to the event driver + * documentation. + * + * \subsection asfdoc_sam0_rtc_count_module_overview_correction Digital Frequency Correction + * The RTC module contains Digital Frequency Correction logic to compensate for + * inaccurate source clock frequencies which would otherwise result in skewed + * time measurements. The correction scheme requires that at least two bits + * in the RTC module prescaler are reserved by the correction logic. As a + * result of this implementation, frequency correction is only available when + * the RTC is running from a 1Hz reference clock. + * + * The correction procedure is implemented by subtracting or adding a single + * cycle from the RTC prescaler every 1024 RTC GCLK cycles. The adjustment is + * applied the specified number of time (maximum 127) over 976 of these periods. The + * corresponding correction in PPM will be given by: + * + * \f[ Correction(PPM) = \frac{VALUE}{999424}10^6 \f] + * + * The RTC clock will tick faster if provided with a positive correction value, + * and slower when given a negative correction value. + * + * + * \section asfdoc_sam0_rtc_count_special_considerations Special Considerations + * + * \subsection asfdoc_sam0_rtc_count_special_considerations_clock Clock Setup + * \subsubsection asfdoc_sam0_rtc_count_clock_samd_r SAM D20/D21/R21/D10/D11 Clock Setup + * The RTC is typically clocked by a specialized GCLK generator that has a + * smaller prescaler than the others. By default the RTC clock is on, selected + * to use the internal 32KHz RC-oscillator with a prescaler of 32, giving a + * resulting clock frequency of 1KHz to the RTC. When the internal RTC + * prescaler is set to 1024, this yields an end-frequency of 1Hz. + * + * The implementer also has the option to set other end-frequencies. + * \ref asfdoc_sam0_rtc_count_rtc_out_freq "The table below" lists the + * available RTC frequencies for each possible GCLK and RTC input prescaler + * options. + * + * \anchor asfdoc_sam0_rtc_count_rtc_out_freq + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
RTC Output Frequencies from Allowable Input Clocks
End-frequencyGCLK prescalerRTC prescaler
32KHz11
1KHz321
1Hz321024
+ * + * The overall RTC module clocking scheme is shown in + * \ref asfdoc_sam0_rtc_count_rtc_clock_fig "the figure below". + * + * \anchor asfdoc_sam0_rtc_count_rtc_clock_fig + * \dot + * digraph clocking_scheme { + * rankdir=LR; + * GCLK [shape="record", label=" GCLK | RTC_GCLK", + * bgcolor="lightgray", style="filled"]; + * RTCPRE [shape="record" label=" RTC | RTC PRESCALER"]; + * RTC [shape="record", label=" RTC | RTC CLOCK"]; + * + * GCLK:f1 -> RTCPRE:f1; + * RTCPRE:f1 -> RTC:f1; + * } + * \enddot + * + * \subsubsection asfdoc_sam0_rtc_count_clock_saml SAM L21 Clock Setup + * The RTC clock can be selected from OSC32K,XOSC32K or OSCULP32K , and a 32KHz + * or 1KHz oscillator clock frequency is required. This clock must be + * configured and enabled in the 32KHz oscillator controller before using the RTC. + * + * The table below lists the available RTC clock \ref asfdoc_sam0_rtc_count_rtc_clk + * + * \anchor asfdoc_sam0_rtc_count_rtc_clk + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
RTC clocks source
RTC clock frequencyClock sourceDescription
1.024KHzULP1K1.024KHz from 32KHz internal ULP oscillator
32.768KHzULP32K32.768KHz from 32KHz internal ULP oscillator
1.024KHzOSC1K1.024KHz from 32KHz internal oscillator
32.768KHzOSC32K32.768KHz from 32KHz internal oscillator
1.024KHzXOSC1K1.024KHz from 32KHz internal oscillator
32.768KHzXOSC32K32.768KHz from 32KHz external crystal oscillator
+ * + * \section asfdoc_sam0_rtc_count_extra_info Extra Information + * + * For extra information, see \ref asfdoc_sam0_rtc_count_extra. This includes: + * - \ref asfdoc_sam0_rtc_count_extra_acronyms + * - \ref asfdoc_sam0_rtc_count_extra_dependencies + * - \ref asfdoc_sam0_rtc_count_extra_errata + * - \ref asfdoc_sam0_rtc_count_extra_history + * + * + * \section asfdoc_sam0_rtc_count_examples Examples + * + * For a list of examples related to this driver, see + * \ref asfdoc_sam0_rtc_count_exqsg. + * + * + * \section asfdoc_sam0_rtc_count_api_overview API Overview + * @{ + */ + +#include +#include + +#if RTC_COUNT_ASYNC == true +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Define port features set according to different device family + * @{ +*/ +#if (SAML21) || defined(__DOXYGEN__) +/** RTC periodic interval interrupt. */ +# define FEATURE_RTC_PERIODIC_INT +/** RTC prescaler is off. */ +# define FEATURE_RTC_PRESCALER_OFF +/** RTC clock selection. */ +# define FEATURE_RTC_CLOCK_SELECTION +/** General purpose registers. */ +# define FEATURE_RTC_GENERAL_PURPOSE_REG +#else +/** RTC continuously updated. */ +# define FEATURE_RTC_CONTINUOUSLY_UPDATED +#endif +/*@}*/ + +#ifdef FEATURE_RTC_CLOCK_SELECTION +/** + * \brief Available clock source for RTC. + * RTC clock source. + */ +enum rtc_clock_sel { + /** 1.024KHz from 32KHz internal ULP oscillator. */ + RTC_CLOCK_SELECTION_ULP1K = OSC32KCTRL_RTCCTRL_RTCSEL_ULP1K_Val, + /** 32.768KHz from 32KHz internal ULP oscillator. */ + RTC_CLOCK_SELECTION_ULP32K = OSC32KCTRL_RTCCTRL_RTCSEL_ULP32K_Val, + /** 1.024KHz from 32KHz internal oscillator. */ + RTC_CLOCK_SELECTION_OSC1K = OSC32KCTRL_RTCCTRL_RTCSEL_OSC1K_Val, + /** 32.768KHz from 32KHz internal oscillator. */ + RTC_CLOCK_SELECTION_OSC32K = OSC32KCTRL_RTCCTRL_RTCSEL_OSC32K_Val, + /** 1.024KHz from 32KHz internal oscillator. */ + RTC_CLOCK_SELECTION_XOSC1K = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC1K_Val, + /** 32.768KHz from 32.768KHz external crystal oscillator. */ + RTC_CLOCK_SELECTION_XOSC32K = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC32K_Val, +}; +#endif + +/** + * \brief Available operation modes for the RTC. + * + * RTC Count operating modes, to select the counting width and associated module + * operation. + */ +enum rtc_count_mode { + /** RTC Count module operates in 16-bit mode. */ + RTC_COUNT_MODE_16BIT = 0, + /** RTC Count module operates in 32-bit mode. */ + RTC_COUNT_MODE_32BIT = 1, +}; + +#if !defined (RTC_NUM_OF_COMP16) && defined(RTC_COMP16_NUM) +#define RTC_NUM_OF_COMP16 RTC_COMP16_NUM +#endif + +/** + * \brief Available compare channels. + * + * \note Not all compare channels are available in all devices and modes. + */ +enum rtc_count_compare { + /** Compare channel 0. */ + RTC_COUNT_COMPARE_0 = 0, +#if (RTC_NUM_OF_COMP16 > 1) || defined(__DOXYGEN__) + /** Compare channel 1. */ + RTC_COUNT_COMPARE_1 = 1, +#endif +#if (RTC_NUM_OF_COMP16 > 2) || defined(__DOXYGEN__) + /** Compare channel 2. */ + RTC_COUNT_COMPARE_2 = 2, +#endif +#if (RTC_NUM_OF_COMP16 > 3) || defined(__DOXYGEN__) + /** Compare channel 3. */ + RTC_COUNT_COMPARE_3 = 3, +#endif +#if (RTC_NUM_OF_COMP16 > 4) || defined(__DOXYGEN__) + /** Compare channel 4. */ + RTC_COUNT_COMPARE_4 = 4, +#endif +#if (RTC_NUM_OF_COMP16 > 5) || defined(__DOXYGEN__) + /** Compare channel 5. */ + RTC_COUNT_COMPARE_5 = 5, +#endif +}; + +#ifdef FEATURE_RTC_PERIODIC_INT +/** + * \brief Available periodic interval source. + */ +enum rtc_count_periodic_interval{ + /** Periodic interval 0 */ + RTC_COUNT_PERIODIC_INTERVAL_0 = 0, + /** Periodic interval 1 */ + RTC_COUNT_PERIODIC_INTERVAL_1 = 1, + /** Periodic interval 2 */ + RTC_COUNT_PERIODIC_INTERVAL_2 = 2, + /** Periodic interval 3 */ + RTC_COUNT_PERIODIC_INTERVAL_3 = 3, + /** Periodic interval 4 */ + RTC_COUNT_PERIODIC_INTERVAL_4 = 4, + /** Periodic interval 5 */ + RTC_COUNT_PERIODIC_INTERVAL_5 = 5, + /** Periodic interval 6 */ + RTC_COUNT_PERIODIC_INTERVAL_6 = 6, + /** Periodic interval 7 */ + RTC_COUNT_PERIODIC_INTERVAL_7 = 7, +}; +#endif + +#if RTC_COUNT_ASYNC == true +#ifdef FEATURE_RTC_PERIODIC_INT +/** + * \brief Callback types. + * + * The available callback types for the RTC count module. + */ +enum rtc_count_callback { + /** Callback for Periodic Interval 0 Interrupt. */ + RTC_COUNT_CALLBACK_PERIODIC_INTERVAL_0 = 0, + /** Callback for Periodic Interval 1 Interrupt. */ + RTC_COUNT_CALLBACK_PERIODIC_INTERVAL_1, + /** Callback for Periodic Interval 2 Interrupt. */ + RTC_COUNT_CALLBACK_PERIODIC_INTERVAL_2, + /** Callback for Periodic Interval 3 Interrupt. */ + RTC_COUNT_CALLBACK_PERIODIC_INTERVAL_3, + /** Callback for Periodic Interval 4 Interrupt. */ + RTC_COUNT_CALLBACK_PERIODIC_INTERVAL_4, + /** Callback for Periodic Interval 5 Interrupt. */ + RTC_COUNT_CALLBACK_PERIODIC_INTERVAL_5, + /** Callback for Periodic Interval 6 Interrupt. */ + RTC_COUNT_CALLBACK_PERIODIC_INTERVAL_6, + /** Callback for Periodic Interval 7 Interrupt. */ + RTC_COUNT_CALLBACK_PERIODIC_INTERVAL_7, + /** Callback for compare channel 0. */ + RTC_COUNT_CALLBACK_COMPARE_0, +# if (RTC_NUM_OF_COMP16 > 1) || defined(__DOXYGEN__) + /** Callback for compare channel 1. */ + RTC_COUNT_CALLBACK_COMPARE_1, +# endif +# if (RTC_NUM_OF_COMP16 > 2) || defined(__DOXYGEN__) + /** Callback for compare channel 2. */ + RTC_COUNT_CALLBACK_COMPARE_2, +# endif +# if (RTC_NUM_OF_COMP16 > 3) || defined(__DOXYGEN__) + /** Callback for compare channel 3. */ + RTC_COUNT_CALLBACK_COMPARE_3, +# endif +# if (RTC_NUM_OF_COMP16 > 4) || defined(__DOXYGEN__) + /** Callback for compare channel 4. */ + RTC_COUNT_CALLBACK_COMPARE_4, +# endif +# if (RTC_NUM_OF_COMP16 > 5) || defined(__DOXYGEN__) + /** Callback for compare channel 5. */ + RTC_COUNT_CALLBACK_COMPARE_5, +# endif + + /** Callback for overflow. */ + RTC_COUNT_CALLBACK_OVERFLOW, +# if !defined(__DOXYGEN__) + /** Total number of callbacks. */ + _RTC_COUNT_CALLBACK_N +# endif +}; +#else +/** + * \brief Callback types. + * + * The available callback types for the RTC count module. + */ +enum rtc_count_callback { + /** Callback for compare channel 0. */ + RTC_COUNT_CALLBACK_COMPARE_0 = 0, +# if (RTC_NUM_OF_COMP16 > 1) || defined(__DOXYGEN__) + /** Callback for compare channel 1. */ + RTC_COUNT_CALLBACK_COMPARE_1, +# endif +# if (RTC_NUM_OF_COMP16 > 2) || defined(__DOXYGEN__) + /** Callback for compare channel 2. */ + RTC_COUNT_CALLBACK_COMPARE_2, +# endif +# if (RTC_NUM_OF_COMP16 > 3) || defined(__DOXYGEN__) + /** Callback for compare channel 3. */ + RTC_COUNT_CALLBACK_COMPARE_3, +# endif +# if (RTC_NUM_OF_COMP16 > 4) || defined(__DOXYGEN__) + /** Callback for compare channel 4. */ + RTC_COUNT_CALLBACK_COMPARE_4, +# endif +# if (RTC_NUM_OF_COMP16 > 5) || defined(__DOXYGEN__) + /** Callback for compare channel 5. */ + RTC_COUNT_CALLBACK_COMPARE_5, +# endif + /** Callback for overflow. */ + RTC_COUNT_CALLBACK_OVERFLOW, +# if !defined(__DOXYGEN__) + /** Total number of callbacks. */ + _RTC_COUNT_CALLBACK_N +# endif +}; +#endif + +# if !defined(__DOXYGEN__) +typedef void (*rtc_count_callback_t)(void); +# endif +#endif + +#ifdef FEATURE_RTC_PRESCALER_OFF +/** + * \brief RTC input clock prescaler settings. + * + * The available input clock prescaler values for the RTC count module. + */ +enum rtc_count_prescaler { + /** RTC prescaler is off, and the input clock frequency is + prescaled by a factor of 1. */ + RTC_COUNT_PRESCALER_OFF = RTC_MODE0_CTRLA_PRESCALER_OFF, + /** RTC input clock frequency is prescaled by a factor of 1. */ + RTC_COUNT_PRESCALER_DIV_1 = RTC_MODE0_CTRLA_PRESCALER_DIV1, + /** RTC input clock frequency is prescaled by a factor of 2. */ + RTC_COUNT_PRESCALER_DIV_2 = RTC_MODE0_CTRLA_PRESCALER_DIV2, + /** RTC input clock frequency is prescaled by a factor of 4. */ + RTC_COUNT_PRESCALER_DIV_4 = RTC_MODE0_CTRLA_PRESCALER_DIV4, + /** RTC input clock frequency is prescaled by a factor of 8. */ + RTC_COUNT_PRESCALER_DIV_8 = RTC_MODE0_CTRLA_PRESCALER_DIV8, + /** RTC input clock frequency is prescaled by a factor of 16. */ + RTC_COUNT_PRESCALER_DIV_16 = RTC_MODE0_CTRLA_PRESCALER_DIV16, + /** RTC input clock frequency is prescaled by a factor of 32. */ + RTC_COUNT_PRESCALER_DIV_32 = RTC_MODE0_CTRLA_PRESCALER_DIV32, + /** RTC input clock frequency is prescaled by a factor of 64. */ + RTC_COUNT_PRESCALER_DIV_64 = RTC_MODE0_CTRLA_PRESCALER_DIV64, + /** RTC input clock frequency is prescaled by a factor of 128. */ + RTC_COUNT_PRESCALER_DIV_128 = RTC_MODE0_CTRLA_PRESCALER_DIV128, + /** RTC input clock frequency is prescaled by a factor of 256. */ + RTC_COUNT_PRESCALER_DIV_256 = RTC_MODE0_CTRLA_PRESCALER_DIV256, + /** RTC input clock frequency is prescaled by a factor of 512. */ + RTC_COUNT_PRESCALER_DIV_512 = RTC_MODE0_CTRLA_PRESCALER_DIV512, + /** RTC input clock frequency is prescaled by a factor of 1024. */ + RTC_COUNT_PRESCALER_DIV_1024 = RTC_MODE0_CTRLA_PRESCALER_DIV1024, +}; +#else +/** + * \brief RTC input clock prescaler settings. + * + * The available input clock prescaler values for the RTC count module. + */ +enum rtc_count_prescaler { + /** RTC input clock frequency is prescaled by a factor of 1. */ + RTC_COUNT_PRESCALER_DIV_1 = RTC_MODE0_CTRL_PRESCALER_DIV1, + /** RTC input clock frequency is prescaled by a factor of 2. */ + RTC_COUNT_PRESCALER_DIV_2 = RTC_MODE0_CTRL_PRESCALER_DIV2, + /** RTC input clock frequency is prescaled by a factor of 4. */ + RTC_COUNT_PRESCALER_DIV_4 = RTC_MODE0_CTRL_PRESCALER_DIV4, + /** RTC input clock frequency is prescaled by a factor of 8. */ + RTC_COUNT_PRESCALER_DIV_8 = RTC_MODE0_CTRL_PRESCALER_DIV8, + /** RTC input clock frequency is prescaled by a factor of 16. */ + RTC_COUNT_PRESCALER_DIV_16 = RTC_MODE0_CTRL_PRESCALER_DIV16, + /** RTC input clock frequency is prescaled by a factor of 32. */ + RTC_COUNT_PRESCALER_DIV_32 = RTC_MODE0_CTRL_PRESCALER_DIV32, + /** RTC input clock frequency is prescaled by a factor of 64. */ + RTC_COUNT_PRESCALER_DIV_64 = RTC_MODE0_CTRL_PRESCALER_DIV64, + /** RTC input clock frequency is prescaled by a factor of 128. */ + RTC_COUNT_PRESCALER_DIV_128 = RTC_MODE0_CTRL_PRESCALER_DIV128, + /** RTC input clock frequency is prescaled by a factor of 256. */ + RTC_COUNT_PRESCALER_DIV_256 = RTC_MODE0_CTRL_PRESCALER_DIV256, + /** RTC input clock frequency is prescaled by a factor of 512. */ + RTC_COUNT_PRESCALER_DIV_512 = RTC_MODE0_CTRL_PRESCALER_DIV512, + /** RTC input clock frequency is prescaled by a factor of 1024. */ + RTC_COUNT_PRESCALER_DIV_1024 = RTC_MODE0_CTRL_PRESCALER_DIV1024, +}; +#endif + +/** + * \brief RTC Count event enable/disable structure. + * + * Event flags for the \ref rtc_count_enable_events() and + * \ref rtc_count_disable_events(). + */ +struct rtc_count_events { + /** Generate an output event on each overflow of the RTC count. */ + bool generate_event_on_overflow; + /** Generate an output event on a compare channel match against the RTC + * count. */ + bool generate_event_on_compare[RTC_NUM_OF_COMP16]; + /** Generate an output event periodically at a binary division of the RTC + * counter frequency. */ + bool generate_event_on_periodic[8]; +}; + +#if !defined(__DOXYGEN__) +/** + * \brief Device structure. + */ +struct rtc_module { + /** RTC hardware module. */ + Rtc *hw; + /** Operation mode of count. */ + enum rtc_count_mode mode; +#ifdef FEATURE_RTC_CONTINUOUSLY_UPDATED + /** Set if counter value should be continuously updated. */ + bool continuously_update; +#endif +# if RTC_COUNT_ASYNC == true + /** Pointers to callback functions. */ + volatile rtc_count_callback_t callbacks[_RTC_COUNT_CALLBACK_N]; + /** Mask for registered callbacks. */ + volatile uint16_t registered_callback; + /** Mask for enabled callbacks. */ + volatile uint16_t enabled_callback; +# endif +}; +#endif + +/** + * \brief RTC Count configuration structure. + * + * Configuration structure for the RTC instance. This structure should + * be initialized using the \ref rtc_count_get_config_defaults() before any + * user configurations are set. + */ +struct rtc_count_config { + /** Input clock prescaler for the RTC module. */ + enum rtc_count_prescaler prescaler; + /** Select the operation mode of the RTC.*/ + enum rtc_count_mode mode; + /** If true, clears the counter value on compare match. Only available + * whilst running in 32-bit mode. */ + bool clear_on_match; +#ifdef FEATURE_RTC_CONTINUOUSLY_UPDATED + /** Continuously update the counter value so no synchronization is + * needed for reading. */ + bool continuously_update; +#endif + /** Array of Compare values. Not all Compare values are available in 32-bit + * mode. */ + uint32_t compare_values[RTC_NUM_OF_COMP16]; +}; + + +/** + * \name Configuration and Initialization + * @{ + */ + +/** + * \brief Gets the RTC default configurations. + * + * Initializes the configuration structure to default values. This + * function should be called at the start of any RTC initialization. + * + * The default configuration is as follows: + * - Input clock divided by a factor of 1024 + * - RTC in 32-bit mode + * - Clear on compare match off + * - Continuously sync count register off + * - No event source on + * - All compare values equal 0 + * + * \param[out] config Configuration structure to be initialized to default + * values. + */ +static inline void rtc_count_get_config_defaults( + struct rtc_count_config *const config) +{ + /* Sanity check argument */ + Assert(config); + + /* Set default into configuration structure */ + config->prescaler = RTC_COUNT_PRESCALER_DIV_1024; + config->mode = RTC_COUNT_MODE_32BIT; + config->clear_on_match = false; + +#ifdef FEATURE_RTC_CONTINUOUSLY_UPDATED + config->continuously_update = false; +#endif + + for (uint8_t i = 0; i < RTC_NUM_OF_COMP16; i++) { + config->compare_values[i] = 0; + } +} + +void rtc_count_reset(struct rtc_module *const module); +void rtc_count_enable(struct rtc_module *const module); +void rtc_count_disable(struct rtc_module *const module); + +#if (RTC_INST_NUM > 1) && !defined(__DOXYGEN__) +/** + * \internal Find the index of given RTC module instance. + * + * \param[in] RTC module instance pointer + * + * \return Index of the given AC module instance. + */ +uint8_t _rtc_get_inst_index( + Rtc *const hw) +{ + /* List of available RTC modules. */ + static Rtc *const rtc_modules[RTC_INST_NUM] = RTC_INSTS; + + /* Find index for RTC instance. */ + for (uint32_t i = 0; i < RTC_INST_NUM; i++) { + if (hw == rtc_modules[i]) { + return i; + } + } + + /* Invalid data given. */ + Assert(false); + return 0; +} +#endif /* (RTC_INST_NUM > 1) && !defined(__DOXYGEN__) */ + +enum status_code rtc_count_init( + struct rtc_module *const module, + Rtc *const hw, + const struct rtc_count_config *const config); + +enum status_code rtc_count_frequency_correction( + struct rtc_module *const module, + const int8_t value); + +/** @} */ + +/** \name Count and Compare Value Management + * @{ + */ +enum status_code rtc_count_set_count( + struct rtc_module *const module, + const uint32_t count_value); + +uint32_t rtc_count_get_count(struct rtc_module *const module); + +enum status_code rtc_count_set_compare( + struct rtc_module *const module, + const uint32_t comp_value, + const enum rtc_count_compare comp_index); + +enum status_code rtc_count_get_compare( + struct rtc_module *const module, + uint32_t *const comp_value, + const enum rtc_count_compare comp_index); + +enum status_code rtc_count_set_period( + struct rtc_module *const module, + uint16_t period_value); + +enum status_code rtc_count_get_period( + struct rtc_module *const module, + uint16_t *const period_value); + +/** @} */ + + +/** \name Status Management + * @{ + */ + +/** + * \brief Check if an RTC overflow has occurred. + * + * Checks the overflow flag in the RTC. The flag is set when there + * is an overflow in the clock. + * + * \param[in,out] module RTC hardware module + * + * \return Overflow state of the RTC module. + * + * \retval true If the RTC count value has overflowed + * \retval false If the RTC count value has not overflowed + */ + +static inline bool rtc_count_is_overflow(struct rtc_module *const module) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + /* Return status of flag */ + return (rtc_module->MODE0.INTFLAG.reg & RTC_MODE0_INTFLAG_OVF); +} + +/** + * \brief Clears the RTC overflow flag. + * + * Clears the RTC module counter overflow flag, so that new overflow conditions + * can be detected. + * + * \param[in,out] module RTC hardware module + */ +static inline void rtc_count_clear_overflow(struct rtc_module *const module) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + /* Clear OVF flag */ + rtc_module->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_OVF; +} + +#ifdef FEATURE_RTC_PERIODIC_INT +/** + * \brief Check if an RTC periodic interval interrupt has occurred. + * + * Checks the periodic interval flag in the RTC. + * + * \param[in,out] module RTC hardware module + * \param[in] n RTC periodic interval interrupt + * + * \return periodic interval interrupt state of the RTC module. + * + * \retval true RTC periodic interval interrupt occurs + * \retval false RTC periodic interval interrupt dosen't occurs + */ +static inline bool rtc_count_is_periodic_interval(struct rtc_module *const module, + enum rtc_count_periodic_interval n) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + /* Return status of flag */ + return (rtc_module->MODE0.INTFLAG.reg & RTC_MODE0_INTFLAG_PER(1 << n)); +} + +/** + * \brief Clears the RTC periodic interval flag. + * + * Clears the RTC module counter periodic interval flag, so that new periodic + * interval conditions can be detected. + * + * \param[in,out] module RTC hardware module + * \param[in] n RTC periodic interval interrupt + */ +static inline void rtc_count_clear_periodic_interval(struct rtc_module *const module, + enum rtc_count_periodic_interval n) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + /* Clear periodic interval flag */ + rtc_module->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_PER(1 << n); +} +#endif +bool rtc_count_is_compare_match( + struct rtc_module *const module, + const enum rtc_count_compare comp_index); + +enum status_code rtc_count_clear_compare_match( + struct rtc_module *const module, + const enum rtc_count_compare comp_index); + +/** @} */ + + +/** + * \name Event Management + * @{ + */ + +/** + * \brief Enables a RTC event output. + * + * Enables one or more output events from the RTC module. See + * \ref rtc_count_events for a list of events this module supports. + * + * \note Events cannot be altered while the module is enabled. + * + * \param[in,out] module RTC hardware module + * \param[in] events Struct containing flags of events to enable + */ +static inline void rtc_count_enable_events( + struct rtc_module *const module, + struct rtc_count_events *const events) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + uint32_t event_mask = 0; + + /* Check if the user has requested an overflow event. */ + if (events->generate_event_on_overflow) { + event_mask |= RTC_MODE0_EVCTRL_OVFEO; + } + + /* Check if the user has requested any compare events. */ + for (uint8_t i = 0; i < RTC_NUM_OF_COMP16; i++) { + if (events->generate_event_on_compare[i]) { + event_mask |= RTC_MODE0_EVCTRL_CMPEO(1 << i); + } + } + + /* Check if the user has requested any periodic events. */ + for (uint8_t i = 0; i < 8; i++) { + if (events->generate_event_on_periodic[i]) { + event_mask |= RTC_MODE0_EVCTRL_PEREO(1 << i); + } + } + + /* Enable given event(s). */ + rtc_module->MODE0.EVCTRL.reg |= event_mask; +} + +/** + * \brief Disables a RTC event output. + * + * Disabled one or more output events from the RTC module. See + * \ref rtc_count_events for a list of events this module supports. + * + * \note Events cannot be altered while the module is enabled. + * + * \param[in,out] module RTC hardware module + * \param[in] events Struct containing flags of events to disable + */ +static inline void rtc_count_disable_events( + struct rtc_module *const module, + struct rtc_count_events *const events) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + uint32_t event_mask = 0; + + /* Check if the user has requested an overflow event. */ + if (events->generate_event_on_overflow) { + event_mask |= RTC_MODE0_EVCTRL_OVFEO; + } + + /* Check if the user has requested any compare events. */ + for (uint8_t i = 0; i < RTC_NUM_OF_COMP16; i++) { + if (events->generate_event_on_compare[i]) { + event_mask |= RTC_MODE0_EVCTRL_CMPEO(1 << i); + } + } + + /* Check if the user has requested any periodic events. */ + for (uint8_t i = 0; i < 8; i++) { + if (events->generate_event_on_periodic[i]) { + event_mask |= RTC_MODE0_EVCTRL_PEREO(1 << i); + } + } + + /* Disable given event(s). */ + rtc_module->MODE0.EVCTRL.reg &= ~event_mask; +} + +/** @} */ + +#ifdef FEATURE_RTC_GENERAL_PURPOSE_REG +/** + * \name RTC General Purpose Registers + * @{ + */ + +/** + * \brief Write a value into general purpose register. + * + * \param[in] module Pointer to the software instance struct + * \param[in] n General purpose type + * \param[in] index General purpose register index (0..3) + * + */ +static inline void rtc_write_general_purpose_reg( + struct rtc_module *const module, + const uint8_t index, + uint32_t value) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + Assert(index <= 3); + + Rtc *const rtc_module = module->hw; + + rtc_module->MODE0.GP[index].reg = value; +} + +/** + * \brief Read the value from general purpose register. + * + * \param[in] module Pointer to the software instance struct + * \param[in] index General purpose register index (0..3) + * + * \retval Value of general purpose register + */ +static inline uint32_t rtc_read_general_purpose_reg( + struct rtc_module *const module, + const uint8_t index) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + Assert(index <= 3); + + Rtc *const rtc_module = module->hw; + + return rtc_module->MODE0.GP[index].reg; +} + +/** @} */ +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +/** + * \page asfdoc_sam0_rtc_count_extra Extra Information for RTC COUNT Driver + * + * \section asfdoc_sam0_rtc_count_extra_acronyms Acronyms + * Below is a table listing the acronyms used in this module, along with their + * intended meanings. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Acronym + * Description + *
RTCReal Time Counter
PPMPart Per Million
RCResistor/Capacitor
+ * + * + * \section asfdoc_sam0_rtc_count_extra_dependencies Dependencies + * This driver has the following dependencies: + * + * - None + * + * + * \section asfdoc_sam0_rtc_count_extra_errata Errata + * There are no errata related to this driver. + * + * + * \section asfdoc_sam0_rtc_count_extra_history Module History + * An overview of the module history is presented in the table below, with + * details on the enhancements and fixes made to the module since its first + * release. The current version of this corresponds to the newest version in + * the table. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Changelog
Added support for SAML21
+ * Added support for SAMD21 and added driver instance parameter to all + * API function calls, except get_config_defaults + *
Updated initialization function to also enable the digital interface + * clock to the module if it is disabled
Initial Release
+ */ + +/** + * \page asfdoc_sam0_rtc_count_exqsg Examples for RTC (COUNT) Driver + * + * This is a list of the available Quick Start guides (QSGs) and example + * applications for \ref asfdoc_sam0_rtc_count_group. QSGs are simple + * examples with step-by-step instructions to configure and use this driver in a + * selection of use cases. Note that QSGs can be compiled as a standalone + * application or be added to the user application. + * + * - \subpage asfdoc_sam0_rtc_count_basic_use_case + * \if RTC_COUNT_CALLBACK_MODE + * - \subpage asfdoc_sam0_rtc_count_callback_use_case + * \endif + * + * \page asfdoc_sam0_rtc_count_document_revision_history Document Revision History + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Doc. Rev. + * Date + * Comments + *
E11/2014Added support for SAML21.
D12/2014Added support for SAMR21 and SAMD10/D11.
C01/2014Added support for SAMD21.
B06/2013Added additional documentation on the event system. Corrected + * documentation typos.
A06/2013Initial release
+ */ + +#endif /* RTC_COUNT_H_INCLUDED */ diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_sam_d_r/rtc_calendar.c b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_sam_d_r/rtc_calendar.c deleted file mode 100644 index 6f1377e238..0000000000 --- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_sam_d_r/rtc_calendar.c +++ /dev/null @@ -1,653 +0,0 @@ -/** - * \file - * - * \brief SAM RTC Driver (Calendar Mode) - * - * 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 - * - */ -/** -* Support and FAQ: visit Atmel Support -*/ -#include "rtc_calendar.h" -#include - -#if !defined(__DOXYGEN__) -struct rtc_module *_rtc_instance[RTC_INST_NUM]; -#endif - -/** - * \brief Determines if the hardware module(s) are currently synchronizing to the bus. - * - * Checks to see if the underlying hardware peripheral module(s) are currently - * synchronizing across multiple clock domains to the hardware bus, This - * function can be used to delay further operations on a module until such time - * that it is ready, to prevent blocking delays for synchronization in the - * user application. - * - * \param[in] module RTC hardware module - * - * \return Synchronization status of the underlying hardware module(s). - * - * \retval true if the module has completed synchronization - * \retval false if the module synchronization is ongoing - */ -static inline bool rtc_calendar_is_syncing(struct rtc_module *const module) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - if (rtc_module->MODE2.STATUS.reg & RTC_STATUS_SYNCBUSY) { - return true; - } - - return false; -} - -/** - * \brief Enables the RTC module. - * - * Enables the RTC module once it has been configured, ready for use. Most - * module configuration parameters cannot be altered while the module is enabled. - * - * \param[in,out] module Pointer to the software instance struct - */ -void rtc_calendar_enable(struct rtc_module *const module) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - -#if RTC_CALENDAR_ASYNC == true - system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_RTC); -#endif - - while (rtc_calendar_is_syncing(module)) { - /* Wait for synchronization */ - } - - /* Enable RTC module. */ - rtc_module->MODE2.CTRL.reg |= RTC_MODE2_CTRL_ENABLE; -} - -/** - * \brief Disables the RTC module. - * - * Disables the RTC module. - * - * \param[in,out] module Pointer to the software instance struct - */ -void rtc_calendar_disable(struct rtc_module *const module) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - -#if RTC_CALENDAR_ASYNC == true - system_interrupt_disable(SYSTEM_INTERRUPT_MODULE_RTC); -#endif - - while (rtc_calendar_is_syncing(module)) { - /* Wait for synchronization */ - } - - /* Disable RTC module. */ - rtc_module->MODE2.CTRL.reg &= ~RTC_MODE2_CTRL_ENABLE; -} - -/** - * \brief Resets the RTC module - * Resets the RTC module to hardware defaults. - * - * \param[in,out] module Pointer to the software instance struct - */ -void rtc_calendar_reset(struct rtc_module *const module) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - /* Disable module before reset. */ - rtc_calendar_disable(module); - -#if RTC_CALENDAR_ASYNC == true - module->registered_callback = 0; - module->enabled_callback = 0; -#endif - - while (rtc_calendar_is_syncing(module)) { - /* Wait for synchronization */ - } - - /* Initiate software reset. */ - rtc_module->MODE2.CTRL.reg |= RTC_MODE2_CTRL_SWRST; -} - -/** - * \internal Convert time structure to register_value. - */ -static uint32_t _rtc_calendar_time_to_register_value( - struct rtc_module *const module, - const struct rtc_calendar_time *const time) -{ - /* Initialize return value. */ - uint32_t register_value; - - /* Set year value into register_value minus initial year. */ - register_value = (time->year - module->year_init_value) << - RTC_MODE2_CLOCK_YEAR_Pos; - - /* Set month value into register_value. */ - register_value |= (time->month << RTC_MODE2_CLOCK_MONTH_Pos); - - /* Set day value into register_value. */ - register_value |= (time->day << RTC_MODE2_CLOCK_DAY_Pos); - - /* Set 24 hour value into register_value. */ - register_value |= (time->hour << RTC_MODE2_CLOCK_HOUR_Pos); - - /* Check if 24 h clock and set pm flag. */ - if (!(module->clock_24h) && (time->pm)) { - /* Set pm flag. */ - register_value |= RTC_MODE2_CLOCK_HOUR_PM; - } - - /* Set minute value into register_value. */ - register_value |= (time->minute << RTC_MODE2_CLOCK_MINUTE_Pos); - - /* Set second value into register_value. */ - register_value |= (time->second << RTC_MODE2_CLOCK_SECOND_Pos); - - return register_value; -} - -/** - * \internal Convert register_value to time structure. - */ -static void _rtc_calendar_register_value_to_time( - struct rtc_module *const module, - const uint32_t register_value, - struct rtc_calendar_time *const time) -{ - /* Set year plus value of initial year. */ - time->year = ((register_value & RTC_MODE2_CLOCK_YEAR_Msk) >> - RTC_MODE2_CLOCK_YEAR_Pos) + module->year_init_value; - - /* Set month value into time struct. */ - time->month = ((register_value & RTC_MODE2_CLOCK_MONTH_Msk) >> - RTC_MODE2_CLOCK_MONTH_Pos); - - /* Set day value into time struct. */ - time->day = ((register_value & RTC_MODE2_CLOCK_DAY_Msk) >> - RTC_MODE2_CLOCK_DAY_Pos); - - if (module->clock_24h) { - /* Set hour in 24h mode. */ - time->hour = ((register_value & RTC_MODE2_CLOCK_HOUR_Msk) >> - RTC_MODE2_CLOCK_HOUR_Pos); - } else { - /* Set hour in 12h mode. */ - time->hour = ((register_value & - (RTC_MODE2_CLOCK_HOUR_Msk & ~RTC_MODE2_CLOCK_HOUR_PM)) >> - RTC_MODE2_CLOCK_HOUR_Pos); - - /* Set pm flag */ - time->pm = ((register_value & RTC_MODE2_CLOCK_HOUR_PM) != 0); - } - - /* Set minute value into time struct. */ - time->minute = ((register_value & RTC_MODE2_CLOCK_MINUTE_Msk) >> - RTC_MODE2_CLOCK_MINUTE_Pos); - - /* Set second value into time struct. */ - time->second = ((register_value & RTC_MODE2_CLOCK_SECOND_Msk) >> - RTC_MODE2_CLOCK_SECOND_Pos); -} - -/** - * \internal Applies the given configuration. - * - * Set the configurations given from the configuration structure to the - * hardware module. - * - * \param[in,out] module Pointer to the software instance struct - * \param[in] config Pointer to the configuration structure. - */ -static void _rtc_calendar_set_config( - struct rtc_module *const module, - const struct rtc_calendar_config *const config) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - /* Set up temporary register value. */ - uint16_t tmp_reg; - - /* Set to calendar mode and set the prescaler. */ - tmp_reg = RTC_MODE2_CTRL_MODE(2) | config->prescaler; - - /* Check clock mode. */ - if (!(config->clock_24h)) { - /* Set clock mode 12h. */ - tmp_reg |= RTC_MODE2_CTRL_CLKREP; - } - - /* Check for clear on compare match. */ - if (config->clear_on_match) { - /* Set clear on compare match. */ - tmp_reg |= RTC_MODE2_CTRL_MATCHCLR; - } - - /* Set temporary value to register. */ - rtc_module->MODE2.CTRL.reg = tmp_reg; - - /* Check to set continuously clock read update mode. */ - if (config->continuously_update) { - /* Set continuously mode. */ - rtc_module->MODE2.READREQ.reg |= RTC_READREQ_RCONT; - } - - /* Set alarm time registers. */ - for (uint8_t i = 0; i < RTC_NUM_OF_ALARMS; i++) { - rtc_calendar_set_alarm(module, &(config->alarm[i]), (enum rtc_calendar_alarm)i); - } -} - -/** - * \brief Initializes the RTC module with given configurations. - * - * Initializes the module, setting up all given configurations to provide - * the desired functionality of the RTC. - * - * \param[out] module Pointer to the software instance struct - * \param[in] hw Pointer to hardware instance - * \param[in] config Pointer to the configuration structure. - */ -void rtc_calendar_init( - struct rtc_module *const module, - Rtc *const hw, - const struct rtc_calendar_config *const config) -{ - /* Sanity check arguments */ - Assert(module); - Assert(hw); - Assert(config); - - /* Initialize device instance */ - module->hw = hw; - - /* Turn on the digital interface clock */ - system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBA, PM_APBAMASK_RTC); - - /* Set up GCLK */ - struct system_gclk_chan_config gclk_chan_conf; - system_gclk_chan_get_config_defaults(&gclk_chan_conf); - gclk_chan_conf.source_generator = GCLK_GENERATOR_2; - system_gclk_chan_set_config(RTC_GCLK_ID, &gclk_chan_conf); - system_gclk_chan_enable(RTC_GCLK_ID); - - /* Reset module to hardware defaults. */ - rtc_calendar_reset(module); - - /* Save conf_struct internally for continued use. */ - module->clock_24h = config->clock_24h; - module->continuously_update = config->continuously_update; - module->year_init_value = config->year_init_value; - -#if (RTC_INST_NUM == 1) - _rtc_instance[0] = module; -#else - /* Register this instance for callbacks*/ - _rtc_instance[_rtc_get_inst_index(hw)] = module; -#endif - - /* Set config. */ - _rtc_calendar_set_config(module, config); -} - -/** - * \brief Swaps between 12h and 24h clock mode. - * - * Swaps the current RTC time mode: - * - If currently in 12h mode, it will swap to 24h - * - If currently in 24h mode, it will swap to 12h - * - * \note This will not change setting in user's configuration structure. - * - * \param[in, out] module Pointer to the software instance struct - */ -void rtc_calendar_swap_time_mode(struct rtc_module *const module) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - /* Initialize time structure. */ - struct rtc_calendar_time time; - struct rtc_calendar_alarm_time alarm; - - /* Get current time. */ - rtc_calendar_get_time(module, &time); - - /* Check current mode. */ - if (module->clock_24h) { - /* Set pm flag. */ - time.pm = (uint8_t)(time.hour / 12); - - /* Set 12h clock hour value. */ - time.hour = time.hour % 12; - if (time.hour == 0) { - time.hour = 12; - } - - /* Update alarms */ - for (uint8_t i = 0; i < RTC_NUM_OF_ALARMS; i++) { - rtc_calendar_get_alarm(module, &alarm, (enum rtc_calendar_alarm)i); - alarm.time.pm = (uint8_t)(alarm.time.hour / 12); - alarm.time.hour = alarm.time.hour % 12; - if (alarm.time.hour == 0) { - alarm.time.hour = 12; - } - module->clock_24h = false; - rtc_calendar_set_alarm(module, &alarm, (enum rtc_calendar_alarm)i); - module->clock_24h = true; - } - - /* Change value in configuration structure. */ - module->clock_24h = false; - } else { - /* Set hour value based on pm flag. */ - if (time.pm == 1) { - time.hour = time.hour + 12; - - time.pm = 0; - } else if (time.hour == 12) { - time.hour = 0; - } - - /* Update alarms */ - for (uint8_t i = 0; i < RTC_NUM_OF_ALARMS; i++) { - rtc_calendar_get_alarm(module, &alarm, (enum rtc_calendar_alarm)i); - if (alarm.time.pm == 1) { - alarm.time.hour = alarm.time.hour + 12; - alarm.time.pm = 0; - module->clock_24h = true; - rtc_calendar_set_alarm(module, &alarm, (enum rtc_calendar_alarm)i); - module->clock_24h = false; - } else if (alarm.time.hour == 12) { - alarm.time.hour = 0; - } - } - - /* Change value in configuration structure. */ - module->clock_24h = true; - } - - /* Disable RTC so new configuration can be set. */ - rtc_calendar_disable(module); - - /* Toggle mode. */ - rtc_module->MODE2.CTRL.reg ^= RTC_MODE2_CTRL_CLKREP; - - /* Enable RTC. */ - rtc_calendar_enable(module); - - /* Set new time format in CLOCK register. */ - rtc_calendar_set_time(module, &time); -} - -/** - * \brief Set the current calendar time to desired time. - * - * Sets the time provided to the calendar. - * - * \param[in, out] module Pointer to the software instance struct - * \param[in] time The time to set in the calendar. - */ -void rtc_calendar_set_time( - struct rtc_module *const module, - const struct rtc_calendar_time *const time) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - uint32_t register_value = _rtc_calendar_time_to_register_value(module, time); - - while (rtc_calendar_is_syncing(module)) { - /* Wait for synchronization */ - } - - /* Write value to register. */ - rtc_module->MODE2.CLOCK.reg = register_value; -} - -/** - * \brief Get the current calendar value. - * - * Retrieves the current time of the calendar. - * - * \param[in, out] module Pointer to the software instance struct - * \param[out] time Pointer to value that will be filled with current time. - */ -void rtc_calendar_get_time( - struct rtc_module *const module, - struct rtc_calendar_time *const time) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - /* Change of read method based on value of continuously_update value in - * the configuration structure. */ - if (!(module->continuously_update)) { - /* Request read on CLOCK register. */ - rtc_module->MODE2.READREQ.reg = RTC_READREQ_RREQ; - - while (rtc_calendar_is_syncing(module)) { - /* Wait for synchronization */ - } - } - - /* Read value. */ - uint32_t register_value = rtc_module->MODE2.CLOCK.reg; - - /* Convert value to time structure. */ - _rtc_calendar_register_value_to_time(module, register_value, time); -} - -/** - * \brief Set the alarm time for the specified alarm. - * - * Sets the time and mask specified to the requested alarm. - * - * \param[in, out] module Pointer to the software instance struct - * \param[in] alarm The alarm struct to set the alarm with. - * \param[in] alarm_index The index of the alarm to set. - * - * \return Status of setting alarm. - * \retval STATUS_OK If alarm was set correctly. - * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided. - */ -enum status_code rtc_calendar_set_alarm( - struct rtc_module *const module, - const struct rtc_calendar_alarm_time *const alarm, - const enum rtc_calendar_alarm alarm_index) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - /* Sanity check. */ - if ((uint32_t)alarm_index > RTC_NUM_OF_ALARMS) { - return STATUS_ERR_INVALID_ARG; - } - - /* Get register_value from time. */ - uint32_t register_value = _rtc_calendar_time_to_register_value(module, &(alarm->time)); - - while (rtc_calendar_is_syncing(module)) { - /* Wait for synchronization */ - } - - /* Set alarm value. */ - rtc_module->MODE2.Mode2Alarm[alarm_index].ALARM.reg = register_value; - - /* Set alarm mask */ - rtc_module->MODE2.Mode2Alarm[alarm_index].MASK.reg = alarm->mask; - - return STATUS_OK; -} - -/** - * \brief Get the current alarm time of specified alarm. - * - * Retrieves the current alarm time for the alarm specified. - * - * \param[in, out] module Pointer to the software instance struct - * \param[out] alarm Pointer to the struct that will be filled with alarm - * time and mask of the specified alarm. - * \param[in] alarm_index Index of alarm to get alarm time from. - * - * \return Status of getting alarm. - * \retval STATUS_OK If alarm was read correctly. - * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided. - */ -enum status_code rtc_calendar_get_alarm( - struct rtc_module *const module, - struct rtc_calendar_alarm_time *const alarm, - const enum rtc_calendar_alarm alarm_index) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - /* Sanity check. */ - if ((uint32_t)alarm_index > RTC_NUM_OF_ALARMS) { - return STATUS_ERR_INVALID_ARG; - } - - /* Read alarm value. */ - uint32_t register_value = - rtc_module->MODE2.Mode2Alarm[alarm_index].ALARM.reg; - - /* Convert to time structure. */ - _rtc_calendar_register_value_to_time(module, register_value, &(alarm->time)); - - /* Read alarm mask */ - alarm->mask = (enum rtc_calendar_alarm_mask)rtc_module->MODE2.Mode2Alarm[alarm_index].MASK.reg; - - return STATUS_OK; -} - -/** - * \brief Calibrate for too-slow or too-fast oscillator. - * - * When used, the RTC will compensate for an inaccurate oscillator. The - * RTC module will add or subtract cycles from the RTC prescaler to adjust the - * frequency in approximately 1 PPM steps. The provided correction value should - * be between -127 and 127, allowing for a maximum 127 PPM correction in either - * direction. - * - * If no correction is needed, set value to zero. - * - * \note Can only be used when the RTC is operated at 1Hz. - * - * \param[in, out] module Pointer to the software instance struct - * \param[in] value Between -127 and 127 used for the correction. - * - * \return Status of the calibration procedure. - * \retval STATUS_OK If calibration was done correctly. - * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided. - */ -enum status_code rtc_calendar_frequency_correction( - struct rtc_module *const module, - const int8_t value) -{ - /* Sanity check arguments */ - Assert(module); - Assert(module->hw); - - Rtc *const rtc_module = module->hw; - - /* Check if valid argument. */ - if (abs(value) > 0x7F) { - /* Value bigger than allowed, return invalid argument. */ - return STATUS_ERR_INVALID_ARG; - } - - uint32_t new_correction_value; - - /* Load the new correction value as a positive value, sign added later */ - new_correction_value = abs(value); - - /* Convert to positive value and adjust register sign bit. */ - if (value < 0) { - new_correction_value |= RTC_FREQCORR_SIGN; - } - - while (rtc_calendar_is_syncing(module)) { - /* Wait for synchronization */ - } - - /* Set value. */ - rtc_module->MODE2.FREQCORR.reg = new_correction_value; - - return STATUS_OK; -} diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_sam_d_r/rtc_count.c b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_sam_d_r/rtc_count.c new file mode 100644 index 0000000000..81aff76f22 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/rtc/rtc_sam_d_r/rtc_count.c @@ -0,0 +1,773 @@ +/** + * \file + * + * \brief SAM RTC Driver (Count Mode) + * + * 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 + * + */ + /** + * Support and FAQ: visit Atmel Support + */ +#include "rtc_count.h" +#include + +#if !defined(__DOXYGEN__) +struct rtc_module *_rtc_instance[RTC_INST_NUM]; +#endif + +/** + * \brief Determines if the hardware module(s) are currently synchronizing to the bus. + * + * Checks to see if the underlying hardware peripheral module(s) are currently + * synchronizing across multiple clock domains to the hardware bus, This + * function can be used to delay further operations on a module until such time + * that it is ready, to prevent blocking delays for synchronization in the + * user application. + * + * \param[in] module RTC hardware module + * + * \return Synchronization status of the underlying hardware module(s). + * + * \retval true if the module synchronization is ongoing + * \retval false if the module has completed synchronization + */ +static bool rtc_count_is_syncing(struct rtc_module *const module) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + if (rtc_module->MODE0.STATUS.reg & RTC_STATUS_SYNCBUSY) { + return true; + } + + return false; +} + +/** + * \brief Enables the RTC module. + * + * Enables the RTC module once it has been configured, ready for use. Most + * module configuration parameters cannot be altered while the module is enabled. + * + * \param[in,out] module RTC hardware module + */ +void rtc_count_enable(struct rtc_module *const module) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + +#if RTC_COUNT_ASYNC == true + system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_RTC); +#endif + + while (rtc_count_is_syncing(module)) { + /* Wait for synchronization */ + } + + /* Enable RTC module. */ + rtc_module->MODE0.CTRL.reg |= RTC_MODE0_CTRL_ENABLE; +} + +/** + * \brief Disables the RTC module. + * + * Disables the RTC module. + * + * \param[in,out] module RTC hardware module + */ +void rtc_count_disable(struct rtc_module *const module) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + +#if RTC_COUNT_ASYNC == true + system_interrupt_disable(SYSTEM_INTERRUPT_MODULE_RTC); +#endif + + while (rtc_count_is_syncing(module)) { + /* Wait for synchronization */ + } + + /* Disable RTC module. */ + rtc_module->MODE0.CTRL.reg &= ~RTC_MODE0_CTRL_ENABLE; +} + +/** + * \brief Resets the RTC module. + * Resets the RTC to hardware defaults. + * + * \param[in,out] module Pointer to the software instance struct + */ +void rtc_count_reset(struct rtc_module *const module) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + /* Disable module before reset. */ + rtc_count_disable(module); + +#if RTC_COUNT_ASYNC == true + module->registered_callback = 0; + module->enabled_callback = 0; +#endif + + while (rtc_count_is_syncing(module)) { + /* Wait for synchronization */ + } + + /* Initiate software reset. */ + rtc_module->MODE0.CTRL.reg |= RTC_MODE0_CTRL_SWRST; +} + +/** + * \internal Applies the given configuration. + * + * Sets the configurations given from the configuration structure to the + * hardware module. + * + * \param[in,out] module Pointer to the software instance struct + * \param[in] config Pointer to the configuration structure. + * + * \return Status of the configuration procedure. + * \retval STATUS_OK RTC configurations was set successfully. + * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were given. + */ +static enum status_code _rtc_count_set_config( + struct rtc_module *const module, + const struct rtc_count_config *const config) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + rtc_module->MODE0.CTRL.reg = RTC_MODE0_CTRL_MODE(0) | config->prescaler; + + /* Set mode and clear on match if applicable. */ + switch (config->mode) { + case RTC_COUNT_MODE_32BIT: + /* Set 32bit mode and clear on match if applicable. */ + rtc_module->MODE0.CTRL.reg |= RTC_MODE0_CTRL_MODE(0); + + /* Check if clear on compare match should be set. */ + if (config->clear_on_match) { + /* Set clear on match. */ + rtc_module->MODE0.CTRL.reg |= RTC_MODE0_CTRL_MATCHCLR; + } + /* Set compare values. */ + for (uint8_t i = 0; i < RTC_NUM_OF_COMP32; i++) { + while (rtc_count_is_syncing(module)) { + /* Wait for synchronization */ + } + + rtc_count_set_compare(module, config->compare_values[i], + (enum rtc_count_compare)i); + } + break; + + case RTC_COUNT_MODE_16BIT: + /* Set 16bit mode. */ + rtc_module->MODE1.CTRL.reg |= RTC_MODE1_CTRL_MODE(1); + + /* Check if match on clear is set, and return invalid + * argument if set. */ + if (config->clear_on_match) { + Assert(false); + return STATUS_ERR_INVALID_ARG; + } + /* Set compare values. */ + for (uint8_t i = 0; i < RTC_NUM_OF_COMP16; i++) { + while (rtc_count_is_syncing(module)) { + /* Wait for synchronization */ + } + + rtc_count_set_compare(module, config->compare_values[i], + (enum rtc_count_compare)i); + } + break; + default: + Assert(false); + return STATUS_ERR_INVALID_ARG; + } + + /* Check to set continuously clock read update mode. */ + if (config->continuously_update) { + /* Set continuously mode. */ + rtc_module->MODE0.READREQ.reg |= RTC_READREQ_RCONT; + } + + /* Return status OK if everything was configured. */ + return STATUS_OK; +} + +/** + * \brief Initializes the RTC module with given configurations. + * + * Initializes the module, setting up all given configurations to provide + * the desired functionality of the RTC. + * + * \param[out] module Pointer to the software instance struct + * \param[in] hw Pointer to hardware instance + * \param[in] config Pointer to the configuration structure. + * + * \return Status of the initialization procedure. + * \retval STATUS_OK If the initialization was run stressfully. + * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were given. + */ +enum status_code rtc_count_init( + struct rtc_module *const module, + Rtc *const hw, + const struct rtc_count_config *const config) +{ + /* Sanity check arguments */ + Assert(module); + Assert(hw); + Assert(config); + + /* Initialize device instance */ + module->hw = hw; + + /* Turn on the digital interface clock */ + system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBA, PM_APBAMASK_RTC); + + /* Set up GCLK */ + struct system_gclk_chan_config gclk_chan_conf; + system_gclk_chan_get_config_defaults(&gclk_chan_conf); + gclk_chan_conf.source_generator = GCLK_GENERATOR_2; + system_gclk_chan_set_config(RTC_GCLK_ID, &gclk_chan_conf); + system_gclk_chan_enable(RTC_GCLK_ID); + + /* Reset module to hardware defaults. */ + rtc_count_reset(module); + + /* Save conf_struct internally for continued use. */ + module->mode = config->mode; + module->continuously_update = config->continuously_update; + +# if (RTC_INST_NUM == 1) + _rtc_instance[0] = module; +# else + /* Register this instance for callbacks*/ + _rtc_instance[_rtc_get_inst_index(hw)] = module; +# endif + + /* Set config and return status. */ + return _rtc_count_set_config(module, config); +} + +/** + * \brief Set the current count value to desired value. + * + * Sets the value of the counter to the specified value. + * + * \param[in,out] module Pointer to the software instance struct + * \param[in] count_value The value to be set in count register. + * + * \return Status of setting the register. + * \retval STATUS_OK If everything was executed correctly. + * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided. + */ +enum status_code rtc_count_set_count( + struct rtc_module *const module, + const uint32_t count_value) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + while (rtc_count_is_syncing(module)) { + /* Wait for synchronization */ + } + + /* Set count according to mode */ + switch(module->mode){ + case RTC_COUNT_MODE_32BIT: + /* Write value to register. */ + rtc_module->MODE0.COUNT.reg = count_value; + + break; + + case RTC_COUNT_MODE_16BIT: + /* Check if 16-bit value is provided. */ + if(count_value > 0xffff){ + return STATUS_ERR_INVALID_ARG; + } + + /* Write value to register. */ + rtc_module->MODE1.COUNT.reg = (uint32_t)count_value; + + break; + + default: + Assert(false); + return STATUS_ERR_INVALID_ARG; + } + return STATUS_OK; +} + +/** + * \brief Get the current count value. + * + * \param[in,out] module Pointer to the software instance struct + * + * Returns the current count value. + * + * \return The current counter value as a 32-bit unsigned integer. + */ +uint32_t rtc_count_get_count(struct rtc_module *const module) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + /* Initialize return value. */ + uint32_t ret_val; + + /* Change of read method based on value of continuously_update value in + * the configuration structure. */ + if(!(module->continuously_update)) { + /* Request read on count register. */ + rtc_module->MODE0.READREQ.reg = RTC_READREQ_RREQ; + + while (rtc_count_is_syncing(module)) { + /* Wait for synchronization */ + } + } + + /* Read value based on mode. */ + switch (module->mode) { + case RTC_COUNT_MODE_32BIT: + /* Return count value in 32-bit mode. */ + ret_val = rtc_module->MODE0.COUNT.reg; + + break; + + case RTC_COUNT_MODE_16BIT: + /* Return count value in 16-bit mode. */ + ret_val = (uint32_t)rtc_module->MODE1.COUNT.reg; + + break; + + default: + Assert(false); + /* Counter not initialized. Assume counter value 0.*/ + ret_val = 0; + break; + } + + return ret_val; +} + +/** + * \brief Set the compare value for the specified compare. + * + * Sets the value specified by the implementer to the requested compare. + * + * \note Compare 4 and 5 are only available in 16-bit mode. + * + * \param[in,out] module Pointer to the software instance struct + * \param[in] comp_value The value to be written to the compare. + * \param[in] comp_index Index of the compare to set. + * + * \return Status indicating if compare was successfully set. + * \retval STATUS_OK If compare was successfully set. + * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided. + * \retval STATUS_ERR_BAD_FORMAT If the module was not initialized in a mode. + */ +enum status_code rtc_count_set_compare( + struct rtc_module *const module, + const uint32_t comp_value, + const enum rtc_count_compare comp_index) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + while (rtc_count_is_syncing(module)) { + /* Wait for synchronization */ + } + + /* Set compare values based on operation mode. */ + switch (module->mode) { + case RTC_COUNT_MODE_32BIT: + /* Check sanity of comp_index. */ + if ((uint32_t)comp_index > RTC_NUM_OF_COMP32) { + return STATUS_ERR_INVALID_ARG; + } + + /* Set compare value for COMP. */ + rtc_module->MODE0.COMP[comp_index].reg = comp_value; + + break; + + case RTC_COUNT_MODE_16BIT: + /* Check sanity of comp_index. */ + if ((uint32_t)comp_index > RTC_NUM_OF_COMP16) { + return STATUS_ERR_INVALID_ARG; + } + + /* Check that 16-bit value is provided. */ + if (comp_value > 0xffff) { + Assert(false); + return STATUS_ERR_INVALID_ARG; + } + + /* Set compare value for COMP. */ + rtc_module->MODE1.COMP[comp_index].reg = comp_value & 0xffff; + + break; + + default: + Assert(false); + return STATUS_ERR_BAD_FORMAT; + } + + /* Return status if everything is OK. */ + return STATUS_OK; +} + +/** + * \brief Get the current compare value of specified compare. + * + * Retrieves the current value of the specified compare. + * + * \note Compare 4 and 5 are only available in 16-bit mode. + * + * \param[in,out] module Pointer to the software instance struct + * \param[out] comp_value Pointer to 32-bit integer that will be populated with + * the current compare value. + * \param[in] comp_index Index of compare to check. + * + * \return Status of the reading procedure. + * \retval STATUS_OK If the value was read correctly. + * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided. + * \retval STATUS_ERR_BAD_FORMAT If the module was not initialized in a mode. + */ +enum status_code rtc_count_get_compare( + struct rtc_module *const module, + uint32_t *const comp_value, + const enum rtc_count_compare comp_index) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + switch (module->mode) { + case RTC_COUNT_MODE_32BIT: + /* Check sanity of comp_index. */ + if ((uint32_t)comp_index > RTC_NUM_OF_COMP32) { + return STATUS_ERR_INVALID_ARG; + } + + /* Get compare value for COMP. */ + *comp_value = rtc_module->MODE0.COMP[comp_index].reg; + + break; + + case RTC_COUNT_MODE_16BIT: + /* Check sanity of comp_index. */ + if ((uint32_t)comp_index > RTC_NUM_OF_COMP16) { + return STATUS_ERR_INVALID_ARG; + } + + /* Get compare value for COMP. */ + *comp_value = (uint32_t)rtc_module->MODE1.COMP[comp_index].reg; + + break; + + default: + Assert(false); + return STATUS_ERR_BAD_FORMAT; + } + /* Return status showing everything is OK. */ + return STATUS_OK; +} + +/** + * \brief Retrieves the value of period. + * + * Retrieves the value of the period for the 16-bit mode counter. + * + * \note Only available in 16-bit mode. + * + * \param[in,out] module Pointer to the software instance struct + * \param[out] period_value Pointer to value for return argument. + * + * \return Status of getting the period value. + * \retval STATUS_OK If the period value was read correctly. + * \retval STATUS_ERR_UNSUPPORTED_DEV If incorrect mode was set. + */ +enum status_code rtc_count_get_period( + struct rtc_module *const module, + uint16_t *const period_value) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + /* Check that correct mode is set. */ + if (module->mode != RTC_COUNT_MODE_16BIT) { + return STATUS_ERR_UNSUPPORTED_DEV; + } + + /* Returns the value. */ + *period_value = rtc_module->MODE1.PER.reg; + + return STATUS_OK; +} + +/** + * \brief Set the given value to the period. + * + * Sets the given value to the period. + * + * \note Only available in 16-bit mode. + * + * \param[in,out] module Pointer to the software instance struct + * \param[in] period_value The value to set to the period. + * + * \return Status of setting the period value. + * \retval STATUS_OK If the period was set correctly. + * \retval STATUS_ERR_UNSUPPORTED_DEV If module is not operated in 16-bit mode. + */ +enum status_code rtc_count_set_period( + struct rtc_module *const module, + const uint16_t period_value) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + /* Check that correct mode is set. */ + if (module->mode != RTC_COUNT_MODE_16BIT) { + return STATUS_ERR_UNSUPPORTED_DEV; + } + + while (rtc_count_is_syncing(module)) { + /* Wait for synchronization */ + } + + /* Write value to register. */ + rtc_module->MODE1.PER.reg = period_value; + + return STATUS_OK; +} + +/** + * \brief Check if RTC compare match has occurred. + * + * Checks the compare flag to see if a match has occurred. The compare flag is + * set when there is a compare match between counter and the compare. + * + * \note Compare 4 and 5 are only available in 16-bit mode. + * + * \param[in,out] module Pointer to the software instance struct + * \param[in] comp_index Index of compare to check current flag. + */ +bool rtc_count_is_compare_match( + struct rtc_module *const module, + const enum rtc_count_compare comp_index) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + /* Check sanity. */ + switch (module->mode) { + case RTC_COUNT_MODE_32BIT: + /* Check sanity for 32-bit mode. */ + if (comp_index > RTC_NUM_OF_COMP32) { + return false; + } + + break; + + case RTC_COUNT_MODE_16BIT: + /* Check sanity for 16-bit mode. */ + if (comp_index > RTC_NUM_OF_COMP16) { + return false; + } + + break; + + default: + Assert(false); + return false; + } + + /* Set status of INTFLAG as return argument. */ + return (rtc_module->MODE0.INTFLAG.reg & (1 << comp_index)); +} + +/** + * \brief Clears RTC compare match flag. + * + * Clears the compare flag. The compare flag is set when there is a compare + * match between the counter and the compare. + * + * \note Compare 4 and 5 are only available in 16-bit mode. + * + * \param[in,out] module Pointer to the software instance struct + * \param[in] comp_index Index of compare to check current flag. + * + * \return Status indicating if flag was successfully cleared. + * \retval STATUS_OK If flag was successfully cleared. + * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided. + * \retval STATUS_ERR_BAD_FORMAT If the module was not initialized in a mode. + */ +enum status_code rtc_count_clear_compare_match( + struct rtc_module *const module, + const enum rtc_count_compare comp_index) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + /* Check sanity. */ + switch (module->mode){ + case RTC_COUNT_MODE_32BIT: + /* Check sanity for 32-bit mode. */ + if (comp_index > RTC_NUM_OF_COMP32) { + return STATUS_ERR_INVALID_ARG; + } + + break; + + case RTC_COUNT_MODE_16BIT: + /* Check sanity for 16-bit mode. */ + if (comp_index > RTC_NUM_OF_COMP16) { + return STATUS_ERR_INVALID_ARG; + } + + break; + + default: + Assert(false); + return STATUS_ERR_BAD_FORMAT; + } + + /* Clear INTFLAG. */ + rtc_module->MODE0.INTFLAG.reg = RTC_MODE1_INTFLAG_CMP(1 << comp_index); + + return STATUS_OK; +} + +/** + * \brief Calibrate for too-slow or too-fast oscillator. + * + * When used, the RTC will compensate for an inaccurate oscillator. The + * RTC module will add or subtract cycles from the RTC prescaler to adjust the + * frequency in approximately 1 PPM steps. The provided correction value should + * be between 0 and 127, allowing for a maximum 127 PPM correction. + * + * If no correction is needed, set value to zero. + * + * \note Can only be used when the RTC is operated in 1Hz. + * + * \param[in,out] module Pointer to the software instance struct + * \param[in] value Ranging from -127 to 127 used for the correction. + * + * \return Status of the calibration procedure. + * \retval STATUS_OK If calibration was executed correctly. + * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided. + */ +enum status_code rtc_count_frequency_correction( + struct rtc_module *const module, + const int8_t value) +{ + /* Sanity check arguments */ + Assert(module); + Assert(module->hw); + + Rtc *const rtc_module = module->hw; + + /* Check if valid argument. */ + if (abs(value) > 0x7F) { + /* Value bigger than allowed, return invalid argument. */ + return STATUS_ERR_INVALID_ARG; + } + + uint32_t new_correction_value; + + /* Load the new correction value as a positive value, sign added later */ + new_correction_value = abs(value); + + /* Convert to positive value and adjust register sign bit. */ + if (value < 0) { + new_correction_value |= RTC_FREQCORR_SIGN; + } + + while (rtc_count_is_syncing(module)) { + /* Wait for synchronization */ + } + + /* Set value. */ + rtc_module->MODE0.FREQCORR.reg = new_correction_value; + + return STATUS_OK; +} + diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/rtc_api.c b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/rtc_api.c new file mode 100644 index 0000000000..6e47a9bf69 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/rtc_api.c @@ -0,0 +1,114 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "rtc_api.h" + +#include + +#include "cmsis.h" +#include "system.h" + +#include "rtc_count.h" + +/* Global RTC instance*/ +static struct rtc_module rtc_instance; + +static int rtc_inited = 0; + +/* Extern variables */ +extern uint8_t g_sys_init; + +/** Initialize the RTC + * + * Initialize the RTC with default time + * @param[void] void + */ +void rtc_init(void) +{ + if (g_sys_init == 0) { + system_init(); + g_sys_init = 1; + } + + struct rtc_count_config config_rtc_count; + + rtc_count_get_config_defaults(&config_rtc_count); + + config_rtc_count.prescaler = RTC_COUNT_PRESCALER_DIV_1024; + config_rtc_count.mode = RTC_COUNT_MODE_32BIT; +#ifdef FEATURE_RTC_CONTINUOUSLY_UPDATED + config_rtc_count.continuously_update = true; +#endif + + rtc_count_init(&rtc_instance, RTC, &config_rtc_count); + + rtc_count_enable(&rtc_instance); + rtc_inited = 1; +} + +/** Frees the RTC + * + * Not implemented now + * @param[void] void + */ +void rtc_free(void) +{ + rtc_inited = 0; + // [TODO] +} + +/** Checks whether RTC is enabled or not + * + * To check whether RTC module is enabled or not + * @param[void] void + * @return Non zero if RTC is already enabled, else zero + */ +int rtc_isenabled(void) +{ + return rtc_inited; +} + +/** Reads the RTC value + * + * Reads and return the current time in RTC + * @param[void] void + * @return the current value in RTC + */ +time_t rtc_read(void) +{ + if (!rtc_inited) { + /* Return invalid time for now! */ + return 0; + } + return (time_t)rtc_count_get_count(&rtc_instance); +} + +/** Write the RTC value + * + * Update the time value in RTC + * @param[in] t The time value to be written + * @return void + */ +void rtc_write(time_t t) +{ + if (!rtc_inited) { + /* Initialize the RTC is not yet initialized */ + rtc_init(); + } + + uint32_t count_value = (uint32_t)t; + rtc_count_set_count(&rtc_instance, count_value); +} \ No newline at end of file diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/config/conf_clocks.h b/libraries/mbed/targets/hal/TARGET_Atmel/config/conf_clocks.h index 36527870f2..6cf074cb0c 100644 --- a/libraries/mbed/targets/hal/TARGET_Atmel/config/conf_clocks.h +++ b/libraries/mbed/targets/hal/TARGET_Atmel/config/conf_clocks.h @@ -41,8 +41,8 @@ * */ /** -* Support and FAQ: visit Atmel Support -*/ + * Support and FAQ: visit Atmel Support + */ #include #ifndef CONF_CLOCKS_H_INCLUDED @@ -79,13 +79,15 @@ # define CONF_CLOCK_XOSC32K_ON_DEMAND true # define CONF_CLOCK_XOSC32K_RUN_IN_STANDBY false +//! [oscillator_settings] /* SYSTEM_CLOCK_SOURCE_OSC32K configuration - Internal 32KHz oscillator */ -# define CONF_CLOCK_OSC32K_ENABLE false +# define CONF_CLOCK_OSC32K_ENABLE true # define CONF_CLOCK_OSC32K_STARTUP_TIME SYSTEM_OSC32K_STARTUP_130 # define CONF_CLOCK_OSC32K_ENABLE_1KHZ_OUTPUT true # define CONF_CLOCK_OSC32K_ENABLE_32KHZ_OUTPUT true # define CONF_CLOCK_OSC32K_ON_DEMAND true # define CONF_CLOCK_OSC32K_RUN_IN_STANDBY false +//! [oscillator_settings] /* SYSTEM_CLOCK_SOURCE_DFLL configuration - Digital Frequency Locked Loop */ # define CONF_CLOCK_DFLL_ENABLE false @@ -140,12 +142,14 @@ # define CONF_CLOCK_GCLK_1_PRESCALER 1 # define CONF_CLOCK_GCLK_1_OUTPUT_ENABLE false +//! [gclk_settings] /* Configure GCLK generator 2 (RTC) */ -# define CONF_CLOCK_GCLK_2_ENABLE false +# define CONF_CLOCK_GCLK_2_ENABLE true # define CONF_CLOCK_GCLK_2_RUN_IN_STANDBY false # define CONF_CLOCK_GCLK_2_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC32K # define CONF_CLOCK_GCLK_2_PRESCALER 32 # define CONF_CLOCK_GCLK_2_OUTPUT_ENABLE false +//! [gclk_settings] /* Configure GCLK generator 3 */ # define CONF_CLOCK_GCLK_3_ENABLE false