0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux RTC開發(fā)指南

嵌入式Linux那些事 ? 來源:嵌入式Linux那些事 ? 作者:嵌入式Linux那些事 ? 2023-03-06 10:22 ? 次閱讀

Linux RTC 開發(fā)指南

1 概述

1.1 編寫目的

介紹Linux 內(nèi)核中RTC 驅(qū)動的適配和DEBUG 方法,為RTC 設(shè)備的使用者和維護者提供參考。

1.2 適用范圍

內(nèi)核版本 驅(qū)動文件
LINUX-4.9 及以上 RTC-SUNXI.C

1.3 相關(guān)人員

RTC 驅(qū)動及應(yīng)用層的開發(fā)/維護人員。

2 模塊介紹

Linux 內(nèi)核中,RTC 驅(qū)動的結(jié)構(gòu)圖如下所示, 可以分為三個層次:

image-20221216114050541

接口層,負責(zé)向用戶空間提供操作的結(jié)點以及相關(guān)接口。 ? RTC Core, 為rtc 驅(qū)動提供了一套API, 完成設(shè)備和驅(qū)動的注冊等。 ? RTC 驅(qū)動層,負責(zé)具體的RTC 驅(qū)動實現(xiàn),如設(shè)置時間、鬧鐘等設(shè)置寄存器的操作。

2.2 相關(guān)術(shù)語介紹

術(shù)語 解釋說明
Sunxi 指Allwinner 的一系列SoC 硬件平臺
RTC Real Time Clock,實時時鐘

2.3 源碼結(jié)構(gòu)介紹

linux-4.9

└-- drivers

└-- rtc

|-- class.c

|-- hctosys.c

|-- interface.c

|-- rtc-dev.c

|-- rtc-lib.c

|-- rtc-proc.c

|-- rtc-sysfs.c

|-- systohc.c

|-- rtc-core.h

|-- rtc-sunxi.c

└-- rtc-sunxi.h

linux-5.4

└-- drivers

└-- rtc

|-- class.c

|-- hctosys.c

|-- interface.c

|-- dev.c

|-- lib.c

|-- proc.c

|-- sysfs.c

|-- systohc.c

|-- rtc-core.h

|-- rtc-sunxi.c

└-- rtc-sunxi.h

3 模塊配置介紹

3.1 kernel menuconfig 配置

3.1.1 linux-4.9 版本下

在命令行中進入內(nèi)核根目錄(kernel/linux-4.9),執(zhí)行make ARCH=arm64(arm) menuconfig(32 位系統(tǒng)為make ARCH=arm menuconfig) 進入配置主界面(linux-5.4 內(nèi)核版本在longan 目錄下執(zhí)行:./build.sh menuconfig 進入配置主界面),并按以下步驟操作: 首先,選擇Device Drivers 選項進入下一級配置,如下圖所示:

image-20221216114515324

選擇Real Time Clock,進入下級配置,如下圖所示:

image-20221216114527372

選擇Allwinner sunxi RTC,如下圖所示:

image-20221216114542981

由于在關(guān)機過程中,RTC 一般都是獨立供電的,因此在RTC 電源域中的寄存器不會掉電且RTC寄存器的值也不會恢復(fù)為默認值。利用此特性,Sunxi 平臺支持reboot 命令的一些擴展功能和 假關(guān)機功能,但需要打開support ir fake poweroff 和Sunxi rtc reboot Feature 選項,RTC驅(qū)動才能支持這些擴展功能。

3.1.2 linux-5.4 版本下

在命令行中進入longan 頂層目錄,執(zhí)行./build.sh config,按照提示配置平臺、板型等信息(如果之前已經(jīng)配置過,可跳過此步驟)。 然后執(zhí)行./build.sh menuconfig,進入內(nèi)核圖形化配置界面,并按以下步驟操作: 選擇Device Driver選項進入下一級配置,如下圖所示:

image-20221216114823615

選擇Real Time Clock進入下一級配置,如下圖所示:

image-20221216114840997

選擇Allwinner sunxi RTC配置,如下圖所示。

image-20221216114857679

由于在關(guān)機過程中,RTC 一般都是獨立供電的,因此在RTC 電源域中的寄存器不會掉電且RTC寄存器的值也不會恢復(fù)為默認值。利用此特性,Sunxi 平臺支持reboot 命令的一些擴展功能,但需要打開Sunxi rtc reboot flag和Sunxi rtc general register save bootcount選項,RTC 驅(qū)動才能支持這些擴展功能。

