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

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

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

如何在Linux中驅(qū)動(dòng)Generic Timer

Linux閱碼場(chǎng) ? 來(lái)源:未知 ? 作者:胡薇 ? 2018-07-10 11:42 ? 次閱讀

一、前言

關(guān)注ARM平臺(tái)上timer driver(clocksource chip driver和clockevent chip driver)的驅(qū)動(dòng)工程師應(yīng)該會(huì)注意到timer硬件的演化過(guò)程。在單核時(shí)代,各個(gè)SOC vendor廠(chǎng)商購(gòu)買(mǎi)ARM core的IP,然后自己設(shè)計(jì)SOC上的peripherals,這里面就包括了timer的硬件。由于沒(méi)有統(tǒng)一的標(biāo)準(zhǔn),各個(gè)廠(chǎng)商的設(shè)計(jì)各不相同,這給驅(qū)動(dòng)工程師帶來(lái)了工作量。然而,如果僅僅是工作量的話(huà)就還好,實(shí)際上,不僅僅如此。linux的時(shí)間子系統(tǒng)要求硬件timer提供下面兩種能力:一是free running的counter,此外需要能夠在指定的counter值上產(chǎn)生中斷的能力。有些硬件廠(chǎng)商會(huì)考慮到軟件的需求(例如:PXA270的timer硬件),但是有些硬件廠(chǎng)商做的就不夠,例如:S3C2451的timer硬件。我們?cè)趯?xiě)PXA270的timer硬件驅(qū)動(dòng)的時(shí)候是毫無(wú)壓力的,而在寫(xiě)S3C2451的timer的驅(qū)動(dòng)的時(shí)候,最大的愿望就是把三星的HW timer的設(shè)計(jì)人員拉出來(lái)打一頓。

進(jìn)入多核時(shí)代后,ARM公司提供了timer的硬件設(shè)計(jì),集成在了自己的多核結(jié)構(gòu)中。例如:在Cortex A15 MPcore的硬件體系結(jié)構(gòu)中有一個(gè)HW block叫做Generic Timer(該硬件取代了A9中的global timer、private timer的功能),為系統(tǒng)提供了計(jì)時(shí)以及觸發(fā)timer event的功能。

本文主要描述了Generic Timer的相關(guān)硬件知識(shí)以及在linux kernel中如何驅(qū)動(dòng)該硬件。Generic Timer的代碼位于linux-3.14/drivers/clocksource/目錄下,該目錄保存了所有clock source相關(guān)的driver,arm_arch_timer.c就是驅(qū)動(dòng)Cortex A15 MPcore的Generic Timer的。

二、硬件描述

1、block diagram

ARM generic timer相關(guān)的硬件block如下圖所示(用綠色標(biāo)記):

ARM generic timer的硬件block主要是SOC上的System counter(多個(gè)process共享,用來(lái)記錄時(shí)間的流逝)以及附著在各個(gè)processor上的Timer(用于觸發(fā)timer event)組成,其他的generic timer的硬件電路主要是用來(lái)進(jìn)行交流generic time event的。例如各個(gè)processor中的timer和system counter外設(shè)進(jìn)行交互,各個(gè)processor中的timer進(jìn)行信息交互。System counter的功能很簡(jiǎn)單,就是計(jì)算輸入時(shí)鐘已經(jīng)過(guò)了多少個(gè)clock,開(kāi)始的時(shí)候是0,每一個(gè)clock,System counter會(huì)加一。System counter的counter value需要分發(fā)到各個(gè)timer中,也就是說(shuō),從各個(gè)timer的角度看,system counter value應(yīng)該是一致的。Timer其實(shí)就是定時(shí)器,它可以定義一段指定的時(shí)間,當(dāng)時(shí)間到了,就會(huì)assert一個(gè)外部的輸出信號(hào)(可以輸出到GIC,作為一個(gè)interrupt source)。

從power domain來(lái)看,ARM generic timer分成兩個(gè)部分:System counter和各個(gè)Multiprocessor系統(tǒng)中的Timer_x、接口電路等。之所以這么分原因很明顯:功耗方面(電源管理)的考量。在power saving mode下,可以shutdown各個(gè)processor系統(tǒng)的供電,但是可以保持system counter的供電,這樣,至少系統(tǒng)時(shí)間可以保持住。

