Magicoe是攻城狮 · 2022年08月31日 · 上海市长宁区

【MM32F5270开发板试用】七、在rt-thread 上RTC实时时钟的驱动实现

这第七篇算是停不下键盘的动力来写的,RTC不是什么大的IP,但是对后边我的demo有一丢丢重要。
简单写写记录下,希望对后来者有所帮助
rt-thread的组件component下有RTC的框架程序rtc.c,添加到工程里
1.png

添加这两个宏定义到rtconfig.h

#define RT_USING_RTC
#define BSP_USING_RTC

在工程里添加drv_rtc.c的驱动程序,代码如下

/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-03-15     Liuguang     the first version.
 * 2019-07-19     Magicoe      The first version for LPC55S6x
 * 2022-08-17     Magicoe      port to MM32F5270
 */
#include <rtthread.h>
#include "rtconfig.h"

#include "drv_rtc.h" 


#include <time.h>

#ifdef RT_USING_RTC
#include "hal_rtc.h"

static time_t get_timestamp(void) 
{
    struct tm tm_new = {0}; 
    
    RTC_Time_Type rtc_time;
    
    rtc_time.Lyears  = 1970u;
    while ( 0u == (RTC_GetStatus(RTC) & RTC_STATUS_SYNC) )  /* Wait to register synchronization. Only register synchronization can read RTC register. */
    {
    }
    RTC_CalcTime(RTC, &rtc_time);

    tm_new.tm_sec  = rtc_time.Secs; 
    tm_new.tm_min  = rtc_time.Mins; 
    tm_new.tm_hour = rtc_time.Hours;
    
    tm_new.tm_mday = rtc_time.Days; 
    tm_new.tm_mon  = rtc_time.Months - 1; 
    tm_new.tm_year = rtc_time.Years - 1900; 

    return mktime(&tm_new);
}

static int set_timestamp(time_t timestamp)
{
    struct tm *p_tm;
    
    p_tm = localtime(&timestamp);
    
#if 0
    rtc_datetime_t rtcDate; 
    rtcDate.second = p_tm->tm_sec ; 
    rtcDate.minute = p_tm->tm_min ; 
    rtcDate.hour   = p_tm->tm_hour; 

    rtcDate.day    = p_tm->tm_mday; 
    rtcDate.month  = p_tm->tm_mon  + 1;  
    rtcDate.year   = p_tm->tm_year + 1900; 
    
    /* RTC time counter has to be stopped before setting the date & time in the TSR register */
    RTC_StopTimer(RTC);
    
    /* Set RTC time to default */
    RTC_SetDatetime(RTC, &rtcDate);

    /* Start the RTC time counter */
    RTC_StartTimer(RTC);
#endif
    
    return RT_EOK;
}

static rt_err_t lpc_rtc_init(rt_device_t dev)
{
    /* Init RTC */
    RTC_Init_Type rtc_init;
    RTC_Time_Type rtc_time;

    rtc_init.ClockFreq     =  32768u;
    rtc_init.CountFreq     =  1u;

    /* Setup RTC clock initialization time. */
    rtc_time.Years         =  2022u;
    rtc_time.Months        =  8u;
    rtc_time.Days          =  17u;
    rtc_time.Hours         =  17;
    rtc_time.Mins          =  45;
    rtc_time.Secs          =  10;
    rtc_time.Lyears        =  1970u;

    while ( 0u == (RTC_GetStatus(RTC) & RTC_STATUS_SYNC) ) /* Wait for register synchronization. */
    {
    }

    RTC_Init(RTC, &rtc_init);    /* Initialize RTC. */
    while ( 0u == (RTC_GetStatus(RTC) & RTC_STATUS_OPERATION)  )  /* Wait for write operation finish. */
    {
    }
    
    RTC_SetTime(RTC, &rtc_time);
    while ( 0u == (RTC_GetStatus(RTC) & RTC_STATUS_OPERATION)  )  /* Wait for write operation finish. */
    {
    }
    
    return RT_EOK; 
}

static rt_err_t lpc_rtc_open(rt_device_t dev, rt_uint16_t oflag)
{
    return RT_EOK; 
}

static rt_err_t lpc_rtc_close(rt_device_t dev) 
{
    return RT_EOK; 
} 

static rt_size_t lpc_rtc_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
    return 0; 
}

static rt_size_t lpc_rtc_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
    return 0; 
}

static rt_err_t lpc_rtc_control(rt_device_t dev, int cmd, void *args)
{
    RT_ASSERT(dev != RT_NULL);
    
    switch(cmd)
    {
        case RT_DEVICE_CTRL_RTC_GET_TIME: 
        {
            *(uint32_t *)args = get_timestamp(); 
        }
        break;
            
        case RT_DEVICE_CTRL_RTC_SET_TIME: 
        {
            set_timestamp(*(time_t *)args); 
        }
        break;
            
        default:
            return RT_EINVAL; 
    }
    
    return RT_EOK; 
}

static struct rt_device device = 
{
    .type    = RT_Device_Class_RTC, 
    .init    = lpc_rtc_init, 
    .open    = lpc_rtc_open, 
    .close   = lpc_rtc_close, 
    .read    = lpc_rtc_read,
    .write   = lpc_rtc_write,
    .control = lpc_rtc_control, 
};

int rt_hw_rtc_init(void)
{
    rt_err_t ret = RT_EOK;
    
    ret = rt_device_register(&device, "rtc", RT_DEVICE_FLAG_RDWR); 
    if(ret != RT_EOK)
    {
        return ret; 
    }
    
    rt_device_open(&device, RT_DEVICE_OFLAG_RDWR); 
    
    return RT_EOK; 
}
INIT_DEVICE_EXPORT(rt_hw_rtc_init); 

#endif /*RT_USING_RTC */

细节代码可以参考MM家的SDK里的参考例程

rtc相关msh的命令是date,编译下载运行后的效果如下图
2.png

随手一篇,记录记录,有问题大家讨论

推荐阅读
关注数
6110
内容数
272
灵动MM32 MCU相关技术知识,欢迎关注~
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息