3.2 device tree 源碼結(jié)構(gòu)和路徑

SoC 級設(shè)備樹文件(sun*.dtsi)是針對該SoC 所有方案的通用配置:

? 對于ARM64 CPU 而言,SoC 級設(shè)備樹的路徑為:arch/arm64/boot/dts/sunxi/sun*.dtsi

? 對于ARM32 CPU 而言,SoC 級設(shè)備樹的路徑為:arch/arm/boot/dts/sun*.dtsi

板級設(shè)備樹文件(board.dts)是針對該板型的專用配置:

? 板級設(shè)備樹路徑:device/config/chips/{IC}/configs/{BOARD}/board.dts

板級設(shè)備樹文件(board.dts)是針對該板型的專用配置: ? 板級設(shè)備樹路徑:device/config/chips/{IC}/configs/{BOARD}/board.dts

3.2.1 linux-4.9 版本下

device tree 的源碼結(jié)構(gòu)關(guān)系如下:

board.dts

└--------sun*.dtsi

|------sun*-pinctrl.dtsi

└------sun*-clk.dtsi

3.2.2 linux-5.4 版本下

device tree 的源碼結(jié)構(gòu)關(guān)系如下:

board.dts

└--------sun*.dtsi

3.3 device tree 對RTC 控制器的通用配置

3.3.1 linux-4.9 版本下

1 / {

2 rtc: rtc@07000000 {

3 compatible = "allwinner,sunxi-rtc"; //用于probe驅(qū)動

4 device_type = "rtc";

5 auto_switch; //支持RTC使用的32k時鐘源硬件自動切換

6 wakeup-source; //表示RTC是具備休眠喚醒能力的中斷喚醒源

7 reg = <0x0 0x07000000 0x0 0x200>; //RTC寄存器基地址和映射范圍

8 interrupts = ; //RTC硬件中斷號

9 gpr_offset = <0x100>; //RTC通用寄存器的偏移

10 gpr_len = <8>; //RTC通用寄存器的個數(shù)

11 gpr_cur_pos = <6>;

12 };

13 }

說明 對于linux-4.9 內(nèi)核,當(dāng)RTC 結(jié)點下配置auto_switch 屬性時,RTC 硬件會自動掃描檢查外部32k 晶體振蕩器的起振情 況。當(dāng)外部晶體振蕩器工作異常時,RTC 硬件會自動切換到內(nèi)部RC16M 時鐘分頻出來的32k 時鐘,從而保證RTC 工作正 常。當(dāng)沒有配置該屬性時,驅(qū)動代碼中直接把RTC 時鐘源設(shè)置為外部32k 晶體的,當(dāng)外部32K 晶體工作異常時,RTC 會工 作異常。因此建議配置上該屬性。

3.3.2 linux-5.4 版本下

1 / {

2 rtc: rtc@7000000 {

3 compatible = "allwinner,sun50iw10p1-rtc"; //用于probe驅(qū)動

4 device_type = "rtc";

5 wakeup-source; //表示RTC是具備休眠喚醒能力的中斷喚醒源

6 reg = <0x0 0x07000000 0x0 0x200>; //RTC寄存器基地址和映射范圍

7 interrupts = ; //RTC硬件中斷號

8 clocks = <&r_ccu CLK_R_AHB_BUS_RTC>, <&rtc_ccu CLK_RTC_1K>; //RTC所用到的時鐘

9 clock-names = "r-ahb-rtc", "rtc-1k"; //上述時鐘的名字

10 resets = <&r_ccu RST_R_AHB_BUS_RTC>;

11 gpr_cur_pos = <6>; //當(dāng)前被用作reboot-flag的通用寄存器的序號

12 };

13 }

在Device Tree 中對每一個RTC 控制器進行配置, 一個RTC 控制器對應(yīng)一個RTC 節(jié)點, 節(jié)點屬性的含義見注釋。

3.4 board.dts 板級配置

board.dts用于保存每個板級平臺的設(shè)備信息(如demo 板、demo2.0 板等等)。board.dts路徑如下:

device/config/chips/{IC}/configs/{BOARD}/boar d.dts

在board.dts中的配置信息如果在*.dtsi(如sun50iw9p1.dtsi等) 中存在,則會存在以下覆蓋規(guī)則:

在board.dts中的配置信息如果在*.dtsi(如sun50iw9p1.dtsi等) 中存在,則會存在以下覆蓋規(guī)則:

