0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

R-Rhealstone框架使用教程

jf_NsPBt3VS 来源:风火轮技术团队 2024-01-18 10:54 次阅读

本篇文章描述基于Rhealstone的系统实时性的测量基准的框架--R-Rhealstone框架。

嵌入式软件设计和集成中,实时多任务操作系统的性能分析是至关重要的,它需要保证应用的时间限制得到满足,即是运行时间不能超过应用的时间限制。为了选择满足用于特定应用的嵌入式系统的一个适当的操作系统,我们需要对操作系统服务进行分析。这些操作系统服务是由形成性能指标的参数确定的,既定的性能指标包括上下文切换时间、任务抢占时间、中断延迟时间、信号量混洗时间、死锁解除时间、信息传输延迟。

关于实时操作系统对性能指标进行分析,是为了选择满足用于特定应用的嵌入式系统的最优的操作系统。

Rhealstone

Rhealstone是系统实时性的测量基准之一,Rhealstone性能基准程序是实时系统的六个关键操作的时间量进行操作,这六个关键操作是:上下文切换时间、任务抢占时间、中断延迟时间、信号量混洗时间、死锁解除时间、信息传输延迟。这六项操作作为Rhealstone的六个组件,每个组件被单独测量。然后将经验结果合并为单一的测量值,即是Rhealstone值。

测量Rhealstone值方式:

序号 说明
方式 1 通用Rhealstone
方式 2 每个组件应用于具体应用程序的特定Rhealstone

Rhealstone性能基准程的缺点:

序号 说明
缺点 1 测量的是平均时间,而不是最坏值
缺点 2 后的结论是加权平均值,没有给出确定权值的依据

R-Rhealstone框架

设计R-Rhealstone框架的目的:为了能让对比的系统实时性的测量的一致性,必须保证同一个环境,解除差异性带来测量干扰,所以R-Rhealstone框架提供了操作系统适配层,统一适配不同操作系统的各个接口,目的可以达到上层调用层次一致。

a8aed314-b520-11ee-8b88-92fbcf53809c.png

上下文切换时间

描述:

上下文切换时间也称任务切换时间(task switching time),定义为系统在两个独立的、处于就绪态并且具有相同优先级的任务之间切换所需要的时间。它包括三个部分,即保存当前任务上下文的时间、调度程序选中新任务的时间和恢复新任务上下文的时间。切换所需的时间主要取决于保存任务上下文所用的数据结构以及操作系统采用的调度算法的效率。产生任务切换的原因可以是资源可得,信号量的获取等。任务切换是任一多任务系统中基本效率的测量点,它是同步的,非抢占的,实时控制软件实现了一种基于同等优先级任务的时间片轮转算法。影响任务切换的因素有:主机CPU的结构,指令集以及CPU特性。

任务切换过程增加了应用程序的额外负荷。CPU的内部寄存器越多,额外负荷就越重。任务切换所需要的时间取决于CPU有多少寄存器要入栈。实时内核的性能不应该以每秒钟能做多少次任务切换来评价,RTOS中通常是1微秒左右。

流程:

原理:创建两个同等优先级的任务,两个任务相互切换多次,最后求平均值。

注意:①需要减去多次切换的循环时间(loop_overhead);②需要减去主动让CPU执行时间(dir_overhead)

时间计算公式:

total_time:多次上下文切换总时间

loop_overhead:多次切换的循环时间

iterations:切换的次数

dir_overhead:调用让出CPU接口的时间

a8bd3512-b520-11ee-8b88-92fbcf53809c.png

代码:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

staticfloatloop_overhead=0.0;
staticfloatdir_overhead=0.0;
staticfloattelapsed=0.0;

staticuint32_tcount1,count2;

