有关ecos设备表入口DEVTAB_ENTRY分析 编写eCos设备驱动时,比较重要的就是设备表入口DEVTAB_ENTRY,通过给指定的设备定义DEVTAB_ENTRY,来达到 对设备的注册过程,DEVTAB_ENTRY就是一个宏定义,定义在ecos/packages/io/common/current/include/devtab.h中, 原形如下: #define DEVTAB_ENTRY(_l, _name, _dep_name, _handlers, _init, _lookup, _priv) \ CHAR_DEVTAB_ENTRY(_l, _name, dep_name, _handlers, _init, _lookup, _priv)
默认下使用DEVTAB_ENTRY定义的是字符设备,如果要注册一个块设备就必须使用BLOCK_DEVTAB_ENTRY, 以CHAR_DEVTAB_ENTRY为例,定义在同一个文件当中: #define CHAR_DEVTAB_ENTRY(_l, _name, _dep_name, _handlers, _init, _lookup, _priv) \ cyg_devtab_entry_t _l CYG_HAL_TABLE_ENTRY(devtab) = { \ _name, \ _dep_name, \ _handlers, \ _init, \ _lookup, \ _priv, \ CYG_DEVTAB_STATUS_CHAR \ }; 就是定义一个cyg_devtab_entry_t结构的变量,需要注意的是CYG_HAL_TABLE_ENTRY,他其实是将定义的 变量_l放到指定的数据段中,来看看他的定义,在ecos/packages/hal/common/current/include/hal_tables.h文件中, #define CYG_HAL_TABLE_ENTRY( _name ) \ CYGBLD_ATTRIB_SECTION(".ecos.table." __xstring(_name)".data.") \ CYGBLD_ATTRIB_USED
看看CYGBLD_ATTRIB_SECTION和CYGBLD_ATTRIB_USED的定义,文件ecos/packages/infra/current/include/cyg_type.h中, #define CYGBLD_ATTRIB_SECTION(__sect__) __attribute__((section (__sect__)))
#define CYGBLD_ATTRIB_USED __attribute__((unused))
现在将CYG_HAL_TABLE_ENTRY(devtab)展开是: __atrribute__((section (".ecos.table.devtab.data."))) __attribute__((unused))
也就是将所有的设备表入口放到.ecos.table.devtab.data.数据段中,有关__attribute__的可以参考GNU手册中的说明, 可以看出这和linux中的_init的使用是相同的,后面的__attribute__((unused))启动作用就是在编译时防止 出现“变量未使用”警告的出现。
系统访问的时候,并不直接使用设备表入口的名称_l,而是通过两个指针来操作.ecos.table.devtab.data.数据段, 分别是__DEVTAB__和__DEVTAB_END__,这两个指针定义在ecos/packages/io/common/current/src/ioinit.cxx中, CYG_HAL_TABLE_BEGIN( __DEVTAB__, devtab ); CYG_HAL_TABLE_END( __DEVTAB_END__, devtab );
定义在ecos/packages/hal/common/current/include/hal_tables.h
#define CYG_HAL_TABLE_BEGIN( _label, _name ) \ __asm__(".section \".ecos.table." __xstring(_name) ".begin\",\"aw\"\n" \ ".globl" __xstring(CYG_LABEL_DEFN(_label)) "\n" \ ".type " __xstring(CYG_LABEL_DEFN((_label)) ",object\n" \ ".p2align " __xstring((CYGARC_P2ALIGNMENT) "\n" \ __xstring(CYG_LABEL_DEFN(_label)) ":\n" \ ".previous\n" \ )
#define CYG_HAL_TABLE_END( _label, _name ) \ __asm__(".section \".ecos.table." __xstring(_name) ".finish\",\"aw\"\n" \ ".globl" __xstring(CYG_LABEL_DEFN(_label)) "\n" \ ".type " __xstring(CYG_LABEL_DEFN((_label)) ",object\n" \ ".p2align " __xstring((CYGARC_P2ALIGNMENT) "\n" \ __xstring(CYG_LABEL_DEFN(_label)) ":\n" \ ".previous\n" \ ) 简单的说明一下就是,定义两个指针指向.ecos.table.devtab.data.的开始和结尾。
系统启动时会通过调用cyg_io_init函数完成对所有设备的初始化,具体代码是: cyg_devtab_entry_t *t; for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++) { if (t->init(t)) { t->status |= CYG_DEVTAB_STATUS_AVAIL; } else { t->status &= ~CYG_DEVTAB_STATUS_AVAIL; } }
用户是通过cyg_io_lookup获取设备句柄的,具体代码如下: for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++) { if (cyg_io_compare(name, t->name, &name_ptr)) { if (t->dep_name) { res = cyg_io_lookup(t->dep_name, &stunion.h); } if (t->lookup) { res = (t->lookup)(&t, stunion.st, name_ptr); } *handle = (cyg_io_handle_t)t; } }
|