当前位置: 首页 > 进阶技术 > 沁恒 TMOS系统用法简介

沁恒 TMOS系统用法简介

发布于:2022-1-20 最后更新:2022-5-2 进阶技术 0条评论 959 views

一 TMOS诞生背景

CH573是南京沁恒推出的一款Risc-V的BLE芯片,该芯片相比较于普通的Risc-V 32位单片机,又增加了BLE通讯功能和USB全速通讯功能。沁恒的BLE方案为软核方式,也就是说,该器件的数据编码部分完全由软件实现。 根据蓝牙通讯标准,蓝牙每隔625us需要进行一次跳频操作。为了维持稳定的主从蓝牙设备通讯,处理器必须每625us进行一次数据发送。 为了既满足于BLE通讯要求,又满足其他逻辑控制功能,实现处理器的分时复用,就需要一个机制进行精确的时间调度, TMOS就是在这样的一个需求背景下出现的。

二 TMOS是什么

TMOS作为调度核心,BLE协议栈、profile定义、所有的应用都围绕它来实现。TMOS是一个允许软件建立和执行事件的多任务循环调度系统。多任务管理方式在某一时刻实际上只有一个任务在运行,但是可以使用任务调度的策略将多个任务进行调度,每个任务占用一定的时间,所有的任务通过时间分片的方式处理。TMOS 系统的调度周期是 625us,以 RTC 为基准得到所有需要系统的时间,每隔625us,系统自动切换一次任务。

三 TMOS使用方法

TMOS主要由三个步骤来实现

1. Task ID 初始化

static unit8 Peripheral_TaskID = INVALID_TASK_ID;

Peripheral_TaskID 是您要新建的任务的ID号,这句语句给他赋一个无效的空值作为初始化

2. 创建 user_ProcessEvent 函数

uint16 user_ProcessEvent(uint8 task_id, uint16 events)

user_ProcessEvent是一个自定义的回调函数,用户在这个函数里写自己要要完成的业务代码。这个函数在任务函数注册后由系统调用,系统将返回两个参数:

  1. task_id, 这是返回的调用该任务的taskID值,我们一般不用

  2. events,传入的unit16参数,代表触发该人物函数的事件,沁恒公司的代码推荐按位使用,共有16个状态位,某个状态位被置1则意味着该状态位对应的事件触发了这个回调函数。除最高位被系统保留用来表示系统消息外,低位的15个状态位都可以由用户自定义,每个状态位的具体含义由用户自定义。

3. 任务函数注册并创建任务Task

Peripheral_TaskID = TMOS_ProcessEventRegister (user_ProcessEvent)

使用沁恒TMOS调度系统底层封装的 TMOS_ProcessEventResister 函数注册该任务, 并取得系统分配的 TaskID

4. 启动任务task

有两种方式启动task 一种是立即启动,使用这个底层系统函数可以立即执行user_TaskID所标识的任务函数

tmos_set_event(user_TaskID,events)

另一种是延迟启动,使用这个底层系统函数可以挂起user_TaskID所标识的任务函数一定时间后再执行,挂起的时间为625us的整倍数,调用参数为n,则延迟n*625us,

tmos_start_task(user_TaskID,events,n)

5 任务的循环执行

以上的两种任务执行方式都是单次执行,为了使任务能够定期重复执行,我们需要利用event事件,在回调函数里循环调用,当任务执行完成后,调用 tmos_start_task 函数,挂起一定时间后继续执行该任务

tmos_start_task(user_TaskID,events,n)
{
    ...
    if (events & SBP_PERIODIC_EVENT)
    {
        //延迟6.25ms后再次执行该任务
        tmos_start_task(user_TaskID,SBP_PERIODIC_EVT,10);
        return(events ^ SBP_PERIODIC_EVT);
    }
}

四 例子

下面我们以一个完整的例子介绍一下上面的整个内容,建立两个独立的TMOS任务,每隔0.625秒分别打印Task1 running 和 Task2 running

static tmosTaskID task1;
static tmosTaskID task2;
tmosEvents Task1_ProcessEvent( tmosTaskID task_id, tmosEvents events )
{
  int * msgPtr;

  if( events & 0x01 )
  {
    PRINT("%s\n","Task1 running");
    tmos_start_task( task_id , 0x01 ,1000 ); // 0.625s 后循环启动
    return events ^ 0x01;
  }
  return 0;

}

tmosEvents Task2_ProcessEvent( tmosTaskID task_id, tmosEvents events )
{
  int * msgPtr;

  if( events & 0x01 )
  {
    PRINT("%s\n","Task2 running");
    tmos_start_task( task_id , 0x01 ,1000 ); // 0.625s 后循环启动
    return events ^ 0x01;
  }
  return 0;

}

 void TEST_Init( )
{
   task1 = TMOS_ProcessEventRegister(Task1_ProcessEvent);
   task2 = TMOS_ProcessEventRegister(Task2_ProcessEvent);
   tmos_set_event(task1, 0x01); // 添加一个测试任务
   tmos_set_event(task2, 0x01); // 添加一个测试任务

}

执行效果如下

Task1 running Task2 running ...

您可以在附件中下载例子源码,谢谢。 源文件下载


标签: , ,

发表回复

您的电子邮箱地址不会被公开。