相同屬性和結(jié)點,board.dts的配置信息會覆蓋*.dtsi中的配置信息

新增加的屬性和結(jié)點,會添加到編譯生成的dtb 文件中

4 接口描述

RTC 驅(qū)動會注冊生成串口設(shè)備/dev/rtcN,應(yīng)用層的使用只需遵循Linux 系統(tǒng)中的標準RTC 編程方法即可。

4.1 打開/關(guān)閉RTC 設(shè)備

使用標準的文件打開函數(shù):

1 int open(const char *pathname, int flags); 2 int close(int fd);

需要引用頭文件:

1 #include 2 #include 3 #include 4 #include

4.2 設(shè)置和獲取RTC 時間

同樣使用標準的ioctl 函數(shù):

1 int ioctl(int d, int request, ...);

需要引用頭文件:

1 #include 2 #include

5 模塊使用范例

此demo 程序是打開一個RTC 設(shè)備,然后設(shè)置和獲取RTC 時間以及設(shè)置鬧鐘功能。

1 #include /*標準輸入輸出定義*/ 2 #include /*標準函數(shù)庫定義*/ 3 #include /*Unix 標準函數(shù)定義*/ 4 #include 5 #include 6 #include /*文件控制定義*/ 7 #include /*RTC支持的CMD*/ 8 #include /*錯誤號定義*/ 9 #include 10 11 #define RTC_DEVICE_NAME "/dev/rtc0" 12 13 int set_rtc_timer(int fd) 14 { 15 struct rtc_time rtc_tm = {0}; 16 struct rtc_time rtc_tm_temp = {0}; 17 18 rtc_tm.tm_year = 2020 - 1900; /* 需要設(shè)置的年份,需要減1900 */ 19 rtc_tm.tm_mon = 11 - 1; /* 需要設(shè)置的月份,需要確保在0-11范圍*/ 20 rtc_tm.tm_mday = 21; /* 需要設(shè)置的日期*/ 21 rtc_tm.tm_hour = 10; /* 需要設(shè)置的時間*/ 22 rtc_tm.tm_min = 12; /* 需要設(shè)置的分鐘時間*/ 23 rtc_tm.tm_sec = 30; /* 需要設(shè)置的秒數(shù)*/ 24 25 /* 設(shè)置RTC時間*/ 26 if (ioctl(fd, RTC_SET_TIME, &rtc_tm) < 0) { 27 printf("RTC_SET_TIME failedn"); 28 return -1; 29 } 30 31 /* 獲取RTC時間*/ 32 if (ioctl(fd, RTC_RD_TIME, &rtc_tm_temp) < 0) { 33 printf("RTC_RD_TIME failedn"); 34 return -1; 35 } 36 printf("RTC_RD_TIME return %04d-%02d-%02d %02d:%02d:%02dn", 37 rtc_tm_temp.tm_year + 1900, rtc_tm_temp.tm_mon + 1, rtc_tm_temp.tm_mday, 38 rtc_tm_temp.tm_hour, rtc_tm_temp.tm_min, rtc_tm_temp.tm_sec); 39 return 0; 40 } 41 42 int set_rtc_alarm(int fd) 43 { 44 struct rtc_time rtc_tm = {0}; 45 struct rtc_time rtc_tm_temp = {0}; 46 47 rtc_tm.tm_year = 0; /* 鬧鐘忽略年設(shè)置*/ 48 rtc_tm.tm_mon = 0; /* 鬧鐘忽略月設(shè)置*/ 49 rtc_tm.tm_mday = 0; /* 鬧鐘忽略日期設(shè)置*/ 50 rtc_tm.tm_hour = 10; /* 需要設(shè)置的時間*/ 51 rtc_tm.tm_min = 12; /* 需要設(shè)置的分鐘時間*/ 52 rtc_tm.tm_sec = 30; /* 需要設(shè)置的秒數(shù)*/ 53 54 /* set alarm time */ 55 if (ioctl(fd, RTC_ALM_SET, &rtc_tm) < 0) { 56 printf("RTC_ALM_SET failedn"); 57 return -1; 58 } 59 60 if (ioctl(fd, RTC_AIE_ON) < 0) { 61 printf("RTC_AIE_ON failed!n"); 62 return -1; 63 } 64 65 if (ioctl(fd, RTC_ALM_READ, &rtc_tm_temp) < 0) { 66 printf("RTC_ALM_READ failedn"); 67 return -1; 68 } 69 70 printf("RTC_ALM_READ return %04d-%02d-%02d %02d:%02d:%02dn", 71 rtc_tm_temp.tm_year + 1900, rtc_tm_temp.tm_mon + 1, rtc_tm_temp.tm_mday, 72 rtc_tm_temp.tm_hour, rtc_tm_temp.tm_min, rtc_tm_temp.tm_sec); 73 return 0; 74 } 75 76 int main(int argc, char *argv[]) 77 { 78 int fd; 79 int ret; 80 81 /* open rtc device */ 82 fd = open(RTC_DEVICE_NAME, O_RDWR); 83 if (fd < 0) { 84 printf("open rtc device %s failedn", RTC_DEVICE_NAME); 85 return -ENODEV; 86 } 87 88 /* 設(shè)置RTC時間*/ 89 ret = set_rtc_timer(fd); 90 if (ret < 0) { 91 printf("set rtc timer errorn"); 92 return -EINVAL; 93 } 94 95 /* 設(shè)置鬧鐘*/ 96 ret = set_rtc_alarm(fd); 97 if (ret < 0) { 98 printf("set rtc alarm errorn"); 99 return -EINVAL; 100 } 101 102 close(fd); 103 return 0; 104 }

