NuttX开发环境搭建及启动流程

NuttX 是一个实时操作系统(RTOS),并且是对接口有着一定要求的系统。原生支持 POSIX 和 ANSI 标准接口,对于这些标准下不可用的接口功能,或不适合嵌入式环境的功能,则采用 Unix 和其他常见 RTOS(如 VxWorks)的标准 API。

Nuttx 支持从8位到32位芯片。采用的开源协议是 Apache2.0 ,也就是完全开源免费的协议。可以使用 menuconfig 进行图形化配置裁剪。

Nuttx 开发环境搭建及启动流程分析 | BalanceTWK的博客

nuttx 开发环境搭建(Ubuntu 20.04)


输入如下命令安装编译 nuttx 所需要的依赖组件:

sudo apt install bison flex gettext texinfo libncurses5-dev libncursesw5-dev gperf automake libtool pkg-config build-essential gperf genromfs libgmp-dev libmpc-dev libmpfr-dev libisl-dev binutils-dev libelf-dev libexpat-dev gcc-multilib g++-multilib picocom u-boot-tools util-linux

nuttx 使用 Kconfig 配置裁剪系统。所以需要安装 kconfig-frontends 软件。

apt install kconfig-frontends

工具链安装

apt install gcc-arm-none-eabi binutils-arm-none-eabi

下载 nuttx 应用与内核 代码

mkdir nuttx_project
cd nuttx_project
git clone https://github.com/apache/nuttx.git nuttx
git clone https://github.com/apache/nuttx-apps apps

查看已经支持的开发板

cd nuttx
./tools/configure.sh -L | less

将 nuttx 代码工程仓库配置成目标开发板,以 sim:nsh 为例:

cd nuttx
./tools/configure.sh -l sim:nsh

编译工程

cd nuttx/
make

编译完成后会在 nuttx 目录下出现 nuttx.bin 文件。

nuttx 模拟开发板配置

将 nuttx 代码工程仓库配置成目标开发板,以 sim:nsh 为例:

cd nuttx
./tools/configure.sh -l sim:nsh

配置裁剪系统

make menuconfig

已关闭 nuttx shell 账户密码登录为例:

配置完成后可退出保存。

编译工程

cd nuttx/
make -j

运行

./nuttx

输入完这个命令后就可以在 PC 端模拟 nuttx 了,如下图是 nut shell 终端组件的窗口。

nuttx 启动流程分析

nuttx 的启动流程一共有五个阶段,并且使用变量 g_nx_initstate 来标识。 g_nx_initstate 的值会在 void nx_start(void) 函数里分阶段改变。

/* Initialization state.  OS bring-up occurs in several phases: */
enum nx_initstate_e
{
  OSINIT_POWERUP   = 0,  /* Power-up.  No initialization yet performed.
                          * Depends on .bss initialization logic for this
                          * value. */
  OSINIT_BOOT      = 1,  /* Basic boot up initialization is complete.  OS
                          * services and hardware resources are not yet
                          * available. */
  OSINIT_TASKLISTS = 2,  /* Head of ready-to-run/assigned task lists valid */
  OSINIT_MEMORY    = 3,  /* The memory manager has been initialized */
  OSINIT_HARDWARE  = 4,  /* MCU-specific hardware is initialized.  Hardware
                          * resources such as timers and device drivers are
                          * now available.  Low-level OS services sufficient
                          * to support the hardware are also available but
                          * the OS has not yet completed its full
                          * initialization. */
  OSINIT_OSREADY   = 5   /* The OS is fully initialized and multi-tasking is
                          * active. */
};
  1. MCU 执行到 nx_start 系统起来之后即为完成 OSINIT_BOOT 阶段。
  2. 在 OSINIT_TASKLISTS 阶段会去初始化任务列表。
  3. 在 OSINIT_MEMORY 阶段需要率先初始化信号量(因为接下来很多系统组件需要使用信号量),然后初始化内存管理。
  4. 在 OSINIT_HARDWARE 阶段需要先初始化文件系统(因为后面的设备驱动需要使用到文件系统,这涉及到了 nuttx 的驱动管理方式,后面我会再讲。),然后配置 中断向量表、看门狗、时钟、系统 tick 、系统信号、系统消息队列、网络、线程栈内容初始化、注册标准的设备(如:/dev/null,/dev/zero,/dev/loop./dev/random)。
  5. 在 OSINIT_OSREADY 阶段需要完成多系统相关的初始化(如启动 IDLE 线程)。

 除了上面的分析,网上还有其他博主对启动流程分析图,这个更为详细。如下所示:

