RTC系统

http://blog.csdn.net/fanqipin/article/details/8089995

一. RTC及驱动简介

RTC即real time clock实时时钟,主要用于为操作系统提供可靠的时间;当系统处于断电 的情况下,RTC记录操作系统时间,并可在电池供电情况下继续正常工作,当系统正常启动后,系统可从RTC读取时间信息,来确保断电后时间运行连续性。

目前,很多CPU中都已集成RTC系统,且有许多独立的外接RTC芯片可用于实现RTC功能;

在内核中RTC驱动可分为两层,一层为于硬件无关的抽象层,主要用于管理RTC设备、设备节点,属性节点注册及操作;另一层为与硬件相关的RTC低层驱动层;抽象层程序在/drivers/rtc目录下,主要涉及下面几个文件:

class.c   用于管理和注册RTC设备结构、sysfs、procfs及RTC类;

rtc-dev.c 用于注册和管理RTC设备节点,为用户空间提供devfs操作接口,主要操作有rtc_read,rtc_ioctl;

rtc-proc.c  用于管理rtc的procfs属性节点,提供一些中断状态、标志查询;

rtc-sysfs.c 用于管理rtc设备的sysfs属性,如获取RTC设备名字、日期、时间等属性信息;

interface.c 为rtc-dev.c 和RTC低层驱动提供操作接口;

RTC系统结构示意图如图1所示;

图1 RTC系统结构图

如图1所示,RTC 设备驱动通过rtc_device_register接口向linux系统注册RTC设备,并成生proc、sys目录下的属性文件;当用户通过/dev/rtcx设备节点或proc、sysfs接口来操作RTC设备时,都需要先通过interface接口才能访问真实的设备驱动。

二. 部分数据结构分析

1. RTC设备结构

struct rtc_device
{

struct device dev;

struct module *owner;

int id;   设备编号

char name[RTC_DEVICE_NAME_SIZE];

const struct rtc_class_ops *ops;  rtc设备低层操作接口;

struct mutex ops_lock;

struct cdev char_dev;    RTC字符型设备结构;

unsigned long flags;

unsigned long irq_data;    中断数据;

spinlock_t irq_lock;

wait_queue_head_t irq_queue;   中断数据等待队列;

struct fasync_struct *async_queue;

struct rtc_task *irq_task;

spinlock_t irq_task_lock;

int irq_freq;         中断频率;

int max_user_freq;

struct timerqueue_head timerqueue;

struct rtc_timer aie_timer;                       报警中断定时器;

struct rtc_timer uie_rtctimer;                  更新中断定时器;

struct hrtimer pie_timer; /* sub second exp, so needs hrtimer */     周期中断高精度定时器;

int pie_enabled;             周期中断使能标志;

struct work_struct irqwork;

#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL    内部仿真update interrupt时所需;

struct work_struct uie_task;

struct timer_list uie_timer;

/* Those fields are protected by rtc->irq_lock */

unsigned int oldsecs;

unsigned int uie_irq_active:1;

unsigned int stop_uie_polling:1;

unsigned int uie_task_active:1;

unsigned int uie_timer_active:1;

#endif
};

2. RTC设备低层操作接口

struct rtc_class_ops {

int (*open)(struct device *);                           打开设备

void (*release)(struct device *);                    释放设备

int (*ioctl)(struct device *, unsigned int, unsigned long);

int (*read_time)(struct device *, struct rtc_time *);   读取RTC时间;

int (*set_time)(struct device *, struct rtc_time *);    设置RTC时间;

int (*read_alarm)(struct device *, struct rtc_wkalrm *);  读取RTC报警时间;

int (*set_alarm)(struct device *, struct rtc_wkalrm *);   设置RTC报警时间;

int (*proc)(struct device *, struct seq_file *);                    用于提供procfs查询rtc状态接口;

int (*set_mmss)(struct device *, unsigned long secs);   设置以S为单位RTC时间接口;

int (*read_callback)(struct device *, int data);

int (*alarm_irq_enable)(struct device *, unsigned int enabled);  中断使能接口;

};