6 FAQ

6.1 RTC 時間不準

按照下圖RTC 時鐘源的路徑,確認一下RTC 所使用的時鐘源

image-20221216124213488

如果確認使用的時鐘源為RC16M,則確認一下有沒有啟用校準功能,因為RC16M 有正負50% 的偏差。

如果使用外部晶體,則確認一下外部晶體的震蕩頻率是否正確。

6.2 RTC 時間不走

請查看RTC 時鐘源圖,確認一下使用的時鐘源。

當(dāng)RTC 時鐘源為外部32K 時,請確認一下外部32k 晶體的起振情況。

說明:當(dāng)使用示波器測量外部32k 晶體起振情況時,有可能會導(dǎo)致32k 晶體起振。

當(dāng)排查完時鐘源,確認時鐘源沒有問題后,通過以下命令dump rtc 相關(guān)寄存器,查看偏移0x0 寄存器的狀態(tài)位bit7 和bit8 是否異常置1 了,如下所示:

/ # echo 0x07000000,0x07000200 > /sys/class/sunxi_dump/dump; cat /sys/class/sunxi_dump/dump 0x0000000007000000: 0x00004010 0x00000004 0x0000000f 0x7a000000 0x0000000007000010: 0x00000001 0x00000023 0x00000000 0x00000000 0x0000000007000020: 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000007000030: 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000007000040: 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000007000050: 0x00000001 0x00000000 0x00000000 0x00000000 0x0000000007000060: 0x00000004 0x00000000 0x00000000 0x00000000 0x0000000007000070: 0x00010003 0x00000000 0x00000000 0x00000000 0x0000000007000080: 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000007000090: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000070000a0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000070000b0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000070000c0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000070000d0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000070000e0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000070000f0: 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000007000100: 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000007000110: 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000007000120: 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000007000130: 0x00000000 0x000030ea 0x04001000 0x00006061 0x0000000007000140: 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000007000150: 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000007000160: 0x083f10f7 0x00000043 0x00000000 0x00000000 0x0000000007000170: 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000007000180: 0x00000000 0x00000000 0x00010001 0x00000000 0x0000000007000190: 0x00000004 0x00000000 0x00000000 0x00000000 0x00000000070001a0: 0x000090ff 0x00000000 0x00000000 0x00000000 0x00000000070001b0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000070001c0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000070001d0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000070001e0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000070001f0: 0x00000000 0x00000001 0x00000000 0x00000000 0x0000000007000200: 0x10000000

說明:

每款SoC 的模塊首地址是不一樣的,具體根據(jù)spec 或data sheet 確認模塊首地址。

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 模塊
    +關(guān)注

    關(guān)注

    7

    文章

    2658

    瀏覽量

    47294
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    3

    文章

    1361

    瀏覽量

    40185
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11212

    瀏覽量

    208724
  • 時鐘
    +關(guān)注

    關(guān)注

    10

    文章

    1714

    瀏覽量

    131282
  • RTC
    RTC
    +關(guān)注

    關(guān)注

    2

    文章

    523

    瀏覽量

    66230