和power domain類(lèi)似,clock domain也是不同的,system counter和processor工作在不同的clock下,軟件修改了CPU的頻率也不會(huì)影響system counter的工作節(jié)奏,從而也不會(huì)改變timer的行為。

2、System counter

關(guān)于System Counter的規(guī)格整理如下:

除了基本的計(jì)時(shí)功能,system count還提供了event stream的功能。我們知道,ARMv7的處理器提供了wait for event的機(jī)制,該機(jī)制允許processor進(jìn)入low power state并等待event的到來(lái)。這個(gè)event可能是來(lái)自另外的process的send event指令,也可能是外部HW block產(chǎn)生的event,比如來(lái)自system counter的wake-up event。軟件可以配置system counter產(chǎn)生周期性的event,具體可以配置的參數(shù)包括:

(1)指定產(chǎn)生event的bit。我們可以選擇system counter中的低16bit。

(2)選定的bit當(dāng)發(fā)生0到1的遷移(或是1到0的遷移)產(chǎn)生event

經(jīng)過(guò)配置后,實(shí)際上system counter產(chǎn)生的是一個(gè)event stream,event產(chǎn)生的頻率是由選定的bit位置決定的。設(shè)定bit 0會(huì)產(chǎn)出頻率非常高的event stream,而設(shè)定15bit會(huì)產(chǎn)生頻率最慢的event stream,因?yàn)閟ystem counter的值不斷累加,直到bit 15發(fā)生翻轉(zhuǎn)才會(huì)觸發(fā)一個(gè)event。

3、Timers

各個(gè)cpu的timer是根據(jù)system counter的值來(lái)觸發(fā)timer event的,因此,系統(tǒng)中一定有一個(gè)機(jī)制讓System counter的值廣播到各個(gè)CPU的timer HW block上,同時(shí)運(yùn)行在各個(gè)processor上的軟件可以通過(guò)接口獲取System counter的值。

處理器可以通過(guò)CNTPCT寄存器來(lái)獲取system counter的當(dāng)前值,我們稱(chēng)之physical counter。有physical就有virtual,processor可以通過(guò)CNTVCT寄存器訪(fǎng)問(wèn)virtual counter,不過(guò),對(duì)于不支持security extension和virtualization extension的系統(tǒng),virtual counter和physical counter是一樣的值。

系統(tǒng)中每個(gè)processor都會(huì)附著多個(gè)timer,具體如下:

(1)對(duì)于不支持security extension的SOC(不支持security extension也就意味著 不支持virtualization extension),timer實(shí)際上有兩個(gè),一個(gè)是physical timer,另外一個(gè)是virtual timer。雖然有兩個(gè),不過(guò)從行為上看,virtual timer和physical timer行為一致

(2)對(duì)于支持security extension但不支持virtualization extension的SOC,每個(gè)cpu有三個(gè)timer:Non-secure physical timer,Secure physical timer和virtual timer

(3)對(duì)于支持virtualization extension的SOC,每個(gè)cpu有四個(gè)timer:Non-secure PL1 physical timer,Secure PL1 physical timer,Non-secure PL2 physical timer和virtual timer

每個(gè)timer都會(huì)有三個(gè)寄存器(我們用physical timer為例描述):

(1)64-bit CompareValue register。該寄存器配合system counter可以實(shí)現(xiàn)一個(gè)64 bit unsigned upcounter。如果physical counter - CompareValue >= 0的話(huà),觸發(fā)中斷。也就是說(shuō),CompareValue register其實(shí)就是一個(gè)64比特的upcounter,設(shè)定為一個(gè)比當(dāng)前system counter要大的值,隨著system counter的不斷累加,當(dāng)system counter value觸及CompareValue register設(shè)定的值的時(shí)候,便會(huì)向GIC觸發(fā)中斷。

