NuttX 启动流程

本文详细介绍了嵌入式实时操作系统NuttX 7.1版本在STM32平台上的启动过程。从处理器的第一条指令开始,经过时钟初始化、外设配置、操作系统初始化等多个步骤,最终创建初始任务并进入空闲任务循环。
(嵌入式 实时操作系统 rtos nuttx 7.1 stm32 源代码分析)

NuttX 启动流程

转载请注明出处: http://blog.youkuaiyun.com/zhumaill/article/details/23261543

[ruby]  view plain  copy
  1. __start--                                 #处理器执行的第一条指令  
  2.         |  
  3.         v  
  4.    stm32_clockconfig()------              #初始化时钟  
  5.                            |  
  6.                            v  
  7.                  rcc_reset()              #复位rcc  
  8.                  stm32_stdclockconfig()   #初始化标准时钟  
  9.                  rcc_enableperipherals()  #使能外设时钟  
  10.                            |  
  11.         --------------------  
  12.         |  
  13.         v  
  14.    stm32_fpuconfig()                      #配置fpu,shenzhou/nsh未调用  
  15.    stm32_lowsetup()                       #基本初始化串口,之后可以使用up_lowputc()  
  16.    stm32_gpioinit()                       #初始化gpio,只是调用stm32_gpioremap()设置重映射  
  17.    up_earlyserialinit()                   #初始化串口,之后可以使用up_putc()  
  18.    stm32_boardinitialize()--              #板级初始化  
  19.                            |  
  20.                            v  
  21.                  stm32_spiinitialize()    #初始化spi,只是调用stm32_configgpio()设置gpio  
  22.                  stm32_usbinitialize()    #初始化usb,只是调用stm32_configgpio()设置gpio  
  23.                  board_led_initialize()   #初始化led,只是调用stm32_configgpio()设置gpio  
  24.                            |  
  25.         --------------------  
  26.         |  
  27.         v  
  28.    os_start()---------------              #初始化操作系统  
  29.                            |  
  30.                            v  
  31.                  dq_init()                #初始化各种状态的任务列表(置为null)  
  32.                  g_pidhash[i]=            #初始化唯一可以确定的元素--进程ID  
  33.                  g_pidhash[PIDHASH(0)]=   #分配空闲任务的进程ID为0  
  34.                  g_idletcb=               #初始化空闲任务的任务控制块  
  35.                  sem_initialize()--       #初始化信号量  
  36.                                   |  
  37.                                   v  
  38.                        dq_init()          #将信号量队列置为null  
  39.                        sem_initholders()  #初始化持有者结构以支持优先级继承,shenzhou/nsh未调用  
  40.                                   |  
  41.                            --------  
  42.                            |  
  43.                            v  
  44.                  up_allocate_heap()       #分配用户模式的堆(设置堆的起点和大小)  
  45.                  kumm_initialize()        #初始化用户模式的堆  
  46.                  up_allocate_kheap()      #分配内核模式的堆,shenzhou/nsh未调用  
  47.                  kmm_initialize()         #初始化内核模式的堆,shenzhou/nsh未调用  
  48.                  task_initialize()        #初始化任务数据结构,shenzhou/nsh未调用  
  49.                  irq_initialize()         #将所有中断向量都指向同一个异常中断处理程序  
  50.                  wd_initialize()          #初始化看门狗数据结构  
  51.                  clock_initialize()       #初始化rtc  
  52.                  timer_initialize()       #配置POSIX定时器  
  53.                  sig_initialize()         #初始化信号  
  54.                  mq_initialize()          #初始化命名消息队列  
  55.                  pthread_initialize()     #初始化线程特定的数据,空函数  
  56.                  fs_initialize()---       #初始化文件系统  
  57.                                   |  
  58.                                   v  
  59.                        sem_init()         #初始化节点信号量为1  
  60.                        files_initialize() #初始化文件数组,空函数  
  61.                                   |  
  62.                            --------  
  63.                            |  
  64.                            v  
  65.                  net_initialize()--       #初始化网络  
  66.                                   |  
  67.                                   v  
  68.                        uip_initialize()   #初始化uIP层  
  69.                        net_initroute()    #初始化路由表,shenzhou/nsh未调用  
  70.                        netdev_seminit()   #初始化网络设备信号量  
  71.                        arptimer_init()    #初始化ARP定时器  
  72.                                   |  
  73.                            --------  
  74.                            |  
  75.                            v  
  76.                  up_initialize()---       #处理器特定的初始化  
  77.                                   |  
  78.                                   v  
  79.                        up_calibratedelay()#校准定时器  
  80.                        up_addregion()     #增加额外的内存段  
  81.                        up_irqinitialize() #设置中断优先级,关联硬件异常处理函数  
  82.                        up_pminitialize()  #初始化电源管理,shenzhou/nsh未调用  
  83.                        up_dmainitialize() #初始化DMA,shenzhou/nsh未调用  
  84.                        up_timerinit()     #初始化定时器中断  
  85.                        devnull_register() #注册/dev/null  
  86.                        devzero_register() #注册/dev/zero,shenzhou/nsh未调用  
  87.                        up_serialinit()    #注册串口控制台/dev/console和串口/dev/ttyS0  
  88.                        up_rnginitialize() #初始化并注册随机数生成器,shenzhou/nsh未调用  
  89.                        up_netinitialize() #初始化网络,是arch/arm/src/chip/stm32_eth.c中的  
  90.                        up_usbinitialize() #初始化usb驱动,shenzhou/nsh未调用  
  91.                        board_led_on()     #打开中断使能led,但很快会被其它地方的led操作改变状态  
  92.                                   |  
  93.                            --------  
  94.                            |  
  95.                            v  
  96.                  lib_initialize()         #初始化c库,空函数  
  97.                  group_allocate()         #分配空闲组  
  98.                  group_setupidlefiles()   #在空闲任务上创建stdout、stderr、stdin  
  99.                  group_initialize()       #完全初始化空闲组  
  100.                  os_bringup()------       #创建初始任务  
  101.                                   |  
  102.                                   v  
  103.                        KEKERNEL_THREAD()  #启动内核工作者线程  
  104.                        board_initialize() #最后一刻的板级初始化,shenzhou/nsh未调用  
  105.                        TASK_CREATE()      #启动默认应用程序  
  106.                                   |  
  107.                            --------  
  108.                            |  
  109.                            v  
  110.                  for up_idle()            #空闲任务循环  
  111.                            |  
  112.         --------------------  
  113.         |  
  114.         v  
  115.    for(;;)                                #不应该到达这里  