三.RTC低层驱动实现

        RTC低层驱动实现相对比较简单,只需要通过rtc_device_register向系统注册RTC设备,并实现RTC低层操作接口;本文以samsung s3cxx系列中自带的RTC来进行分析,驱动为/drivers/rtc/rtc-s3c.c。

1. 设备驱动注册及卸载

        对于集成在CPU内部的RTC一般可通过注册平台驱动的方式进行注册,如果RTC为外扩芯片,则可以根据相应来的接口来选择注册方式,如I2C接口芯片DS1307通过i2c_add_driver方式进行注册;在S3C6410中RTC为集成在系统内部,所以通过平台方式注册,平台驱动结构及注册卸载函数接口如下所示:

static struct platform_driver s3c_rtc_driver ={

.probe = s3c_rtc_probe,

.remove = s3c_rtc_remove,

.suspend = s3c_rtc_suspend,

.resume = s3c_rtc_resume,

.id_table = s3c_rtc_driver_ids,  用于匹配平台设备

.driver = {

.name = "s3c-rtc",

.owner = THIS_MODULE,

},

}

static int __init s3c_rtc_init(void)

{

return platform_driver_register(&s3c_rtc_driver)

}

static void __exit s3c_rtc_exit(void)

{

platform_drvier_unregister(&s3c_rtc_driver)

}

module_init(s3c_rtc_init);

mosule_exit(s3c_rtc_exit)

当linux系统启动后会自动将S3C RTC平台设备驱动添加到系统中,然后会遍历platform 总线上的设备通过match_table,id_table或驱动和设备名字来进行匹配设备,如果找到对应的平台设备就会调用平台驱动中的probe函数;S3C RTC平台设备结构如下所示:

static struct resource s3c_rtc_resource[] = {

[0] = {

.start  = S3C_PA_RTC,                                          RTC寄存器起始地址空间;

.end  = S3C_PA_RTC + 0xff,

.flags  = IORESOURCE_MEM,                                resource为内存类型

},

[1] = {

.start  = IRQ_RTC_ALARM,                                    RTC报警中断号

.end  = IRQ_RTC_ALARM,

.flags  = IORESOURCE_IRQ,                                     resource为中断类型

},

[2] = {

.start  = IRQ_RTC_TIC,                                            RTC TICK中断

.end  = IRQ_RTC_TIC,

.flags  = IORESOURCE_IRQ

}

};
struct platform_device s3c_device_rtc = {

.name  = "s3c64xx-rtc",

.id   = -1,

.num_resources = ARRAY_SIZE(s3c_rtc_resource),

.resource = s3c_rtc_resource,

};

通过platform的match函数匹配完后就会调用平台驱动的probe函数,s3c_rtc_probe函数主要部分如下所示:

static int __devinit s3c_rtc_probe(struct platform_device *pdev)
{

struct rtc_device *rtc;

struct rtc_time rtc_tm;

struct resource *res;

int ret;

pr_debug("%s: probe=%p\n", __func__, pdev);

/* 从平台设备中获取相关的设备资源*/

s3c_rtc_tickno = platform_get_irq(pdev, 1);

if (s3c_rtc_tickno < 0) {

dev_err(&pdev->dev, "no irq for rtc tick\n");

return -ENOENT;

}

s3c_rtc_alarmno = platform_get_irq(pdev, 0);

if (s3c_rtc_alarmno < 0) {

dev_err(&pdev->dev, "no irq for alarm\n");

return -ENOENT;

}

/*内核中,在对内存进行操作前得先申请内存空间,通过ioremap映射完后才能使用*/

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

if (res == NULL) {

dev_err(&pdev->dev, "failed to get memory region resource\n");

return -ENOENT;

}

s3c_rtc_mem = request_mem_region(res->start, resource_size(res), pdev->name);

if (s3c_rtc_mem == NULL) {

dev_err(&pdev->dev, "failed to reserve memory region\n");

ret = -ENOENT;

goto err_nores;

}

s3c_rtc_base = ioremap(res->start, resource_size(res));

if (s3c_rtc_base == NULL) {

dev_err(&pdev->dev, "failed ioremap()\n");

ret = -EINVAL;

goto err_nomap;

}

/*获取并使能RTC 系统时钟信号*/

rtc_clk = clk_get(&pdev->dev, "rtc");

if (IS_ERR(rtc_clk)) {

dev_err(&pdev->dev, "failed to find rtc clock source\n");

ret = PTR_ERR(rtc_clk);

rtc_clk = NULL;

goto err_clk;

}

clk_enable(rtc_clk);

/* 配置S3C RTC 控制寄存器,使能RTCEN,只有当RTCEN有效时才能配置BCD等寄存器,当系统断电前得清除RTCEN,防止对BCD寄存器进行写操作; */

s3c_rtc_enable(pdev, 1);

device_init_wakeup(&pdev->dev, 1);

/*注册RTC设备,s3c_rtcops为需要实现的低层操作接口*/

rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,THIS_MODULE);