(2)32-bit TimerValue register。該寄存器配合system counter可以實(shí)現(xiàn)一個(gè)32 bit signed downcounter(有的時(shí)候,使用downcounter會(huì)讓軟件邏輯更容易,看ARM generic timer的設(shè)計(jì)人員考慮的多么周到)。開(kāi)始的時(shí)候,我們可以設(shè)定TimerValue寄存器的值為1000(假設(shè)我們想down count 1000,然后觸發(fā)中斷),向該寄存器寫(xiě)入1000實(shí)際上也就是設(shè)定了CompareValue register的值是system counter值加上1000。隨著system counter的值不斷累加,TimerValue register的值在遞減,當(dāng)值<=0的時(shí)候,便會(huì)向GIC觸發(fā)中斷

(3)32-bit控制寄存器。該寄存器主要對(duì)timer進(jìn)行控制,具體包括:enable或是disable該timer,mask或者unmask該timer的output signal(timer interrupt)

各個(gè)processor的各個(gè)Timer都可以產(chǎn)生中斷,因此它和GIC有接口。當(dāng)然,由于timer的中斷是屬于各個(gè)CPU的,因此使用PPI類(lèi)型的中斷,具體可以參考GIC文檔。當(dāng)然,如果讓timer觸發(fā)中斷,當(dāng)然要確保該timer是enable并且是umask的。

4、軟件編程接口

由上面的描述可知,ARM generic timer的硬件包括兩個(gè)部分:一個(gè)是per cpu的timer硬件,另外一個(gè)就是system level的counter硬件。對(duì)于per cpu的timer硬件,使用system control register(CP15)來(lái)訪(fǎng)問(wèn)是最合適的,而且速度也快。要訪(fǎng)問(wèn)system level的counter硬件,當(dāng)然使用memory mapped IO的形式(請(qǐng)注意block diagram中的APB總線(xiàn),很多system level的外設(shè)都是通過(guò)APB訪(fǎng)問(wèn)的)。

三、初始化

1、Generic Timer的device node和Generic Timer clocksource driver的匹配過(guò)程

(1)clock source driver中的聲明

在linux/include/linux/clocksource.h目錄下的clocksource.h文件中定義了CLOCKSOURCE_OF_DECLARE宏如下:

CLOCKSOURCE_OF_DECLARE這個(gè)宏其實(shí)就是初始化了一個(gè)struct of_device_id的靜態(tài)常量,并放置在__clksrc_of_table section中。arm_arch_timer.c文件中使用CLOCKSOURCE_OF_DECLARE這個(gè)宏定義了若干個(gè)靜態(tài)的struct of_device_id常量,如下:

這里compatible的名字使用了armv7、armv8這樣的字樣而不是Cortex A15,我猜測(cè)ARM公司是認(rèn)為這樣的generic timer的硬件block是ARMv7或者v8指令集的特性,所有使用這些指令集的core都應(yīng)該使用這樣的generic timer的硬件結(jié)構(gòu)。不論是v7還是v8,其初始化函數(shù)都是一個(gè)arch_timer_init。從這個(gè)角度看,把ARM的generic timer的驅(qū)動(dòng)放到drivers的目錄下更合理(原來(lái)是放在arch目錄下),這樣多個(gè)arch(ARM和ARM64)可以共享一個(gè)ARM ARCH timer的驅(qū)動(dòng)程序。

這里還有一個(gè)疑問(wèn)是:"arm,armv7-timer"和"arm,armv7-timer-mem"有什么不同?實(shí)際上訪(fǎng)問(wèn)ARM generic timer有兩種形式,一種是通過(guò)協(xié)處理器CP15訪(fǎng)問(wèn)timer的寄存器,我們稱(chēng)之CP15 timer。另外一種是通過(guò)寄存器接口訪(fǎng)問(wèn)timer,也就是說(shuō),generic timer的控制寄存器被memory map到CPU的地址空間,這種我們稱(chēng)之memory mapped timer。arch_timer_mem_init是for memory mapped timer類(lèi)型的驅(qū)動(dòng)初始化的,arch_timer_init是for CP15 timer類(lèi)型的驅(qū)動(dòng)進(jìn)行初始化的。

