RIOT(基于CC2538cb)学习1-启动分析/寻找int main()

来源:互联网 发布:jeewx商业版源码下载 编辑:程序博客网 时间:2024/06/14 18:16

硬件平台:cc2538cb (cc2538sf53


TinyOS和Contiki的启动依赖start-gcc.c,RIOT则选择在cortex_common中实现;
三个OS本质启动没有区别都是进入reset_handler_default;该实现在RIOT\cpu\cortexm_common\vectors_cortexm.c中,对于ISR表等的分析就省略了;
来看一下代码实现:

void reset_handler_default(void){    uint32_t *dst;    uint32_t *src = &_etext;    pre_startup();#ifdef DEVELHELP    uint32_t *top;    /* Fill stack space with canary values up until the current stack pointer */    /* Read current stack pointer from CPU register */    asm volatile ("mov %[top], sp" : [top] "=r" (top) : : );    dst = &_sstack;    while (dst < top) {        *(dst++) = STACK_CANARY_WORD;    }#endif    /* load data section from flash to ram */    for (dst = &_srelocate; dst < &_erelocate; ) {        *(dst++) = *(src++);    }    /* default bss section to zero */    for (dst = &_szero; dst < &_ezero; ) {        *(dst++) = 0;    }    post_startup();    /* initialize the board (which also initiates CPU initialization) */    board_init();#if MODULE_NEWLIB    /* initialize std-c library (this must be done after board_init) */    extern void __libc_init_array(void);    __libc_init_array();#endif    /* startup the kernel */    kernel_init();}

pre_startup();post_startup();在文件中是空函数;


和TinyOS和Contiki一样,先完成rom,bss段初始化;Contiki-3.0版本的2538段初始化部分的写法个人觉得不如2.7版本的写法直观,不懂的朋友也可以去看一下arm-none-eabi-gcc提供的文档和源码例子或者去参考TI给的驱动库,他们的startup文件的写法;


我们具体关心的有board_init()kernel_init()函数;
board_init()在RIOT\boards\cc2538cb下board.c中:

void board_init(void){    /* initialize the CPU */    cpu_init();    /* initialize the boards LEDs */    led_init();}


代码简单 不做分析;
下面来到重点函数,我们将看到main函数冒泡了,总算逮到你了
kernel_init()在RIOT\core下kernel_init.c中:

void kernel_init(void){    (void) disableIRQ();    thread_create(idle_stack, sizeof(idle_stack),            THREAD_PRIORITY_IDLE,            THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST,            idle_thread, NULL, idle_name);    thread_create(main_stack, sizeof(main_stack),            THREAD_PRIORITY_MAIN,            THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST,            main_trampoline, NULL, main_name);    cpu_switch_context_exit();}


别着急了解thread的概念,先把他理解成普通的C函数的调用;来看一下俩个thread干了什么:kernel_init.c中:
extern int main(void);static void *main_trampoline(void *arg){    (void) arg;#ifdef MODULE_AUTO_INIT    auto_init();#endif#ifdef MODULE_SCHEDSTATISTICS    schedstat *stat = &sched_pidlist[thread_getpid()];    stat->laststart = 0;#endif    LOG_INFO("main(): This is RIOT! (Version: " RIOT_VERSION ")\n");    main();    return NULL;}static void *idle_thread(void *arg){    (void) arg;    while (1) {        if (lpm_prevent_sleep) {            lpm_set(LPM_IDLE);        }        else {            lpm_set(LPM_IDLE);            /* lpm_set(LPM_SLEEP); */            /* lpm_set(LPM_POWERDOWN); */        }    }    return NULL;}


我们看到main_trampoline中出现了main()了,总算搞清楚了RIOT的启动过程;
其中出现了auto_init(),这个函数非常重要,来看一下实现:
RIOT\sys\auto_init下auto_init.c中:

void auto_init(void){#ifdef MODULE_CONFIG    DEBUG("Auto init loading config\n");    config_load();#endif#ifdef MODULE_XTIMER    DEBUG("Auto init xtimer module.\n");    xtimer_init();#endif#ifdef MODULE_RTC    DEBUG("Auto init rtc module.\n");    rtc_init();#endif#ifdef MODULE_SHT11    DEBUG("Auto init SHT11 module.\n");    sht11_init();#endif#ifdef MODULE_GPIOINT    DEBUG("Auto init gpioint module.\n");    gpioint_init();#endif#ifdef MODULE_LTC4150    DEBUG("Auto init ltc4150 module.\n");    ltc4150_init();#endif#ifdef MODULE_MCI    DEBUG("Auto init mci module.\n");    MCI_initialize();#endif#ifdef MODULE_PROFILING    extern void profiling_init(void);    profiling_init();#endif#ifdef MODULE_GNRC_PKTBUF    DEBUG("Auto init gnrc_pktbuf module\n");    gnrc_pktbuf_init();#endif#ifdef MODULE_GNRC_PKTDUMP    DEBUG("Auto init gnrc_pktdump module.\n");    gnrc_pktdump_init();#endif#ifdef MODULE_GNRC_SIXLOWPAN    DEBUG("Auto init gnrc_sixlowpan module.\n");    gnrc_sixlowpan_init();#endif#ifdef MODULE_GNRC_IPV6    DEBUG("Auto init gnrc_ipv6 module.\n");    gnrc_ipv6_init();#endif#ifdef MODULE_GNRC_UDP    DEBUG("Auto init UDP module.\n");    gnrc_udp_init();#endif/* initialize network devices */#ifdef MODULE_AUTO_INIT_GNRC_NETIF#ifdef MODULE_AT86RF2XX    extern void auto_init_at86rf2xx(void);    auto_init_at86rf2xx();#endif#ifdef MODULE_ENCX24J600    extern void auto_init_encx24j600(void);    auto_init_encx24j600();#endif#ifdef MODULE_ENC28J60    extern void auto_init_enc28j60(void);    auto_init_enc28j60();#endif#ifdef MODULE_GNRC_SLIP    extern void auto_init_slip(void);    auto_init_slip();#endif#ifdef MODULE_CC110X    extern void auto_init_cc110x(void);    auto_init_cc110x();#endif#ifdef MODULE_XBEE    extern void auto_init_xbee(void);    auto_init_xbee();#endif#ifdef MODULE_KW2XRF    extern void auto_init_kw2xrf(void);    auto_init_kw2xrf();#endif#ifdef MODULE_NETDEV2_TAP    extern void auto_init_netdev2_tap(void);    auto_init_netdev2_tap();#endif#endif /* MODULE_AUTO_INIT_GNRC_NETIF */#ifdef MODULE_GNRC_IPV6_NETIF    gnrc_ipv6_netif_init_by_dev();#endif/* initialize sensors and actuators */#ifdef MODULE_AUTO_INIT_SAUL    DEBUG("auto_init SAUL\n");#ifdef MODULE_SAUL_GPIO    extern void auto_init_gpio(void);    auto_init_gpio();#endif#ifdef MODULE_LSM303DLHC    extern void auto_init_lsm303dlhc(void);    auto_init_lsm303dlhc();#endif#ifdef MODULE_LPS331AP    extern void auto_init_lps331ap(void);    auto_init_lps331ap();#endif#ifdef MODULE_ISL29020    extern void auto_init_isl29020(void);    auto_init_isl29020();#endif#ifdef MODULE_L3G4200D    extern void auto_init_l3g4200d(void);    auto_init_l3g4200d();#endif#endif /* MODULE_AUTO_INIT_SAUL */}
应该不用作者多介绍了,这个函数到底是干什么的;


我们看到了MODULE_xxx;让作者感到很亲切,毕竟作者本身是一个TinyOS控



到此我们基本的启动工程分析完成;

RIOT为什么不像TinyOS和Contiki那样,系统提供了int main()函数;

TinyOS是MainC组件/Contiki是contiki-main.c;


RIOT的int main()需要用户自己编写;可以去看一下例程; 通过初步的代码阅读;感觉RIOT的代码风格是本人比较喜欢的先不提他支持C++;在后面的部分我将一层一层揭开他的面纱;
1 0
原创粉丝点击