有關ecos設備表入口DEVTAB_ENTRY分析

================================

Author: taoyuetao
Email: [email protected]
Blog: http://www.eetop.cn/blog/?11145

07-04-20

================================

 

    編寫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;
 }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章