Travelhop同學(xué)在他的程序員的“紀(jì)律性”文章中說(shuō)到:有技術(shù)追求的年輕人要多問(wèn)幾個(gè)為什么?因此,我們這里再追問(wèn)一個(gè)問(wèn)題:為何要有CP15 timer和memory mapped timer呢?都能完成對(duì)ARM generic timer的控制,為什么要提供兩種方式呢?其實(shí)最開(kāi)始的時(shí)候,driver只支持CP15 type的timer訪(fǎng)問(wèn)形態(tài),畢竟這種方式比memory mapped register的訪(fǎng)問(wèn)速度要更快一些。但是,這種方式不能控制system level的counter硬件部分(只能使用memory mapped IO形式訪(fǎng)問(wèn)),因此功能受限。比如:system counter可以提供一組frequency table,可以讓軟件設(shè)定當(dāng)然counter的輸入頻率以及每個(gè)clock下counter增加的數(shù)目。這樣的設(shè)定可以讓system counter的硬件在不同的輸入頻率下工作,有更好的電源管理特性。

此外,有些系統(tǒng)不支持協(xié)處理的訪(fǎng)問(wèn),這種情況下又想給系統(tǒng)增加ARM generic timer的功能,這時(shí)候必須使用memory mapped register的方式來(lái)訪(fǎng)問(wèn)ARM generic timer的所有硬件block(包括system counter和per cpu的timer)。這時(shí)候,在訪(fǎng)問(wèn)timer硬件的時(shí)候雖然性能不佳,但總是好過(guò)功能喪失。

在linux kernel編譯的時(shí)候,你可以配置多個(gè)clocksource進(jìn)入內(nèi)核,編譯系統(tǒng)會(huì)把所有的CLOCKSOURCE_OF_DECLARE宏定義的數(shù)據(jù)放入到一個(gè)特殊的section中(section name是__clksrc_of_table),我們稱(chēng)這個(gè)特殊的section叫做clock source table。這個(gè)table也就保存了kernel支持的所有的clock source的ID信息(最重要的是驅(qū)動(dòng)代碼初始化函數(shù)和DT compatible string)。我們來(lái)看看struct of_device_id的定義:

這個(gè)數(shù)據(jù)結(jié)構(gòu)主要被用來(lái)進(jìn)行Device node和driver模塊進(jìn)行匹配用的。從該數(shù)據(jù)結(jié)構(gòu)的定義可以看出,在匹配過(guò)程中,device name、device type和DT compatible string都是考慮的因素。更細(xì)節(jié)的內(nèi)容請(qǐng)參考__of_device_is_compatible函數(shù)。

(2)device node

一個(gè)示例性的Generic Timer(CP15 type的timer)的device node(我們以瑞芯微的RK3288處理器為例)定義如下:

Generic Timer這個(gè)HW block的Device node中定義了各種屬性,其中就包括了System counter的輸入clock frequency,中斷資源描述等信息。compatible 屬性用于驅(qū)動(dòng)匹配的,在系統(tǒng)啟動(dòng)的時(shí)候,系統(tǒng)中的所有的device node形成一個(gè)樹(shù)狀結(jié)構(gòu),在clock source初始化的時(shí)候進(jìn)行device node和driver匹配(compatible 字符串的比對(duì)),device node攜帶的信息會(huì)在初始化的時(shí)候傳遞給具體的驅(qū)動(dòng)。該節(jié)點(diǎn)的各個(gè)屬性的具體含義后面會(huì)詳細(xì)描述。

MMIO type的timer的device node(我們以高通的msm8974處理器為例)定義如下:

(3)device node和clock source driver的匹配

在系統(tǒng)初始化的時(shí)候start_kernel函數(shù)會(huì)調(diào)用time_init進(jìn)行時(shí)間子系統(tǒng)的初始化,代碼如下:

clock source的初始化有兩種形態(tài),一種是調(diào)用machine driver的init_time函數(shù),另外一種是調(diào)用clocksource_of_init,使用device tree形式的初始化。具體使用哪種形態(tài)的初始化是和系統(tǒng)設(shè)計(jì)相關(guān)的,我們這里來(lái)看看device tree形式的初始化,畢竟device tree是未來(lái)的方向。具體代碼如下:

