您的位置:首页 > 其它

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才学习这个系统,如果有什么错误欢迎大家更正。同时也希望大神级的前辈指导一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nuttx PX4 k64