Nuttx系统启动流程
2016-12-09 14:51
211 查看
Nuttx系统启动流程
借用一位大神的图[天又亮了的博客]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未调用 4000 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(;;) #不应该到达这里
下面我就以FRDM-k64为主介绍一下nuttx的启动代码流程图,因为使用的是Nuttx7.18的代码可能和上面大神的有点区别。
_start()函数启动开始(在Kinetis_start.c)
kinetis_wddisable();//关闭看门狗 kinetis_clockconfig();//配置时钟 stm32_fpuconfig();//初始化FPU功能 kinetis_lowsetup();//芯片最初的一些初始化 #ifdef USE_EARLYSERIALINIT up_earlyserialinit();//系统早期的串口初始化 #endif #ifdef CONFIG_BUILD_PROTECTED kinetis_userspace();//初始化用户空间 #endif kinetis_boardinitialize();//初始化板上的所有资源 /* Then start NuttX */ os_start();//系统开始运行 /* Shouldn't get here */ for (; ; );//不会运行到这
os_start()函数解析,在Os_start.c文件中
/*初始化RTOS数据,初始化任务链表*/ dq_init(&g_readytorun); dq_init(&g_pendingtasks); dq_init(&g_waitingforsemaphore); //这里还初始化了系统运行的其他一些初始参数 /* Initialize the IDLE task TCB 初始化任务块*******************************************/ //在这是初始化一些信号量,内存分配等等系统运行必要参数,上面大神写的比较清楚,我主要看了下面两个函数 up_initialize();//特定处理器的初始化 os_bringup();//创建初始任务
up_initialize(void);在nuttx/arch/arm/src/common/Up_initialize.c中
/* Calibrate the timing loop */ up_calibratedelay();//校正时钟 /* Colorize the interrupt stack */ up_color_intstack();//初始化中断任务块 /* Add any extra memory fragments to the memory manager */ up_addregion(); /* Initialize the interrupt subsystem */ up_irqinitialize();//初始化中断表 /* 在这还有其他的一些初始化比如usb初始化、telnet初始化等等 */ //最后就是 board_autoled_on(LED_IRQSENABLED);//初始化板载中断,有中断产生就点亮RGB
os_bringup();在nuttx/sched/init/Os_bringup.c中
/* Start the page fill worker kernel thread that will resolve page faults. * This should always be the first thread started because it may have to * resolve page faults in other threads */ os_pgworker(); /* Start the worker thread that will serve as the device driver "bottom- * half" and will perform misc garbage clean-up. */ os_workqueues(); /* Once the operating system has been initialized, the system must be * started by spawning the user initialization thread of execution. This * will be the first user-mode thread. */ os_start_application();//开始应用程序初始化
os_start_application();在nuttx/sched/init/Os_bringup.c中
static inline void os_start_application(void)//inline 定义的是一个内联函数 { #ifdef CONFIG_BOARD_INITTHREAD//如果定义了,机会创建一个线程来执行os_do_appstart();如果没有就是直接调用os_do_appstart(); int pid; /* Do the board/application initialization on a separate thread of * execution. */ pid = kernel_thread("AppBringUp", CONFIG_BOARD_INITTHREAD_PRIORITY, CONFIG_BOARD_INITTHREAD_STACKSIZE, (main_t)os_start_task, (FAR char * const *)NULL); ASSERT(pid > 0); #else /* Do the board/application initialization on this thread of execution. */ os_do_appstart(); #endif }
os_do_appstart();在nuttx/sched/init/Os_bringup.c中
static inline void os_do_appstart(void) { int pid; #ifdef CONFIG_BOARD_INITIALIZE /* Perform any last-minute, board-specific initialization, if so * configured. */ board_initialize();//板级初始化 #endif /* Start the application initialization task. In a flat build, this is * entrypoint is given by the definitions, CONFIG_USER_ENTRYPOINT. In * the protected build, however, we must get the address of the * entrypoint from the header at the beginning of the user-space blob. */ sinfo("Starting init thread\n"); #ifdef CONFIG_BUILD_PROTECTED DEBUGASSERT(USERSPACE->us_entrypoint != NULL); pid = task_create("init", SCHED_PRIORITY_DEFAULT, CONFIG_USERMAIN_STACKSIZE, USERSPACE->us_entrypoint, (FAR char * const *)NULL);//创建任务, #else pid = task_create("init", SCHED_PRIORITY_DEFAULT, CONFIG_USERMAIN_STACKSIZE, (main_t)CONFIG_USER_ENTRYPOINT, (FAR char * const *)NULL);//创建任务,CONFIG_USER_ENTRYPOINT指的是NSH_MAIN(nsh_main) #endif ASSERT(pid > 0); }
最后执行up_idle()这个空闲任务,到这整个Nuttx启动就结束了。启动完后有一个可以通过串口进行调试的串口,类似ssh这种命令窗口,但是不知道为什么,只有dev和proc两个文件夹,难道是K64没有完整的移植好,还是我的使用有误。
在整个分析过程中有一部分还不是很清楚,比如任务调度器的运行原理,还是缺乏操作系统原理的知识。
希望正在学习的同学可以一起交流一些,同学习PX4才学习这个系统,如果有什么错误欢迎大家更正。同时也希望大神级的前辈指导一下。
相关文章推荐
- 系统启动流程
- Ubuntu启动流程及系统服务设置
- 开机流程简介--启动系统服务与相关启动设定档 (/etc/rc.d/rc.n )
- 基于ARM的嵌入式系统Bootloader启动流程分析(S3C44B0X)
- android系统启动流程分析:
- 系统初始化流程 跟着启动代码走 !
- linux系统启动大概流程
- Linux系统分析之启动流程
- RHCE课程-RH131Linux管理笔记二-Linux系统启动流程
- Ubuntu启动流程及系统服务设置
- wince4.2系统启动流程
- 基于ARM的嵌入式系统Bootloader启动流程分析----- 转!!
- RHCE课程-RH131Linux管理笔记二-Linux系统启动流程
- Linux系统分析之启动流程
- 系统启动流程
- 关于Linux系统下Grub启动流程的讨论总结
- RHCE课程-RH131Linux管理笔记二-Linux系统启动流程 推荐
- linux系统启动流程
- 系统的启动流程
- 介绍Linux系统如何初始化和启动系统服务的(Linux的开机流程)