TI-RTOS多任务编程

最近在做一些关于一些驱动向TI板子的移植集成的事情,涉及操作系统为RTOS实时操作系统,在这里简单的记录一下。本文主要叙述如何进行多任务的编程,以及我在编程中遇到的一些不解。

  1. Task组成部分:任务函数,任务参数(属性),任务堆栈.
实际上Task是sys/bios提供的一种并发编程手段,也是实时操作系统必备要素之一,
和我们常见到的线程是一个道理,换了个说法。
  1. Task类型:硬中断HWI,软中断SWI,任务Task,空闲任务IDLE.
  2. 优先级排列:硬中断HWI>软中断SWI>任务Task>空闲任务IDLE.
举个例子:
同时存在四种任务,优先处理硬中断;
如果只存在一种类型任务,优先处理该类型中优先级高的任务;
如果只存在一种类型任务,且优先级相同,任务调度取决于系统调度程序;
(特殊情况除外)
  1. 四种类型任务释义
硬中断:实时环境中,它是响应外部触发的异步事件(中断)-----优先级不由sys/bios管理,由cpu的特性决定。
虽然优先级最高,当然也可以被中断。

软中断:软件中断服务例程 ------优先级可以达到 32 级,默认只有 16 级。
SWI 可以被更高优先级的 SWI 和 HWI 抢占,但是 SWI 是不会阻塞的。

任务:用户任务,运行过程中,可以被阻塞直到必要的资源可用;
TASK 要求每个任务要有自己独立的栈空间。
SYS/BIOS 提供了一些机制用于 TASK 间的同步和通信,它们有信号量(Semphore),事件(Events),队列(Queue)和邮箱(Mailboxes)。
优先级也可以达到 32 级,默认是 16 级。
Task 优先级数值越大,其优先级就越高,0 是优先级最低的。Task_setPri 函数动态的更改。新的优先级必须在 1 到 TnumPriorities – 1 之间。当新优先级数低于当前优先级时,可能会发生任务的切换。

空闲任务:优先级最低的任务。
当 SYS/BIOS 没有比空闲任务更高的任务运行时,SYS/BIOS 就会执行空闲任务,并且是连续执行,直到有更高的任务进入就绪状态。
其运行在Task任务 0 优先级上。
  1. 创建一个task过程:
#include <app.h>
#include <utils/console_io/include/app_log.h>
#include <xdc/runtime/Error.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <app_ipc_rsctable.h>

static Void appMain(UArg arg0, UArg arg1){   //任务函数
	//do something
	printf("this is thread function\n");
} 

void StartupEmulatorWaitFxn (void){
    volatile uint32_t enableDebug = 0;
    do{
    }while (enableDebug);
}

static uint8_t gTskStackMain[4*1024]                 //任务使用的栈空间
__attribute__ ((section(".bss:taskStackSection")))
__attribute__ ((aligned(4096)))
;

int main(void)
{
    Task_Params tskParams;
    Error_Block eb;
    Task_Handle task;
    /* This is for debug purpose - see the description of function header */
    StartupEmulatorWaitFxn();
    Error_init(&eb);
    Task_Params_init(&tskParams);

    tskParams.arg0 = (UArg) NULL;
    tskParams.arg1 = (UArg) NULL;
    tskParams.priority = 10u;                //指定任务优先级
    tskParams.stack = gTskStackMain;         //指定任务使用的堆栈
    tskParams.stackSize = 4096;              //指定堆栈的大小
    task = Task_create(appMain, &tskParams, &eb); //动态创建一个task
    /*
		You can continue to create other tasks from here......
	*/
    if(NULL == task){
        BIOS_exit(0);
    }
    BIOS_start();                  //运行到这里程序不会退出,相当于是个死循环,操作系统将会调度执行任务
    return 0;
}

  1. SDK版本以及引用路径
/psdk_rtos_auto_j7_06_01_00_15/bios_6_76_03_01/packages/ti/sysbios/knl
  1. 如何在程序中获取任务的信息以及状态
// bios_6_76_03_01/packages/ti/sysbios/knl/Task.h:105:struct  ti_sysbios_knl_Task_Stat ; 任务信息声明处
//解释几个我用到的成员:
struct ti_sysbios_knl_Task_Stat {
      xdc_Int priority;    //优先级
      xdc_Ptr stack;        //使用的堆栈地址
      xdc_SizeT stackSize;  //使用的堆栈的大小
      xdc_runtime_IHeap_Handle stackHeap;
      xdc_Ptr env;
      ti_sysbios_knl_Task_Mode mode;//休眠态,就绪态,运行态,挂起态,被中断态
      xdc_Ptr sp;
      xdc_SizeT used;               //已经使用了的堆栈空间大小
 };

如何在一个任务中动态获取当前任务的状态信息:

    Task_Stat statbuf;
    Task_stat(Task_self(),&statbuf);
    printf("In appMain task,stack buff used = %d\n",statbuf.used);//查看当前任务已经使用的
    printf("In appMain task,stack total size = %d\n",statbuf.stackSize);//查看当前任务分配的总stack
    printf("In appMain task,task priority =%d\n",statbuf.priority); //查看当前任务的优先级
  1. 关于任务堆栈
    大小:
    尽量使用自定义数组来充当任务执行时的堆栈,不要依靠于系统的堆栈,如果内存不足,将发生致命错误;
    关于给任务分配多大内存为合适,我查看了一些资料,有说到一个任务最少需要分配512个字节,这是理论值,或者说这个任务的函数是一个空函数,啥都不干,这512是用来满足上下文的保存的,不符合实际开发,如果条件允许,简单的函数给予2k,稍微复杂的给予4k.(具体值还请各位尝试,这里作为参考)
    注意:我这里是跑在R5F mcu2_0上的,和使用的SDK版本也有关系。

对齐方式:(不添加对齐应该也可以运行)
我理解cpu为了提高取指速率,需要进行内存对齐。
一般而言,选择对齐数num * n = stackSize,其中n%2 == 0,num可能更满足要求,如
static uint8_t TskStackMain[4*1024]
attribute ((section(".bss:taskStackSection")))
attribute ((aligned(4096)));

这个我并没有找到官方的文档的来解释说明,仅仅作为一种猜测,当然不是凭空猜测,是经过实验的。

  1. 任务阻塞方式:

Task_sleep():使用:Task_sleep(5300 / Clock_tickPeriod);// 延时5.3ms Clock_tickPeriod定义在ti/sysbios/knl/Clock.h

Task_yield():使得任务主动让出自己的时间片

Semaphore_pend():信号量,获取临界资源

  1. 同步方式
    信号量、邮箱、事件等,如需要可以参考官方文档。实际上原理和用法与多线程同步方式一个道理,只不过换了个名字罢了。

最后说一下我的遇到几个很奇怪的现象:

1.替换固件,板子断电重启,系统运行的结果是前一次,为什么上一次数据没有被擦除?
2.相同优先级的任务存在某一个任务一直运行,不释放cpu的现象,只好通过一些接口
让他主动释放,并没有像一些文档中描述的,类似于时间片轮转?
3.为什么我在main()函数中打印的log不能查看到,只能看到在任务中打印的log?

这里猜测可能是SDK版本的原因,也可能是板子还是不够成熟吧
发布了237 篇原创文章 · 获赞 98 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/KingOfMyHeart/article/details/105016563