rt-thread/bsp/stm32f429-apollo/drivers/drv_rtc.c

315 lines
8.9 KiB
C
Raw Normal View History

/*
2018-10-16 13:00:37 +08:00
* Copyright (c) 2006-2018, RT-Thread Development Team
*
2018-10-16 13:00:37 +08:00
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-04-05 lizhen9880 the first version for STM32F429
*/
/* Includes ------------------------------------------------------------------*/
#include "board.h"
#include "drv_rtc.h"
#include <rtdevice.h>
#if defined(RT_USING_RTC)
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#ifdef RT_RTC_DEBUG
#define rtc_debug(format,args...) rt_kprintf(format, ##args)
#else
#define rtc_debug(format,args...)
#endif
/* Private variables ---------------------------------------------------------*/
static struct rt_device rtc;
RTC_HandleTypeDef RTC_Handler; //RTC<54><43><EFBFBD><EFBFBD>
//RTC<54><43>ʼ<EFBFBD><CABC>
//<2F><><EFBFBD><EFBFBD>ֵ:0,<2C><>ʼ<EFBFBD><CABC><EFBFBD>ɹ<EFBFBD>;
// 2,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ģʽʧ<CABD><CAA7>;
rt_uint8_t RTC_Init(void)
{
RTC_Handler.Instance=RTC;
RTC_Handler.Init.HourFormat=RTC_HOURFORMAT_24;//RTC<54><43><EFBFBD><EFBFBD>Ϊ24Сʱ<D0A1><CAB1>ʽ
RTC_Handler.Init.AsynchPrediv=0X7F; //RTC<54><EFBFBD><ECB2BD>Ƶϵ<C6B5><CFB5>(1~0X7F)
RTC_Handler.Init.SynchPrediv=0XFF; //RTCͬ<43><CDAC><EFBFBD><EFBFBD>Ƶϵ<C6B5><CFB5>(0~7FFF)
RTC_Handler.Init.OutPut=RTC_OUTPUT_DISABLE;
RTC_Handler.Init.OutPutPolarity=RTC_OUTPUT_POLARITY_HIGH;
RTC_Handler.Init.OutPutType=RTC_OUTPUT_TYPE_OPENDRAIN;
if(HAL_RTC_Init(&RTC_Handler)!=HAL_OK) return 2;
if(HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR0)!=0X5050)//<2F>Ƿ<EFBFBD><C7B7><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
// RTC_Set_Time(23,59,56,RTC_HOURFORMAT12_PM); //<2F><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1> ,<2C><><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>ʱ<EFBFBD><CAB1><EFBFBD>޸<EFBFBD>
// RTC_Set_Date(15,12,27,7); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
HAL_RTCEx_BKUPWrite(&RTC_Handler,RTC_BKP_DR0,0X5050);//<2F><><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
return 0;
}
//RTC<54>ײ<EFBFBD><D7B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F>˺<EFBFBD><CBBA><EFBFBD><EFBFBD>ᱻHAL_RTC_Init()<29><><EFBFBD><EFBFBD>
//hrtc:RTC<54><43><EFBFBD><EFBFBD>
void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE();//ʹ<>ܵ<EFBFBD>Դʱ<D4B4><CAB1>PWR
HAL_PWR_EnableBkUpAccess();//ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>
RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_LSE;//LSE<53><45><EFBFBD><EFBFBD>
RCC_OscInitStruct.PLL.PLLState=RCC_PLL_NONE;
RCC_OscInitStruct.LSEState=RCC_LSE_ON; //RTCʹ<43><CAB9>LSE
HAL_RCC_OscConfig(&RCC_OscInitStruct);
PeriphClkInitStruct.PeriphClockSelection=RCC_PERIPHCLK_RTC;//<2F><><EFBFBD><EFBFBD>ΪRTC
PeriphClkInitStruct.RTCClockSelection=RCC_RTCCLKSOURCE_LSE;//RTCʱ<43><CAB1>ԴΪLSE
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
__HAL_RCC_RTC_ENABLE();//RTCʱ<43><CAB1>ʹ<EFBFBD><CAB9>
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,24Сʱ<D0A1><CAB1>)
//week:<3A><><EFBFBD>ڼ<EFBFBD>(1~7) @ref RTC_WeekDay_Definitions
//hour,min,sec:Сʱ,<2C><><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD>
void RTC_Set_AlarmA(rt_uint8_t week,rt_uint8_t hour,rt_uint8_t min,rt_uint8_t sec)
{
RTC_AlarmTypeDef RTC_AlarmSturuct;
RTC_AlarmSturuct.AlarmTime.Hours=hour; //Сʱ
RTC_AlarmSturuct.AlarmTime.Minutes=min; //<2F><><EFBFBD><EFBFBD>
RTC_AlarmSturuct.AlarmTime.Seconds=sec; //<2F><>
RTC_AlarmSturuct.AlarmTime.SubSeconds=0;
RTC_AlarmSturuct.AlarmTime.TimeFormat=RTC_HOURFORMAT12_AM;
RTC_AlarmSturuct.AlarmMask=RTC_ALARMMASK_NONE;//<2F><>ȷƥ<C8B7><C6A5><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
RTC_AlarmSturuct.AlarmSubSecondMask=RTC_ALARMSUBSECONDMASK_NONE;
RTC_AlarmSturuct.AlarmDateWeekDaySel=RTC_ALARMDATEWEEKDAYSEL_WEEKDAY;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RTC_AlarmSturuct.AlarmDateWeekDay=week; //<2F><><EFBFBD><EFBFBD>
RTC_AlarmSturuct.Alarm=RTC_ALARM_A; //<2F><><EFBFBD><EFBFBD>A
HAL_RTC_SetAlarm_IT(&RTC_Handler,&RTC_AlarmSturuct,RTC_FORMAT_BIN);
HAL_NVIC_SetPriority(RTC_Alarm_IRQn,0x01,0x02); //<2F><>ռ<EFBFBD><D5BC><EFBFBD>ȼ<EFBFBD>1,<2C><><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>2
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
}
//<2F><><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD><D4BB>Ѷ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/*wksel: @ref RTCEx_Wakeup_Timer_Definitions
#define RTC_WAKEUPCLOCK_RTCCLK_DIV16 ((uint32_t)0x00000000)
#define RTC_WAKEUPCLOCK_RTCCLK_DIV8 ((uint32_t)0x00000001)
#define RTC_WAKEUPCLOCK_RTCCLK_DIV4 ((uint32_t)0x00000002)
#define RTC_WAKEUPCLOCK_RTCCLK_DIV2 ((uint32_t)0x00000003)
#define RTC_WAKEUPCLOCK_CK_SPRE_16BITS ((uint32_t)0x00000004)
#define RTC_WAKEUPCLOCK_CK_SPRE_17BITS ((uint32_t)0x00000006)
*/
//cnt:<3A>Զ<EFBFBD><D4B6><EFBFBD>װ<EFBFBD><D7B0>ֵ.<2E><><EFBFBD><EFBFBD>0,<2C><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>.
void RTC_Set_WakeUp(rt_uint32_t wksel,rt_uint16_t cnt)
{
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RTC_Handler, RTC_FLAG_WUTF);//<2F><><EFBFBD><EFBFBD>RTC WAKE UP<55>ı<EFBFBD>־
HAL_RTCEx_SetWakeUpTimer_IT(&RTC_Handler,cnt,wksel); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0>ֵ<EFBFBD><D6B5>ʱ<EFBFBD><CAB1>
HAL_NVIC_SetPriority(RTC_WKUP_IRQn,0x02,0x02); //<2F><>ռ<EFBFBD><D5BC><EFBFBD>ȼ<EFBFBD>1,<2C><><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>2
HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
}
//RTC<54><43><EFBFBD><EFBFBD><EFBFBD>жϷ<D0B6><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void RTC_Alarm_IRQHandler(void)
{
HAL_RTC_AlarmIRQHandler(&RTC_Handler);
}
//RTC<54><43><EFBFBD><EFBFBD>A<EFBFBD>жϴ<D0B6><CFB4><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
rt_kprintf("ALARM A!\r\n");
}
//RTC WAKE UP<55>жϷ<D0B6><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void RTC_WKUP_IRQHandler(void)
{
HAL_RTCEx_WakeUpTimerIRQHandler(&RTC_Handler);
}
time_t GetRTCTimeStamp(void)
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
struct tm tm_new;
HAL_RTC_GetTime(&RTC_Handler,&RTC_TimeStruct,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&RTC_Handler,&RTC_DateStruct,RTC_FORMAT_BIN);
tm_new.tm_sec = RTC_TimeStruct.Seconds;
tm_new.tm_min = RTC_TimeStruct.Minutes;
tm_new.tm_hour = RTC_TimeStruct.Hours;
tm_new.tm_mday = RTC_DateStruct.Date;
tm_new.tm_mon = RTC_DateStruct.Month-1;
tm_new.tm_year = RTC_DateStruct.Year+100;
return mktime(&tm_new);
}
rt_err_t SetRTCTimeStamp(time_t time_stamp)
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
struct tm *p_tm;
p_tm = localtime(&time_stamp);
if(p_tm->tm_year<100)
{
return RT_ERROR;
}
RTC_TimeStruct.Seconds = p_tm->tm_sec ;
RTC_TimeStruct.Minutes = p_tm->tm_min ;
RTC_TimeStruct.Hours = p_tm->tm_hour;
RTC_DateStruct.Date = p_tm->tm_mday;
RTC_DateStruct.Month = p_tm->tm_mon+1 ;
RTC_DateStruct.Year = p_tm->tm_year-100;
RTC_DateStruct.WeekDay = p_tm->tm_wday+1;
HAL_RTC_SetTime(&RTC_Handler,&RTC_TimeStruct,RTC_FORMAT_BIN);
HAL_RTC_SetDate(&RTC_Handler,&RTC_DateStruct,RTC_FORMAT_BIN);
return RT_EOK;
}
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
static rt_err_t rt_rtc_open(rt_device_t dev, rt_uint16_t oflag)
{
if (dev->rx_indicate != RT_NULL)
{
/* Open Interrupt */
}
return RT_EOK;
}
static rt_size_t rt_rtc_read(
rt_device_t dev,
rt_off_t pos,
void* buffer,
rt_size_t size)
{
return 0;
}
/***************************************************************************//**
* @brief
* Configure RTC device
*
* @details
*
* @note
*
* @param[in] dev
* Pointer to device descriptor
*
* @param[in] cmd
* RTC control command
*
* @param[in] args
* Arguments
*
* @return
* Error code
******************************************************************************/
static rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void *args)
{
rt_err_t result;
RT_ASSERT(dev != RT_NULL);
switch (cmd)
{
case RT_DEVICE_CTRL_RTC_GET_TIME:
*(rt_uint32_t *)args = GetRTCTimeStamp();
rtc_debug("RTC: get rtc_time %x\n", *(rt_uint32_t *)args());
break;
case RT_DEVICE_CTRL_RTC_SET_TIME:
{
result = SetRTCTimeStamp(*(rt_uint32_t *)args);
rtc_debug("RTC: set rtc_time %x\n", *(rt_uint32_t *)args);
/* Reset counter */
}
break;
}
return result;
}
/***************************************************************************//**
* @brief
* Register RTC device
*
* @details
*
* @note
*
* @param[in] device
* Pointer to device descriptor
*
* @param[in] name
* Device name
*
* @param[in] flag
* Configuration flags
*
* @return
* Error code
******************************************************************************/
rt_err_t rt_hw_rtc_register(
rt_device_t device,
const char *name,
rt_uint32_t flag)
{
RT_ASSERT(device != RT_NULL);
device->type = RT_Device_Class_RTC;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
device->init = RT_NULL;
device->open = rt_rtc_open;
device->close = RT_NULL;
device->read = rt_rtc_read;
device->write = RT_NULL;
device->control = rt_rtc_control;
device->user_data = RT_NULL; /* no private */
/* register a character device */
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
}
/***************************************************************************//**
* @brief
* Initialize all RTC module related hardware and register RTC device to kernel
*
* @details
*
* @note
******************************************************************************/
int rt_hw_rtc_init(void)
{
RTC_Init();
/* register rtc device */
rt_hw_rtc_register(&rtc, RT_RTC_NAME, 0);
return RT_EOK;
}
INIT_BOARD_EXPORT(rt_hw_rtc_init);
#endif
/***************************************************************************//**
* @}
******************************************************************************/