mirror of
https://github.com/taubel/sdk-ameba-v4.0b-gcc.git
synced 2026-07-09 04:45:43 +00:00
initial commit
This commit is contained in:
commit
60a7afcc83
2528 changed files with 1001987 additions and 0 deletions
357
component/common/mbed/targets/hal/rtl8711b/rtc_api.c
Normal file
357
component/common/mbed/targets/hal/rtl8711b/rtc_api.c
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
/** mbed Microcontroller Library
|
||||
******************************************************************************
|
||||
* @file rtc_api.c
|
||||
* @author
|
||||
* @version V1.0.0
|
||||
* @date 2016-08-01
|
||||
* @brief This file provides mbed API for RTC.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* This module is a confidential and proprietary property of RealTek and
|
||||
* possession or use of this module requires written permission of RealTek.
|
||||
*
|
||||
* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rtc_api.h"
|
||||
|
||||
#include <time.h>
|
||||
#include "timer_api.h"
|
||||
|
||||
static struct tm rtc_timeinfo;
|
||||
static int rtc_en = 0;
|
||||
static alarm_irq_handler rtc_alarm_handler;
|
||||
|
||||
const static u8 dim[12] = {
|
||||
31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
|
||||
/**
|
||||
* @brief This function is used to tell a year is a leap year or not.
|
||||
* @param year: The year need to be told.
|
||||
* @retval value:
|
||||
* - 1: This year is leap year.
|
||||
* - 0: This year is not leap year.
|
||||
*/
|
||||
static inline bool is_leap_year(unsigned int year)
|
||||
{
|
||||
u32 full_year = year + 1900;
|
||||
return (!(full_year % 4) && (full_year % 100)) || !(full_year % 400);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function tells how many days in a month of a year.
|
||||
* @param year: Specified year
|
||||
* @param month: Specified month
|
||||
* @retval value: Number of days in the month.
|
||||
*/
|
||||
static u8 days_in_month (u8 month, u8 year)
|
||||
{
|
||||
u8 ret = dim[month];
|
||||
if (ret == 0)
|
||||
ret = is_leap_year (year) ? 29 : 28;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is used to calculate month and day of month according to year and day of the year.
|
||||
* @param year: years since 1900.
|
||||
* @param yday: day of the year.
|
||||
* @param mon: pointer to the variable which stores month, the value can be 0-11
|
||||
* @param mday: pointer to the variable which stores day of month, the value can be 1-31
|
||||
* @retval value: none
|
||||
*/
|
||||
static void rtc_calculate_mday(int year, int yday, int* mon, int* mday)
|
||||
{
|
||||
int t_mon = -1, t_yday = yday + 1;
|
||||
|
||||
while(t_yday > 0){
|
||||
t_mon ++;
|
||||
t_yday -= days_in_month(t_mon, year);
|
||||
}
|
||||
|
||||
*mon = t_mon;
|
||||
*mday = t_yday + days_in_month(t_mon, year);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is used to calculate day of week according to date.
|
||||
* @param year: years since 1900.
|
||||
* @param mon: which month of the year
|
||||
* @param mday: pointer to the variable which store day of month
|
||||
* @param wday: pointer to the variable which store day of week, the value can be 0-6, and 0 means Sunday
|
||||
* @retval value: none
|
||||
*/
|
||||
static void rtc_calculate_wday(int year, int mon, int mday, int* wday)
|
||||
{
|
||||
int t_year = year + 1900, t_mon = mon + 1;
|
||||
|
||||
if(t_mon == 1 || t_mon == 2){
|
||||
t_year --;
|
||||
t_mon += 12;
|
||||
}
|
||||
|
||||
int c = t_year / 100;
|
||||
int y = t_year % 100;
|
||||
int week = (c / 4) - 2 * c + (y + y / 4) + (26 * (t_mon + 1) / 10) + mday -1;
|
||||
|
||||
while(week < 0){
|
||||
week += 7;
|
||||
}
|
||||
week %= 7;
|
||||
|
||||
*wday = week;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is used to restore rtc_timeinfo global variable whose value is lost after system reset.
|
||||
* @param none
|
||||
* @retval value: none
|
||||
*/
|
||||
static void rtc_restore_timeinfo(void)
|
||||
{
|
||||
u32 value, days_in_year;
|
||||
|
||||
RTC_TimeTypeDef RTC_TimeStruct;
|
||||
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
|
||||
rtc_timeinfo.tm_sec = RTC_TimeStruct.RTC_Seconds;
|
||||
rtc_timeinfo.tm_min = RTC_TimeStruct.RTC_Minutes;
|
||||
rtc_timeinfo.tm_hour = RTC_TimeStruct.RTC_Hours;
|
||||
rtc_timeinfo.tm_yday = RTC_TimeStruct.RTC_Days;
|
||||
|
||||
value = BKUP_Read(0);
|
||||
rtc_timeinfo.tm_year = (value & BIT_RTC_BACKUP) >> 8;
|
||||
|
||||
days_in_year = (is_leap_year(rtc_timeinfo.tm_year) ? 366 : 365);
|
||||
if(rtc_timeinfo.tm_yday > days_in_year - 1){
|
||||
rtc_timeinfo.tm_year ++;
|
||||
rtc_timeinfo.tm_yday -= days_in_year;
|
||||
|
||||
/* over one year, update days in RTC_TR */
|
||||
RTC_TimeStruct.RTC_Days = rtc_timeinfo.tm_yday;
|
||||
RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
|
||||
}
|
||||
|
||||
rtc_calculate_mday(rtc_timeinfo.tm_year, rtc_timeinfo.tm_yday, &rtc_timeinfo.tm_mon, &rtc_timeinfo.tm_mday);
|
||||
rtc_calculate_wday(rtc_timeinfo.tm_year, rtc_timeinfo.tm_mon, rtc_timeinfo.tm_mday, &rtc_timeinfo.tm_wday);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is used to backup tm_year parameter in rtc_timeinfo global variable before system reset.
|
||||
* @param none
|
||||
* @retval value: none
|
||||
*/
|
||||
void rtc_backup_timeinfo(void)
|
||||
{
|
||||
u32 value = BKUP_Read(0);
|
||||
value = (value & ~BIT_RTC_BACKUP) | (rtc_timeinfo.tm_year << 8);
|
||||
|
||||
BKUP_Write(0, value);
|
||||
|
||||
BKUP_Set(0, BIT_RTC_RESTORE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the RTC device, include clock, RTC registers and function.
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void rtc_init(void)
|
||||
{
|
||||
RTC_InitTypeDef RTC_InitStruct;
|
||||
|
||||
RTC_ClokSource(0);
|
||||
|
||||
RTC_StructInit(&RTC_InitStruct);
|
||||
RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
|
||||
|
||||
RTC_Init(&RTC_InitStruct);
|
||||
|
||||
/* 32760 need add need add 15 cycles (256Hz) every 4 min*/
|
||||
//RTC_SmoothCalibConfig(RTC_CalibSign_Positive, 15,
|
||||
// RTC_CalibPeriod_4MIN, RTC_Calib_Enable);
|
||||
|
||||
rtc_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitializes the RTC device.
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void rtc_free(void)
|
||||
{
|
||||
rtc_en = 0;
|
||||
rtc_alarm_handler = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function tells whether RTC is enabled or not.
|
||||
* @param none
|
||||
* @retval status:
|
||||
* - 1: RTC is enable.
|
||||
* - 0: RTC is disable.
|
||||
*/
|
||||
int rtc_isenabled(void)
|
||||
{
|
||||
return rtc_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the specified timestamp in seconds to RTC.
|
||||
* @param t: Seconds from 1970.1.1 00:00:00 to specified data and time
|
||||
* which is to be set.
|
||||
* @retval none
|
||||
*/
|
||||
void rtc_write(time_t t)
|
||||
{
|
||||
/* Convert the time in to a tm*/
|
||||
struct tm *timeinfo = localtime(&t);
|
||||
|
||||
RTC_TimeTypeDef RTC_TimeStruct;
|
||||
|
||||
/*set time in RTC */
|
||||
RTC_TimeStruct.RTC_H12_PMAM = RTC_H12_AM;
|
||||
RTC_TimeStruct.RTC_Days = timeinfo->tm_yday;
|
||||
RTC_TimeStruct.RTC_Hours = timeinfo->tm_hour;
|
||||
RTC_TimeStruct.RTC_Minutes = timeinfo->tm_min;
|
||||
RTC_TimeStruct.RTC_Seconds = timeinfo->tm_sec;
|
||||
RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
|
||||
|
||||
/* Set rtc_timeinfo*/
|
||||
_memcpy((void*)&rtc_timeinfo, (void*)timeinfo, sizeof(struct tm));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current timestamp in seconds from RTC.
|
||||
* @param none
|
||||
* @retval value: The current timestamp in seconds which is calculated from
|
||||
* 1970.1.1 00:00:00.
|
||||
*/
|
||||
time_t rtc_read(void)
|
||||
{
|
||||
time_t t;
|
||||
struct tm tm_temp;
|
||||
RTC_TimeTypeDef RTC_TimeStruct;
|
||||
u32 delta_days = 0;
|
||||
|
||||
if(BKUP_Read(0) & BIT_RTC_RESTORE){
|
||||
rtc_restore_timeinfo();
|
||||
BKUP_Clear(0, BIT_RTC_RESTORE);
|
||||
}
|
||||
|
||||
_memcpy((void*)&tm_temp, (void*)&rtc_timeinfo, sizeof(struct tm));
|
||||
|
||||
/*hour, min, sec get from RTC*/
|
||||
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
|
||||
tm_temp.tm_sec = RTC_TimeStruct.RTC_Seconds;
|
||||
tm_temp.tm_min = RTC_TimeStruct.RTC_Minutes;
|
||||
tm_temp.tm_hour = RTC_TimeStruct.RTC_Hours;
|
||||
|
||||
/* calculate how many days later from last time update rtc_timeinfo */
|
||||
delta_days = RTC_TimeStruct.RTC_Days - tm_temp.tm_yday;
|
||||
|
||||
/* calculate wday, mday, yday, mon, year*/
|
||||
tm_temp.tm_wday += delta_days;
|
||||
if(tm_temp.tm_wday >= 7){
|
||||
tm_temp.tm_wday = tm_temp.tm_wday % 7;
|
||||
}
|
||||
|
||||
tm_temp.tm_yday += delta_days;
|
||||
tm_temp.tm_mday += delta_days;
|
||||
|
||||
while(tm_temp.tm_mday > days_in_month(tm_temp.tm_mon, tm_temp.tm_year)){
|
||||
tm_temp.tm_mday -= days_in_month(tm_temp.tm_mon, tm_temp.tm_year);
|
||||
tm_temp.tm_mon++;
|
||||
|
||||
if(tm_temp.tm_mon >= 12){
|
||||
tm_temp.tm_mon -= 12;
|
||||
tm_temp.tm_yday -= is_leap_year(tm_temp.tm_year) ? 366 : 365;
|
||||
tm_temp.tm_year ++;
|
||||
|
||||
/* over one year, update days in RTC_TR */
|
||||
RTC_TimeStruct.RTC_Days = tm_temp.tm_yday;
|
||||
RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
|
||||
|
||||
/* update rtc_timeinfo */
|
||||
_memcpy((void*)&rtc_timeinfo, (void*)&tm_temp, sizeof(struct tm));
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert to timestamp(seconds from 1970.1.1 00:00:00)*/
|
||||
t = mktime(&tm_temp);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTC alarm interrupt handler function.
|
||||
* @param data: RTC IRQ callback data
|
||||
* @retval none
|
||||
*/
|
||||
void rtc_alarm_intr_handler(u32 data)
|
||||
{
|
||||
alarm_irq_handler hdl;
|
||||
|
||||
/*clear alarm flag*/
|
||||
RTC_AlarmClear();
|
||||
|
||||
/* execute user handler*/
|
||||
if(rtc_alarm_handler != NULL){
|
||||
hdl = (alarm_irq_handler)rtc_alarm_handler;
|
||||
hdl();
|
||||
}
|
||||
|
||||
/*disable alarm*/
|
||||
rtc_disable_alarm();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the specified RTC Alarm and interrupt.
|
||||
* @param alarm: alarm object define in application software.
|
||||
* @param alarmHandler: alarm interrupt callback function.
|
||||
* @retval status:
|
||||
* - 1: success
|
||||
* - Others: failure
|
||||
*/
|
||||
u32 rtc_set_alarm(alarm_t *alrm, alarm_irq_handler alarmHandler)
|
||||
{
|
||||
RTC_AlarmTypeDef RTC_AlarmStruct_temp;
|
||||
|
||||
rtc_alarm_handler = alarmHandler;
|
||||
|
||||
/* set alarm */
|
||||
RTC_AlarmStructInit(&RTC_AlarmStruct_temp);
|
||||
RTC_AlarmStruct_temp.RTC_AlarmTime.RTC_H12_PMAM = RTC_H12_AM;
|
||||
RTC_AlarmStruct_temp.RTC_AlarmTime.RTC_Days = alrm->yday;
|
||||
RTC_AlarmStruct_temp.RTC_AlarmTime.RTC_Hours = alrm->hour;
|
||||
RTC_AlarmStruct_temp.RTC_AlarmTime.RTC_Minutes = alrm->min;
|
||||
RTC_AlarmStruct_temp.RTC_AlarmTime.RTC_Seconds = alrm->sec;
|
||||
|
||||
RTC_AlarmStruct_temp.RTC_AlarmMask = RTC_AlarmMask_None;
|
||||
RTC_AlarmStruct_temp.RTC_Alarm2Mask = RTC_Alarm2Mask_None;
|
||||
|
||||
RTC_SetAlarm(RTC_Format_BIN, &RTC_AlarmStruct_temp);
|
||||
|
||||
RTC_AlarmCmd(ENABLE);
|
||||
InterruptRegister((IRQ_FUN)rtc_alarm_intr_handler, RTC_IRQ, (u32)alrm, 4);
|
||||
InterruptEn(RTC_IRQ, 4);
|
||||
|
||||
return _TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable RTC Alarm and function.
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void rtc_disable_alarm(void)
|
||||
{
|
||||
InterruptDis(RTC_IRQ);
|
||||
InterruptUnRegister(RTC_IRQ);
|
||||
RTC_AlarmCmd(DISABLE);
|
||||
|
||||
rtc_alarm_handler = NULL;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue