Chinaunix首页 | 论坛 | 博客
  • 博客访问: 875868
  • 博文数量: 149
  • 博客积分: 3671
  • 博客等级: 中校
  • 技术积分: 1701
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-03 16:52
文章分类

全部博文(149)

文章存档

2011年(57)

2010年(92)

分类: 嵌入式

2010-08-17 19:18:36

eCos设备驱动程序(二)



关于设备入口表DEVTAB_ENTRY:
在eCos中, 是通过给指定的设备定义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定义的是字符设备,这里就以一个字符设备为例进行说明了,
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 );

CYG_HAL_TABLE_BEGIN和CYG_HAL_TABLE_END的定义在
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)) ",objectn"                   
    ".p2align " __xstring((CYGARC_P2ALIGNMENT) "n"                             
    __xstring(CYG_LABEL_DEFN(_label)) ":n"                                     
    ".previousn"                                                               
    )
#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)) ",objectn"                   
    ".p2align " __xstring((CYGARC_P2ALIGNMENT) "n"                             
    __xstring(CYG_LABEL_DEFN(_label)) ":n"                                     
    ".previousn"                                                               
    )
也就是,
__DEVTAB__和__DEVTAB_END__两个指针分别指向.ecos.table.devtab.data.的开始和结尾

这样就把该设备的
设备的入口表放入了__DEVTAB__和__DEVTAB_END__ 之间有数据段中.

系统在启动时会通过调用cyg_io_init函数完成对所有设备的初始化,具体代码是:
void
cyg_io_init(void)
{
    static int _init = false;
    cyg_devtab_entry_t *t;
    if (_init) return;
/*******************************************************************/
   
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; 
        }
    }
/*******************************************************************/
    _init = true;
}

用户可以通过cyg_io_lookup获取设备句柄,具体代码如下:
Cyg_ErrNo
cyg_io_lookup(const char *name, cyg_io_handle_t *handle)
{
    union devtab_entry_handle_union {
        cyg_devtab_entry_t *st;
        cyg_io_handle_t h;
    } stunion;
    cyg_devtab_entry_t *t;
    Cyg_ErrNo res;
    const char *name_ptr;
/*******************************************************************/
 
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 (res != ENOERR) {
                    return res;
                }
/*******************************************************************/
            } else {
                stunion.st = NULL;
            }
            if (t->lookup) {
                res = (t->lookup)(&t, stunion.st, name_ptr);
                if (res != ENOERR) {
                    return res;
                }
            }
            *handle = (cyg_io_handle_t)t;
            return ENOERR;
        }
    }
    return -ENOENT; 
}
阅读(4271) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~