if (IS_ERR(rtc)) {

dev_err(&pdev->dev, "cannot attach rtc\n");

ret = PTR_ERR(rtc);

goto err_nortc;

}

s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;

/* Check RTC Time */

s3c_rtc_gettime(NULL, &rtc_tm);

if (rtc_valid_tm(&rtc_tm)) {

rtc_tm.tm_year = 100;

rtc_tm.tm_mon = 0;

rtc_tm.tm_mday = 1;

rtc_tm.tm_hour = 0;

rtc_tm.tm_min = 0;

rtc_tm.tm_sec = 0;

s3c_rtc_settime(NULL, &rtc_tm);

dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");

}

if (s3c_rtc_cpu_type == TYPE_S3C64XX)

rtc->max_user_freq = 32768;

else

rtc->max_user_freq = 128;

platform_set_drvdata(pdev, rtc);

/*设置时钟频率为1HZ*/

s3c_rtc_setfreq(&pdev->dev, 1);

clk_disable(rtc_clk);

return 0;

err_nortc:

s3c_rtc_enable(pdev, 0);

clk_disable(rtc_clk);

clk_put(rtc_clk);

err_clk:

iounmap(s3c_rtc_base);

err_nomap:

release_resource(s3c_rtc_mem);

err_nores:

return ret;

}

2. RTC低层操作函数接口

static const struct rtc_class_ops s3c_rtcops = {

.open  = s3c_rtc_open,

.release  = s3c_rtc_release,

.read_time = s3c_rtc_gettime,

.set_time = s3c_rtc_settime,

.read_alarm = s3c_rtc_getalarm,

.set_alarm = s3c_rtc_setalarm,

.proc  = s3c_rtc_proc,

.alarm_irq_enable = s3c_rtc_setaie,

};

static int s3c_rtc_open(struct device *dev)
{

struct platform_device *pdev = to_platform_device(dev);

struct rtc_device *rtc_dev = platform_get_drvdata(pdev);

int ret;

ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,IRQF_DISABLED,  "s3c2410-rtc alarm", rtc_dev);

if (ret) {

dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);

return ret;

}

ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, IRQF_DISABLED,  "s3c2410-rtc tick", rtc_dev);

if (ret) {

dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);

goto tick_err;

}

return ret;

tick_err:

free_irq(s3c_rtc_alarmno, rtc_dev);

return ret;

}

static void s3c_rtc_release(struct device *dev)
{

struct platform_device *pdev = to_platform_device(dev);

struct rtc_device *rtc_dev = platform_get_drvdata(pdev);

free_irq(s3c_rtc_alarmno, rtc_dev);

free_irq(s3c_rtc_tickno, rtc_dev);

}

在s3c_rtc_open()和s3c_rtc_release()用于申请和释放s3c rtc 的报警和TICK中断资源;因为中断信号线资源有限,所以最好在打开设备时申请,关闭设备时释放;

static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
{

unsigned int have_retried = 0;

void __iomem *base = s3c_rtc_base;

clk_enable(rtc_clk);

retry_get_time:

/*读取年、月、日、天、小时、分、秒数据*/

rtc_tm->tm_min  = readb(base + S3C2410_RTCMIN);

rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);

rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE);

rtc_tm->tm_mon  = readb(base + S3C2410_RTCMON);

rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);

rtc_tm->tm_sec  = readb(base + S3C2410_RTCSEC);

if (rtc_tm->tm_sec == 0 && !have_retried) {

have_retried = 1;

goto retry_get_time;

}

/*将读取出来的数据进行BCD转二进制操作*/

rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);

rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);

rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);

rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);

rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);

rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);

rtc_tm->tm_year += 100;

rtc_tm->tm_mon -= 1;

clk_disable(rtc_clk);

return rtc_valid_tm(rtc_tm);

}

s3c_rtc_gettime用于从S3C RTC里读出RTC 日期和时间,RTC时间1S更新一次,在读时间的过程中如果秒为0,表示从秒从59到0跳变,则需要重新读取时间,S3C RTC的时候为BCD码形式,需要进行简单的转换才能得到正确时间信息。

static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
{

void __iomem *base = s3c_rtc_base;

int year = tm->tm_year - 100;

clk_enable(rtc_clk);

/* we get around y2k by simply not supporting it */

if (year < 0 || year >= 100) {

dev_err(dev, "rtc only supports 100 years\n");

return -EINVAL;

}

/*将时间数据转成BCD码形式后存入到相应寄存器*/

writeb(bin2bcd(tm->tm_sec),  base + S3C2410_RTCSEC);

writeb(bin2bcd(tm->tm_min),  base + S3C2410_RTCMIN);

writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR);

writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);

writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);

writeb(bin2bcd(year), base + S3C2410_RTCYEAR);

clk_disable(rtc_clk);

return 0;

}

s3c_rtc_settime()设置RTC时间,在应用层用hwclock -w来进行同步系统和RTC时间时会调用该函数。

static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
{

struct rtc_time *alm_tm = &alrm->time;

void __iomem *base = s3c_rtc_base;

unsigned int alm_en;

clk_enable(rtc_clk);

alm_tm->tm_sec  = readb(base + S3C2410_ALMSEC);

alm_tm->tm_min  = readb(base + S3C2410_ALMMIN);

alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);

alm_tm->tm_mon  = readb(base + S3C2410_ALMMON);

alm_tm->tm_mday = readb(base + S3C2410_ALMDATE);

alm_tm->tm_year = readb(base + S3C2410_ALMYEAR);

alm_en = readb(base + S3C2410_RTCALM);

alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;

/* decode the alarm enable field */

if (alm_en & S3C2410_RTCALM_SECEN)

alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);

else

alm_tm->tm_sec = -1;

if (alm_en & S3C2410_RTCALM_MINEN)

alm_tm->tm_min = bcd2bin(alm_tm->tm_min);

else

alm_tm->tm_min = -1;

if (alm_en & S3C2410_RTCALM_HOUREN)

alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);

else

alm_tm->tm_hour = -1;

if (alm_en & S3C2410_RTCALM_DAYEN)

alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);

else

alm_tm->tm_mday = -1;

if (alm_en & S3C2410_RTCALM_MONEN) {

alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);

alm_tm->tm_mon -= 1;

} else {

alm_tm->tm_mon = -1;

}

if (alm_en & S3C2410_RTCALM_YEAREN)

alm_tm->tm_year = bcd2bin(alm_tm->tm_year);

else

alm_tm->tm_year = -1;

clk_disable(rtc_clk);

return 0;

}

s3c_rtc_getalarm()函数读 ALARM 中BCD码时间信息,并根据ALARM控制寄存器的值来进行BCD转二进制,如果ALARM控制寄存器中使能相应位,则进行BCD转换,否则相应数据填-1处理;

