`
jiagou
  • 浏览: 2595283 次
文章分类
社区版块
存档分类
最新评论

时钟中断是rt-thread的线程调度器的驱动力

 
阅读更多

1 系统时钟中断驱动引擎

rt-thread操作系统中当线程时间片耗尽,或是当线程sleep一段时间后唤醒再被调度,此过程又是如何进行的呢?到底是谁来驱动这一过程的呢?

答案是时钟中断源。且来看看时钟中断例程:

在bsp/stm32f20x/drivers/board.c源文件中存在这么一个时钟中断例程代码:(这里以stm32f20x的MCU为例)

/**
 * This is the timer interrupt service routine.
 *
 */
void SysTick_Handler(void)
{
	/* enter interrupt */
	rt_interrupt_enter();//进入中断

	rt_tick_increase();//增加tick

	/* leave interrupt */
	rt_interrupt_leave();//离开中断
}

其中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 */
    ++ rt_tick;//全局变量rt_tick加1

    /* check time slice */
    thread = rt_thread_self();//获取当前调度的线程

    -- thread->remaining_tick;//当前调度的线程的剩余时间片减1
    if (thread->remaining_tick == 0)//如果当前调度的线程没有剩余时间片了
    {
        /* change to initialized tick */
        thread->remaining_tick = thread->init_tick;//重新将剩余时间片设置为初始化时间片

        /* yield */
        rt_thread_yield();//将此线程从调度器就绪队列中取出来放到末尾,再次然后调度
    }

    /* check timer */
    rt_timer_check();//检查时钟链表上是否有时间到达的时钟
}
rt_thread_yield函数已在之前的文章http://blog.csdn.net/flydream0/article/details/8584362一文的第7章已有介绍,而rt_timer_check函数在http://blog.csdn.net/flydream0/article/details/8570841#t4一文中第3.3节也已有介绍。

由上述代码可见,一旦系统产生时钟中断,在中断例程中,系统首先将检查当前正在运行的线程剩余时间片是否耗尽,如果耗尽则将其从调度器就绪队列中取出放到末尾,然后再重新调度线程,接着检查是否有休眠的线程时间到达,如果有,则触发其时钟超时回调函数,这个时钟超时回调函数在之前的文章http://blog.csdn.net/flydream0/article/details/8584362#t2一文中的2.1节介绍初始化线程函数_rt_thread_init时有如下代码:

//...
 /* init thread timer */
    rt_timer_init(&(thread->thread_timer),//初始化线程的定时器
                  thread->name,
                  rt_thread_timeout,
                  thread,
                  0,
                  RT_TIMER_FLAG_ONE_SHOT);
//...

可见在线程初始化时,就设置了线程内部时钟的超时回调函数rt_thread_timeout函数,关键就是这个函数会进行一些线程调度的操作,其源码如下定义:

/**
 * This function is the timeout function for thread, normally which is invoked
 * when thread is timeout to wait some resource.
 *
 * @param parameter the parameter of thread timeout function
 */
void rt_thread_timeout(void *parameter)
{
    struct rt_thread *thread;

    thread = (struct rt_thread *)parameter;

    /* thread check */
    RT_ASSERT(thread != RT_NULL);
    RT_ASSERT(thread->stat == RT_THREAD_SUSPEND);

    /* set error number */
    thread->error = -RT_ETIMEOUT;

    /* remove from suspend list *///从挂起链表中移除
    rt_list_remove(&(thread->tlist));

    /* insert to schedule ready list */
    rt_schedule_insert_thread(thread);//加入调度器

    /* do schedule */
    rt_schedule();//重新调度
}
可见,其会将当前挂起的线程加入到调度器就绪队列,然后重新调度。

2 系统时钟中断引擎小结

综上所述,当系统产生时钟中断时,首先检查当前正在运行的线程是否还有剩余时间片,如果耗尽则从就绪队列中移除放到末尾再重新调度,接着检查是否存在挂起的线程有时间到达的,如果有,则加入到调度器就绪队列中,然后重新调度。

3 软件定时器模式下的驱动引擎

此外,需要注意地是,如果用户设置使用软件软件定时器方式,则系统中还存在一时钟线程timer_thread,见http://blog.csdn.net/flydream0/article/details/8570841一文,此线程专门随时系统时钟tick的增加来检查定时器是否时间到达,这其中就包含线程的定时器,一旦线程对应的定时器时间到达,则将加入到线程调度器就绪队列中进行调度。由此可见,在设置了软件定时器模式时(默认情况下,rt-thread使用硬件定时器),这个timer_thread线程也是rt_thread操作系统线程调度的驱动引擎.


4 如何设置系统时钟中断间隔

查看rt-thread操作系统的用户手册时,上面有提到rt_thead操作系统的时钟每个tick的默认间隔为10ms,那么这个10 ms双是如何来的呢?

答案是在/bsp/stm32f20x/drivers/board.c源文件中,且看SysTick_Configuration函数的实现:

/*******************************************************************************
 * Function Name  : SysTick_Configuration
 * Description    : Configures the SysTick for OS tick.
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void  SysTick_Configuration(void)
{
	RCC_ClocksTypeDef  rcc_clocks;
	rt_uint32_t         cnts;

	RCC_GetClocksFreq(&rcc_clocks);//获得系统的晶振频率

	cnts = (rt_uint32_t)rcc_clocks.HCLK_Frequency / RT_TICK_PER_SECOND;//计算出多少次晶振才是一个tick时间片

	SysTick_Config(cnts);//配置系统tick
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//配置时钟源
}

由上述代码可见,rt_thread的系统tick是由RT_TICK_PER_SECOND这个宏来配置的,RT_TICK_PER_SECOND在头文件rtconfig.h文件中定义,如下:

/* Tick per Second */
#define RT_TICK_PER_SECOND	100
此参数的含义是1秒包含多少个tick, 这里默认是100,则默认情况下1秒包含100个tick,那么即每个tick为10ms,现在明白了吧?

如果我们要修改每个tick的时间隔,则只需要修改RT_TICK_PER_SECOND这个宏的值即可.


分享到:
评论

相关推荐

    stm32f103c8t6移植RT-Thread之线程管理

    在RT-Thread中,中断服务需要在适当的位置调用`rt_interrupt_enter`和`rt_interrupt_leave`来通知调度器,保证中断处理的上下文安全。 此外,为了调试和优化,我们还可以利用RT-Thread提供的各种调试工具,如RTT ...

    RT-thread+GD32F450+HWTIMER

    在嵌入式系统开发中,实时操作系统(RTOS)RT-thread与高性能微控制器的结合是常见的选择,尤其在需要精准时序控制的场景。本教程将详细探讨RT-thread在兆易创新GD32F450系列MCU上的应用,特别是针对硬件定时器...

    RT-Thread.pdf

    文档中还提供了多个编程示例,包括创建线程示例、线程调度器钩子、定时器管理示例等,这些示例对理解和掌握RT-Thread编程非常有帮助。 ### 总结 RT-Thread单片机微操作系统电子书教程为嵌入式开发者提供了一种强大...

    AT32使用RT-thread studio 流程

    AT32使用RT-thread studio流程 AT32是微控制器(Microcontroller,MCU)系列,由安富利(Atmel)公司生产。RT-Thread Studio是基于RT-Thread操作系统的集成开发环境(Integrated Development Environment,IDE),...

    RT-Thread线程-创建线程

    本篇将深入讲解如何在STM32H750VBT6微控制器上使用RT-Thread Studio创建线程,这是一款功能强大的集成开发环境,为开发者提供了友好的图形化配置界面。 首先,了解线程的基本概念。在操作系统中,线程是程序执行的...

    RT-thread相关介绍与面试问题+答案

    RT-thread的初始化过程主要包括硬件初始化、内核对象初始化、创建主线程以及启动调度器等步骤。这些步骤通过定义在链接脚本中的初始化函数表实现,确保了系统的稳定启动和可靠运行。 - **初始化顺序**: - INIT_...

    RT-thread移植指南-RISC-V.docx

    - **RT-thread启动流程**:调整RT-thread的启动代码,使其适应RISC-V的启动过程,通常包括初始化内存管理、调度器和基本系统服务。 - **配置宏、全局符号的适配**:根据RISC-V的特性修改RT-thread的配置宏和全局...

    STM32H750移植rt-thread操作系统完整工程.zip

    5. **RTOS初始化**:调用rtthread_init()函数进行rt-thread的初始化,包括创建第一个线程、设置调度策略等。 6. **应用程序开发**:基于rt-thread的API开发用户应用,可以创建任务、信号量、消息队列等,实现特定的...

    【正点原子-探索者STM32F407-RT-Thread】示例-标准库版本.7z

    【正点原子-探索者STM32F407-RT-Thread】示例-标准库版本是一个关于嵌入式系统开发的项目,主要聚焦在使用RT-Thread实时操作系统在STM32F407微控制器上的应用。STM32F407是一款基于ARM Cortex-M4内核的高性能微控制...

    RT-thread+GD32F450+i2c

    在本文中,我们将深入探讨如何在RT-thread操作系统上结合GD32F450系列微控制器(MCU)实现I2C通信。RT-thread是一个开源、实时、可扩展的嵌入式操作系统,广泛应用于物联网设备和智能硬件。GD32F450是兆易创新公司...

    RTThread Stm32 标准库参考工程.zip_RT-Thread STD库_rtos stm32_rtthread_rt

    在RTThread STM32标准库参考工程中,你可能找到以下关键知识点: 1. **RT-Thread初始化**:了解如何配置RT-Thread内核,包括设置系统时钟、初始化堆内存、设置中断处理等步骤。 2. **线程管理**:学习如何创建、...

    stm32f103c8t6移植RT-Thread 之建立工程

    - 配置RT-Thread的初始化代码,如rtthread_init(),并调用rt_components_board_init()来启动特定板级组件。 - 设置系统时钟,如启用HSE振荡器,然后配置RCC预分频器以达到所需的系统时钟速度。 - 编译并调试工程...

    【正点原子-miniSTM32F103-RT-Thread】示例-标准库版本.7z

    《正点原子-miniSTM32F103-RT-Thread》示例教程是一套针对RT-Thread实时操作系统在正点原子战舰/精英F103开发板上的实践教学资料。该压缩包包含了多个实验项目,旨在帮助学习者深入理解和掌握RT-Thread在STM32F103微...

    rt-thread操作系统API

    4. API使用:文档详细介绍了RT-Thread提供的API,包括用于线程调度与管理、线程间同步与通信、内存管理、异常与中断处理、定时器与系统时钟、I/O设备管理以及图形用户界面等。这些API的设计和使用对于开发者深入理解...

    GD32_rt-thread.rar

    线程调度器会根据优先级自动切换不同线程的执行。 3. **控制台输出**:在GD32上,通常使用串口(UART)作为控制台输出设备。rt-thread内建了串口驱动,可以使用rt_device_find找到串口设备,然后调用rt_device_open...

    rt-thread-rt-smart.rar

    RT-Thread-Smart的核心是其调度器和内核服务。我们需要配置系统时钟、任务调度策略、中断处理等。在RT-Thread的配置文件中,可以设定系统时钟频率、堆栈大小、任务优先级等参数,确保系统运行稳定高效。 5. **移植...

    RT-Thread在STM32F429上的应用-驱动篇。包括BSP的制作,驱动的添加及使用

    在本文中,我们将深入探讨如何在STM32F429微控制器上应用RT-Thread实时操作系统,并专注于驱动程序的开发和使用。RT-Thread是一个轻量级、高效率的实时操作系统,它为嵌入式系统提供了丰富的中间件支持,如网络服务...

    rt-thread内核源码

    rt-thread内核主要由调度器、任务管理、中断管理、内存管理、信号量、互斥锁、消息队列、事件标志组、定时器等核心组件构成。这些组件协同工作,为应用程序提供了一个高效可靠的运行环境。 1. 调度器:rt-thread...

Global site tag (gtag.js) - Google Analytics