RTOS平台上--代码运行速度提升测试

1.简介

  在实际使用过程中,部分代码,比如需要实时进行处理,比如需要实时卡尔曼处理数据, 算法模块,编解码操作,大量循环,UI操作。   由于部分RTOS设备,代码指令存储在FLASH中,对于存储在内部FLASH的,执行过程中,取指令速度可控,但是实际使用过程中,有些设备 使用了外部flash存储代码(正常量产,一般需要进行多供,降低供应链风险)。 这个会导致部分平台上,我们代码存储在不同flash上,执行过程中,存在速度差异(部分较差的flash,存取指令周期变长)。

2.优化提升

  优化提升,一方面如果平台存在icache,可能会比较友好,因为指令一旦命中,就会从cache中获取,速度相当,对于 未命中,就需要从flash取指令,执行。   另外一个策略,就是在RAM较充足下,将代码指令放置到RAM空间上,我们在实际使用过程中,遇到紫光展锐W217平台 上,运行效率问题,因此考虑进行优化部分放置到内存,进行提升速度。

3.操作流程

涉及的主要流程有,链接脚本调整、代码指令拷贝、运行,以紫光展锐UWS6121E实例部分伪代码策略:

3.1 链接脚本

  这个部分要将我们需要执行的代码,链接到一个空间里面,需要在RAM上占个位置, 这个部分的代码其实也是会在ROM里面占位置,如果不需要RAM里面占,可以补充到FLASH后面,单独链接成一段。

;将用户代码单独放置  
RAM_EXEC_USER_CODE  +0
    {
        ; 所有标记 USER_RAM_CODE 的代码都会放在这里
        *(USER_RAM_CODE)

        ;user_fast_code.o (*.text)   <=== 整个文件所有代码都进来!
    }

    ;IMG$$RAM_RW$$LIMIT will be used to check the case of overflow
    RAM_RW +0
    {
        * (+RW)
        * (+ZI)
    }

    HEAP_AREA +0 ALIGN 4   
    {
        mem_prod*.o (BYTE_HEAP_AREA)
    }

    SYS_STACK +0 ALIGN 4   
    {
        mem_prod*.o (SYS_STACK_AREA)
        mem_prod*.o (FIQ_STACK_AREA)
    }
;断言--保证没有用超内存
    ScatterAssert(ImageLimit(SYS_STACK) <= (MEM_RAM_AP_END_ADDR))
3.2 开机阶段处理

开机阶段主要需要的工作就是将,需要优化的代码放入到RAM上,上面已经占好了空间,对于编译器ARMCC平台,会 自动导入宏定义(标记我定义的段的位置,大小等)

extern unsigned char Image$$RAM_EXEC_USER_CODE$$Base;
extern unsigned char Load$$RAM_EXEC_USER_CODE$$Base;
extern unsigned int  Image$$RAM_EXEC_USER_CODE$$Length;

// 从Flash 位置 拷贝到 RAM位置(之前已经占位了)
void copy_user_code_to_ram(void)
{
    memcpy(
        &Image$$RAM_EXEC_USER_CODE$$Base,   // 目标 RAM
        &Load$$RAM_EXEC_USER_CODE$$Base,    // 源 Flash
        &Image$$RAM_EXEC_USER_CODE$$Length
    );
}
3.3 测试阶段

伪代码测试效果(实际工程中,可以让自己需要进行优化代码,比如UI相关的、算法相关的)

__attribute__((section("USER_RAM_CODE")))
void my_fast_func(void)
{
    volatile int i = 0;
    for(i=0; i < 1000000;i++)
    {
        //SCI_TRACE_LOW("index:%d",i);
    }
}

void my_normal_func()
{
    volatile int i = 0;
    for(i=0; i < 1000000;i++)
    {
        //SCI_TRACE_LOW("index:%d",i);
    }

}


void test_func_all()
{
    uint32 start_tick = 0;
    uint32 end_tick = 0;
    uint32 end_all_tick = 0;

    start_tick = SCI_GetTickCount();
        my_fast_func();
    end_tick = SCI_GetTickCount();

        my_normal_func();
    end_all_tick = SCI_GetTickCount();

    SCI_TRACE_LOW("time1: %d, time2: %d", (end_tick-start_tick), (end_all_tick-end_tick) );

}
3.4 实际测试效果

实际测试效果,在指令较少(或者有cache平台上)差距不大,但是对于指令较多,速度问题,立马就会显现出来:

[test_func_all]<4487> time1: 8, time2: 11                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 11                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 9, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 11                   
[test_func_all]<4487> time1: 8, time2: 10                   
[test_func_all]<4487> time1: 8, time2: 11

4.总结

主要是针对RAM足够,外挂FLASH存储代码,且外挂FLASH品质差异,或者对实时性,要求高的场景。