rtc为操作系统提供时钟、日历、闹钟、周期性中断等功能,并且在断电的情况下,可以由电池供电,以很小的耗电继续运行下去,Linux内核已经支持s3c2416的rtc驱动。
1. rtc设备
rtc设备包含了名字、独有的资源等等一些驱动程序的硬件或自定义信息。通过platform_add_devices(platform_device_register)函数将定义的平台设备注册到内核中,用于匹配设备驱动。
内核在drivers\rtc\rtc-s3c.c中实现了s3c2416 rtc驱动, rtc设备平台代码如下。
static struct resources3c_rtc_resource[] = {[0]= DEFINE_RES_MEM(S3C24XX_PA_RTC, SZ_256),[1]= DEFINE_RES_IRQ(IRQ_RTC),[2]= DEFINE_RES_IRQ(IRQ_TICK),};struct platform_device s3c_device_rtc ={.name = "s3c2410-rtc",.id = -1,.num_resources = ARRAY_SIZE(s3c_rtc_resource),.resource = s3c_rtc_resource,};
在static struct platform_device *home2416_devices[]板级平台设备列表中加入&3c_device_rtc,使rtc设备能够注册到内核中。
rtc-s3c.c默认只支持devices tree匹配驱动的方式,修改rtc-s3c.c使之支持平台匹配的驱动方式。
s3c_rtc_driver结构体中加入s3c_rtc_driver_id。
// addstatic const struct platform_device_ids3c_rtc_driver_ids[] = {{.name = "s3c2410-rtc",.driver_data = (unsigned long)&s3c2410_rtc_data,},{.name = "s3c2416-rtc",.driver_data = (unsigned long)&s3c2416_rtc_data,},{.name = "s3c2443-rtc",.driver_data = (unsigned long)&s3c2443_rtc_data,},{.name = "e3c6410-rtc",.driver_data = (unsigned long)&s3c6410_rtc_data,},{.name = "exynos3250-rtc",.driver_data = (unsigned long)&s3c6410_rtc_data,},{},};MODULE_DEVICE_TABLE(platform,s3c_rtc_driver_ids);static struct platform_drivers3c_rtc_driver = {.probe = s3c_rtc_probe,.remove = s3c_rtc_remove,.id_table = s3c_rtc_driver_ids, // add.driver = {.name = "s3c-rtc",.pm = &s3c_rtc_pm_ops,.of_match_table = of_match_ptr(s3c_rtc_dt_match),},};
s3c_rtc_probe函数中更改从platform_device_id表中获取rtc的driver data。
conststruct platform_device_id *platid; // add// info->data= s3c_rtc_get_data(pdev); // deleteplatid= platform_get_device_id(pdev); // addinfo->data= (struct s3c_rtc_data *)platid->driver_data; // add
2. 内核配置
Linux配置支持rtc设备驱动,选中Device Drivers-> Real Time Clock ->Samsung S3C series SoC RTC。

3. rtc测试
编译内核并启动。用date命令设置、显示时间。

4. 应用编程
cat/proc/devices可以知道rtc的主设备号为253,次设备号为0,在/dev目录中创建rtc设备文件。
mknod /dev/rtc0 c 253 0
应用程序可以通过设备文件访问rtc,rtc应用测试代码rtc_test.c如下。
#include "fcntl.h"#include <stdio.h>#include <stdlib.h>#include <linux/rtc.h>#include <sys/ioctl.h>int main(void){intfd;intret;structrtc_time rtc_tm;fd= open("/dev/rtc0", O_RDONLY);if(fd == -1) {printf("Openrtc failed\n");exit(1);}ret= ioctl(fd, RTC_RD_TIME, &rtc_tm);if(ret == -1) {printf("Readrtc failed\n");close(fd);exit(1);}printf("Oldtime: %d-%d-%d, %02d:%02d:%02d\n",rtc_tm.tm_year + 1900,rtc_tm.tm_mon + 1,rtc_tm.tm_mday,rtc_tm.tm_hour, rtc_tm.tm_min,rtc_tm.tm_sec);rtc_tm.tm_year= 2017 - 1900;rtc_tm.tm_mon= 2 - 1;rtc_tm.tm_mday= 20;rtc_tm.tm_hour= 21;rtc_tm.tm_min= 0;rtc_tm.tm_sec= 0;ret= ioctl(fd, RTC_SET_TIME, &rtc_tm);if(ret == -1) {printf("Writertc failed\n");close(fd);exit(1);}printf("Settime: %d-%d-%d, %02d:%02d:%02d\n",rtc_tm.tm_year + 1900,rtc_tm.tm_mon + 1,rtc_tm.tm_mday,rtc_tm.tm_hour, rtc_tm.tm_min,rtc_tm.tm_sec);ret= ioctl(fd, RTC_RD_TIME, &rtc_tm);if(ret == -1) {printf("Readrtc failed\n");close(fd);exit(1);}printf("Newtime: %d-%d-%d, %02d:%02d:%02d\n",rtc_tm.tm_year + 1900,rtc_tm.tm_mon + 1,rtc_tm.tm_mday,rtc_tm.tm_hour, rtc_tm.tm_min,rtc_tm.tm_sec);close(fd);return0;}
用arm-linux-gcc静态编译,使之生成arm cpu可执行的指令,并且可脱离任何库独立运行,arm-linux-gcc -static -o rtc_test rtc_test.c,生成rtc_test可执行文件。复制可执行文件到根文件系统,目标板启动后在目录输入./rtc_test即可执行。

5、附录
| 文件 | 下载地址 |
|---|---|
| bootloader源码以及使用说明 | https://pan.baidu.com/s/1slczwhJ |
| Qt5.8官网源码 | https://pan.baidu.com/s/1eRDJtNs |
| 本系列例程的根文件系统 | https://pan.baidu.com/s/1nuGmSqt |
| opev3.2.0官网源码 | https://pan.baidu.com/s/1i5btLGT |
| yaffs官网源码 | https://pan.baidu.com/s/1pLpuHw3 |
| busybox-1.26.2官网源码 | https://pan.baidu.com/s/1bpkZynt |
| tslib官网源码 | https://pan.baidu.com/s/1i4EtjfR |
| mplayer-1.3.0官网源码 | https://pan.baidu.com/s/1i5MGRhb |
| 基于S3C2416修改的linux-4.10.10源码 | https://pan.baidu.com/s/1sl0fXlr |
