HAL包中定义了各个平台启动信息,在某个processor family中选择一个,找到一个具体的variant,找到其ld文件(连接描述文件,eCos中使用binutils包中的连接工具)。ld文件中定义了首先连接哪个文件,并以哪个函数为入口。一般启动的汇编文件为vector.S,入口函数为_start,(AT使用reset_vector为入口)。
从vector.S的入口执行,到这段代码的最后会跳转到cyg_start函数,这便开始正式进入C语言编写的代码。
eCos中用户程序的入口函数有两个cyg_user_start()和main()。
eCos在infra包中startup.cxx定义了weak的cyg_user_start()函数,如果用户定义了cyg_user_start()会代替这个默认的函数进行执行。但是要注意的是cyg_user_start在eCos中的cyg_start()中被调用之后,才会调用Cyg_Scheduler::start(),这就是说如果要使用调度,那就不能让cyg_user_start处于一个死循环中。
第二个可以使用的入口函数名为main()函数,注意的是这个需要增加libc才能够使用。
既然cyg_start()调用了cyg_user_start(),那么当然的想法就是在libc中应当存在一个cyg_user_start(),并且这个cyg_user_start()中调用了main()函数,这样就可以使用main()函数作为入口了。从CStartUp.cxx中发现,实际这只是两种main函数启动的方法之一,在eCos中选CYGSEM_LIBC_STARTUP_MAIN_INITCONTEXT就是使用这种方法的main()函数,使用的时候需要和cyg_user_start一样的使用注意,不能死循环。
第二种是CYGSEM_LIBC_STARTUP_MAIN_THREAD定义的方法,建立一个main函数的线程。mainthread.cxx中定义全局Cyg_Thread cyg_libc_main_thread,建立了一个线程对象,而CStartUp.cxx中定义了函数cyg_iso_c_start()内部实现内容为让cyg_libc_main_thread运行,该函数作为cyg_libc_startup_dummy_constructor_class的构造函数的实现。接着定义了静态的cyg_libc_startup_dummy_constructor_class类对象,这个对象构造的时候会使cyg_libc_main_thread开始运行。在这当中,需要注意对cyg_libc_main_thread和cyg_libc_startup_dummy_constructor_class类对象的构造时机进行控制。
实际上cyg_start()也可以作为入口函数,因为该函数也是weak的,不过需要增加一些必需的函数比如调度器的打开等。AT就是使用cyg_start()作为入口。