TI am335x 核心分析2--資源遍歷程式碼分析
MPU平臺:OAMP3352
核心版本:3.2.0
宣告:我講解的範疇是從核心解壓以後經過彙編程式碼執行最後跳到第一個C程式碼這個點開始講解,一直講到檔案系統被正確的掛載起來,使用者可以登入!至於之前的彙編程式碼我會以後另開文章講解.
1. init/main.c
init/main.c 檔案是彙編過來的第一個被呼叫的C程式碼檔案;
void __init start_kernel(void)是彙編過來的第一個被執行的C函式;
MACHINE_START(AM335XEVM, "am335xevm")
/* Maintainer: Texas Instruments */
.atag_offset = 0x100,
.map_io = am335x_evm_map_io,
.init_early = am33xx_init_early,
.init_irq = ti81xx_init_irq,
.handle_irq = omap3_intc_handle_irq,
.timer = &omap3_am33xx_timer,
.init_machine = am335x_evm_init,
MACHINE_END
這樣我們板級程式碼的初始化就完成了,但這只是僅僅資料結構得到初始化,真正的資源都在這個結構體裡面,那在哪裡通過這個變數呼叫這個資料結構裡面的成員或成員函式的呢?
OMAP的hwmod程式碼在裝置啟動過程中也可以進行復位或睡眠這個裝置,這樣讓裝置可以處於一個正確的執行狀態。OMAP硬體模組的狀態:
剛一開始時候硬體模組是未知的狀態,一旦被註冊的話,就處於被註冊狀態,若果該模組的時鐘被得到分配,就進入時鐘已初始化狀態,最後模組設定完成了就出一個已經初始化狀態。
Hwmod程式碼也包括:處理I/O對映程式碼功能匯流排的吞吐率和模組延時的測試程式碼。上面零零碎碎的囉嗦了一下這個hwmod的是個什麼東西,當時 “最好的文件還是程式碼本身” 這是我一直奉行的觀念!
2.第一步: struct omap_hwmod
這個結構體TI的解釋是:
integration data for OMAP hardware "modules" (IP blocks)
struct omap_hwmod {
const char *name; //硬體模組的名稱
struct omap_hwmod_class *class; //硬體模組屬於哪個類(硬體都有類了)
struct omap_device *od; //硬體模組對應的具體裝置
struct omap_hwmod_mux_info *mux; //硬體模組的管教複用資訊
struct omap_hwmod_irq_info *mpu_irqs; //硬體模組的中斷資訊
struct omap_hwmod_dma_info *sdma_reqs;//硬體模組的DMA資訊
struct omap_hwmod_rst_info*rst_lines; //硬體模組的設定資訊
union {
struct omap_hwmod_omap2_prcm omap2;//硬體模組特殊的PRCM資料
struct omap_hwmod_omap4_prcm omap4;//硬體模組特殊的PRCM資料
} prcm;
const char*main_clk; //OMAP時鐘的名字
struct clk*_clk; //主時鐘
struct omap_hwmod_opt_clk *opt_clks; //其他裝置的時鐘
char *clkdm_name; //
struct clockdomain *clkdm;
char *vdd_name;//電壓的名稱
struct omap_hwmod_ocp_if**masters; /* connect to *_IA */ //IA是指發生器的代理(就是說模組和互聯器之前不是直接相連的而是通過這個代理器來收發資料和命令,嗨TI搞的好複雜可見BSP和硬體的耦合性是多麼的緊密!)
struct omap_hwmod_ocp_if**slaves; /* connect to *_TA *///TA是目標的代理
void *dev_attr;
u32 _sysc_cache;
void __iomem *_mpu_rt_va; //模組cache暫存器的起始地址
spinlock_t _lock;
struct list_head node;
u16 flags;
u8 _mpu_port_index;
u8 response_lat;
u8 rst_lines_cnt;
u8 opt_clks_cnt;
u8 masters_cnt;
u8 slaves_cnt;
u8 hwmods_cnt;
u8 _int_flags;
u8 _state; //模組的狀態(未知、已註冊、已初始化)
u8 _postsetup_state;
}
3. 第二步: omap_hwmod_33xx_data.c
該檔案裡面定義了所有的片內資源(以hwmod形式);
int __init am33xx_hwmod_init(void)
{
return omap_hwmod_register(am33xx_hwmods);//註冊了所有的片內模組資源並以連結串列形式連結在一起!omap_hwmod_list
}
int __init omap_hwmod_register(struct omap_hwmod **ohs)
{
intr, i;
if(!ohs)
return0;
i= 0;
do{
r= _register(ohs[i]);
WARN(r,"omap_hwmod: %s: _register returned %d\n", ohs[i]->name,
r);
}while (ohs[++i]);
return0;
}
4.第三步:omap_hwmod.c
omap_hwmod.c 裡面的函式是在devices.c中呼叫的。
至少明確了:為什麼TI要高一套hwmod的軟體機制(硬體使用了這套L3和L4的硬體模組互聯機制);
至少明確了:hwmod在BSP啟動中充當一個什麼的角色(一個hwmod封裝了所有的當前屬於這個硬體模組的所有資源,以及對硬體模組的操作功能函式,注意這個是和平臺有關性的,所以omap_device.c(基於linux驅動模型的方式)對這些功能函式又進行一次平臺無關性的封裝,這個下一節講。)
明確了:真正的BSP程式碼是和硬體的耦合性很大的,這一部分的程式碼才是水平的體現,你不僅要對整個硬體體系架構很清楚而且還要對每個硬體資源的效能有使用經驗,而且還要把這些東西抽象出一套符合平臺型的一個軟體架構。最後這個架構還要很好的整合到linux那套底層BSP架構中。而且還要考慮到核心的一系列問題(效能、資源利用、排程、通訊協議等等)。這些基本上都是晶片廠商的事情,等我們拿到一塊TI的評估板這一切的一切 都已經做的很好了,連頂層的應用程式都在一個SDK的包裡面提供給使用者,所以我們工作中很多的是軟體方面事情。
.