staticrst_task_idrst_task1=NULL;
staticrst_task_idrst_task2=NULL;

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task2_attr={
.name="task2",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_task2_func(void*arg);

staticvoidrst_task1_func(void*arg)
{
rst_task_create(&rst_task2,rst_task2_func,NULL,&rst_task2_attr);
if(rst_task2==NULL)
{
RST_LOGE("RST:task2createfailed");
rst_task_delete(NULL);
return;
}
/*Yieldprocessorsosecondtaskcanstartupandrun*/
rst_task_yield();

for(count1=0;count1< RST_BENCHMARKS_COUNT; count1++)
    {
        rst_task_yield();
    }
    rst_task_delete(NULL);
}

static void rst_task2_func(void *arg)
{
    /* All overhead accounted for now, we can begin benchmark */
    rst_benchmark_time_init();

    for(count2 = 0; count2 < RST_BENCHMARKS_COUNT; count2++)
    {
        rst_task_yield();
    }

    telapsed = rst_benchmark_time_read();

    RST_PRINT_TIME(
        "R-Rhealstone: task switch time", 
        telapsed,                       /* Total time of all benchmarks */
        (RST_BENCHMARKS_COUNT * 2) - 1, /* ( BENCHMARKS * 2 ) - 1 total benchmarks */
        loop_overhead,                  /* Overhead of loop */
        dir_overhead                    /* Overhead of rst_task_yield directive */
    );
    rst_task_delete(NULL);
}

rst_status rst_task_switch_init(void)
{
    /* find overhead of routine (no task switches) */
    rst_benchmark_time_init();
    for(count1 = 0; count1 < RST_BENCHMARKS_COUNT; count1 ++)
    {
    }
    for(count1 = 0; count1 < RST_BENCHMARKS_COUNT; count1 ++)
    {
    }
    loop_overhead = rst_benchmark_time_read();

    /* find overhead of rtems_task_wake_after call (no task switches) */
    rst_benchmark_time_init();
    rst_task_yield();
    dir_overhead = rst_benchmark_time_read();;

    rst_task_create(&rst_task1, rst_task1_func, NULL, &rst_task1_attr);
    if(rst_task1 == NULL)
    {
        RST_LOGE("RST: task1 create failed");
        return RST_ERROR;
    }

    return RST_OK;
}

任务抢占时间

描述:

抢占时间即系统将控制权从低优先级的任务转移到高优先级任务所花费的时间。为了对任务进行抢占,系统必须首先识别引起高优先级任务就绪的事件,比较两个任务的优先级,最后进行任务的切换,所以抢占时间中包括了任务切换时间。

它和任务切换有些类似,但是抢占时间通常花费时间更长。这是因为执行中首先要确认唤醒事件,并评估正在运行的任务和请求运行的任务的优先级高低,然后才决定是否切换任务。实质上,所有的多处理任务可以在执行期间动态分配优先级,所以,抢占时间也是衡量实时性能的重要指标。

流程:

原理:创建两个任务,任务1优先级比任务2优先级低,两个任务进行抢占多次,最后求平均值。

注意:①需要减去多次任务抢占的循环时间(loop_overhead);②需要减去挂起任务所需要的时间(dir_overhead)

时间计算公式:

total_time:多次任务抢占总时间

loop_overhead:多次任务抢占的循环时间

iterations:任务抢占的次数

switch_overhead:挂起任务所需要的时间

a8cb3216-b520-11ee-8b88-92fbcf53809c.png

代码:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

staticfloatloop_overhead=0.0;
staticfloatswitch_overhead=0.0;
staticfloattelapsed=0.0;

staticuint32_tcount;

staticrst_task_idrst_task1=NULL;
staticrst_task_idrst_task2=NULL;

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-3,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+3,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task2_attr={
.name="task2",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_task2_func(void*arg);

staticvoidrst_task1_func(void*arg)
{
/*Startuptask2,getpreempted*/
rst_task_create(&rst_task2,rst_task2_func,NULL,&rst_task2_attr);
if(rst_task2==NULL)
{
RST_LOGE("RST:task2createfailed");
rst_task_delete(NULL);
return;
}
switch_overhead=rst_benchmark_time_read();

rst_benchmark_time_init();
/*Benchmarkcode*/
for(count=0;count< RST_BENCHMARKS_COUNT; count++)
    {
        rst_task_resume(rst_task2);     /* Awaken task2, preemption occurs */
    }
    rst_task_delete(NULL);
}

static void rst_task2_func(void *arg)
{
    /* Find overhead of task switch back to task1 (not a preemption) */
    rst_benchmark_time_init();
    rst_task_suspend(rst_task2);

    /* Benchmark code */
    for(; count < RST_BENCHMARKS_COUNT - 1;)
    {
        rst_task_suspend(rst_task2);
    }

    telapsed = rst_benchmark_time_read();

    RST_PRINT_TIME(
        "R-Rhealstone: task preempt time", 
        telapsed,                       /* Total time of all benchmarks */
        RST_BENCHMARKS_COUNT - 1,       /* BENCHMARKS - 1 total benchmarks */
        loop_overhead,                  /* Overhead of loop */
        switch_overhead                 /* Overhead of task switch back to task1 */
    );
    rst_task_delete(NULL);
}

rst_status rst_task_preempt_init(void)
{
    /* Find loop overhead */
    rst_benchmark_time_init();
    for(count = 0; count < ((RST_BENCHMARKS_COUNT * 2) - 1); count++)
    {
    }
    loop_overhead = rst_benchmark_time_read();

    rst_task_create(&rst_task1, rst_task1_func, NULL, &rst_task1_attr);
    if(rst_task1 == NULL)
    {
        RST_LOGE("RST: task1 create failed");
        return RST_ERROR;
    }

    return RST_OK;
}

中断延迟时间

描述:

中断延迟时间是指从接收到中断信号到操作系统做出响应,并完成进入中断服务例程所需要的时间。多任务操作系统中,中断处理首先进入一个中断服务的总控程序,然后才进入驱动程序的ISR。

中断延迟时间=最大关中断时间+硬件开始处理中断到开始执行中断服务例程第一条指令之间的时间。

硬件开始处理中断到开始执行中断服务例程的第一条指令之间的时间由硬件决定,所以,中断延迟时间的长短主要取决于最大关中断的时间。硬实时操作系统的关中断时间通常是几微秒,而Linux最坏可达几毫秒。

流程:

原理:创建一个任务,任务执行主动触发中断,执行完中断服务程序返回,统计其时间。

注意:①需要减去读取时间接口的耗时时间(timer_overhead);

时间计算公式:

isr_enter_time:多次任务抢占总时间

iterations:任务抢占的次数

timer_overhead:读取时间接口的耗时时间

a8d9fbe8-b520-11ee-8b88-92fbcf53809c.png

代码:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

staticfloattimer_overhead=0.0;
staticfloatisr_enter_time=0.0;

staticrst_task_idrst_task1=NULL;

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_LOWEST_PRIORITY+1,
#else
.priority=RST_TASK_LOWEST_PRIORITY-1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_isr_handler(void*param)
{
isr_enter_time=rst_benchmark_time_read();
}

staticvoidrst_task1_func(void*arg)
{
rst_isr_install(RST_ISR_NUM,rst_isr_handler,NULL);

/*Benchmarkcode*/
rst_benchmark_time_init();
/*goestoIsr_handler*/
rst_isr_trigger(RST_ISR_NUM);

RST_PRINT_TIME(
"R-Rhealstone:interruptlatencytime",
isr_enter_time,
1,/*OnlyRhealstonethatisn'tanaverage*/
timer_overhead,
0
);
rst_task_delete(NULL);
}

rst_statusrst_interrupt_latency_init(void)
{
rst_task_create(&rst_task1,rst_task1_func,NULL,&rst_task1_attr);
if(rst_task1==NULL)
{
RST_LOGE("RST:task1createfailed");
returnRST_ERROR;
}

rst_benchmark_time_init();
rst_benchmark_time_read();
rst_benchmark_time_init();
timer_overhead=rst_benchmark_time_read();

returnRST_OK;
}

信号量混洗时间

描述:

信号量混洗时间(semaphore shuffling time),是指从一个任务释放信号量到另一个等待该信号量的任务被激活的时间延迟。在RTOS中,通常有许多任务同时竞争某一共享资源,基于信号量的互斥访问保证了任一时刻只有一个任务能够访问公共资源。信号量混洗时间反映了与互斥有关的时间开销,因此也是衡量RTOS实时性能的一个重要指标。

流程:

原理:创建一个信号量和两个相同优先级的任务。代码需要执行两次,第一次信号量不介入调度,计算任务切换的时间,第二次多次循环,信号量接入调度,信号量在两个任务中ping-pong执行,计算总时间。

注意:①需要减去任务切换的时间(switch_overhead);

时间计算公式:

telapsed:多次信号量混洗总时间

iterations:信号量混洗的次数

switch_overhead:切换的时间

a8e89d38-b520-11ee-8b88-92fbcf53809c.png

代码:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

staticfloatswitch_overhead=0.0;
staticfloattelapsed=0.0;

staticuint32_tcount=0;
staticuint32_tsem_exe=1;

staticrst_task_idrst_task1=NULL;
staticrst_task_idrst_task2=NULL;

staticrst_sem_idrst_sem=NULL;

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task2_attr={
.name="task2",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_task2_func(void*arg);

staticvoidrst_task1_func(void*arg)
{
/*Startuptask2,yieldsoitcanrun*/
rst_task_create(&rst_task2,rst_task2_func,NULL,&rst_task2_attr);
if(rst_task2==NULL)
{
RST_LOGE("RST:task2createfailed");
rst_task_delete(NULL);
return;
}
rst_task_yield();

/*Benchmarkcode*/
for(;count< RST_BENCHMARKS_COUNT; ) {
        if ( sem_exe == 1 )
        {
            rst_sem_lock(rst_sem, (rst_time_t)RST_WAIT_FOREVER);
            rst_task_yield();
            rst_sem_unlock(rst_sem);
            rst_task_yield();
        }
    }
    rst_task_delete(NULL);
}

static void rst_task2_func(void *arg)
{
    /* Benchmark code */
    rst_benchmark_time_init();
    for(count = 0; count < RST_BENCHMARKS_COUNT; count++)
    {
        if(sem_exe == 1)
        {
            rst_sem_lock(rst_sem, (rst_time_t)RST_WAIT_FOREVER);
            rst_task_yield();
            rst_sem_unlock(rst_sem);
            rst_task_yield();
        }
    }
    telapsed = rst_benchmark_time_read();

    if(sem_exe == 0)
    {
        switch_overhead = telapsed;
    }
    else
    {
        RST_PRINT_TIME(
            "R-Rhealstone: senaphore shuffle time", 
            telapsed,                       /* Total time of all benchmarks */
            (RST_BENCHMARKS_COUNT * 2),     /* Total number of times deadlock broken*/
            switch_overhead,                /* Overhead of loop and task switches */
            0
        );
    }
    rst_task_delete(NULL);
}

rst_status rst_semaphore_shuffle_init(void)
{
    rst_sem = rst_sem_create(1);
    if(rst_sem == NULL)
    {
        RST_LOGE("RST: sem create failed");
        return RST_ERROR;
    }

__RESTART:
    sem_exe = !sem_exe;

    /* Get time of benchmark with no semaphore shuffling */
    rst_task_create(&rst_task1, rst_task1_func, NULL, &rst_task1_attr);
    if(rst_task1 == NULL)
    {
        RST_LOGE("RST: task1 create failed");
        rst_sem_delete(rst_sem);
        return RST_ERROR;
    }

    /* Get time of benchmark with semaphore shuffling */
    if(sem_exe == 0)
    {
        goto __RESTART;
    }

    return RST_OK;
}

死锁解除时间

描述:

死锁解除时间(deadlock breaking time),即系统解开处于死锁状态的多个任务所需花费的时间。死锁解除时间反映了RTOS解决死锁的算法的效率。

流程:

原理:创建一个信号量和三个任务,优先级排序:任务1 < 任务2 < 任务3。代码需要执行两次,第一次信号量不介入调度,计算任务3切换到任务2,任务2切换到任务1得时间(即从高优先级切换到低优先级得时间),第二次多次循环,信号量接入调度,任务3死锁,任务2唤醒任务1,任务1解除死锁,通过统计多次,求平均值。

注意:①需要减去任务切换的时间(switch_overhead);

时间计算公式:

telapsed:多次死锁解除总时间

iterations:死锁解除的次数

switch_overhead:任务切换的时间

lock_overhead:调用信号量持有接口所需要得时间

a8f4038a-b520-11ee-8b88-92fbcf53809c.png

代码:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

staticfloatswitch_overhead=0.0;
staticfloatlock_overhead=0.0;
staticfloattelapsed=0.0;

staticuint32_tcount=0;
staticuint32_tsem_exe=1;

staticrst_task_idrst_task1=NULL;
staticrst_task_idrst_task2=NULL;
staticrst_task_idrst_task3=NULL;

staticrst_sem_idrst_sem=NULL;

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task2_attr={
.name="task2",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-3,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+3,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task3_attr={
.name="task3",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-5,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+5,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_task1_func(void*arg)
{
/*AlltaskshavehadtimetostartuponceTA01isrunning*/

/*Benchmarkcode*/
rst_benchmark_time_init();
for(count=0;count< RST_BENCHMARKS_COUNT; count++)
    {
        if(sem_exe == 1)
        {
            /* Block on call */
            rst_sem_lock(rst_sem, (rst_time_t)RST_WAIT_FOREVER);

            /* Release semaphore immediately after obtaining it */
            rst_sem_unlock(rst_sem);
        }
        /* Suspend self, go to task2 */
        rst_task_suspend(rst_task1);
    }
    telapsed = rst_benchmark_time_read();

    if(sem_exe == 0)
    {
        switch_overhead = telapsed;
    }
    else
    {
        RST_PRINT_TIME(
            "R-Rhealstone: deadlock break time", 
            telapsed,                       /* Total time of all benchmarks */
            RST_BENCHMARKS_COUNT,           /* Total number of times deadlock broken*/
            switch_overhead,                /* Overhead of loop and task switches */
            lock_overhead
        );
    }
    rst_task_delete(NULL);
}

static void rst_task2_func(void *arg)
{
    /* Start up task1, get preempted */
    rst_task_create(&rst_task1, rst_task1_func, NULL, &rst_task1_attr);
    if(rst_task1 == NULL)
    {
        RST_LOGE("RST: task1 create failed");
        rst_task_delete(NULL);
        return;
    }

    /* Benchmark code */
    for( ; count < RST_BENCHMARKS_COUNT; )
    {
        /* Suspend self, go to task1 */
        rst_task_suspend(rst_task2);

        /* Wake up task1, get preempted */
        rst_task_resume(rst_task1);
    }
    rst_task_delete(NULL);
}

static void rst_task3_func(void *arg)
{
    if(sem_exe == 1)
    {
        /* Low priority task holds mutex */
        rst_sem_lock(rst_sem, (rst_time_t)RST_WAIT_FOREVER);
    }

    /* Start up task2, get preempted */
    rst_task_create(&rst_task2, rst_task2_func, NULL, &rst_task2_attr);
    if(rst_task2 == NULL)
    {
        RST_LOGE("RST: task2 create failed");
        rst_task_delete(NULL);
        return;
    }

    for( ; count < RST_BENCHMARKS_COUNT; )
    {
        if(sem_exe == 1)
        {
            /* Preempted by task1 upon release */
            rst_sem_unlock(rst_sem);

            /* Prepare for next Benchmark */
            rst_sem_lock(rst_sem, (rst_time_t)RST_WAIT_FOREVER);
        }
        /* Wake up task2, get preempted */
        rst_task_resume(rst_task2);
    }
    rst_task_delete(NULL);
}

rst_status rst_deadlock_break_init(void)
{
    rst_sem = rst_sem_create(1);
    if(rst_sem == NULL)
    {
        RST_LOGE("RST: sem create failed");
        return RST_ERROR;
    }

    /* find overhead of obtaining semaphore */
    rst_benchmark_time_init();
    rst_sem_lock(rst_sem, (rst_time_t)RST_WAIT_FOREVER);
    lock_overhead = rst_benchmark_time_read();
    rst_sem_unlock(rst_sem);

__RESTART:
    sem_exe = !sem_exe;

    /* Get time of benchmark with no semaphores involved, i.e. find overhead */
    rst_task_create(&rst_task3, rst_task3_func, NULL, &rst_task3_attr);
    if(rst_task3 == NULL)
    {
        RST_LOGE("RST: task3 create failed");
        rst_sem_delete(rst_sem);
        return RST_ERROR;
    }

    /* Get time of benchmark with semaphores */
    if(sem_exe == 0)
    {
        goto __RESTART;
    }

    rst_sem_delete(rst_sem);
    return RST_OK;
}

信息传输延迟

描述:

信息传输延迟(datagram throuShput time),指一个任务通过调用RTOS的消息队列,把数据传送到另一个任务去时,每秒可以传送的字节数。

流程:

原理:创建一个消息队列和两个任务,优先级排序:任务1 < 任务2。任务1负责发送数据,任务2负责接收数据,执行多次,求平均值

注意:①需要减去调用消息队列接收函数的时间(receive_overhead);

时间计算公式:

telapsed:多次信息传输总时间

iterations:死锁解除的次数

loop_overhead:多次循环的时间

receive_overhead:调用消息队列接收函数的时间

a901de6a-b520-11ee-8b88-92fbcf53809c.png

代码:

#include"rst.h"
#include"rst_ipc.h"
#include"rst_btime.h"

#defineRST_QUEUE_BUFF_SIZE4

staticfloatloop_overhead=0.0;
staticfloatreceive_overhead=0.0;
staticfloattelapsed=0.0;

staticuint32_tcount;

staticrst_task_idrst_task1=NULL;
staticrst_task_idrst_task2=NULL;

staticrst_queue_idrst_queue=NULL;

staticintqueue_buff[RST_QUEUE_BUFF_SIZE]={0};

staticrst_task_attrrst_task1_attr={
.name="task1",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-3,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+3,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticrst_task_attrrst_task2_attr={
.name="task2",
#ifRST_BIG_NUM_HIGH_PRIORITY
.priority=RST_TASK_HIGHEST_PRIORITY-1,
#else
.priority=RST_TASK_HIGHEST_PRIORITY+1,
#endif
.stack_size=RST_TASK_STACK_SIZE,
};

staticvoidrst_task2_func(void*arg);

staticvoidrst_task1_func(void*arg)
{
/*Putamessageinthequeuesorecieveoverheadcanbefound.*/
rst_queue_send(rst_queue,
(constvoid*)queue_buff,
(uint32_t)sizeof(queue_buff),
(rst_time_t)RST_WAIT_FOREVER);

/*Startupsecondtask,getpreempted*/
rst_task_create(&rst_task2,rst_task2_func,NULL,&rst_task2_attr);
if(rst_task2==NULL)
{
RST_LOGE("RST:task2createfailed");
rst_task_delete(NULL);
return;
}

for(;count< RST_BENCHMARKS_COUNT; count++)
    {
        rst_queue_send(rst_queue, 
                       (const void *)queue_buff, 
                       (uint32_t)sizeof(queue_buff), 
                       (rst_time_t)RST_WAIT_FOREVER);
    }
    rst_task_delete(NULL);
}

static void rst_task2_func(void *arg)
{
    /* find recieve overhead - no preempt or task switch */
    rst_benchmark_time_init();
    rst_queue_recv(rst_queue, (void *)queue_buff, 
                   (uint32_t)sizeof(queue_buff));
    receive_overhead = rst_benchmark_time_read();

    /* Benchmark code */
    rst_benchmark_time_init();
    for(count = 0; count < RST_BENCHMARKS_COUNT - 1; count++)
    {
        rst_queue_recv(rst_queue, (void *)queue_buff, 
                       (uint32_t)sizeof(queue_buff));
    }
    telapsed = rst_benchmark_time_read();

    RST_PRINT_TIME(
        "R-Rhealstone: message latency time", 
        telapsed,                       /* Total time of all benchmarks */
        RST_BENCHMARKS_COUNT - 1,       /* BENCHMARKS - 1 total benchmarks */
        loop_overhead,                  /* Overhead of loop */
        receive_overhead                /* Overhead of recieve call and task switch */
    );
    rst_task_delete(NULL);
}

rst_status rst_message_latency_init(void)
{
    rst_queue = rst_queue_create(sizeof(queue_buff), 1);
    if(rst_queue == NULL)
    {
        RST_LOGE("RST: queue create failed");
        return RST_ERROR;
    }

    rst_benchmark_time_init();
    for(count = 0; count < (RST_BENCHMARKS_COUNT - 1); count++)
    {
    }
    loop_overhead = rst_benchmark_time_read();

    rst_task_create(&rst_task1, rst_task1_func, NULL, &rst_task1_attr);
    if(rst_task1 == NULL)
    {
        RST_LOGE("RST: task1 create failed");
        rst_queue_delete(rst_queue);
        return RST_ERROR;
    }

    return RST_OK;
}

RTOS对比结论

对比环境说明

说明
芯片 芯片型号:stm32f401
芯片架构:Cortex-M4
主频:84 MHz
开发环境 KEIL 5.x
工具链 ARMCC

对比结果说明

对比项 RT-Thread LiteOS FreeRTOS TobudOS
上下文切换 2.594596 us 6.739740 us 1.049049 us 2.343343
任务抢占 7.360721 us 7.603206 us 2.715431 us 4.523046 us
中断延迟 2.000000 us 1.000000 us 1.000000 us 1.000000 us
信号量混洗 23.829000 us 25.588000 us 19.496000 us 18.451000 us
死锁解除 18.108000 us 18.074000 us 21.522000 us 31.606000 us
信息传输延迟 7.749499 us 7.390782 us 7.298597 us 3.446894 us

总结

作者测试过程采用定时器计数器是1us,精度上有所欠缺,策略结果大致对比

中断延时部分,RT-Thread的中断是有框架的,而LiteOS和FreeRTOS直接使用STM32的HAL库,时间差异在框架的耗时

FreeRTOS在本次的对比的优势比较明显,除了死锁解除稍微逊色一点,其他的持平或由于RT-Thread和LiteOS

LiteOS在本次对比表现最差,尤其是上下文切换的耗时是RT-Thread和FreeRTOS的2~3倍。

说明:该框架目前已经适配作为RT-Thread的软件包,可以通过软件包体验其功能

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    30

    文章

    5031

    浏览量

    117734
  • 嵌入式系统
    +关注

    关注

    40

    文章

    3430

    浏览量

    128221
  • RTOS
    +关注

    关注

    20

    文章

    776

    浏览量

    118796
  • 实时操作系统

    关注

    1

    文章

    184

    浏览量

    30518

原文标题:如何选择RTOS?使用R-Rhealstone框架评估

文章出处:【微信号:风火轮技术团队,微信公众号:风火轮技术团队】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    英特尔(R)动态平台和散热框架解决方案ESIF(8.1.10600.150)类型错误?

    我的电脑只是随机进入sllep,因为围绕最后一个主要的Windows 10更新...发生这种情况后我发现错误英特尔(R)动态平台和热框架:ESIF(8.1.10600.150)类型:错误英特尔(R
    发表于 11-05 11:14

    Spring框架的设计理念

    Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框架中的hqC应用做过报道。本文将从另外一个视角试图剖析出Spring框架的作者设计Spring框架
    发表于 07-15 08:17

    LiteOS通信模组教程04-深度剖析LiteOS的AT框架

    本帖最后由 小熊派开源社区 于 2020-2-26 09:11 编辑 1. AT客户端框架在之前的三篇教程中,我们都是直接使用串口助手发送AT指令与模组通信,本篇教程就来探索一下
    发表于 02-26 09:03

    JS应用开发框架组件

    JS应用开发框架组件简介目录接口使用相关仓简介JS应用开发框架,是OpenHarmony为开发者提供的一套开发OpenHarmony JS应用的开发框架。其组成如下所示:图 1 JS应用开发
    发表于 04-23 18:05

    【入门】1 升级轻应用框架固件

    本帖最后由 jf_39160458 于 2021-5-21 16:04 编辑 首次拿到开发板后,开发板可能内置不是轻应用框架的固件,此时需要我们自己刷机。刷机流程如下:轻应用框架固件:“【04
    发表于 05-21 15:51

    什么是框架?为什么要有框架

    前言什么是框架?程序框架其实就类似一个文件大纲或者模板。因为写程序就和类似于写文章,如果没有大纲或者模板那么你写起来就会比较费劲。而。为什么要有框架?节约时间,减少错误。因为对于一种类型的程序它们
    发表于 11-09 07:38

    openharmony ACE开发框架详解

      ACE(Ability Cross-platform Environment)开发框架是ACE框架的轻量实现。它可以提供一套跨平台的类web应用开发框架,然后通过Toolkit将开发者编写
    发表于 04-07 14:52

    ARM时钟框架与编程实现概述

    明显的提升。本次学习使用的开发板为:JZ2440ARM版本为:AMR9一、时钟框架概述1.框架结构在讲解如何通过程序改变芯片的运行时钟频率之前,先搞清楚ARM9时钟框架,如下图所示为S3C2440芯片
    发表于 05-25 17:31

    基于SSH框架的图书管理应用框架研究张敏

    基于SSH框架的图书管理应用框架研究_张敏
    发表于 03-17 08:00 0次下载

    漫谈MCU程序框架

    话题1、真的有一种框架是完美的吗?现在的回答: 没有一种万能的框架,只有针对不同的场景选择最合适的框架 话题2、如何构建一个基础框架? ...
    发表于 10-28 13:05 14次下载
    漫谈MCU程序<b class='flag-5'>框架</b>

    智能上位机框架

    框架这个词,我相信大家都不陌生,C#框架有很多,主流的框架有Json.NET、NPOI、Log4Net、NLog、SuperWebSocket、 SuperSocket、Quartz.NET等等
    发表于 05-08 11:02 1次下载
    智能上位机<b class='flag-5'>框架</b>

    fastapi框架原理及应用

    Starlette 是目前测试最快的 Python 框架。只有 Uvicorn 超越了它,Uvicorn 不是框架,而是服务器。   Starlette 提供了所有基本的 Web 微框架功能。但是它不提供自动数据验证,序列化或
    发表于 07-18 11:30 572次阅读

    深度学习框架是什么?深度学习框架有哪些?

    深度学习框架是什么?深度学习框架有哪些?  深度学习框架是一种软件工具,它可以帮助开发者轻松快速地构建和训练深度神经网络模型。与手动编写代码相比,深度学习框架可以大大减少开发和调试的时
    的头像 发表于 08-17 16:03 1781次阅读

    谷歌模型框架是什么?有哪些功能和应用?

    谷歌模型框架(Google Model Framework)并不是一个特定的框架,而是指谷歌开发的一系列软件框架,用于支持机器学习和人工智能的应用。以下是一些与谷歌模型框架相关的关键组
    的头像 发表于 02-29 18:11 665次阅读

    谷歌模型框架是什么软件?谷歌模型框架怎么用?

    谷歌模型框架通常指的是谷歌开发的用于机器学习和人工智能的软件框架,其中最著名的是TensorFlow。TensorFlow是一个开源的机器学习框架,由谷歌的机器学习团队开发,用于构建和训练各种机器学习模型。
    的头像 发表于 03-01 16:25 239次阅读