当前位置:网站首页>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);
}
边栏推荐
- 【JVM】G1垃圾回收器简述
- Setting up the d2lbook environment for Li Mu's "hands on learning and deep learning"
- ModuleNotFoundError: No module named ‘_swigfaiss‘
- 二极管如何工作?
- KOREANO ESSENTIAL打造气质职场范
- ‘Failed to fetch current robot state‘ when using the ‘plan_ kinematic_ path‘ service #868
- Use and description of event delegation
- SolidWorks质量特性详解(惯性张量、转动惯量、惯性主轴)
- 1033 To Fill or Not to Fill
- 文章内容无法复制复制不了
猜你喜欢

力扣 428. 序列化和反序列化 N 叉树 DFS

Koreano essential creates a professional style

开源了!文心大模型ERNIE-Tiny轻量化技术,又准又快,效果全开

JS obtient la chaîne spécifiée spécifiant la position du caractère & sous - chaîne spécifiant la plage de position du caractère 【 détails simples 】

Appium automation test foundation - 12 Introduction to appium automated testing framework

7. development of mobile login function

逸仙電商發布一季報:堅持研發及品牌投入,實現可持續高質量發展

C语言实现扫雷游戏,附详解及完整代码

机械臂速成小指南(四):机械臂关键部件之减速机

Force buckle 428 Serialize and deserialize n-tree DFS
随机推荐
Network based BGP
How to seize the opportunity of NFT's "chaos"?
“昆明城市咖啡地图”活动再度开启
Memorize the text and remember the words. Read the text and remember the words. Read the article and remember the words; 40 articles with 3500 words; 71 articles broke through the words in the middle
栈题目:字符串解码
【JVM】G1垃圾回收器简述
Setting up the d2lbook environment for Li Mu's "hands on learning and deep learning"
Launch of Rural Revitalization public welfare fund and release of public welfare bank for intangible cultural heritage protection of ancient tea tree
Didn't receive robot state (joint angles) with recent timestamp within 1 seconds
Basic MySQL operation commands of database
KOREANO ESSENTIAL打造气质职场范
无人机项目跟踪记录八十三---pcb图完成
OSError: [Errno 28] No space left on device
7.手机登陆功能开发
Applying applet container technology to IOT ecological construction
NLopt--非线性优化--原理介绍及使用方法
AttributeError: ‘Version‘ object has no attribute ‘major‘
Regular expression Basics
"Kunming City coffee map" activity was launched again
Detailed explanation of SolidWorks mass characteristics (inertia tensor, moment of inertia, inertia spindle)