精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

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

3天內不再提示

淺析Linux RTC實時時鐘

嵌入式攻城獅 ? 來源:嵌入式攻城獅 ? 作者:嵌入式攻城獅 ? 2022-11-25 15:07 ? 次閱讀
實時時鐘是個常用的外設,可以用來獲取年、月、日和時間等信息。目前大多數的芯片內部都自帶了實時時鐘外設模塊。例如本實驗所使用的I.MX6ULL芯片內部SNVS就提供了RTC(實時計數器)功能。SNVS(安全的非易性存儲)里面主要是一些低功耗的外設,其可以在芯片掉電后由電池供電繼續運行。RTC需要外接晶振來提供時鐘,本實驗中I.MX6ULL芯片外接了一個32.768KHz的晶振,原理圖如下

ccc42222-6c8d-11ed-8abf-dac502259ad0.png

1. Linux內核RTC驅動簡介

RTC 設備驅動是一個標準的字符設備驅動,應用程序通過open、release、read、write和ioctl等函數完成對 RTC 設備的操作

內核將 RTC 設備抽象為rtc_device結構體,RTC設備驅動就是申請并初始化rtc_device,最后將 rtc_device 注冊到Linux內核里面,此結構體定義在include/linux/rtc.h文件中

structrtc_device
{
structdevicedev;/*設備*/
structmodule*owner;

intid;/*ID*/
charname[RTC_DEVICE_NAME_SIZE];/*名字*/

conststructrtc_class_ops*ops;/*RTC設備底層操作函數*/
structmutexops_lock;

structcdevchar_dev;/*字符設備*/
unsignedlongflags;
......
......
};

結構體中的ops成員變量是RTC設備的底層操作函數集合,是一個 rtc_class_ops 類型的指針變量,需要用戶根據所使用的RTC設備編寫的,此結構體定義在include/linux/rtc.h 文件中,內容如下

structrtc_class_ops{
int(*open)(structdevice*);
void(*release)(structdevice*);
int(*ioctl)(structdevice*,unsignedint,unsignedlong);
int(*read_time)(structdevice*,structrtc_time*);
int(*set_time)(structdevice*,structrtc_time*);
int(*read_alarm)(structdevice*,structrtc_wkalrm*);
int(*set_alarm)(structdevice*,structrtc_wkalrm*);
int(*proc)(structdevice*,structseq_file*);
int(*set_mmss64)(structdevice*,time64_tsecs);
int(*set_mmss)(structdevice*,unsignedlongsecs);
int(*read_callback)(structdevice*,intdata);
int(*alarm_irq_enable)(structdevice*,unsignedintenabled);
};

rtc_class_ops 是最底層的 RTC 設備操作函數,并不是提供給應用層的。內核提供了一個 RTC 通用字符設備驅動文件,文件名為 drivers/rtc/rtc-dev.c, 理論提供了所有 RTC 設備共用的 file_operations 函數操作集,如下所示:

staticconststructfile_operationsrtc_dev_fops={
.owner=THIS_MODULE,
.llseek=no_llseek,
.read=rtc_dev_read,
.poll=rtc_dev_poll,
.unlocked_ioctl=rtc_dev_ioctl,
.open=rtc_dev_open,
.release=rtc_dev_release,
.fasync=rtc_dev_fasync,
};
應用程序可以通過 ioctl 函數來設置/讀取時間、設置/讀取鬧鐘的操作,那么對應的 rtc_dev_ioctl 函數就會執行,rtc_dev_ioctl 最終會通過操作 rtc_class_ops 中的 read_time、 set_time 等函數來對具體 RTC 設備的讀寫操作。內核中 RTC 驅動調用流程圖如下示

cce959f2-6c8d-11ed-8abf-dac502259ad0.png

2.Linux內核RTC驅動分析

一般情況下,半導體廠商都會編寫好內部RTC驅動,無需我們自已動手編寫。但是有必要了解一下是如何編寫的

打開imx6ull.dtsi,然后找到 snvs_rtc 節點內容,如下所示:

