ecos代码分析(3)
在看cyg_start()之前,先要解决3个问题:
1. __startup_stack在哪里定义?
2. cyg_hal_invoke_constructors()这个机制是如何使用?
3. CALL_IF*机制是如何实现?
1. __startup_stack在哪里定义?
PTR(__startup_stack)
#define PTR(name) .##name: .word name
等价于 .__startup_stack: .word __startup_stack
后面有
.section ".bss"
.balign 16
__startup_stack_base:
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
.rept 512
#else
.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
#endif
.byte 0
.endr
.balign 16
__startup_stack:
#endif
说明__startup_stack这个标号在.bss段中,和__startup_stack_base一起限定__startup_stack的范围。
汇编.rept和.endr之间的语句count次,即运行”.byte 0” 512次,相当于申请了512byte的空间,作为stack空间。
在__startup_stack上面还有很多stack的定义,都一样的,没啥好说的。
没看懂这个,at&t汇编的伪指令要看看了。
2. cyg_hal_invoke_constructors()这个机制是如何使用?
void cyg_hal_invoke_constructors (void)
{
pfunc *p;
for (p = &CONSTRUCTORS_START; p != CONSTRUCTORS_END; NEXT_CONSTRUCTOR(p))
(*p)();
}
// EABI uses different symbols, and constructors are in opposite order.
#ifdef CYGBLD_HAL_ARM_EABI
extern pfunc __init_array_start__[];
extern pfunc __init_array_end__[];
#define CONSTRUCTORS_START (__init_array_start__[0])
#define CONSTRUCTORS_END (__init_array_end__)
#define NEXT_CONSTRUCTOR(c) ((c)++)
#else
extern pfunc __CTOR_LIST__[];
extern pfunc __CTOR_END__[];
#define CONSTRUCTORS_START (__CTOR_END__[-1])
#define CONSTRUCTORS_END (&__CTOR_LIST__[-1])
#define NEXT_CONSTRUCTOR(c) ((c)--)
#endif
#define SECTION_text(_region_, _vma_, _lma_) \
SECTION_ARM_extab(_region_, _vma_, _lma_) \
SECTION_ARM_exidx(_region_, ALIGN(AAPCS_ALIGN), FOLLOWING_ALIGNED(.ARM.extab, AAPCS_ALIGN)) \
.text ALIGN(AAPCS_ALIGN) : FOLLOWING_ALIGNED(.ARM.exidx, AAPCS_ALIGN) \
{ \
*(.text*) *(.gnu.warning) *(.gnu.linkonce.t.*) *(.init) \
*(.glue_7) *(.glue_7t) \
__CTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.ctors*))) __CTOR_END__ = ABSOLUTE (.); \
__DTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.dtors*))) __DTOR_END__ = ABSOLUTE (.); \
} > _region_ \
_etext = .; PROVIDE (__etext = .);
查遍整个工程,也找不到相关的内容。
在网上找到一篇关于C++全局构造函数的文章,里面有写到:
.ctors 该section保存着程序的全局的构造函数的指针数组。
.dtors 该section保存着程序的全局的析构函数的指针数组。
这个段是由编译器自己填充的,不必由代码显示的说明。
运行cyg_hal_invoke_constructors()就是把全局构造函数全都运行一下,都构造好。
可以想象,退出的时候,是要把全局析构函数全都运行一下。
3. CALL_IF*机制是如何实现?
首先IF应该是interface的缩写
都在diag_if.h中定义,挑几个出来看看。
#define CYGACC_CALL_IF_VERSION() \
CYGACC_DATA_VV(__call_if_version_t, CYGNUM_CALL_IF_VERSION)
__data_VV(CYGNUM_CALL_IF_VERSION, __call_if_version_t)
#define CYGACC_CALL_IF_VERSION_SET(_x_) \
hal_virtual_vector_table[CYGNUM_CALL_IF_VERSION]=(CYG_ADDRWORD)(_x_)
两个是一对,前面定义调用,后面定义调用的函数
hal_virtual_vector_table[]是一个全局的系统调用接口数组,每一个成员对一个系统调用。这个前面提到了。
#define CYGNUM_CALL_IF_VERSION 0
这里就是定义0号调用,调用到的函数就是参数_x_
hal_virtual_vector_table[0]=(CYG_ADDRWORD)(_x_)
#define CYGACC_DATA_VV(t,e) __call_vv_##e()
#define __data_VV(_n_,_tt_) \
static __inline__ _tt_ \
__call_vv_##_n_(void) \
{ \
return ((_tt_)hal_virtual_vector_table[_n_]); \
}
所以前面的展开就是:
#define CYGACC_CALL_IF_VERSION() __call_vv_0()
static __inline__ __call_if_version_t __call_vv_0(void)
{
return ((__call_if_version_t)hal_virtual_vector_table[0]);
}
这样一个设置一个调用。
可能还有类似的东西,以后看到再说。