__clksrc_of_table就是內(nèi)核的clock source table,這個(gè)table也就保存了kernel支持的所有的clock source driver的ID信息(用于和device node的匹配)。clocksource_of_init函數(shù)執(zhí)行之前,系統(tǒng)已經(jīng)完成了device tree的初始化,因此系統(tǒng)中的所有的設(shè)備節(jié)點(diǎn)都已經(jīng)形成了一個(gè)樹(shù)狀結(jié)構(gòu),每個(gè)節(jié)點(diǎn)代表一個(gè)設(shè)備的device node。clocksource_of_init是針對(duì)系統(tǒng)中的所有的device node,掃描clock source table,進(jìn)行匹配,一旦匹配到,就調(diào)用該clock source driver的初始化函數(shù),并把該timer硬件的device node作為參數(shù)傳遞給clocksource driver。

2、CP15 Timer初始化代碼分析

CP15 Timer初始化代碼如下所示:

(1)arch_timers_present用來(lái)記錄系統(tǒng)中的timer情況,定義如下:

該變量只有兩個(gè)bit有效,bit 0標(biāo)識(shí)是否有CP15 timer,bit 1標(biāo)識(shí)memory mapped timer是否已經(jīng)初始化。

如果在調(diào)用arch_timer_init之前,ARCH_CP15_TIMER已經(jīng)置位,說(shuō)明之前已經(jīng)有一個(gè)ARM arch timer的device node進(jìn)行了初始化的動(dòng)作,這多半是由于device tree的database中有兩個(gè)或者多個(gè)cp15 timer的節(jié)點(diǎn),這時(shí)候,我們初始化一個(gè)就OK了。

(2)這部分的代碼是分配IRQ。ARM generic timer使用4個(gè)PPI的中斷,對(duì)于Cortex A15,和timer相關(guān)的PPI包括:

函數(shù)irq_of_parse_and_map對(duì)該device node中的interrupt屬性進(jìn)行分析,并分配IRQ number,建立HW interrupt ID和該IRQ number的映射。irq_of_parse_and_map這個(gè)函數(shù)在中斷子系統(tǒng)中已經(jīng)詳細(xì)描述過(guò)了,這里不再贅述。至此,arch_timer_ppi數(shù)組中保存了ARM generic timer使用IRQ number。

(3)arch_timer_detect_rate這個(gè)函數(shù)用來(lái)確定system counter的輸入clock頻率,具體實(shí)現(xiàn)如下:

arch_timer_rate這個(gè)全局變量用來(lái)保存system counter的輸入頻率,基本上,這個(gè)數(shù)據(jù)有兩個(gè)可能的來(lái)源:

(a)device tree node中的clock-frequency屬性

(b)寄存器CNTFRQ

我們優(yōu)先考慮從clock-frequency屬性中獲取該數(shù)據(jù),如果device node中沒(méi)有定義該屬性,那么從CNTFRQ寄存器中讀取。訪(fǎng)問(wèn)CNTFRQ寄存器有兩種形態(tài),如果cntbase是NULL的話(huà),說(shuō)明是CP15 timer,可以通過(guò)協(xié)處理器來(lái)獲取該值(調(diào)用arch_timer_get_cntfrq函數(shù))。如果給出了cntbase的值,說(shuō)明是memory mapped的方式來(lái)訪(fǎng)問(wèn)CNTFRQ寄存器(直接使用readl_relaxed函數(shù))。

(4)如果沒(méi)有定義virtual timer的中斷(arch_timer_ppi[VIRT_PPI]==0),那么我們只能是使用physical timer的,這時(shí)候,需要設(shè)定arch_timer_use_virtual這個(gè)全局變量為false。arch_timer_use_virtual這個(gè)變量名字已經(jīng)說(shuō)明的很清楚了,它標(biāo)識(shí)系統(tǒng)是否使用virtual timer。ok,既然使用physical timer,那么需要定義physical timer中斷,包括secure和non-secure physical timer event PPI。只要有一個(gè)沒(méi)有定義,那么就出錯(cuò)退出了。