static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{

struct rtc_time *tm = &alrm->time;

void __iomem *base = s3c_rtc_base;

unsigned int alrm_en;

clk_enable(rtc_clk);

alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;

writeb(0x00, base + S3C2410_RTCALM);

if (tm->tm_sec < 60 && tm->tm_sec >= 0) {

alrm_en |= S3C2410_RTCALM_SECEN;

writeb(bin2bcd(tm->tm_sec), base + S3C2410_ALMSEC);

}

if (tm->tm_min < 60 && tm->tm_min >= 0) {

alrm_en |= S3C2410_RTCALM_MINEN;

writeb(bin2bcd(tm->tm_min), base + S3C2410_ALMMIN);

}

if (tm->tm_hour < 24 && tm->tm_hour >= 0) {

alrm_en |= S3C2410_RTCALM_HOUREN;

writeb(bin2bcd(tm->tm_hour), base + S3C2410_ALMHOUR);

}

writeb(alrm_en, base + S3C2410_RTCALM);

s3c_rtc_setaie(dev, alrm->enabled);

clk_disable(rtc_clk);

return 0;

}

s3c_rtc_setalarm()检查填入的报警时间是否合法,如果合法则将时间信息存入ALARM时间寄存器,并使能小时、分、秒相应ALARM使能位;当正常BCD寄存器里的时间和ALARM寄存器里的时间相等时,发生报警中断 ;中断发生后就会调用在s3c_rtc_open函数中申请alarm中断服务程序s3c_rtc_alarmirq();

static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
{

struct rtc_device *rdev = id;

clk_enable(rtc_clk);

rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);

if (s3c_rtc_cpu_type == TYPE_S3C64XX)

writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);

clk_disable(rtc_clk);

return IRQ_HANDLED;

}

s3c_rtc_alarmirq()中断服务程序主要通过rtc_update_irq来更新中断数据;

3. 使用过程中出现问题及解决方法

       在使用hwclock命令进行同步系统和硬件时间时,调试口输出“select() to /dev/rtc0 to wait for clock tick timed out.”;后来跟踪hwclock源码发现,原来在用hwclock进行显示,设置RTC硬件时间之前都会先通过进行时钟tick同步,同步方法是开启1S 一次update interrupt,每过1S RTC都会产生一次报警中断,并更新相应的中断数据,在应用层通过select来监控是否有RTC数据可读,如果有数据则会继续显示或设置硬件时间操作,否则输出

“select() to /dev/rtc0 to wait for clock tick timed out.”

linux系统中/proc/interrupt可以用来查询中断号,中断使用次数等信息,由于S3C RTC中的中断申请是在s3c_rtc_open中,所以每次使用完就会在s3c_rtc_release中释放,所以无法在/proc/interrupt中查询到rtc相应信息,为了确定是否有中断产生,把中断申请和释放移到s3c_rtc_probe和s3c_rtc_remove函数中。更新程序后发现S3C RTC中的alarm 和tick中断相应的次数都为0,说明根本就没有产生中断。后来经过测试和分析发现,原来S3C RTC中的低层操作接口在每次设置完相应的寄存器后都会关闭RTC时钟,即clk_disable(rtc_clk);而没有RTC时钟就不会产生相应ALARM 和TICK中断,所以解决的方法就是使能RTC时钟;解决方法是在打开 RTC设备时,就一直使能时钟直到关闭设备;

后来在看源码修改历史时,发现源码中已经解决并更新了这个BUG,有兴趣的可以去看源码修改记录;

时间: 2024-12-12 20:30:34

RTC系统的相关文章

RTC系统【转】

http://blog.csdn.net/fanqipin/article/details/8089995 转自:http://www.cnblogs.com/muhuacat/p/5276306.html 一. RTC及驱动简介 RTC即real time clock实时时钟,主要用于为操作系统提供可靠的时间:当系统处于断电 的情况下,RTC记录操作系统时间,并可在电池供电情况下继续正常工作,当系统正常启动后,系统可从RTC读取时间信息,来确保断电后时间运行连续性. 目前,很多CPU中都已集成

Android系统移植:驱动篇

