RT-Thread

※前提条件:本情報はRT-Thraead 3.0.4を基づいて説明してる

1)首先在main函数内调用了 rtthread_startup() 函数;

2)在void rtthread_startup(void)内调用了 rt_hw_board_init() 函数;

3)在 rt_hw_board_init() 函数内调用 rt_components_board_init();

void rt_components_board_init(void)
{
  #if RT_DEBUG_INIT
  int result;
  const struct rt_init_desc *desc;
  for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++)
  {
    rt_kprintf("initialize %s", desc->fn_name);
    result = desc->fn();
    rt_kprintf(":%d done\n", result);
  }
#else
  const init_fn_t *fn_ptr;

  for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
  {
    (*fn_ptr)();
  }
#endif
}

这里需要注意两个变量__rt_init_rti_board_start和__rt_init_rti_board_end,查找__rt_init_rti_board_start定义,导向到这个语句:INIT_EXPORT(rti_board_start, "0.end");

继续查找INIT_EXPORT,导向到 RT_USED const init_fn_t __rt_init_##fn SECTION(".rti_fn."level) = fn,

查找SECTION,到想到(#define SECTION(x) __attribute__*1)),这里作用是将作用的函数或数据放入指定名为"section_name"输入段,在链接的时候会被自动调用

知道__rt_init_rti_board_end 是通过宏定义INIT_EXPORT来组合前部分 __rt_init_和后部分rti_board_start,并放入到section指定的名称段内; __rt_init_rti_board_end类似。

__rt_init_rti_board_end 指向了section的“0.end”名称段,__rt_init_rti_board_end指向了section的"1.end"名称段,(*fn_ptr)()函数指针会依次调用这两段之间的所有函数。

这样,在rt_components_board_init函数内,就会把通过宏定义#define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1")定义的函数进行调用。

4)在void rtthread_startup(void)内调用了 rt_application_init() 函数;

5)在rt_application_init()函数内创建的线程内,调用了rt_components_init()函数;

void rt_components_init(void)
{
  #if RT_DEBUG_INIT
  int result;
  const struct rt_init_desc *desc;

  rt_kprintf("do components intialization.\n");
  for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++)
  {
    rt_kprintf("initialize %s", desc->fn_name);
    result = desc->fn();
    rt_kprintf(":%d done\n", result);
  }
#else
  const init_fn_t *fn_ptr;

  for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++)
  {
    (*fn_ptr)();
  }
#endif
}

这里需要注意两个变量__rt_init_rti_board_end和__rt_init_rti_end,

__rt_init_rti_board_end通过上面分析,可以知道它指向的是输入段section的"1.end"名称段,

__rt_init_rti_end通过了INIT_EXPORT(rti_end, "6.end"),它指向的是输入段section的"6.end"名称段,

(*fn_ptr)()函数指针会依次调用这两段之间的所有函数。

这样,在rt_components_init函数内,就会把通过以下5个宏定义

#define INIT_PREV_EXPORT(fn) INIT_EXPORT(fn, "2")

#define INIT_DEVICE_EXPORT(fn) INIT_EXPORT(fn, "3")

#define INIT_COMPONENT_EXPORT(fn) INIT_EXPORT(fn, "4")

#define INIT_ENV_EXPORT(fn) INIT_EXPORT(fn, "5")

#define INIT_APP_EXPORT(fn) INIT_EXPORT(fn, "6")

定义的函数进行调用。

6)所以,在自己代码中需要进行硬件初始化、线程启动等函数调用时,在函数定义下面直接使用以上6个宏中的一个,即可实现自动调用。



フレッツ光が月額556円~【GMOとくとくBB】

コメント:



(画像の文字列を入力して下さい)

*1 section(x

トップ   編集 凍結 差分 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019/12/02 (月) 12:35:43 (504d)