规划
尝试学会以移植为最终目标,循序渐进学习RTThread,通过分析RTThread官方的demo程序,学习从任务线程的创建到调度的一些细节最终到自己移植一份RTThread工程简单的点灯到项目落实,把以前做的项目移植到RTThread上
RTThread线程的创建细节
首先是对程序执行的流程,程序在startup.S中启动初始化异常向量表、栈之后才跳转到main()函数中,官方demo用了一个机制$Sub$$main,在调用main函数前会执行这个函数,所以在main()函数里一直没有找到相关的初始化函数。
初始化函数
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();
#ifdef RT_USING_SMP
rt_hw_spin_lock(&_cpus_lock);
#endif /*RT_USING_SMP*/
/* start scheduler */
rt_system_scheduler_start();
/* never reach here */
return 0;
}
#endif
实现任务调度前首先要进行的是任务的创建使用的
/**
* 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;
}
需要执行的操作有
1.申请RT对象类内存
2.按创建线程传递的栈大小参数申请内存
3.调用_rt_thread_init
static rt_err_t _rt_thread_init(struct rt_thread *thread,
const char *name,
void (*entry)(void *parameter),
void *parameter,
void *stack_start,
rt_uint32_t stack_size,
rt_uint8_t priority,
rt_uint32_t tick)
{
/* init thread list */
rt_list_init(&(thread->tlist));
thread->entry = (void *)entry;
thread->parameter = parameter;
/* stack init */
thread->stack_addr = stack_start;
thread->stack_size = stack_size;
/* init thread stack */
rt_memset(thread->stack_addr, '#', thread->stack_size);
#ifdef ARCH_CPU_STACK_GROWS_UPWARD
thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
(void *)((char *)thread->stack_addr),
(void *)rt_thread_exit);
#else
thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
(rt_uint8_t *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)),
(void *)rt_thread_exit);
#endif
/* priority init */
RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX);
thread->init_priority = priority;
thread->current_priority = priority;
thread->number_mask = 0;
#if RT_THREAD_PRIORITY_MAX > 32
thread->number = 0;
thread->high_mask = 0;
#endif
/* tick init */
thread->init_tick = tick;
thread->remaining_tick = tick;
/* error and flags */
thread->error = RT_EOK;
thread->stat = RT_THREAD_INIT;
#ifdef RT_USING_SMP
/* not bind on any cpu */
thread->bind_cpu = RT_CPUS_NR;
thread->oncpu = RT_CPU_DETACHED;
/* lock init */
thread->scheduler_lock_nest = 0;
thread->cpus_lock_nest = 0;
thread->critical_lock_nest = 0;
#endif /*RT_USING_SMP*/
/* initialize cleanup function and user data */
thread->cleanup = 0;
thread->user_data = 0;
/* initialize thread timer */
rt_timer_init(&(thread->thread_timer),
thread->name,
rt_thread_timeout,
thread,
0,
RT_TIMER_FLAG_ONE_SHOT);
/* initialize signal */
#ifdef RT_USING_SIGNALS
thread->sig_mask = 0x00;
thread->sig_pending = 0x00;
#ifndef RT_USING_SMP
thread->sig_ret = RT_NULL;
#endif
thread->sig_vectors = RT_NULL;
thread->si_list = RT_NULL;
#endif
#ifdef RT_USING_LWP
thread->lwp = RT_NULL;
#endif
RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread));
return RT_EOK;
}