snvs_rtc:snvs-rtc-lp{
compatible="fsl,sec-v4.0-mon-rtc-lp";
regmap=<&snvs>;
offset=<0x34>;
interrupts=19IRQ_TYPE_LEVEL_HIGH>,
20IRQ_TYPE_LEVEL_HIGH>;
};

根據compatible屬性值,在Linux源碼中搜索"fsl,sec-v4.0-mon-rtc-lp"符串,即可找到對應的驅動文件drivers//rtc/rtc-snvs.c

staticconststructof_device_idsnvs_dt_ids[]={
{.compatible="fsl,sec-v4.0-mon-rtc-lp",},
{/*sentinel*/}
};
MODULE_DEVICE_TABLE(of,snvs_dt_ids);
staticstructplatform_driversnvs_rtc_driver={
.driver={
.name="snvs_rtc",
.pm=SNVS_RTC_PM_OPS,
.of_match_table=snvs_dt_ids,
},
.probe=snvs_rtc_probe,
};
module_platform_driver(snvs_rtc_driver);

可見這是一個標準的platform驅動,當驅動和設備匹配以后snvs_rtc_probe函數就會執行

staticintsnvs_rtc_probe(structplatform_device*pdev){
structsnvs_rtc_data*data;
structresource*res;
intret;
void__iomem*mmio;

data=devm_kzalloc(&pdev->dev,sizeof(*data),GFP_KERNEL);
if(!data)
return-ENOMEM;

data->regmap=syscon_regmap_lookup_by_phandle(pdev->dev.of_node,"regmap");
if(IS_ERR(data->regmap)){
dev_warn(&pdev->dev,"snvsrtc:youuseolddtsfile,pleaseupdateit
");
//從設備樹中獲取RTC外設寄存器基地址
res=platform_get_resource(pdev,IORESOURCE_MEM,0);
//內存映射,獲得RTC外設寄存器物理基地址對應的虛擬地址
mmio=devm_ioremap_resource(&pdev->dev,res);
if(IS_ERR(mmio))
returnPTR_ERR(mmio);
//采用regmap機制來讀寫RTC底層硬件寄存器
data->regmap=devm_regmap_init_mmio(&pdev->dev,mmio,&snvs_rtc_config);
}else{
data->offset=SNVS_LPREGISTER_OFFSET;
of_property_read_u32(pdev->dev.of_node,"offset",&data->offset);
}

if(!data->regmap){
dev_err(&pdev->dev,"Can'tfindsnvssyscon
");
return-ENODEV;
}
//從設備樹中獲取RTC的中斷號
data->irq=platform_get_irq(pdev,0);
if(data->irq0)
returndata->irq;
......

platform_set_drvdata(pdev,data);

//用regmap機制的regmap_write函數完成對寄存器進行寫操作
regmap_write(data->regmap,data->offset+SNVS_LPPGDR,SNVS_LPPGDR_INIT);
//清除LPSR寄存器
regmap_write(data->regmap,data->offset+SNVS_LPSR,0xffffffff);
//使能RTC
snvs_rtc_enable(data,true);
device_init_wakeup(&pdev->dev,true);
//請求RTC中斷
ret=devm_request_irq(&pdev->dev,data->irq,
snvs_rtc_irq_handler,
IRQF_SHARED,"rtcalarm",&pdev->dev);
if(ret){
dev_err(&pdev->dev,"failedtorequestirq%d:%d
",data->irq,ret);
gotoerror_rtc_device_register;
}
//向系統注冊rtc_devcie
data->rtc=devm_rtc_device_register(&pdev->dev,pdev->name,&snvs_rtc_ops,THIS_MODULE);
if(IS_ERR(data->rtc)){
ret=PTR_ERR(data->rtc);
dev_err(&pdev->dev,"failedtoregisterrtc:%d
",ret);
gotoerror_rtc_device_register;
}

return0;

error_rtc_device_register:
if(data->clk)
clk_disable_unprepare(data->clk);
returnret;
}

RTC 底層驅動snvs_rtc_ops操作集包含了讀取/設置RTC時間,讀取/設置鬧鐘等函數。其內容如下

staticconststructrtc_class_opssnvs_rtc_ops={
.read_time=snvs_rtc_read_time,
.set_time=snvs_rtc_set_time,
.read_alarm=snvs_rtc_read_alarm,
.set_alarm=snvs_rtc_set_alarm,
.alarm_irq_enable=snvs_rtc_alarm_irq_enable,
};

以 snvs_rtc_read_time 函數為例,介紹RTC底層操作函數該如何去編寫,該函數用于讀取RTC時間值

staticintsnvs_rtc_read_time(structdevice*dev,structrtc_time*tm){
structsnvs_rtc_data*data=dev_get_drvdata(dev);
//獲取RTC計數值,該值是秒數
unsignedlongtime=rtc_read_lp_counter(data);
//將獲取到的秒數轉換為時間值,也就是rtc_time結構體類型
rtc_time_to_tm(time,tm);

return0;
}

rtc_time 結構體定義如下:

structrtc_time{
inttm_sec;
inttm_min;
inttm_hour;
inttm_mday;
inttm_mon;
inttm_year;
inttm_wday;
inttm_yday;
inttm_isdst;
};

rtc_read_lp_counter 函數,此函數用于讀取 RTC 計數值,函數內容如下

staticu32rtc_read_lp_counter(structsnvs_rtc_data*data){
u64read1,read2;
u32val;
//讀取RTC_LPSRTCMR和RTC_LPSRTCLR這兩個寄存器,得到RTC的計數值
do{
regmap_read(data->regmap,data->offset+SNVS_LPSRTCMR,&val);
read1=val;
read1<<=?32;
regmap_read(data->regmap,data->offset+SNVS_LPSRTCLR,&val);
read1|=val;
regmap_read(data->regmap,data->offset+SNVS_LPSRTCMR,&val);
read2=val;
read2<<=?32;
regmap_read(data->regmap,data->offset+SNVS_LPSRTCLR,&val);
read2|=val;
}while((read1>>CNTR_TO_SECS_SH)!=(read2>>CNTR_TO_SECS_SH));

/*Convert47-bitcounterto32-bitrawsecondcount*/
return(u32)(read1>>CNTR_TO_SECS_SH);
}

3. RTC時間相關設置

RTC 是用來計時的,最基本的就是查看時間,Linux內核啟動時可以看到系統時鐘設置信息

cd0f0404-6c8d-11ed-8abf-dac502259ad0.png

查看時間命令:date

設置當前時間:date -s

date-s"2022-08-151300"
將當前時間寫入到RTC里:hwclock -w

cd213840-6c8d-11ed-8abf-dac502259ad0.png


審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11229

    瀏覽量

    208927
  • 晶振
    +關注

    關注

    34

    文章

    2826

    瀏覽量

    67904
  • 時鐘
    +關注

    關注

    10

    文章

    1720

    瀏覽量

    131364

原文標題:淺析 Linux RTC 實時時鐘

文章出處:【微信號:嵌入式攻城獅,微信公眾號:嵌入式攻城獅】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    愛普生RTC實時時鐘模塊助力車載BMS系統更好運行

    的使用壽命;此外,BMS模塊還能夠實時監測電池狀態,確保電池運行的安全性和穩定性。愛普生RTC實時時鐘模塊助力車載BMS系統更好運行,該模塊集成了32.768kHz石
    的頭像 發表于 11-20 14:18 ?99次閱讀
    愛普生<b class='flag-5'>RTC</b><b class='flag-5'>實時時鐘</b>模塊助力車載BMS系統更好運行

    實時時鐘芯片RTC

    FRTC8563是NYFEA徠飛公司推出的一款實時時鐘芯片,采用SOP-8封裝形式。這種封裝形式具有體積小、引腳間距小、便于集成等特點,使得FRTC8563能夠方便地應用于各種電子設備中
    的頭像 發表于 10-22 11:33 ?192次閱讀

    使用實時時鐘

    電子發燒友網站提供《使用實時時鐘庫.pdf》資料免費下載
    發表于 10-22 10:09 ?0次下載
    使用<b class='flag-5'>實時時鐘</b>庫

    適用于智能門鎖的低功耗RTC實時時鐘模塊RX8010SJ

    隨著智能家居的普及,智能門鎖已成為保障家庭安全的重要設備。作為智能門鎖的關鍵組件之一,實時時鐘RTC)模塊負責提供準確的時間基準,確保門鎖的各種時間相關功能正常運行。一款適用于智能門鎖的低功耗
    的頭像 發表于 08-28 14:29 ?319次閱讀
    適用于智能門鎖的低功耗<b class='flag-5'>RTC</b><b class='flag-5'>實時時鐘</b>模塊RX8010SJ

    bq32000實時時鐘(RTC)數據表

    電子發燒友網站提供《bq32000實時時鐘(RTC)數據表.pdf》資料免費下載
    發表于 08-23 11:23 ?0次下載
    bq32000<b class='flag-5'>實時時鐘</b>(<b class='flag-5'>RTC</b>)數據表

    BQ32002實時時鐘(RTC)數據表

    電子發燒友網站提供《BQ32002實時時鐘(RTC)數據表.pdf》資料免費下載
    發表于 08-23 11:23 ?0次下載
    BQ32002<b class='flag-5'>實時時鐘</b>(<b class='flag-5'>RTC</b>)數據表

    bq3285E/L實時時鐘(RTC)數據表

    電子發燒友網站提供《bq3285E/L實時時鐘(RTC)數據表.pdf》資料免費下載
    發表于 08-23 11:22 ?0次下載
    bq3285E/L<b class='flag-5'>實時時鐘</b>(<b class='flag-5'>RTC</b>)數據表

    bq3285實時時鐘(RTC)數據表

    電子發燒友網站提供《bq3285實時時鐘(RTC)數據表.pdf》資料免費下載
    發表于 08-23 11:21 ?0次下載
    bq3285<b class='flag-5'>實時時鐘</b>(<b class='flag-5'>RTC</b>)數據表

    DP8573A實時時鐘(RTC)數據表

    電子發燒友網站提供《DP8573A實時時鐘(RTC)數據表.pdf》資料免費下載
    發表于 08-23 10:11 ?0次下載
    DP8573A<b class='flag-5'>實時時鐘</b>(<b class='flag-5'>RTC</b>)數據表

    TCXO RTC實時時鐘模塊的特性

    高精度實時時鐘模塊內建TCXO數字式實時時鐘模塊的特征【序文】時間是我們日常生活中的基本概念。火車運行管理、進出場管理等各種處理系統和應用程序按照時間信息工作。在金融、股市領域中,時間操縱著巨大利益
    的頭像 發表于 08-14 11:44 ?294次閱讀
    TCXO <b class='flag-5'>RTC</b><b class='flag-5'>實時時鐘</b>模塊的特性

    RTC實時時鐘的基本概念和工作原理

    在現代電子設備中,精確的時間管理和控制是至關重要的。為了實現這一功能,實時時鐘RTC, Real-Time Clock)模塊被廣泛應用于各種設備和系統中。RTC模塊作為一個獨立的定時器,能夠提供
    的頭像 發表于 05-27 15:43 ?3402次閱讀

    stm8l051 RTC LSI作為實時時鐘不準怎么校準?

    (CLK_RTCCLKSource_LSI, CLK_RTCCLKDiv_1); CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE); 現在以LSI作為實時時鐘,十分鐘內快了2分鐘,分頻2后右邊慢了 請問大神么 這個
    發表于 04-30 07:13

    愛普生實時時鐘模塊RTC

    愛普生是一家IC和晶體自主研發的公司,有自己的IC和晶振產線。所以我們能將RTC IC+晶體單元+外結電容封裝在一起,組成獨立RTC模塊。外圍不需要在接晶體和匹配電容。愛普生RTC能夠簡化客戶
    發表于 04-17 11:10 ?0次下載

    基于51單片機的實時時鐘設計

    電子發燒友網站提供《基于51單片機的實時時鐘設計.rar》資料免費下載
    發表于 01-12 10:43 ?12次下載

    基于51單片機的實時時鐘設計

    電子發燒友網站提供《基于51單片機的實時時鐘設計.rar》資料免費下載
    發表于 01-02 10:15 ?43次下載