启动流程
1.上电;
2.运行复位函数Reset_Hhandler();
3.c库函数_mian(),初始化系统堆和栈;
4.执行
s
u
b
sub
submain函数(main扩展函数,可在执行main之前执行submain,做一些硬件初始化等预操作,是keil自带的指令);
/* re-define main function */
int $Sub$$main(void)
{
rtthread_startup();
return 0;
}
5.关中断rt_hw_interrupt_disable();
6.启动rtthread_startup():
[1 ] 关中断rt_hw_interrupt_disable();
[2 ] 硬件初始化rt_hw_board_init();
[3 ] 显示版本rt_show_version();
[4 ] 系统定时器初始化rt_system_timer_init();
[5 ] 调度器初始化rt_system_scheduler_init();
[6 ] 创建初始化线程rt_application_init();
[7 ] 创建定时器线程rt_system_timer_thread_init();
[8 ] 创建空闲线程rt_thread_idle_init();
[9 ] 开启调度器rt_system_scheduler_start();
int rtthread_startup(void)
{
rt_hw_interrupt_disable();
/* board level initialization
* NOTE: please initialize heap inside board initialization.
*/
rt_hw_board_init();
/* show RT-Thread version */
rt_show_version();
/* timer system initialization */
rt_system_timer_init();
/* scheduler system initialization */
rt_system_scheduler_init();
#ifdef RT_USING_SIGNALS
/* signal system initialization */
rt_system_signal_init();
#endif
/* create init_thread */
rt_application_init();
/* timer thread initialization */
rt_system_timer_thread_init();
/* idle thread initialization */
rt_thread_idle_init();
/* start scheduler */
rt_system_scheduler_start();
/* never reach here */
return 0;
}
在上述 [6 ] 创建初始化线程rt_application_init()中,实际创建了一个main线程,如图:
void rt_application_init(void)
{
rt_thread_t tid;
#ifdef RT_USING_HEAP
tid = rt_thread_create("main", main_thread_entry, RT_NULL,
RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
RT_ASSERT(tid != RT_NULL);
#else
rt_err_t result;
tid = &main_thread;
result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
RT_ASSERT(result == RT_EOK);
/* if not define RT_USING_HEAP, using to eliminate the warning */
(void)result;
#endif
rt_thread_startup(tid);
}
点击线程处理函数“main_thread_entry”,跳转至该线程处理函数,发现执行此线程会进行组件的初始化(INIT_BOARD_EXPORT(fn)、INIT_DEVICE_EXPORT(fn)、。。。、INIT_APP_EXPORT(fn))。然后调用supermain()函数(与submain()对应),去到main()。
/* the system main thread */
void main_thread_entry(void *parameter)
{
extern int main(void);
extern int $Super$$main(void);
/* RT-Thread components initialization */
rt_components_init();
/* invoke system main function */
#if defined(__CC_ARM) || defined(__CLANG_ARM)
$Super$$main(); /* for ARMCC. */
#elif defined(__ICCARM__) || defined(__GNUC__)
main();
#endif
}
当然,由于在 [6 ] 创建初始化线程rt_application_init()时,系统调度器并没有开启,所以该线程在上述 [9 ] 开启调度器rt_system_scheduler_start()之后才会执行。
main线程执行到最后(完成所有应用线程的创建),通过LR寄存器指定的链接地址退出(如下图),rt_thread_exit()会把main线程占用的内存空间释放。
线程
1.一系列独立线程的集合,每个线程在自己的环境中运行,具有独立的栈;
2.在任何时刻,只有一个线程得到运行;
3.线程执行环境(寄存器值、堆栈内容等)保存在线程堆栈中;
#ifdef RT_USING_HEAP
/**
* This function will create a thread object and allocate thread object memory
* and stack.
*
* @param name the name of thread, which shall be unique
* @param entry the entry function of thread
* @param parameter the parameter of thread enter function
* @param stack_size the size of thread stack
* @param priority the priority of thread
* @param tick the time slice if there are same priority thread
*
* @return the created thread object
*/
rt_thread_t rt_thread_create(const char *name,
void (*entry)(void *parameter),
void *parameter,
rt_uint32_t stack_size,
rt_uint8_t priority,
rt_uint32_t tick)
{
struct rt_thread *thread;
void *stack_start;
thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,
name);
if (thread == RT_NULL)
return RT_NULL;
stack_start = (void *)RT_KERNEL_MALLOC(stack_size);
if (stack_start == RT_NULL)
{
/* allocate stack failure */
rt_object_delete((rt_object_t)thread);
return RT_NULL;
}
_rt_thread_init(thread,
name,
entry,
parameter,
stack_start,
stack_size,
priority,
tick);
return thread;
}
RTM_EXPORT(rt_thread_create);
调度器
1.中断处理函数、调度器上锁部分、禁止中断的代码不可抢占,其余都可抢占,包括调度器自身;
2.基于位图的优先级算法,时间复杂度为O(1),响应时间与就绪线程的多少无关;
线程状态
1.初始态:创建线程时;
2.就绪态:等待cpu,在就绪列表中;
3.运行态:占用cpu,正在运行;
4.挂起态:在挂起列表中;
5.关闭态:运行结束,系统回收资源;
注:
1.当前已经挂起的线程,不可重复挂起;
2.挂起态不可直接进入运行态,需参照挂起态------就绪态------运行态的步骤;
3.只有运行态、挂起态线程可进入关闭态;
4.挂起:
[1].主动挂起:调用delay、suspend等函数,主动挂起。调用resume函数恢复;
[2].被动挂起:调用sem_take、mb_recv、mutex_take、event_recv等函数,且资源不可用时,被动挂起;
5.若suspend线程本身,需要在suspend之后调用schedule函数进行调度;
空闲线程
创建空闲线程(启动时创建)
/**
* @ingroup SystemInit
*
* This function will initialize idle thread, then start it.
*
* @note this function must be invoked when system init.
*/
void rt_thread_idle_init(void)
{
/* initialize thread */
rt_thread_init(&idle,
"tidle",
rt_thread_idle_entry,
RT_NULL,
&rt_thread_stack[0],
sizeof(rt_thread_stack),
RT_THREAD_PRIORITY_MAX - 1,
32);
/* startup */
rt_thread_startup(&idle);
}
空闲线程处理函数
static void rt_thread_idle_entry(void *parameter)
{
while (1)
{
#ifdef RT_USING_IDLE_HOOK
rt_size_t i;
for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
{
if (idle_hook_list[i] != RT_NULL)
{
idle_hook_list[i]();
}
}
#endif
rt_thread_idle_excute();
#ifdef RT_USING_PM
rt_system_power_manager();
#endif
}
}
1.空闲线程是系统在没有其他工作时,自动进入的系统线程;
2.是系统中唯一不允许阻塞,不允许挂起、不允许delay的线程(必须保证系统有一个可以随时进入运行的线程);
3.在空闲线程中包含钩子函数,可自定义一下非紧急的处理函数;
4.在空闲线程中对系统的栈内存释放,对象删除等处理,如下图;
/**
* @ingroup Thread
*
* This function will perform system background job when system idle.
*/
void rt_thread_idle_excute(void)
{
/* Loop until there is no dead thread. So one call to rt_thread_idle_excute
* will do all the cleanups. */
while (_has_defunct_thread())
{
rt_base_t lock;
rt_thread_t thread;
#ifdef RT_USING_MODULE
struct rt_dlmodule *module = RT_NULL;
#endif
RT_DEBUG_NOT_IN_INTERRUPT;
/* disable interrupt */
lock = rt_hw_interrupt_disable();
/* re-check whether list is empty */
if (_has_defunct_thread())
{
/* get defunct thread */
thread = rt_list_entry(rt_thread_defunct.next,
struct rt_thread,
tlist);
#ifdef RT_USING_MODULE
module = (struct rt_dlmodule*)thread->module_id;
if (module)
{
dlmodule_destroy(module);
}
#endif
/* remove defunct thread */
rt_list_remove(&(thread->tlist));
/* lock scheduler to prevent scheduling in cleanup function. */
rt_enter_critical();
/* invoke thread cleanup */
if (thread->cleanup != RT_NULL)
thread->cleanup(thread);
#ifdef RT_USING_SIGNALS
rt_thread_free_sig(thread);
#endif
/* if it's a system object, not delete it */
if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
{
/* detach this object */
rt_object_detach((rt_object_t)thread);
/* unlock scheduler */
rt_exit_critical();
/* enable interrupt */
rt_hw_interrupt_enable(lock);
return;
}
/* unlock scheduler */
rt_exit_critical();
}
else
{
/* enable interrupt */
rt_hw_interrupt_enable(lock);
/* may the defunct thread list is removed by others, just return */
return;
}
/* enable interrupt */
rt_hw_interrupt_enable(lock);
#ifdef RT_USING_HEAP
/* release thread's stack */
RT_KERNEL_FREE(thread->stack_addr);
/* delete thread object */
rt_object_delete((rt_object_t)thread);
#endif
}
}
中断服务函数
RT-Thread中程序运行的上下文包括:
1.中断服务函数;
2.普通线程;
3.空闲线程;
中断服务函数:
1.中断服务函数运行在非线程的执行环境下,一般为芯片的一种特殊运行模式(特权模式);
2.中断服务函数不允许任何阻塞,要保持精简短小,快进快出,一般只用来标记;
3.中断服务函数的优先级高于全部线程,不管该中断优先级如何,不管线程优先级如何;
4.若支持中断嵌套,在执行中断过程中,发生了更高优先级的中断,则先去执行高优先级中断,结束之后再执行原中断;
优先级
线程优先级的设置:
需要紧急处理、执行时间短的线程优先级应该设置高一点;