mbed-os/targets/TARGET_STM/TARGET_STM32F1/rtc_api.c

200 lines
6.5 KiB
C

/* mbed Microcontroller Library
*******************************************************************************
* Copyright (c) 2014, STMicroelectronics
* All rights reserved.
*
* 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. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
*******************************************************************************
*/
#include "rtc_api.h"
#if DEVICE_RTC
#include "mbed_error.h"
static int rtc_inited = 0;
static RTC_HandleTypeDef RtcHandle;
void rtc_init(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
if (rtc_inited) return;
rtc_inited = 1;
RtcHandle.Instance = RTC;
#if !RTC_LSI
// Enable LSE Oscillator
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured!
RCC_OscInitStruct.LSEState = RCC_LSE_ON; // External 32.768 kHz clock on OSC_IN/OSC_OUT
RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK) { // Check if LSE has started correctly
// Connect LSE to RTC
__HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
} else {
error("Cannot initialize RTC with LSE\n");
}
#else
// Enable Power clock
__HAL_RCC_PWR_CLK_ENABLE();
// Enable access to Backup domain
HAL_PWR_EnableBkUpAccess();
// Reset Backup domain
__HAL_RCC_BACKUPRESET_FORCE();
__HAL_RCC_BACKUPRESET_RELEASE();
// Enable LSI clock
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured!
RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
error("Cannot initialize RTC with LSI\n");
}
// Connect LSI to RTC
__HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI);
// This value is LSI typical value. To be measured precisely using a timer input capture for example.
#endif
// Enable RTC
__HAL_RCC_RTC_ENABLE();
RtcHandle.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
if (HAL_RTC_Init(&RtcHandle) != HAL_OK) {
error("RTC error: RTC initialization failed.");
}
}
void rtc_free(void)
{
#if RTC_LSI
// Enable Power clock
__PWR_CLK_ENABLE();
// Enable access to Backup domain
HAL_PWR_EnableBkUpAccess();
// Reset Backup domain
__HAL_RCC_BACKUPRESET_FORCE();
__HAL_RCC_BACKUPRESET_RELEASE();
// Disable access to Backup domain
HAL_PWR_DisableBkUpAccess();
#endif
// Disable LSI and LSE clocks
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
rtc_inited = 0;
}
int rtc_isenabled(void)
{
return rtc_inited;
}
/*
RTC Registers
RTC_WeekDay 1=monday, 2=tuesday, ..., 7=sunday
RTC_Month 1=january, 2=february, ..., 12=december
RTC_Date day of the month 1-31
RTC_Year year 0-99
struct tm
tm_sec seconds after the minute 0-61
tm_min minutes after the hour 0-59
tm_hour hours since midnight 0-23
tm_mday day of the month 1-31
tm_mon months since January 0-11
tm_year years since 1900
tm_wday days since Sunday 0-6
tm_yday days since January 1 0-365
tm_isdst Daylight Saving Time flag
*/
time_t rtc_read(void)
{
RTC_DateTypeDef dateStruct;
RTC_TimeTypeDef timeStruct;
struct tm timeinfo;
RtcHandle.Instance = RTC;
// Read actual date and time
// Warning: the time must be read first!
HAL_RTC_GetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
HAL_RTC_GetDate(&RtcHandle, &dateStruct, FORMAT_BIN);
// Setup a tm structure based on the RTC
timeinfo.tm_wday = dateStruct.WeekDay;
timeinfo.tm_mon = dateStruct.Month - 1;
timeinfo.tm_mday = dateStruct.Date;
timeinfo.tm_year = dateStruct.Year;
timeinfo.tm_hour = timeStruct.Hours;
timeinfo.tm_min = timeStruct.Minutes;
timeinfo.tm_sec = timeStruct.Seconds;
// Daylight Saving Time information is not available
timeinfo.tm_isdst = -1;
// Convert to timestamp
time_t t = mktime(&timeinfo);
return t;
}
void rtc_write(time_t t)
{
RTC_DateTypeDef dateStruct;
RTC_TimeTypeDef timeStruct;
RtcHandle.Instance = RTC;
// Convert the time into a tm
struct tm *timeinfo = localtime(&t);
// Fill RTC structures
dateStruct.WeekDay = timeinfo->tm_wday;
dateStruct.Month = timeinfo->tm_mon + 1;
dateStruct.Date = timeinfo->tm_mday;
dateStruct.Year = timeinfo->tm_year;
timeStruct.Hours = timeinfo->tm_hour;
timeStruct.Minutes = timeinfo->tm_min;
timeStruct.Seconds = timeinfo->tm_sec;
// Change the RTC current date/time
HAL_RTC_SetDate(&RtcHandle, &dateStruct, FORMAT_BIN);
HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
}
#endif