MPU平台:OAMP3352
内核版本:3.2.0
声明:我讲解的范畴是从内核解压以后经过汇编代码执行最后跳到第一个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的是个什么东西,当时 “最好的文档还是代码本身” 这是我一直奉行的观念!
这个结构体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;
}
该文件里面定义了所有的片内资源(以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;
}
omap_hwmod.c 里面的函数是在devices.c中调用的。
至少明确了:为什么TI要高一套hwmod的软件机制(硬件使用了这套L3和L4的硬件模块互联机制);
至少明确了:hwmod在BSP启动中充当一个什么的角色(一个hwmod封装了所有的当前属于这个硬件模块的所有资源,以及对硬件模块的操作功能函数,注意这个是和平台有关性的,所以omap_device.c(基于linux驱动模型的方式)对这些功能函数又进行一次平台无关性的封装,这个下一节讲。)
明确了:真正的BSP代码是和硬件的耦合性很大的,这一部分的代码才是水平的体现,你不仅要对整个硬件体系架构很清楚而且还要对每个硬件资源的性能有使用经验,而且还要把这些东西抽象出一套符合平台型的一个软件架构。最后这个架构还要很好的整合到linux那套底层BSP架构中。而且还要考虑到内核的一系列问题(性能、资源利用、调度、通信协议等等)。这些基本上都是芯片厂商的事情,等我们拿到一块TI的评估板这一切的一切 都已经做的很好了,连顶层的应用程序都在一个SDK的包里面提供给用户,所以我们工作中很多的是软件方面事情。
.