如果系統(tǒng)支持虛擬化,那么CPU會(huì)處于HYP mode,這時(shí)候,我們也是應(yīng)該使用physical timer的,virtual timer是guest OS需要訪(fǎng)問(wèn)的。

(5) arch_timer_register的代碼如下:

(a)分配一個(gè)類(lèi)型是struct clock_event_device的per cpu變量。struct clock_event_device是對(duì)一個(gè)能夠觸發(fā)timer event的設(shè)備進(jìn)行抽象。對(duì)于ARM generic timer而言,每個(gè)CPU都有一個(gè)timer硬件block,就是一個(gè)clock event device。

(b)根據(jù)當(dāng)前是使用physical timer還是virtual timer,分別注冊(cè)一個(gè)per cpu的IRQ。如果使用physical timer的話(huà),需要注冊(cè)secure和non-secure physical timer event PPI。如果使用virtual timer的話(huà),需要注冊(cè)virtual timer中斷。

(c)這里的代碼主要是formulti core系統(tǒng)的,用于non-BSP上的generic timer硬件的初始化,其概念類(lèi)似GIC driver的初始化,這里就不再具體描述了。

(d)這里主要是注冊(cè)一個(gè)回調(diào)函數(shù),在processor進(jìn)入和退出low power state的時(shí)候會(huì)調(diào)用該回調(diào)函數(shù)進(jìn)行電源管理相關(guān)的處理。

(e)初始化BSP上的timer硬件對(duì)應(yīng)的clock event device,并調(diào)用clockevents_register_device函數(shù)將該clock event device注冊(cè)到linux kernel的時(shí)間子系統(tǒng)中。non-BSP的timer硬件的setup是通過(guò)event notifier機(jī)制完成的,具體請(qǐng)參考步驟c。

(6)CP15 timer和memory mapped timer雖然接口形態(tài)不一樣,但是總是有共同的部分,這些代碼被封裝到arch_timer_common_init函數(shù)中,具體如下:

(a)實(shí)際上,即便是系統(tǒng)中存在兩種timer,這個(gè)函數(shù)的代碼執(zhí)行一次就OK了。這很好理解,例如arch_counter_register函數(shù)用來(lái)注冊(cè)system count,而實(shí)際上,無(wú)論是CP15 timer還是memory mapped的timer,system counter是system level的,只有一個(gè),注冊(cè)一次就OK了。

明白了上面的思路后,這段代碼就比較簡(jiǎn)單了。在系統(tǒng)中存在兩種timer的時(shí)候,要等到后一個(gè)timer初始化的時(shí)候再執(zhí)行后面具體的arch_timer_banner到arch_timer_arch_init部分的代碼。

(b)輸出ARM generic timer的相關(guān)信息到控制臺(tái)

(c)向linux kernel的時(shí)間子系統(tǒng)注冊(cè)clock source、timer counter、shed clock設(shè)備。

(d)主要是注冊(cè)delay timer(忙等待那種)。

3、memory mapped Timer初始化代碼分析

TODO

四、和linux kernel時(shí)間子系統(tǒng)的接口

linux的時(shí)間子系統(tǒng)需要兩種時(shí)間相關(guān)的硬件:一個(gè)是free running的counter(system counter),抽象為clock source device,另外一個(gè)就是能夠產(chǎn)生中斷的能力的timer(per cpu timer),抽象為clock event device。對(duì)于ARM generic timer driver而言,我們需要定義linux kernel時(shí)間子系統(tǒng)的clock source和clock event device并注冊(cè)到系統(tǒng)。

1、定義clocksource并注冊(cè)到系統(tǒng)

ARM generic timer中的system counter硬件block對(duì)應(yīng)的clock source定義如下:

