Chinaunix首页 | 论坛 | 博客
  • 博客访问: 452658
  • 博文数量: 150
  • 博客积分: 2706
  • 博客等级: 少校
  • 技术积分: 1200
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-09 11:41
文章分类

全部博文(150)

文章存档

2012年(7)

2011年(6)

2010年(68)

2009年(69)

我的朋友

分类:

2010-01-04 14:21:41



我现在在写一个eCos上面的usb驱动。我是在cyg_start里面想自己调用,可是我自己调用不成功,就边diag_printf()都不能用了,哪位大哥看可不可以帮我一下。谢谢了。
我的做法是:
1.在自己的驱动代码里面写好char_devtab_entry{…………}里的东西。
2.在cyg_start()里面用
      CYG_HAL_TABLE_BEGIN(__KIXRP435_INIT_TAB__,devtab);
      CYG_HAL_TABLE_END(__KIXRP435_INIT_TAB_END__,devtab);
      extern struct cyg_devtab_entry __KIXRP435_INIT_TAB__[], __KIXRP435_INIT_TAB_END_

3.初始化:
    struct cyg_devtab_entry* init_entry;
    for(init_entry = __KIXRP435_INIT_TAB__; init_entry != &__KIXRP435_INIT_TAB_END__; init_entry++)
{
   (*init_entry->init)(init_entry);
}

cygnus,2008-04-22 17:58:34

难道 说CHAR_DEVTAB_ENTRY不用自己调用,系统会在什么地方调用?

但是我看redboot的源码他就自己调用的啊。

ning,2008-04-23 00:05:54

下面是内核代码的跟踪,你看一下,就基本明白了。

1.用CHAR_DEVTAB_ENTRY定义的数据结构,会放在ecos的.ecos.table.devtab.data数据段中。

io/common/current/include/devtab.h
#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                                               \
};

#ifndef CYG_HAL_TABLE_ENTRY
#define CYG_HAL_TABLE_ENTRY( _name ) \
        CYGBLD_ATTRIB_SECTION(".ecos.table." __xstring(_name) ".data") \
        CYGBLD_ATTRIB_USED
#endif

这是我的设备的map文件的.ecos.table.*数据段的显示, br104h_serial_io0是串口设备,
unimac_eth0_netdev是网口设备。

 *(SORT(.ecos.table.*))
 .ecos.table.devtab.data
                0x0003f8cc       0x54 /home/ning/work/lib/install/lib/extras.o
                0x0003f904                haldiag_io0
                0x0003f8e8                tty_io_diag
                0x0003f8cc                br104h_serial_io0
 .ecos.table.fstab.data
                0x0003f920       0x40 /home/ning/work/lib/install/lib/extras.o
                0x0003f920                dev_fste
 .ecos.table.mtab.data
                0x0003f960       0x1c /home/ning/work/lib/install/lib/extras.o
                0x0003f960                dev_mte
 .ecos.table.mtab.extra
                0x0003f97c       0xe0 /home/ning/work/lib/install/lib/extras.o
                0x0003f97c                cyg_mtab_extra
 .ecos.table.netdev.data
                0x0003fa5c       0x10 /home/ning/work/lib/install/lib/extras.o
                0x0003fa5c                unimac_eth0_netdev
 .ecos.table.nstab.data
                0x0003fa6c       0x1c /home/ning/work/lib/install/lib/extras.o
                0x0003fa6c                bsd_nste
                0x0003fa88                . = ALIGN (0x4)
                0x0003fa88                __CTOR_LIST__ = (.)


2. 这里定义了.ecos.table.*数据段,用_label符号可以找到,这样c语言可以直接调用它
hal/common/current/include/hal_tables.h
#ifndef CYG_HAL_TABLE_BEGIN
#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"                                                            \
       )
#endif

#ifndef CYG_HAL_TABLE_END
#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"                                                            \
       )
#endif

3. 只要你添加了io模块,也就定义了该表。

io/common/current/src/ioinit.cxx
#include
#include

// This is a dummy class just so we can execute the I/O package
// initialization at it's proper priority

externC void cyg_io_init(void);

class cyg_io_init_class {
public:
    cyg_io_init_class(void) {
        cyg_io_init();
    }
};