收藏 人收藏

    評論

    相關(guān)推薦

    EAC0945 linux開發(fā)指南

    EAC0945 linux開發(fā)指南
    發(fā)表于 09-28 12:40

    EAC0945 linux開發(fā)指南

    `EAC0945 linux開發(fā)指南`
    發(fā)表于 10-31 12:18

    Rockchip Linux SDK uboot logo開發(fā)指南

    arm嵌入式vs-rk3399 板卡uboot logo 開發(fā)指南概述:本文檔主要介紹 rockchip linux sdk uboot logo 顯示的相關(guān)功能、配置以及開發(fā)過程中的注意事項。適用于 rockhip
    發(fā)表于 10-09 08:12

    CPLD FPGA高級應(yīng)用開發(fā)指南

    CPLD FPGA高級應(yīng)用開發(fā)指南
    發(fā)表于 04-15 10:56 ?58次下載
    CPLD FPGA高級應(yīng)用<b class='flag-5'>開發(fā)指南</b>

    Tiny6410 Linux開發(fā)指南詳解

    Tiny6410 Linux 開發(fā)指南
    發(fā)表于 07-08 17:12 ?210次下載
    Tiny6410 <b class='flag-5'>Linux</b><b class='flag-5'>開發(fā)指南</b>詳解

    A64開發(fā)板LCD開發(fā)指南

    A64開發(fā)板LCD開發(fā)指南,驅(qū)動開發(fā)指南
    發(fā)表于 06-21 17:02 ?0次下載

    彩光燈開發(fā)指南

    彩光燈開發(fā)指南
    發(fā)表于 12-29 20:15 ?0次下載

    Linux的平臺下Mini210S裸機程序開發(fā)指南

    Linux的平臺下Mini210S裸機程序開發(fā)指南
    發(fā)表于 10-29 10:52 ?59次下載
    <b class='flag-5'>Linux</b>的平臺下Mini210S裸機程序<b class='flag-5'>開發(fā)指南</b>

    Rockchip Linux SDK的開發(fā)指南的詳細資料說明

    本文檔的主要內(nèi)容詳細介紹的是Rockchip Linux SDK的開發(fā)指南的詳細資料說明。
    發(fā)表于 01-10 17:17 ?74次下載
    Rockchip <b class='flag-5'>Linux</b> SDK的<b class='flag-5'>開發(fā)指南</b>的詳細資料說明

    迅為RK3399開發(fā)板嵌入式linux開發(fā)指南

    迅為RK3399開發(fā)板嵌入式linux開發(fā)指南迅為RK3399開發(fā)板發(fā)布《北京迅為嵌入式linux開發(fā)指
    發(fā)表于 11-01 16:58 ?76次下載
    迅為RK3399<b class='flag-5'>開發(fā)</b>板嵌入式<b class='flag-5'>linux</b><b class='flag-5'>開發(fā)指南</b>

    nRF52832開發(fā)指南-上冊

    nRF52832開發(fā)指南-上冊
    發(fā)表于 06-16 14:15 ?75次下載

    Tina_Linux_系統(tǒng)軟件開發(fā)指南

    Tina_Linux_系統(tǒng)軟件開發(fā)指南
    的頭像 發(fā)表于 03-02 15:25 ?1747次閱讀
    Tina_<b class='flag-5'>Linux</b>_系統(tǒng)軟件<b class='flag-5'>開發(fā)指南</b>

    Tina Linux配置開發(fā)指南

    Tina Linux配置開發(fā)指南
    的頭像 發(fā)表于 03-02 15:28 ?1.6w次閱讀
    Tina <b class='flag-5'>Linux</b>配置<b class='flag-5'>開發(fā)指南</b>

    Linux NOR開發(fā)指南

    Linux NOR開發(fā)指南
    的頭像 發(fā)表于 03-06 09:55 ?908次閱讀
    <b class='flag-5'>Linux</b> NOR<b class='flag-5'>開發(fā)指南</b>

    【北京迅為】itop-龍芯2k1000開發(fā)指南Linux基礎(chǔ)入門vim 編輯器

    【北京迅為】itop-龍芯2k1000開發(fā)指南Linux基礎(chǔ)入門vim 編輯器
    的頭像 發(fā)表于 10-25 14:56 ?230次閱讀
    【北京迅為】itop-龍芯2k1000<b class='flag-5'>開發(fā)指南</b><b class='flag-5'>Linux</b>基礎(chǔ)入門vim 編輯器