(這里順便吐槽一下clocksource_counter這個(gè)變量名,實(shí)在是太差了)rating標(biāo)識(shí)該clock source的精度等級(jí),數(shù)字越大,精度等級(jí)越高。read函數(shù)用來(lái)讀取當(dāng)前counter的值。在ARM generic timer驅(qū)動(dòng)初始化的過(guò)程中會(huì)調(diào)用arch_counter_register函數(shù)注冊(cè)該clock source:

(1)在定義ARM generic timer的clock source的時(shí)候,read函數(shù)被設(shè)定成arch_counter_read,該函數(shù)會(huì)調(diào)用arch_timer_read_counter 函數(shù),而這個(gè)函數(shù)指針會(huì)在初始化的時(shí)候根據(jù)timer的類(lèi)型進(jìn)行設(shè)定。

(2)向系統(tǒng)注冊(cè)一個(gè)clock soure(也就是一個(gè)free running的counter),并給出counter的工作頻率作為傳入的參數(shù)。linux時(shí)間子系統(tǒng)的clock source模塊會(huì)根據(jù)counter的工作頻率設(shè)定struct clocksource的各個(gè)成員,例如mult和shitf等

(3)clocksource模塊是為timekeeping模塊提供服務(wù)的,但是其他的驅(qū)動(dòng)模塊也有一些計(jì)時(shí)需求,這時(shí)候可以考慮使用timercounter。ARM generic timer靜態(tài)定義了一個(gè)timercounter的全局變量,其他模塊可以通過(guò)arch_timer_get_timecounter獲取timercounter,并可以調(diào)用timecounter_read獲取一個(gè)納秒值。

(4)TODO

2、定義clock_event_device并注冊(cè)到系統(tǒng)

和clocksource不同,ARM generic timer是由alloc_percpu動(dòng)態(tài)分配的??紤]到system counter只有一個(gè),而timer是附著在各個(gè)CPU上,這樣的分配也是合理的。在driver的初始化過(guò)程中(先是BSP初始化,然后其他CPU的初始化是通過(guò)event notifier機(jī)制完成),會(huì)調(diào)用arch_timer_setup來(lái)初始化clock_event_device數(shù)據(jù)結(jié)構(gòu)并注冊(cè)到系統(tǒng)中。

TODO:這里等到完成clockevent文檔之后再來(lái)更新。

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

    關(guān)注

    134

    文章

    9006

    瀏覽量

    366037
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11164

    瀏覽量

    208468

原文標(biāo)題:郭健:? Linux時(shí)間子系統(tǒng)之ARM generic timer驅(qū)動(dòng)代碼分析

