经过好几天的摸索,终于正常驱动了一个串口设备,并成功移植到雅特力的板子上!当然,还得继续努力把RTT的内核搞清楚,这样才会构建整个项目程序,毕竟项目是有时间限制的。
因为之前接触过只有两个任务的OS,在那个OS中SysTick的用处非常大,一方面是执行一些周期的设备任务,另一方面定时切换线程,是不是RTT也有类似的机制呢??
先从官方文件开始:程序先调用启动文件后,再调用内核文件 components.c 文件中的int $Sub$$main(void),调用rtthread_startup();函数。其调用的函数如下:
drv_common.c中的rt_hw_board_init() 中完成系统时钟设置,为硬件系统提供心跳、串口初始化,将系统输入输出终端绑定
到这个串口,后续系统运行信息就会从串口打印出来。在此函数中调用了 rt_hw_systick_init()函数,设定了系统的工作时间片。实际指向rtconfig.h中的 #define RT_TICK_PER_SECOND 1000。
调用的这几个函数分别位的的.c文件对应关系为:
rt_hw_board_init() ----------------------------------------- drv_common.c文件中同时属于drivers文件夹
rt_show_version() ----------------------------------------- kservice.c文件中属于Kernel文件夹
rt_system_timer_init() ----------------------------------------- timer.c文件中属于Kernel文件夹
rt_system_scheduler_init() ----------------------------------------- scheduler.c文件中属于Kernel文件夹
rt_system_signal_init() ----------------------------------------- signal.c文件中属于Kernel文件夹
rt_application_init() ----------------------------------------- components.c 文件中属于Kernel文件夹
rt_system_timer_thread_init() ----------------------------------------- timer.c文件中属于Kernel文件夹
rt_thread_idle_init() ----------------------------------------- idle.c 文件中属于Kernel文件夹
rt_hw_spin_lock() ----------------------------------------- rthw.h 文件中属于include文件夹,变相调用关中断
rt_system_scheduler_start() ----------------------------------------- scheduler.c文件中属于Kernel文件夹
可见,rt_hw_board_init() ----> rt_hw_systick_init()后就启动了SysTick了,看中断里做了什么呢?
void SysTick_Handler(void)
{
/* enter interrupt */
rt_interrupt_enter(); //关总中断
HAL_IncTick();//自增一个全局变量,作为应用的时间基准
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();//关中断
}
其中,rt_tick_increase()-------位于clock.c文件中,属于Kernel文件夹;正是自己有疑问的地方,进去一看,果然是进行了内核线程切换,分析如下:首先明白,rt_tick_increase()就是通知系统过去了一个时间片。
/**
* This function will notify kernel there is one tick passed. Normally,
* this function is invoked by clock ISR.
*/
void rt_tick_increase(void)
{
struct rt_thread *thread;
/* increase the global tick */
#ifdef RT_USING_SMP
rt_cpu_self()->tick ++;
#else
++ rt_tick; //自增滴答时钟
#endif
/* check time slice */
thread = rt_thread_self();//检查线程自身的时间片
-- thread->remaining_tick;//剩余时间--
if (thread->remaining_tick == 0)
{
/* change to initialized tick */
thread->remaining_tick = thread->init_tick;//重新分配初始时钟
thread->stat |= RT_THREAD_STAT_YIELD;
/* yield */
rt_thread_yield();//线程挂起,在这里进行了内核线程切换。
}
/* check timer */
rt_timer_check();//在中断中,rt_timer_check()用于检查系统硬件计时器链接列表。
如果存在计时器超时,则将调用相应的超时功能。
如果超时,将从计时器链接列表中删除所有计时器,并在再次启动时将定期计时器添加到计时器链接列表中。
}
基本与自己设想的一样,看来RTOS的内核相似性真的是挺大的。