<think>好的,我现在需要回答用户关于如何在NuttX操作系统中启用全局变量构造函数的问题。首先,我需要理解用户的问题。全局变量的构造函数通常指的是C++中全局对象的构造函数,这些构造函数需要在main函数执行之前被自动调用。但是在像NuttX这样的嵌入式实时操作系统中,可能没有标准的启动流程来处理这些构造函数,所以需要手动配置。 接下来,我应该回顾NuttX的相关文档或者配置选项。根据用户提供的引用,特别是引用[2]中提到的CMake配置,可能涉及到链接脚本的设置。链接脚本(.ld文件)负责内存布局,包括初始化代码的放置。在C++中,全局构造函数的指针通常存放在.init_array或.ctors段中,因此需要确保链接脚本正确包含这些段,并且启动代码会遍历这些段并调用构造函数。 然后,用户的问题可能涉及到配置NuttX的构建系统,比如通过Kconfig或者修改配置文件来启用相关选项。我需要检查NuttX的配置系统中是否有关于全局构造函数支持的选项,可能需要设置CONFIG_HAVE_CXXINITIALIZE这样的配置宏,这样在系统启动时会调用相应的初始化函数来执行构造函数。 此外,启动代码的处理也很重要。NuttX启动流程可能需要显式地调用一个负责执行全局构造函数的函数,比如_nx_init_array。这个函数通常由工具链提供,但需要确保在链接时正确包含,并且在启动过程中被调用。可能需要修改启动文件(如nuttx_start.c)中的代码,在进入应用程序主函数之前添加对构造函数的调用。 还需要考虑工具链的支持。不同的编译器(如GCC、Clang)可能会有不同的处理方式,确保链接器能够正确处理.init_array段,并且生成正确的初始化代码。如果遇到问题,可能需要检查链接脚本是否包含这些段,或者是否有选项需要传递给编译器或链接器。 最后,验证步骤也是必要的。用户可能需要编写一个简单的C++测试程序,定义带有构造函数的全局对象,并观察构造函数是否在程序启动时被正确调用。如果未调用,可能需要进一步检查配置和链接脚本是否正确,或者是否有遗漏的步骤。 总结一下,步骤可能包括:配置NuttX启用C++支持,修改链接脚本包含必要的段,调整启动代码以调用构造函数,确保工具链正确配置,并进行测试验证。同时,参考用户提供的引用中关于CMake设置全局属性的部分,可能需要在构建过程中正确设置链接脚本的路径,确保链接器能够找到并处理这些初始化段。</think>在NuttX操作系统中启用全局变量构造函数需要以下步骤: ### 1. 配置链接脚本 修改链接描述文件(.ld文件),确保包含全局构造函数指针的段(如`.init_array`或`.ctors`)。例如在`gnu-elf.ld`中添加: $$ SECTIONS { .init_array : { __init_array_start = .; KEEP(*(.init_array*)) __init_array_end = .; } } $$ 这会将所有构造函数指针收集到`.init_array`段中[^2]。 ### 2. 启用C++初始化支持 在NuttX配置中启用相关选项: ```bash # 通过menuconfig配置 CONFIG_HAVE_CXX=y CONFIG_HAVE_CXXINITIALIZE=y ``` 这会激活系统级的C++初始化支持[^1]。 ### 3. 修改启动代码 在NuttX启动流程中(如`nuttx_start.c`)添加构造函数调用: ```c extern void _nx_init_array(void); void nx_start(void) { _nx_init_array(); // 调用全局构造函数 // ...后续初始化代码 } ``` 该函数会遍历`.init_array`段并执行所有构造函数指针[^1]。 ### 4. 验证工具链支持 确保使用的工具链(如GCC)支持标准C++初始化机制。可通过编译测试程序验证: ```cpp class Test { public: Test() { printf("Constructor called\n"); } }; Test global_obj; // 全局对象 int main() { printf("Main started\n"); return 0; } ``` 若输出显示构造函数先于main执行,则配置成功。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值