// And here's an instance of the class just to make the code run
static cyg_io_init_class _cyg_io_init CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO);

// Define table boundaries
CYG_HAL_TABLE_BEGIN( __DEVTAB__, devtab );
CYG_HAL_TABLE_END( __DEVTAB_END__, devtab );

4.该表被初始化的代码,即设备被初始化。
io/common/current/src/iosys.c

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++) {
#ifdef CYGDBG_IO_INIT
        diag_printf("Init device '%s'\n", t->name);
#endif
        if (t->init(t)) {
            t->status |= CYG_DEVTAB_STATUS_AVAIL;
        } else {
            // What to do if device init fails?
            // Device not [currently] available
            t->status &= ~CYG_DEVTAB_STATUS_AVAIL;
        }
    }
    _init = true;
}

5. 因此只要你用CHAR_DEVTAB_ENTRY定义了设备,且在ecc文件中添加了使用该设备的模块,这样在eCos初始化的时候,该模块就会被初始化。如果你不是很确定,可以将CYGDBG_IO_INIT打开。eCos的这种做法,主要还是考虑本身的特点“可配置”,用户只要通过配置,就可以添加或删除相应的设备驱动模块,而不需要修改任何代码,是从模块化和耦合性考虑。但代码晦涩了些。

ning,2008-04-23 00:30:44

to 斑竹:
呵呵,早点看到斑竹的关于devtab的精华帖子,我就不必去grep代码了。

to cygnus:

首先建议你看一下map文件,确定你的 __KIXRP435_INIT_TAB__ 的位置对应就是.ecos.table.devtab.data 的位置,否则代码就跑飞了。

另外一个问题就是,如果你添加了io模块,那么你的devtab(里面不仅有你的usb驱动,还有串口驱动等)就被初始化了两遍,一个是在你写的代码里面,另一个是在ioinit.cxx里面(调用cyg_io_init)。你的diag_printf失效的原因可能就是串口驱动被初始化了两遍。

最好的办法就是添加一些diag_printf(),跟一下代码就可以搞定了。添加打印语句一直到串口不工作了,问题就出在那里。

cygnus,2008-04-23 18:59:22

to ning:
     谢谢你啊。我看看。再次谢谢

cygnus,2008-04-24 09:26:39

还有一个地方不明白,请问一下cyg_io_init(void)谁去调用呢?我只能追到这里了。
ning,2008-04-24 23:14:41

在vector.S中,在调用cyg_start()前,会调用cyg_hal_invoke_contructors(),该函数调用全局C++的构造函数。在cyg_type.h中定义的CYG_INIT_XXXXXXX确定了各个构造函数的初始化顺序。cyg_io_init()就是在class cyg_io_init_class的构造函数中被调用。

这些在massa的书的第二章有描述,你可以看一下。

cygnus,2008-04-28 15:55:41

184 void
185 cyg_hal_invoke_constructors (void)
186 {
187 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
188     static pfunc *p = &__CTOR_END__[-1];
189    
190     cyg_hal_stop_constructors = 0;
191     for (; p >= __CTOR_LIST__; p--) {
192         (*p) ();
193         if (cyg_hal_stop_constructors) {
194             p--;
195             break;
196         }
197     }
198 #else
199     pfunc *p;
200
201     for (p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--)
202         (*p) ();
203 #endif
204 }
这段代码是eCos系统里的那个总的初始化函数,可是&__CTOR_END__[-1]这里怎么写成了-1,   谢谢。

cygnus,2008-04-28 15:56:32

__CTOR_END__[-1]  这样没有语法问题?
ning,2008-04-28 22:07:39

没有语法问题。
在arm.ld里面
    __CTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.ctors*))) __CTOR_END__ = ABSOLUTE (.); \
    __DTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.dtors*))) __DTOR_END__ = ABSOLUTE (.); \

代码的实现就是从内存后往前初始化每个构造函数。__DTOR_LIST__为结束地址,因此最后面的函数地址为__CTOR_END__的地址减四,即__CTOR_END__[-1]

cygnus,2008-05-02 11:14:54

谢谢ning的解答,不过我的问题最终找到是因为没有地址映射。大家也要注意哦。
阅读(1718) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~