Marco Zecchini / Mbed OS Example_RTOS
Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcozecchini 0:9fca2b23d0ba 1 /*
marcozecchini 0:9fca2b23d0ba 2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
marcozecchini 0:9fca2b23d0ba 3 * Copyright 2016-2017 NXP
marcozecchini 0:9fca2b23d0ba 4 *
marcozecchini 0:9fca2b23d0ba 5 * Redistribution and use in source and binary forms, with or without modification,
marcozecchini 0:9fca2b23d0ba 6 * are permitted provided that the following conditions are met:
marcozecchini 0:9fca2b23d0ba 7 *
marcozecchini 0:9fca2b23d0ba 8 * o Redistributions of source code must retain the above copyright notice, this list
marcozecchini 0:9fca2b23d0ba 9 * of conditions and the following disclaimer.
marcozecchini 0:9fca2b23d0ba 10 *
marcozecchini 0:9fca2b23d0ba 11 * o Redistributions in binary form must reproduce the above copyright notice, this
marcozecchini 0:9fca2b23d0ba 12 * list of conditions and the following disclaimer in the documentation and/or
marcozecchini 0:9fca2b23d0ba 13 * other materials provided with the distribution.
marcozecchini 0:9fca2b23d0ba 14 *
marcozecchini 0:9fca2b23d0ba 15 * o Neither the name of the copyright holder nor the names of its
marcozecchini 0:9fca2b23d0ba 16 * contributors may be used to endorse or promote products derived from this
marcozecchini 0:9fca2b23d0ba 17 * software without specific prior written permission.
marcozecchini 0:9fca2b23d0ba 18 *
marcozecchini 0:9fca2b23d0ba 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
marcozecchini 0:9fca2b23d0ba 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
marcozecchini 0:9fca2b23d0ba 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
marcozecchini 0:9fca2b23d0ba 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
marcozecchini 0:9fca2b23d0ba 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
marcozecchini 0:9fca2b23d0ba 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
marcozecchini 0:9fca2b23d0ba 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
marcozecchini 0:9fca2b23d0ba 26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
marcozecchini 0:9fca2b23d0ba 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
marcozecchini 0:9fca2b23d0ba 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
marcozecchini 0:9fca2b23d0ba 29 */
marcozecchini 0:9fca2b23d0ba 30
marcozecchini 0:9fca2b23d0ba 31 #include "fsl_rtc.h"
marcozecchini 0:9fca2b23d0ba 32
marcozecchini 0:9fca2b23d0ba 33 /*******************************************************************************
marcozecchini 0:9fca2b23d0ba 34 * Definitions
marcozecchini 0:9fca2b23d0ba 35 ******************************************************************************/
marcozecchini 0:9fca2b23d0ba 36 #define SECONDS_IN_A_DAY (86400U)
marcozecchini 0:9fca2b23d0ba 37 #define SECONDS_IN_A_HOUR (3600U)
marcozecchini 0:9fca2b23d0ba 38 #define SECONDS_IN_A_MINUTE (60U)
marcozecchini 0:9fca2b23d0ba 39 #define DAYS_IN_A_YEAR (365U)
marcozecchini 0:9fca2b23d0ba 40 #define YEAR_RANGE_START (1970U)
marcozecchini 0:9fca2b23d0ba 41 #define YEAR_RANGE_END (2099U)
marcozecchini 0:9fca2b23d0ba 42
marcozecchini 0:9fca2b23d0ba 43 /*******************************************************************************
marcozecchini 0:9fca2b23d0ba 44 * Prototypes
marcozecchini 0:9fca2b23d0ba 45 ******************************************************************************/
marcozecchini 0:9fca2b23d0ba 46 /*!
marcozecchini 0:9fca2b23d0ba 47 * @brief Checks whether the date and time passed in is valid
marcozecchini 0:9fca2b23d0ba 48 *
marcozecchini 0:9fca2b23d0ba 49 * @param datetime Pointer to structure where the date and time details are stored
marcozecchini 0:9fca2b23d0ba 50 *
marcozecchini 0:9fca2b23d0ba 51 * @return Returns false if the date & time details are out of range; true if in range
marcozecchini 0:9fca2b23d0ba 52 */
marcozecchini 0:9fca2b23d0ba 53 static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime);
marcozecchini 0:9fca2b23d0ba 54
marcozecchini 0:9fca2b23d0ba 55 /*!
marcozecchini 0:9fca2b23d0ba 56 * @brief Converts time data from datetime to seconds
marcozecchini 0:9fca2b23d0ba 57 *
marcozecchini 0:9fca2b23d0ba 58 * @param datetime Pointer to datetime structure where the date and time details are stored
marcozecchini 0:9fca2b23d0ba 59 *
marcozecchini 0:9fca2b23d0ba 60 * @return The result of the conversion in seconds
marcozecchini 0:9fca2b23d0ba 61 */
marcozecchini 0:9fca2b23d0ba 62 static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime);
marcozecchini 0:9fca2b23d0ba 63
marcozecchini 0:9fca2b23d0ba 64 /*!
marcozecchini 0:9fca2b23d0ba 65 * @brief Converts time data from seconds to a datetime structure
marcozecchini 0:9fca2b23d0ba 66 *
marcozecchini 0:9fca2b23d0ba 67 * @param seconds Seconds value that needs to be converted to datetime format
marcozecchini 0:9fca2b23d0ba 68 * @param datetime Pointer to the datetime structure where the result of the conversion is stored
marcozecchini 0:9fca2b23d0ba 69 */
marcozecchini 0:9fca2b23d0ba 70 static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datetime);
marcozecchini 0:9fca2b23d0ba 71
marcozecchini 0:9fca2b23d0ba 72 /*******************************************************************************
marcozecchini 0:9fca2b23d0ba 73 * Code
marcozecchini 0:9fca2b23d0ba 74 ******************************************************************************/
marcozecchini 0:9fca2b23d0ba 75 static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime)
marcozecchini 0:9fca2b23d0ba 76 {
marcozecchini 0:9fca2b23d0ba 77 assert(datetime);
marcozecchini 0:9fca2b23d0ba 78
marcozecchini 0:9fca2b23d0ba 79 /* Table of days in a month for a non leap year. First entry in the table is not used,
marcozecchini 0:9fca2b23d0ba 80 * valid months start from 1
marcozecchini 0:9fca2b23d0ba 81 */
marcozecchini 0:9fca2b23d0ba 82 uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
marcozecchini 0:9fca2b23d0ba 83
marcozecchini 0:9fca2b23d0ba 84 /* Check year, month, hour, minute, seconds */
marcozecchini 0:9fca2b23d0ba 85 if ((datetime->year < YEAR_RANGE_START) || (datetime->year > YEAR_RANGE_END) || (datetime->month > 12U) ||
marcozecchini 0:9fca2b23d0ba 86 (datetime->month < 1U) || (datetime->hour >= 24U) || (datetime->minute >= 60U) || (datetime->second >= 60U))
marcozecchini 0:9fca2b23d0ba 87 {
marcozecchini 0:9fca2b23d0ba 88 /* If not correct then error*/
marcozecchini 0:9fca2b23d0ba 89 return false;
marcozecchini 0:9fca2b23d0ba 90 }
marcozecchini 0:9fca2b23d0ba 91
marcozecchini 0:9fca2b23d0ba 92 /* Adjust the days in February for a leap year */
marcozecchini 0:9fca2b23d0ba 93 if ((((datetime->year & 3U) == 0) && (datetime->year % 100 != 0)) || (datetime->year % 400 == 0))
marcozecchini 0:9fca2b23d0ba 94 {
marcozecchini 0:9fca2b23d0ba 95 daysPerMonth[2] = 29U;
marcozecchini 0:9fca2b23d0ba 96 }
marcozecchini 0:9fca2b23d0ba 97
marcozecchini 0:9fca2b23d0ba 98 /* Check the validity of the day */
marcozecchini 0:9fca2b23d0ba 99 if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U))
marcozecchini 0:9fca2b23d0ba 100 {
marcozecchini 0:9fca2b23d0ba 101 return false;
marcozecchini 0:9fca2b23d0ba 102 }
marcozecchini 0:9fca2b23d0ba 103
marcozecchini 0:9fca2b23d0ba 104 return true;
marcozecchini 0:9fca2b23d0ba 105 }
marcozecchini 0:9fca2b23d0ba 106
marcozecchini 0:9fca2b23d0ba 107 static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime)
marcozecchini 0:9fca2b23d0ba 108 {
marcozecchini 0:9fca2b23d0ba 109 assert(datetime);
marcozecchini 0:9fca2b23d0ba 110
marcozecchini 0:9fca2b23d0ba 111 /* Number of days from begin of the non Leap-year*/
marcozecchini 0:9fca2b23d0ba 112 /* Number of days from begin of the non Leap-year*/
marcozecchini 0:9fca2b23d0ba 113 uint16_t monthDays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
marcozecchini 0:9fca2b23d0ba 114 uint32_t seconds;
marcozecchini 0:9fca2b23d0ba 115
marcozecchini 0:9fca2b23d0ba 116 /* Compute number of days from 1970 till given year*/
marcozecchini 0:9fca2b23d0ba 117 seconds = (datetime->year - 1970U) * DAYS_IN_A_YEAR;
marcozecchini 0:9fca2b23d0ba 118 /* Add leap year days */
marcozecchini 0:9fca2b23d0ba 119 seconds += ((datetime->year / 4) - (1970U / 4));
marcozecchini 0:9fca2b23d0ba 120 /* Add number of days till given month*/
marcozecchini 0:9fca2b23d0ba 121 seconds += monthDays[datetime->month];
marcozecchini 0:9fca2b23d0ba 122 /* Add days in given month. We subtract the current day as it is
marcozecchini 0:9fca2b23d0ba 123 * represented in the hours, minutes and seconds field*/
marcozecchini 0:9fca2b23d0ba 124 seconds += (datetime->day - 1);
marcozecchini 0:9fca2b23d0ba 125 /* For leap year if month less than or equal to Febraury, decrement day counter*/
marcozecchini 0:9fca2b23d0ba 126 if ((!(datetime->year & 3U)) && (datetime->month <= 2U))
marcozecchini 0:9fca2b23d0ba 127 {
marcozecchini 0:9fca2b23d0ba 128 seconds--;
marcozecchini 0:9fca2b23d0ba 129 }
marcozecchini 0:9fca2b23d0ba 130
marcozecchini 0:9fca2b23d0ba 131 seconds = (seconds * SECONDS_IN_A_DAY) + (datetime->hour * SECONDS_IN_A_HOUR) +
marcozecchini 0:9fca2b23d0ba 132 (datetime->minute * SECONDS_IN_A_MINUTE) + datetime->second;
marcozecchini 0:9fca2b23d0ba 133
marcozecchini 0:9fca2b23d0ba 134 return seconds;
marcozecchini 0:9fca2b23d0ba 135 }
marcozecchini 0:9fca2b23d0ba 136
marcozecchini 0:9fca2b23d0ba 137 static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datetime)
marcozecchini 0:9fca2b23d0ba 138 {
marcozecchini 0:9fca2b23d0ba 139 assert(datetime);
marcozecchini 0:9fca2b23d0ba 140
marcozecchini 0:9fca2b23d0ba 141 uint32_t x;
marcozecchini 0:9fca2b23d0ba 142 uint32_t secondsRemaining, days;
marcozecchini 0:9fca2b23d0ba 143 uint16_t daysInYear;
marcozecchini 0:9fca2b23d0ba 144 /* Table of days in a month for a non leap year. First entry in the table is not used,
marcozecchini 0:9fca2b23d0ba 145 * valid months start from 1
marcozecchini 0:9fca2b23d0ba 146 */
marcozecchini 0:9fca2b23d0ba 147 uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
marcozecchini 0:9fca2b23d0ba 148
marcozecchini 0:9fca2b23d0ba 149 /* Start with the seconds value that is passed in to be converted to date time format */
marcozecchini 0:9fca2b23d0ba 150 secondsRemaining = seconds;
marcozecchini 0:9fca2b23d0ba 151
marcozecchini 0:9fca2b23d0ba 152 /* Calcuate the number of days, we add 1 for the current day which is represented in the
marcozecchini 0:9fca2b23d0ba 153 * hours and seconds field
marcozecchini 0:9fca2b23d0ba 154 */
marcozecchini 0:9fca2b23d0ba 155 days = secondsRemaining / SECONDS_IN_A_DAY + 1;
marcozecchini 0:9fca2b23d0ba 156
marcozecchini 0:9fca2b23d0ba 157 /* Update seconds left*/
marcozecchini 0:9fca2b23d0ba 158 secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY;
marcozecchini 0:9fca2b23d0ba 159
marcozecchini 0:9fca2b23d0ba 160 /* Calculate the datetime hour, minute and second fields */
marcozecchini 0:9fca2b23d0ba 161 datetime->hour = secondsRemaining / SECONDS_IN_A_HOUR;
marcozecchini 0:9fca2b23d0ba 162 secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;
marcozecchini 0:9fca2b23d0ba 163 datetime->minute = secondsRemaining / 60U;
marcozecchini 0:9fca2b23d0ba 164 datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;
marcozecchini 0:9fca2b23d0ba 165
marcozecchini 0:9fca2b23d0ba 166 /* Calculate year */
marcozecchini 0:9fca2b23d0ba 167 daysInYear = DAYS_IN_A_YEAR;
marcozecchini 0:9fca2b23d0ba 168 datetime->year = YEAR_RANGE_START;
marcozecchini 0:9fca2b23d0ba 169 while (days > daysInYear)
marcozecchini 0:9fca2b23d0ba 170 {
marcozecchini 0:9fca2b23d0ba 171 /* Decrease day count by a year and increment year by 1 */
marcozecchini 0:9fca2b23d0ba 172 days -= daysInYear;
marcozecchini 0:9fca2b23d0ba 173 datetime->year++;
marcozecchini 0:9fca2b23d0ba 174
marcozecchini 0:9fca2b23d0ba 175 /* Adjust the number of days for a leap year */
marcozecchini 0:9fca2b23d0ba 176 if (datetime->year & 3U)
marcozecchini 0:9fca2b23d0ba 177 {
marcozecchini 0:9fca2b23d0ba 178 daysInYear = DAYS_IN_A_YEAR;
marcozecchini 0:9fca2b23d0ba 179 }
marcozecchini 0:9fca2b23d0ba 180 else
marcozecchini 0:9fca2b23d0ba 181 {
marcozecchini 0:9fca2b23d0ba 182 daysInYear = DAYS_IN_A_YEAR + 1;
marcozecchini 0:9fca2b23d0ba 183 }
marcozecchini 0:9fca2b23d0ba 184 }
marcozecchini 0:9fca2b23d0ba 185
marcozecchini 0:9fca2b23d0ba 186 /* Adjust the days in February for a leap year */
marcozecchini 0:9fca2b23d0ba 187 if (!(datetime->year & 3U))
marcozecchini 0:9fca2b23d0ba 188 {
marcozecchini 0:9fca2b23d0ba 189 daysPerMonth[2] = 29U;
marcozecchini 0:9fca2b23d0ba 190 }
marcozecchini 0:9fca2b23d0ba 191
marcozecchini 0:9fca2b23d0ba 192 for (x = 1U; x <= 12U; x++)
marcozecchini 0:9fca2b23d0ba 193 {
marcozecchini 0:9fca2b23d0ba 194 if (days <= daysPerMonth[x])
marcozecchini 0:9fca2b23d0ba 195 {
marcozecchini 0:9fca2b23d0ba 196 datetime->month = x;
marcozecchini 0:9fca2b23d0ba 197 break;
marcozecchini 0:9fca2b23d0ba 198 }
marcozecchini 0:9fca2b23d0ba 199 else
marcozecchini 0:9fca2b23d0ba 200 {
marcozecchini 0:9fca2b23d0ba 201 days -= daysPerMonth[x];
marcozecchini 0:9fca2b23d0ba 202 }
marcozecchini 0:9fca2b23d0ba 203 }
marcozecchini 0:9fca2b23d0ba 204
marcozecchini 0:9fca2b23d0ba 205 datetime->day = days;
marcozecchini 0:9fca2b23d0ba 206 }
marcozecchini 0:9fca2b23d0ba 207
marcozecchini 0:9fca2b23d0ba 208 void RTC_Init(RTC_Type *base, const rtc_config_t *config)
marcozecchini 0:9fca2b23d0ba 209 {
marcozecchini 0:9fca2b23d0ba 210 assert(config);
marcozecchini 0:9fca2b23d0ba 211
marcozecchini 0:9fca2b23d0ba 212 uint32_t reg;
marcozecchini 0:9fca2b23d0ba 213
marcozecchini 0:9fca2b23d0ba 214 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
marcozecchini 0:9fca2b23d0ba 215 CLOCK_EnableClock(kCLOCK_Rtc0);
marcozecchini 0:9fca2b23d0ba 216 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
marcozecchini 0:9fca2b23d0ba 217
marcozecchini 0:9fca2b23d0ba 218 /* Issue a software reset if timer is invalid */
marcozecchini 0:9fca2b23d0ba 219 if (RTC_GetStatusFlags(RTC) & kRTC_TimeInvalidFlag)
marcozecchini 0:9fca2b23d0ba 220 {
marcozecchini 0:9fca2b23d0ba 221 RTC_Reset(RTC);
marcozecchini 0:9fca2b23d0ba 222 }
marcozecchini 0:9fca2b23d0ba 223
marcozecchini 0:9fca2b23d0ba 224 reg = base->CR;
marcozecchini 0:9fca2b23d0ba 225 /* Setup the update mode and supervisor access mode */
marcozecchini 0:9fca2b23d0ba 226 reg &= ~(RTC_CR_UM_MASK | RTC_CR_SUP_MASK);
marcozecchini 0:9fca2b23d0ba 227 reg |= RTC_CR_UM(config->updateMode) | RTC_CR_SUP(config->supervisorAccess);
marcozecchini 0:9fca2b23d0ba 228 #if defined(FSL_FEATURE_RTC_HAS_WAKEUP_PIN_SELECTION) && FSL_FEATURE_RTC_HAS_WAKEUP_PIN_SELECTION
marcozecchini 0:9fca2b23d0ba 229 /* Setup the wakeup pin select */
marcozecchini 0:9fca2b23d0ba 230 reg &= ~(RTC_CR_WPS_MASK);
marcozecchini 0:9fca2b23d0ba 231 reg |= RTC_CR_WPS(config->wakeupSelect);
marcozecchini 0:9fca2b23d0ba 232 #endif /* FSL_FEATURE_RTC_HAS_WAKEUP_PIN */
marcozecchini 0:9fca2b23d0ba 233 base->CR = reg;
marcozecchini 0:9fca2b23d0ba 234
marcozecchini 0:9fca2b23d0ba 235 /* Configure the RTC time compensation register */
marcozecchini 0:9fca2b23d0ba 236 base->TCR = (RTC_TCR_CIR(config->compensationInterval) | RTC_TCR_TCR(config->compensationTime));
marcozecchini 0:9fca2b23d0ba 237 }
marcozecchini 0:9fca2b23d0ba 238
marcozecchini 0:9fca2b23d0ba 239 void RTC_GetDefaultConfig(rtc_config_t *config)
marcozecchini 0:9fca2b23d0ba 240 {
marcozecchini 0:9fca2b23d0ba 241 assert(config);
marcozecchini 0:9fca2b23d0ba 242
marcozecchini 0:9fca2b23d0ba 243 /* Wakeup pin will assert if the RTC interrupt asserts or if the wakeup pin is turned on */
marcozecchini 0:9fca2b23d0ba 244 config->wakeupSelect = false;
marcozecchini 0:9fca2b23d0ba 245 /* Registers cannot be written when locked */
marcozecchini 0:9fca2b23d0ba 246 config->updateMode = false;
marcozecchini 0:9fca2b23d0ba 247 /* Non-supervisor mode write accesses are not supported and will generate a bus error */
marcozecchini 0:9fca2b23d0ba 248 config->supervisorAccess = false;
marcozecchini 0:9fca2b23d0ba 249 /* Compensation interval used by the crystal compensation logic */
marcozecchini 0:9fca2b23d0ba 250 config->compensationInterval = 0;
marcozecchini 0:9fca2b23d0ba 251 /* Compensation time used by the crystal compensation logic */
marcozecchini 0:9fca2b23d0ba 252 config->compensationTime = 0;
marcozecchini 0:9fca2b23d0ba 253 }
marcozecchini 0:9fca2b23d0ba 254
marcozecchini 0:9fca2b23d0ba 255 status_t RTC_SetDatetime(RTC_Type *base, const rtc_datetime_t *datetime)
marcozecchini 0:9fca2b23d0ba 256 {
marcozecchini 0:9fca2b23d0ba 257 assert(datetime);
marcozecchini 0:9fca2b23d0ba 258
marcozecchini 0:9fca2b23d0ba 259 /* Return error if the time provided is not valid */
marcozecchini 0:9fca2b23d0ba 260 if (!(RTC_CheckDatetimeFormat(datetime)))
marcozecchini 0:9fca2b23d0ba 261 {
marcozecchini 0:9fca2b23d0ba 262 return kStatus_InvalidArgument;
marcozecchini 0:9fca2b23d0ba 263 }
marcozecchini 0:9fca2b23d0ba 264
marcozecchini 0:9fca2b23d0ba 265 /* Set time in seconds */
marcozecchini 0:9fca2b23d0ba 266 base->TSR = RTC_ConvertDatetimeToSeconds(datetime);
marcozecchini 0:9fca2b23d0ba 267
marcozecchini 0:9fca2b23d0ba 268 return kStatus_Success;
marcozecchini 0:9fca2b23d0ba 269 }
marcozecchini 0:9fca2b23d0ba 270
marcozecchini 0:9fca2b23d0ba 271 void RTC_GetDatetime(RTC_Type *base, rtc_datetime_t *datetime)
marcozecchini 0:9fca2b23d0ba 272 {
marcozecchini 0:9fca2b23d0ba 273 assert(datetime);
marcozecchini 0:9fca2b23d0ba 274
marcozecchini 0:9fca2b23d0ba 275 uint32_t seconds = 0;
marcozecchini 0:9fca2b23d0ba 276
marcozecchini 0:9fca2b23d0ba 277 seconds = base->TSR;
marcozecchini 0:9fca2b23d0ba 278 RTC_ConvertSecondsToDatetime(seconds, datetime);
marcozecchini 0:9fca2b23d0ba 279 }
marcozecchini 0:9fca2b23d0ba 280
marcozecchini 0:9fca2b23d0ba 281 status_t RTC_SetAlarm(RTC_Type *base, const rtc_datetime_t *alarmTime)
marcozecchini 0:9fca2b23d0ba 282 {
marcozecchini 0:9fca2b23d0ba 283 assert(alarmTime);
marcozecchini 0:9fca2b23d0ba 284
marcozecchini 0:9fca2b23d0ba 285 uint32_t alarmSeconds = 0;
marcozecchini 0:9fca2b23d0ba 286 uint32_t currSeconds = 0;
marcozecchini 0:9fca2b23d0ba 287
marcozecchini 0:9fca2b23d0ba 288 /* Return error if the alarm time provided is not valid */
marcozecchini 0:9fca2b23d0ba 289 if (!(RTC_CheckDatetimeFormat(alarmTime)))
marcozecchini 0:9fca2b23d0ba 290 {
marcozecchini 0:9fca2b23d0ba 291 return kStatus_InvalidArgument;
marcozecchini 0:9fca2b23d0ba 292 }
marcozecchini 0:9fca2b23d0ba 293
marcozecchini 0:9fca2b23d0ba 294 alarmSeconds = RTC_ConvertDatetimeToSeconds(alarmTime);
marcozecchini 0:9fca2b23d0ba 295
marcozecchini 0:9fca2b23d0ba 296 /* Get the current time */
marcozecchini 0:9fca2b23d0ba 297 currSeconds = base->TSR;
marcozecchini 0:9fca2b23d0ba 298
marcozecchini 0:9fca2b23d0ba 299 /* Return error if the alarm time has passed */
marcozecchini 0:9fca2b23d0ba 300 if (alarmSeconds < currSeconds)
marcozecchini 0:9fca2b23d0ba 301 {
marcozecchini 0:9fca2b23d0ba 302 return kStatus_Fail;
marcozecchini 0:9fca2b23d0ba 303 }
marcozecchini 0:9fca2b23d0ba 304
marcozecchini 0:9fca2b23d0ba 305 /* Set alarm in seconds*/
marcozecchini 0:9fca2b23d0ba 306 base->TAR = alarmSeconds;
marcozecchini 0:9fca2b23d0ba 307
marcozecchini 0:9fca2b23d0ba 308 return kStatus_Success;
marcozecchini 0:9fca2b23d0ba 309 }
marcozecchini 0:9fca2b23d0ba 310
marcozecchini 0:9fca2b23d0ba 311 void RTC_GetAlarm(RTC_Type *base, rtc_datetime_t *datetime)
marcozecchini 0:9fca2b23d0ba 312 {
marcozecchini 0:9fca2b23d0ba 313 assert(datetime);
marcozecchini 0:9fca2b23d0ba 314
marcozecchini 0:9fca2b23d0ba 315 uint32_t alarmSeconds = 0;
marcozecchini 0:9fca2b23d0ba 316
marcozecchini 0:9fca2b23d0ba 317 /* Get alarm in seconds */
marcozecchini 0:9fca2b23d0ba 318 alarmSeconds = base->TAR;
marcozecchini 0:9fca2b23d0ba 319
marcozecchini 0:9fca2b23d0ba 320 RTC_ConvertSecondsToDatetime(alarmSeconds, datetime);
marcozecchini 0:9fca2b23d0ba 321 }
marcozecchini 0:9fca2b23d0ba 322
marcozecchini 0:9fca2b23d0ba 323 void RTC_ClearStatusFlags(RTC_Type *base, uint32_t mask)
marcozecchini 0:9fca2b23d0ba 324 {
marcozecchini 0:9fca2b23d0ba 325 /* The alarm flag is cleared by writing to the TAR register */
marcozecchini 0:9fca2b23d0ba 326 if (mask & kRTC_AlarmFlag)
marcozecchini 0:9fca2b23d0ba 327 {
marcozecchini 0:9fca2b23d0ba 328 base->TAR = 0U;
marcozecchini 0:9fca2b23d0ba 329 }
marcozecchini 0:9fca2b23d0ba 330
marcozecchini 0:9fca2b23d0ba 331 /* The timer overflow flag is cleared by initializing the TSR register.
marcozecchini 0:9fca2b23d0ba 332 * The time counter should be disabled for this write to be successful
marcozecchini 0:9fca2b23d0ba 333 */
marcozecchini 0:9fca2b23d0ba 334 if (mask & kRTC_TimeOverflowFlag)
marcozecchini 0:9fca2b23d0ba 335 {
marcozecchini 0:9fca2b23d0ba 336 base->TSR = 1U;
marcozecchini 0:9fca2b23d0ba 337 }
marcozecchini 0:9fca2b23d0ba 338
marcozecchini 0:9fca2b23d0ba 339 /* The timer overflow flag is cleared by initializing the TSR register.
marcozecchini 0:9fca2b23d0ba 340 * The time counter should be disabled for this write to be successful
marcozecchini 0:9fca2b23d0ba 341 */
marcozecchini 0:9fca2b23d0ba 342 if (mask & kRTC_TimeInvalidFlag)
marcozecchini 0:9fca2b23d0ba 343 {
marcozecchini 0:9fca2b23d0ba 344 base->TSR = 1U;
marcozecchini 0:9fca2b23d0ba 345 }
marcozecchini 0:9fca2b23d0ba 346 }
marcozecchini 0:9fca2b23d0ba 347
marcozecchini 0:9fca2b23d0ba 348 #if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
marcozecchini 0:9fca2b23d0ba 349
marcozecchini 0:9fca2b23d0ba 350 void RTC_GetMonotonicCounter(RTC_Type *base, uint64_t *counter)
marcozecchini 0:9fca2b23d0ba 351 {
marcozecchini 0:9fca2b23d0ba 352 assert(counter);
marcozecchini 0:9fca2b23d0ba 353
marcozecchini 0:9fca2b23d0ba 354 *counter = (((uint64_t)base->MCHR << 32) | ((uint64_t)base->MCLR));
marcozecchini 0:9fca2b23d0ba 355 }
marcozecchini 0:9fca2b23d0ba 356
marcozecchini 0:9fca2b23d0ba 357 void RTC_SetMonotonicCounter(RTC_Type *base, uint64_t counter)
marcozecchini 0:9fca2b23d0ba 358 {
marcozecchini 0:9fca2b23d0ba 359 /* Prepare to initialize the register with the new value written */
marcozecchini 0:9fca2b23d0ba 360 base->MER &= ~RTC_MER_MCE_MASK;
marcozecchini 0:9fca2b23d0ba 361
marcozecchini 0:9fca2b23d0ba 362 base->MCHR = (uint32_t)((counter) >> 32);
marcozecchini 0:9fca2b23d0ba 363 base->MCLR = (uint32_t)(counter);
marcozecchini 0:9fca2b23d0ba 364 }
marcozecchini 0:9fca2b23d0ba 365
marcozecchini 0:9fca2b23d0ba 366 status_t RTC_IncrementMonotonicCounter(RTC_Type *base)
marcozecchini 0:9fca2b23d0ba 367 {
marcozecchini 0:9fca2b23d0ba 368 if (base->SR & (RTC_SR_MOF_MASK | RTC_SR_TIF_MASK))
marcozecchini 0:9fca2b23d0ba 369 {
marcozecchini 0:9fca2b23d0ba 370 return kStatus_Fail;
marcozecchini 0:9fca2b23d0ba 371 }
marcozecchini 0:9fca2b23d0ba 372
marcozecchini 0:9fca2b23d0ba 373 /* Prepare to switch to increment mode */
marcozecchini 0:9fca2b23d0ba 374 base->MER |= RTC_MER_MCE_MASK;
marcozecchini 0:9fca2b23d0ba 375 /* Write anything so the counter increments*/
marcozecchini 0:9fca2b23d0ba 376 base->MCLR = 1U;
marcozecchini 0:9fca2b23d0ba 377
marcozecchini 0:9fca2b23d0ba 378 return kStatus_Success;
marcozecchini 0:9fca2b23d0ba 379 }
marcozecchini 0:9fca2b23d0ba 380
marcozecchini 0:9fca2b23d0ba 381 #endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */