当前位置:网站首页>GD32 RT-Thread RTC驱动函数
GD32 RT-Thread RTC驱动函数
2022-06-30 09:37:00 【Sky_Lannister】
GD32 RTC驱动函数
驱动函数需要修改两个文件,drv_rtc.c,使用RT_USING_RTC进行开启关闭,移植注意事项参见 移植完整版RT-Thread到GD32F4XX(详细) 中关于rtc移植相关内容,移植完成后使用及验证方法同stm32
drv_rtc.c
/** ****************************************************************************** * @file drv_rtc.c * @author yangFei * @brief 按照GD32库实现RTC驱动 * * @version V1.0.0 * @date 2022.06.24 * @verbatim * * @endverbatim ****************************************************************************** * @note 之前为RT-Thread Team的iysheng编写,但是不适用于F4XX系列 * @attention * * Change Logs: * Date Author Notes * 2022-01-25 iysheng first version * 2022.06.24 yangFei 适用芯片为GD32f4xx,使用官方提供标准库,例程移植自https://github.com/RT-Thread/rt-thread/tree/master/bsp/gd32/gd32407v-start * ****************************************************************************** */
#include <sys/time.h>
#define DBG_TAG "drv.rtc"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#ifdef RT_USING_RTC
#define RTC_CLOCK_SOURCE_LXTAL 1
__IO uint32_t prescaler_a = 0, prescaler_s = 0;
typedef struct {
struct rt_device rtc_dev;
} gd32_rtc_device;
static gd32_rtc_device g_gd32_rtc_dev;
static time_t get_rtc_timestamp(void)
{
rtc_parameter_struct rtc_timestamp = {
0}; //add by yf
struct tm tm_new = {
0};
rtc_current_time_get(&rtc_timestamp);
tm_new.tm_sec = rtc_timestamp.second;
tm_new.tm_min = rtc_timestamp.minute;
tm_new.tm_hour = rtc_timestamp.hour;
tm_new.tm_mday = rtc_timestamp.date;
tm_new.tm_mon = rtc_timestamp.month - 1;
tm_new.tm_year = rtc_timestamp.year + 100;
LOG_D("get rtc time.");
return mktime(&tm_new);
}
static rt_err_t set_rtc_timestamp(time_t time_stamp)
{
rtc_parameter_struct rtc_initpara;
struct tm *p_tm;
p_tm = localtime(&time_stamp);
if (p_tm->tm_year < 100)
{
return -RT_ERROR;
}
rtc_initpara.factor_asyn = prescaler_a;
rtc_initpara.factor_syn = prescaler_s;
rtc_initpara.display_format = RTC_24HOUR;
rtc_initpara.am_pm = RTC_AM;
rtc_initpara.second = p_tm->tm_sec ;
rtc_initpara.minute = p_tm->tm_min ;
rtc_initpara.hour = p_tm->tm_hour;
rtc_initpara.date = p_tm->tm_mday;
rtc_initpara.month = p_tm->tm_mon + 1 ;
rtc_initpara.year = p_tm->tm_year - 100;
rtc_initpara.day_of_week = p_tm->tm_wday + 1;
if (rtc_init(&rtc_initpara) == ERROR)
{
return -RT_ERROR;
}
return RT_EOK;
}
static rt_err_t rt_gd32_rtc_control(rt_device_t dev, int cmd, void *args)
{
rt_err_t result = RT_EOK;
RT_ASSERT(dev != RT_NULL);
switch (cmd)
{
case RT_DEVICE_CTRL_RTC_GET_TIME:
*(rt_uint32_t *)args = get_rtc_timestamp();
break;
case RT_DEVICE_CTRL_RTC_SET_TIME:
if (set_rtc_timestamp(*(rt_uint32_t *)args))
{
result = -RT_ERROR;
}
break;
}
return result;
}
#ifdef RT_USING_DEVICE_OPS //暂无定义
const static struct rt_device_ops g_gd32_rtc_ops =
{
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
rt_gd32_rtc_control
};
#endif
static int rt_hw_rtc_init(void)
{
rt_err_t ret;
time_t rtc_counter;
rcu_periph_clock_enable(RCU_PMU);
pmu_backup_write_enable();
rcu_periph_clock_enable(RCU_BKPSRAM);//bug RCU_BKPI - RCU_BKPSRAM
rtc_counter = get_rtc_timestamp();
/* once the rtc clock source has been selected, if can't be changed * anymore unless the Backup domain is reset */
rcu_bkp_reset_enable();
rcu_bkp_reset_disable();
#if RTC_CLOCK_SOURCE_IRC32K
rcu_osci_on(RCU_IRC32K);
if (SUCCESS == rcu_osci_stab_wait(RCU_IRC32K))
{
rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);
}
prescaler_s = 0x13F;
prescaler_a = 0x63;
#elif RTC_CLOCK_SOURCE_LXTAL
rcu_osci_on(RCU_LXTAL);
if (SUCCESS == rcu_osci_stab_wait(RCU_LXTAL))
{
/* set lxtal as rtc clock source */
rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);
}
prescaler_s = 0xFF;
prescaler_a = 0x7F;
#else
LOG_E("RTC clock source should be defined");
#endif /* RTC_CLOCK_SOURCE_IRC32K */
rcu_periph_clock_enable(RCU_RTC);
rtc_register_sync_wait();
set_rtc_timestamp(rtc_counter);
#ifdef RT_USING_DEVICE_OPS
g_gd32_rtc_dev.rtc_dev.ops = &g_gd32_rtc_ops;
#else
g_gd32_rtc_dev.rtc_dev.init = RT_NULL;
g_gd32_rtc_dev.rtc_dev.open = RT_NULL;
g_gd32_rtc_dev.rtc_dev.close = RT_NULL;
g_gd32_rtc_dev.rtc_dev.read = RT_NULL;
g_gd32_rtc_dev.rtc_dev.write = RT_NULL;
g_gd32_rtc_dev.rtc_dev.control = rt_gd32_rtc_control;
#endif
g_gd32_rtc_dev.rtc_dev.type = RT_Device_Class_RTC;
g_gd32_rtc_dev.rtc_dev.rx_indicate = RT_NULL;
g_gd32_rtc_dev.rtc_dev.tx_complete = RT_NULL;
g_gd32_rtc_dev.rtc_dev.user_data = RT_NULL;
ret = rt_device_register(&g_gd32_rtc_dev.rtc_dev, "rtc", \
RT_DEVICE_FLAG_RDWR);
if (ret != RT_EOK)
{
LOG_E("failed register internal rtc device, err=%d", ret);
}
return ret;
}
INIT_DEVICE_EXPORT(rt_hw_rtc_init);
#endif
/************************ (C) COPYRIGHT *****END OF FILE****/
gd32f4xx_rtc.c
//未做大修改,仅对rtc_init及rtc_current_time_get中的传入参数做了字节和BCD码互转的操作,寄存器中关于时间的定义使用BCD码格式
/** * @brief Convert a 2 digit decimal to BCD format. * @param Value Byte to be converted * @retval Converted byte */
uint8_t RTC_ByteToBcd2(uint8_t Value)
{
uint32_t bcdhigh = 0U;
uint8_t temp = Value;
while (temp >= 10U)
{
bcdhigh++;
temp -= 10U;
}
return ((uint8_t)(bcdhigh << 4U) | temp);
}
/** * @brief Convert from 2 digit BCD to Binary. * @param Value BCD value to be converted * @retval Converted word */
uint8_t RTC_Bcd2ToByte(uint8_t Value)
{
uint8_t tmp;
tmp = ((Value & 0xF0U) >> 4U) * 10U;
return (tmp + (Value & 0x0FU));
}
ErrStatus rtc_init(rtc_parameter_struct* rtc_initpara_struct)
{
ErrStatus error_status = ERROR;
uint32_t reg_time = 0U, reg_date = 0U;
reg_date = (DATE_YR(RTC_ByteToBcd2(rtc_initpara_struct->year)) | \
DATE_DOW(rtc_initpara_struct->day_of_week) | \
DATE_MON(RTC_ByteToBcd2(rtc_initpara_struct->month)) | \
DATE_DAY(RTC_ByteToBcd2(rtc_initpara_struct->date)));
reg_time = (rtc_initpara_struct->am_pm| \
TIME_HR(RTC_ByteToBcd2(rtc_initpara_struct->hour)) | \
TIME_MN(RTC_ByteToBcd2(rtc_initpara_struct->minute)) | \
TIME_SC(RTC_ByteToBcd2(rtc_initpara_struct->second)));
/* 1st: disable the write protection */
RTC_WPK = RTC_UNLOCK_KEY1;
RTC_WPK = RTC_UNLOCK_KEY2;
/* 2nd: enter init mode */
error_status = rtc_init_mode_enter();
if(ERROR != error_status){
RTC_PSC = (uint32_t)(PSC_FACTOR_A(rtc_initpara_struct->factor_asyn)| \
PSC_FACTOR_S(rtc_initpara_struct->factor_syn));
RTC_TIME = (uint32_t)reg_time;
RTC_DATE = (uint32_t)reg_date;
RTC_CTL &= (uint32_t)(~RTC_CTL_CS);
RTC_CTL |= rtc_initpara_struct->display_format;
/* 3rd: exit init mode */
rtc_init_mode_exit();
/* 4th: wait the RSYNF flag to set */
error_status = rtc_register_sync_wait();
}
/* 5th: enable the write protection */
RTC_WPK = RTC_LOCK_KEY;
return error_status;
}
void rtc_current_time_get(rtc_parameter_struct* rtc_initpara_struct)
{
uint32_t temp_tr = 0U, temp_dr = 0U, temp_pscr = 0U, temp_ctlr = 0U;
temp_tr = (uint32_t)RTC_TIME;
temp_dr = (uint32_t)RTC_DATE;
temp_pscr = (uint32_t)RTC_PSC;
temp_ctlr = (uint32_t)RTC_CTL;
/* get current time and construct rtc_parameter_struct structure */
rtc_initpara_struct->year = (uint8_t)GET_DATE_YR(temp_dr);
rtc_initpara_struct->month = (uint8_t)GET_DATE_MON(temp_dr);
rtc_initpara_struct->date = (uint8_t)GET_DATE_DAY(temp_dr);
rtc_initpara_struct->day_of_week = (uint8_t)GET_DATE_DOW(temp_dr);
rtc_initpara_struct->hour = (uint8_t)GET_TIME_HR(temp_tr);
rtc_initpara_struct->minute = (uint8_t)GET_TIME_MN(temp_tr);
rtc_initpara_struct->second = (uint8_t)GET_TIME_SC(temp_tr);
rtc_initpara_struct->factor_asyn = (uint16_t)GET_PSC_FACTOR_A(temp_pscr);
rtc_initpara_struct->factor_syn = (uint16_t)GET_PSC_FACTOR_S(temp_pscr);
rtc_initpara_struct->am_pm = (uint32_t)(temp_pscr & RTC_TIME_PM);
rtc_initpara_struct->display_format = (uint32_t)(temp_ctlr & RTC_CTL_CS);
/* Convert the time structure parameters to Binary format */
rtc_initpara_struct->year = (uint8_t)RTC_Bcd2ToByte(rtc_initpara_struct->year);
rtc_initpara_struct->month = (uint8_t)RTC_Bcd2ToByte(rtc_initpara_struct->month);
rtc_initpara_struct->date = (uint8_t)RTC_Bcd2ToByte(rtc_initpara_struct->date);
rtc_initpara_struct->hour = (uint8_t)RTC_Bcd2ToByte(rtc_initpara_struct->hour);
rtc_initpara_struct->minute = (uint8_t)RTC_Bcd2ToByte(rtc_initpara_struct->minute);
rtc_initpara_struct->second = (uint8_t)RTC_Bcd2ToByte(rtc_initpara_struct->second);
}
边栏推荐
- Js获取指定字符串指定字符位置&指定字符位置区间的子串【简单详细】
- Jump table introduction
- About the split and join operations of strings
- train_ de.py: error: argument --save_ steps: invalid int value: ‘$[$[889580/128/4]*10/2]‘
- Guolin was crowned the third place of global popularity of perfect master in the third quarter of 2022
- L'activité "Kunming City coffee map" a rouvert
- log4j
- South China Industrial Group launched digital economy and successfully held the city chain technology conference
- 逸仙电商发布一季报:坚持研发及品牌投入,实现可持续高质量发展
- Some domestic image sources
猜你喜欢

How does the diode work?

unable to convert expression into double array

unable to convert expression into double array

打通供应链 深圳礼品展助跨境电商寻破局之道

The preliminary round of the sixth season of 2022 perfect children's model Hefei competition area was successfully concluded

新冠无情人有情,芸众惠爱心善举暖人间——捐赠商丘市儿童福利院公益行动

【JVM】G1垃圾回收器簡述

Detailed explanation of SolidWorks mass characteristics (inertia tensor, moment of inertia, inertia spindle)

9. cache optimization

Guolin was crowned the third place of global popularity of perfect master in the third quarter of 2022
随机推荐
7. development of mobile login function
MIT-6874-Deep Learning in the Life Sciences Week6
JS get the substring of the specified character position and the specified character position interval of the specified string [simple and detailed]
Automated stock trading ensemble strategy based on Reinforcement Learning
戴森设计大奖,以可持续化设计改变世界
AttributeError: ‘Version‘ object has no attribute ‘major‘
6.Redis新数据类型
unable to convert expression into double array
Appium自动化测试基础 — adb shell 命令
Applying applet container technology to IOT ecological construction
What is the real performance of CK5, the king machine of CKB?
MIT-6874-Deep Learning in the Life Sciences Week4
G 代码解释|最重要的 G 代码命令列表
Robot system dynamics - inertia parameters
Questions about cookies and sessions
South China Industrial Group launched digital economy and successfully held the city chain technology conference
Regular expression Basics
Harvester ch1 of CKB and HNS, connection tutorial analysis
事件对象的说明》
train_ de.py: error: argument --save_ steps: invalid int value: ‘$[$[889580/128/4]*10/2]‘