/**************************************************************/
(出处:http://blog.csdn.net/zhumaill/article/details/23261543)
/**************************************************************/
__start--                                 #处理器执行的第一条指令
        |  
        v  
   stm32_clockconfig()------              #初始化时钟
                           |  
                           v  
                 rcc_reset()              #复位rcc
                 stm32_stdclockconfig()   #初始化标准时钟
                 rcc_enableperipherals()  #使能外设时钟
                           |  
        --------------------  
        |  
        v  
   stm32_fpuconfig()                      #配置fpu,shenzhou/nsh未调用
   stm32_lowsetup()                       #基本初始化串口,之后可以使用up_lowputc()
   stm32_gpioinit()                       #初始化gpio,只是调用stm32_gpioremap()设置重映射
   up_earlyserialinit()                   #初始化串口,之后可以使用up_putc()
   stm32_boardinitialize()--              #板级初始化
                           |  
                           v  
                 stm32_spiinitialize()    #初始化spi,只是调用stm32_configgpio()设置gpio
                 stm32_usbinitialize()    #初始化usb,只是调用stm32_configgpio()设置gpio
                 board_led_initialize()   #初始化led,只是调用stm32_configgpio()设置gpio
                           |  
        --------------------  
        |  
        v  
   os_start()---------------              #初始化操作系统
                           |  
                           v  
                 dq_init()                #初始化各种状态的任务列表(置为null)
                 g_pidhash[i]=            #初始化唯一可以确定的元素--进程ID
                 g_pidhash[PIDHASH(0)]=   #分配空闲任务的进程ID为0
                 g_idletcb=               #初始化空闲任务的任务控制块
                 sem_initialize()--       #初始化信号量
                                  |  
                                  v  
                       dq_init()          #将信号量队列置为null
                       sem_initholders()  #初始化持有者结构以支持优先级继承,shenzhou/nsh未调用
                                  |  
                           --------  
                           |  
                           v  
                 up_allocate_heap()       #分配用户模式的堆(设置堆的起点和大小)
                 kumm_initialize()        #初始化用户模式的堆
                 up_allocate_kheap()      #分配内核模式的堆,shenzhou/nsh未调用
                 kmm_initialize()         #初始化内核模式的堆,shenzhou/nsh未调用
                 task_initialize()        #初始化任务数据结构,shenzhou/nsh未调用
                 irq_initialize()         #将所有中断向量都指向同一个异常中断处理程序
                 wd_initialize()          #初始化看门狗数据结构
                 clock_initialize()       #初始化rtc
                 timer_initialize()       #配置POSIX定时器
                 sig_initialize()         #初始化信号
                 mq_initialize()          #初始化命名消息队列
                 pthread_initialize()     #初始化线程特定的数据,空函数
                 fs_initialize()---       #初始化文件系统
                                  |  
                                  v  
                       sem_init()         #初始化节点信号量为1
                       files_initialize() #初始化文件数组,空函数
                                  |  
                           --------  
                           |  
                           v  
                 net_initialize()--       #初始化网络
                                  |  
                                  v  
                       uip_initialize()   #初始化uIP层
                       net_initroute()    #初始化路由表,shenzhou/nsh未调用
                       netdev_seminit()   #初始化网络设备信号量
                       arptimer_init()    #初始化ARP定时器
                                  |  
                           --------  
                           |  
                           v  
                 up_initialize()---       #处理器特定的初始化
                                  |  
                                  v  
                       up_calibratedelay()#校准定时器
                       up_addregion()     #增加额外的内存段
                       up_irqinitialize() #设置中断优先级,关联硬件异常处理函数
                       up_pminitialize()  #初始化电源管理,shenzhou/nsh未调用
                       up_dmainitialize() #初始化DMA,shenzhou/nsh未调用
                       up_timerinit()     #初始化定时器中断
                       devnull_register() #注册/dev/null
                       devzero_register() #注册/dev/zero,shenzhou/nsh未调用
                       up_serialinit()    #注册串口控制台/dev/console和串口/dev/ttyS0
                       up_rnginitialize() #初始化并注册随机数生成器,shenzhou/nsh未调用
                       up_netinitialize() #初始化网络,是arch/arm/src/chip/stm32_eth.c中的
                       up_usbinitialize() #初始化usb驱动,shenzhou/nsh未调用
                       board_led_on()     #打开中断使能led,但很快会被其它地方的led操作改变状态
                                  |  
                           --------  
                           |  
                           v  
                 lib_initialize()         #初始化c库,空函数
                 group_allocate()         #分配空闲组
                 group_setupidlefiles()   #在空闲任务上创建stdout、stderr、stdin
                 group_initialize()       #完全初始化空闲组
                 os_bringup()------       #创建初始任务
                                  |  
                                  v  
                       KEKERNEL_THREAD()  #启动内核工作者线程
                       board_initialize() #最后一刻的板级初始化,shenzhou/nsh未调用
                       TASK_CREATE()      #启动默认应用程序
                                  |  
                           --------  
                           |  
                           v  
for up_idle()            #空闲任务循环
                           |  
        --------------------  
        |  
        v  
for(;;)                                #不应该到达这里
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值