[导语]在Android系统移植中,有很重要的一个部分工作,就是为新平台上的硬件设备移植驱动程序.因为Android系统是基于Linux kernel内核构建,所以这里说的移植驱动程序,其实就是基于Android系统平台开发适应移动设备的Linux内核驱动程序. 一. Android系统中Linux内核与设备驱动 Android系统中使用了Linux内核作为自己的操作系统,除了linux的通用代码之外,主要还包含三个方面的东西: 体系结构和处理器 体系结构处理器和标准的设备驱动程序这两个方面是和

Linux-NTP-Server+Client

GMT/UTC/CST;/etc/localtime,/usr/share/zoneinfo/*时区文件,/etc/profile加TZ变量;硬件时间RTC,系统时间;date,hwclock,tzselect;/usr/share/zoneinfo/Asia zdump sichuan 查看对于每个time zone当前的时间# hwclock --set --date="mm/dd/yy hh:mm:ss" 设置硬件时间我们可以开机的时候在BIOS里设定.也可以用hwclock命令

2012高校GIS论坛

江苏省会议中心 南京·钟山宾馆(2012年4月21-22日) 以"突破与提升"为主题的"2012高校GIS论坛"将于4月在南京举行,由南京大学和工程中心共同承办.高校GIS论坛每两年举办一次,已在北京九华山庄成功举办三届,现已发展成为国内高校GIS教育界最有权威,最具影响力的高端论坛. 赛迪网直播小组正在现场进行图文.微博直播——2012高校GIS论坛! 主持人:尊敬的李院长.曹省长.陈校长,“突破与提升2012高校GIS论坛”现在开幕!首先请允许我介绍出席今天开幕

Linux系统时间与RTC时间【转】

http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=3637782 Linux的RTC驱动相对还是比较简单的,可以将它作为一个普通的字符型设备,或者一个misc设备,也可以是一个平台设备,这都没有关系,主要还是对rtc_ops这个文件操作结构体中的成员填充,这里主要涉及到两个方面比较重要: 1. 在Linux中有硬件时钟与系统时钟等两种时钟.硬件时钟是指主机板上的时钟设备,也就是通常可在BIOS画面设定的时钟.系统时钟则是指kernel中的

Linux中系统时间和RTC时间的关系

摘自:http://www.yunweipai.com/archives/208.html?utm_source=tuicool&utm_medium=referral Linux中系统时间和RTC时间的关系 2012-08-12 09:08 阅读 4.4k 评论 0 2017年Gdevops全球敏捷运维峰会-成都站(限时优惠),运维派作为本次峰会协办方,您可以点击这里了解详情 RTC(Real-Time Clock),翻译过来是实时时钟芯片,具体就不再往下解释了,有兴趣的就直接百度搜索下吧.对

Linux应用层系统时间写入RTC时钟的方法

Linux内核版本:linux-3.0.35 开发板:i.MX6S MY-IMX6-EK200 系统:Ubuntu12 前言:之前写过一篇关于如何通过应用层程序读取系统时间的blog,今天再写一篇如何写入并保存RTC时钟的blog吧. 一.写入时间 1.预备知识: a.mktime 头文件:#include <time.h> 函数:time_t mktime(struct tm *timeptr) 函数说明:mktime()用来将timeptr所指的tm结构体数据换成从公元1970年1月1日0

linux 系统 /proc

1. /proc目录Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构.改变内核设置的机制.proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间.它以文件系统的方式为访问系统内核数据的操作提供接口. 用户和应用程序可以通过 proc得到系统的信息,并可以改变内核的某些参数.由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是 动态从系统内核读出所需信息并提交的.下面列出的这些文件或子文件夹,并不是都是在你的

[i.MX6q]i.MX6q处理器,linux操作系统平台搭建 从SD卡启动系统

转自:http://www.07net01.com/linux/2016/02/1232094.html 参照1:http://blog.csdn.net/girlkoo/article/details/44536447 参照2:http://blog.csdn.net/girlkoo/article/details/44626011 2017-02-04 22:52:54 目录: 本文的目的是,完成一个从sd卡启动的一个纯净版的linux系统移植,其实就是一个很裸的根文件系统,后期有空会试着把