RT-Thread 隐藏的宝藏之 completion

RT-Thread Completion机制详解
本文详细解析了RT-Thread中的Completion机制,包括其概念、使用方法、内部实现原理及与信号量的区别,并提供了工程中引入Completion的具体步骤。

1. completion 是什么

completion 直接翻译过来是完成,所以我们可以称 rt_completion完成量。在 RT-Thread 的文档中心 中讲线程间同步时,介绍了 信号量互斥量事件集rt_completion 的作用也是实现线程间的同步,他是一个 轻量级的二值信号量

2. completion 怎么使用

completion 的使用非常简单

  1. 定义一个完成量

    struct rt_completion completion;
    
  2. 初始化完成量

    rt_completion_init(&completion);
    
  3. 等待完成量

    rt_completion_wait(&completion);
    
  4. 释放完成量

    rt_completion_done(&completion);
    

3. completion 的实现

completion 的 API 非常少,可以通过简单的代码去分析

  1. 初始化完成量

    void rt_completion_init(struct rt_completion *completion)
    {
        rt_base_t level;
        RT_ASSERT(completion != RT_NULL);
    
        level = rt_hw_interrupt_disable();
        completion->flag = RT_UNCOMPLETED;
        rt_list_init(&completion->suspended_list);
        rt_hw_interrupt_enable(level);
    }
    

    干了两件事:

    • 设置 flagRT_UNCOMPLETED
    • 初始化完成量的链表
  2. 等待完成量(以下代码有删减)

    rt_err_t rt_completion_wait(struct rt_completion *completion,
                                rt_int32_t            timeout)
    {
        result = RT_EOK;
        thread = rt_thread_self();
    
        level = rt_hw_interrupt_disable();
        if (completion->flag != RT_COMPLETED)
        {
            if (timeout == 0)
            {
            
            }
            else
            {
                /* reset thread error number */
                thread->error = RT_EOK;
    
                /* suspend thread */
                rt_thread_suspend(thread);
                /* add to suspended list */
                rt_list_insert_before(&(completion->suspended_list),
                                      &(thread->tlist));
    
                /* current context checking */
                RT_DEBUG_NOT_IN_INTERRUPT;
    
                /* start timer */
                if (timeout > 0)
                {
                    /* reset the timeout of thread timer and start it */
                    rt_timer_control(&(thread->thread_timer),
                                     RT_TIMER_CTRL_SET_TIME,
                                     &timeout);
                    rt_timer_start(&(thread->thread_timer));
                }
                /* enable interrupt */
                rt_hw_interrupt_enable(level);
    
                /* do schedule */
                rt_schedule();
    
                /* thread is waked up */
                result = thread->error;
    
                level = rt_hw_interrupt_disable();
            }
        }
        /* clean completed flag */
        completion->flag = RT_UNCOMPLETED;
    
        return result;
    }
    

    主要做了以下工作:

    • 关中断:rt_hw_interrupt_disable();
    • 挂起当前线程:rt_thread_suspend(thread);
    • 把挂起状态插入到线程的链表中:rt_list_insert_before
    • 确保当前函数执行不是在中断中:RT_DEBUG_NOT_IN_INTERRUPT;
    • 设置并启动定时器:rt_timer_start(&(thread->thread_timer));
    • 开中断:rt_hw_interrupt_enable(level);
    • 开调度器:rt_schedule();
    • 获取当前线程状态:result = thread->error;
    • 设置完成量的标志位:completion->flag = RT_UNCOMPLETED;
    • 返回线程状态

    这样就完成了线程的挂起。

  3. 释放完成量(以下代码有删减)

    void rt_completion_done(struct rt_completion *completion)
    {
        level = rt_hw_interrupt_disable();
        completion->flag = RT_COMPLETED;
    
        if (!rt_list_isempty(&(completion->suspended_list)))
        {
            /* there is one thread in suspended list */
            struct rt_thread *thread;
    
            /* get thread entry */
         thread = rt_list_entry(completion->suspended_list.next,
                                   struct rt_thread,
                                tlist);
    
            /* resume it */
            rt_thread_resume(thread);
            rt_hw_interrupt_enable(level);
    
            /* perform a schedule */
            rt_schedule();
        }
    }
    

    主要做了以下工作:

    • 关中断:rt_hw_interrupt_disable();

    • 设置 flagRT_COMPLETED

    • 检查链表不为空:rt_list_isempty

    • 获取到当前等待完成量的句柄:rt_list_entry

    • 启动被挂起的线程:rt_thread_resume(thread);

    • 开中断:rt_hw_interrupt_enable(level);

    • 开调度:rt_schedule();

4. completion 与信号量的对比

  1. completion API 个数少,资源占用少,只能释放获取,不支持多次释放
  2. semaphore API 个数多,资源占用较多,使用灵活,可以尝试获取,可以多次释放,

5. completion 如何加入工程

  1. 标准版 RT-Thread 中的 completion 源码在 "\rt-thread\components\drivers\src\completion.c"在你要使用的文件中#include completion.h直接就可以使用。
  2. Nano 版 RT-Thread 直接拷贝completion.ccompletion.h 添加到工程就可以使用。
### RT-Thread CanFestival CANopen Protocol Stack Integration and Usage In the context of integrating a CANopen protocol stack into an embedded system using RT-Thread, one viable option is utilizing CanFestival[^1]. CanFestion provides comprehensive support for implementing CANopen nodes within various operating systems including real-Thread. #### Installation Process To integrate CanFestival with RT-Thread, developers should first ensure that both environments are properly set up on their development machine. The installation process involves downloading or cloning the CanFestival repository from its official source control platform. Afterward, configuring it to work alongside RT-Thread requires adjustments in project settings such as adding necessary include paths and linking against required libraries provided by either environment. ```bash git clone https://github.com/CANfestival/canfestival.git cd canfestival make rt-thread ``` This command sequence assumes that Git has been installed along with any prerequisites needed for building projects targeting RT-Thread platforms. #### Configuration Adjustments Once successfully integrated at build time through configuration files (e.g., `rtconfig.h`), specific configurations related to hardware abstraction layers must be addressed so that communication between physical CAN controllers and software components occurs seamlessly without conflicts arising due to differences in timing requirements imposed by different parts involved during runtime operations. For instance, setting up proper interrupt priorities ensures timely processing while avoiding potential issues caused by resource contention among multiple tasks running concurrently under tight scheduling constraints typical found within hard-realtime applications built upon microcontroller units (MCUs). #### Example Code Snippet Demonstrating Basic Initialization Steps Below demonstrates how initialization might look when incorporating CanFestival's API calls directly inside application code written specifically for use cases involving RT-Thread: ```c #include "canfestival.h" // Other includes... void init_can_open(void){ CO_ReturnError_t ret; /* Initialize CAN interface */ if ((ret = CO_CANinit(CO_CANmodule, 0)) != CO_ERROR_NO) { // Handle error... } /* Start CANopen Node */ if((ret = CO_CANsetConfigurationMode(CO_CANmodule))!=CO_ERROR_NO || (ret = CO_init(&NMT,&HeartbeatProducer,CANnodeId,CO_CANmodule)!=CO_ERROR_NO)){ // Error handling here. } } ``` The above C snippet initializes key aspects of working with CANopen via CanFestival APIs tailored towards being compatible with what RT-Thread offers regarding task management and inter-process communications mechanisms which facilitate efficient execution flow throughout entire programs designed around these technologies combined together effectively creating robust solutions capable enough even for mission-critical scenarios where reliability matters most. --related questions-- 1. What challenges may arise when porting CanFestival onto non-standard architectures supported by RT-Thread? 2. How does CanFestival handle errors internally compared to other similar stacks available today? 3. Are there any known limitations concerning performance metrics associated with this particular combination setup described earlier? 4. In terms of security features offered out-of-the-box, how well-equipped is CanFestival relative to alternatives present across market offerings catering especially toward industrial automation sectors relying heavily upon secure data exchange protocols over fieldbuses like those based off CAN technology standards? 5. Could you provide examples illustrating best practices recommended when developing complex multi-node networks leveraging capabilities exposed through integration points established between RT-Thread OS layer abstractions versus lower-level driver implementations interfacing directly with underlying hardware resources managing actual bit transmissions occurring physically over wires connecting all devices participating actively within same network topology instances deployed practically anywhere ranging widely indoors/outdoors environments alike depending largely upon intended application domain specifics driving design choices made upfront before implementation phases commence officially post-planning stages completion milestones reached satisfactorily according stakeholders' expectations outlined clearly documented requirement specifications agreed mutually amongst parties involved collaboratively throughout entire lifecycle span covering conception until decommission eventually?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值