文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場(chǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    何在Linux中使用htop命令

    本文介紹如何在 Linux 中使用 htop 命令。
    的頭像 發(fā)表于 12-04 14:45 ?1652次閱讀
    如<b class='flag-5'>何在</b><b class='flag-5'>Linux</b>中使用htop命令

    linux led key驅(qū)動(dòng)編譯報(bào)錯(cuò)

    linux-headers-3.2.0-29 linux-source-3.2.0linux-headers-3.2.0-29-generic 這3個(gè)文件那個(gè)是我們要去找的 有的沒(méi)有hardware.h 只有g(shù)ta02.h這一個(gè)頭文件 我試過(guò)更改可是還是報(bào)同樣的錯(cuò)誤。。
    發(fā)表于 08-22 16:58

    Linux時(shí)間子系統(tǒng)之ARM generic timer驅(qū)動(dòng)代碼分析

    郭健? Linux時(shí)間子系統(tǒng)之ARM generic timer驅(qū)動(dòng)代碼分析
    發(fā)表于 07-17 09:30

    何在嵌入式操作系統(tǒng)ARM Linux實(shí)現(xiàn)ZLG7290的驅(qū)動(dòng)?

    I2C總線(xiàn)接口的工作模式和特點(diǎn)如何在嵌入式操作系統(tǒng)ARM Linux實(shí)現(xiàn)ZLG7290的驅(qū)動(dòng)?I2C總線(xiàn)在傳送數(shù)據(jù)過(guò)程中有哪幾種信號(hào)?
    發(fā)表于 04-23 06:00

    何在Linux驅(qū)動(dòng)STN彩色LCD?

    何在Linux驅(qū)動(dòng)STN彩色LCD?
    發(fā)表于 06-04 06:29

    I.MX8MM開(kāi)發(fā)板Linux何在內(nèi)核添加驅(qū)動(dòng)

    迅為I.MX8MM開(kāi)發(fā)板編譯驅(qū)動(dòng)到內(nèi)核,在平時(shí)的驅(qū)動(dòng)開(kāi)發(fā),經(jīng)常需要在內(nèi)核配置某種功能,為了方便大家開(kāi)發(fā)和學(xué)習(xí),本小節(jié)講解如何在內(nèi)核
    發(fā)表于 08-29 17:46

    Linux之kernel_timer教程

    Linux之kernel_timer教程,很好的Linux自學(xué)資料,快來(lái)學(xué)習(xí)吧。
    發(fā)表于 04-15 17:59 ?12次下載

    Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》第9章、Linux設(shè)備驅(qū)動(dòng)的異步通知與異步IO

    Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》第9章、Linux設(shè)備驅(qū)動(dòng)的異步通知與異步IO
    發(fā)表于 10-27 11:33 ?0次下載
    《<b class='flag-5'>Linux</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>開(kāi)發(fā)詳解》第9章、<b class='flag-5'>Linux</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>中</b>的異步通知與異步IO

    Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》第8章、Linux設(shè)備驅(qū)動(dòng)的阻塞與非阻塞IO

    Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》第8章、Linux設(shè)備驅(qū)動(dòng)的阻塞與非阻塞IO
    發(fā)表于 10-27 11:35 ?9次下載
    《<b class='flag-5'>Linux</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>開(kāi)發(fā)詳解》第8章、<b class='flag-5'>Linux</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>中</b>的阻塞與非阻塞IO

    Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》第7章、Linux設(shè)備驅(qū)動(dòng)的并發(fā)控制

    Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》第7章、Linux設(shè)備驅(qū)動(dòng)的并發(fā)控制
    發(fā)表于 10-27 11:37 ?10次下載
    《<b class='flag-5'>Linux</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>開(kāi)發(fā)詳解》第7章、<b class='flag-5'>Linux</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>中</b>的并發(fā)控制

    Embeded linux的MMC驅(qū)動(dòng)

    Embeded linux的MMC驅(qū)動(dòng)
    發(fā)表于 05-14 16:08 ?1126次閱讀
    Embeded <b class='flag-5'>linux</b><b class='flag-5'>中</b>的MMC<b class='flag-5'>驅(qū)動(dòng)</b>

    何在linux服務(wù)器打開(kāi)端口

    有時(shí)我們可能需要在Linux服務(wù)器打開(kāi)端口或在Linux服務(wù)器的防火墻啟用端口來(lái)運(yùn)行特定的應(yīng)用程序。在本文中,小編將帶大家分析一下如何在
    的頭像 發(fā)表于 10-17 16:22 ?1.2w次閱讀

    何在Linux使用pidof命令

    `pidof`是一個(gè)命令行程序,可讓您找到正在運(yùn)行程序的進(jìn)程ID。在教程,我們將說(shuō)明如何在Linux 使用pidof命令。
    的頭像 發(fā)表于 12-05 17:01 ?2210次閱讀

    何在Linux查找斷開(kāi)的符號(hào)鏈接

    在之前的文章,我們解釋了什么是 Linux 的符號(hào)鏈接。符號(hào)鏈接(Symbolic links 或 symlinks)或軟鏈接(soft links)用于在 Linux
    的頭像 發(fā)表于 02-06 18:23 ?1570次閱讀

    何在工業(yè)驅(qū)動(dòng)實(shí)現(xiàn)精密的運(yùn)動(dòng)控制

    何在工業(yè)驅(qū)動(dòng)實(shí)現(xiàn)精密的運(yùn)動(dòng)控制
    的頭像 發(fā)表于 08-24 13:37 ?460次閱讀
    如<b class='flag-5'>何在</b>工業(yè)<b class='flag-5'>驅(qū)動(dòng)</b>器<b class='flag-5'>中</b>實(shí)現(xiàn)精密的運(yùn)動(dòng)控制