7.8. OS API

Overview

SDK中提供了两种操作系统API,一种是基于FreeRTOS原接口进行再次封装的API(这里简称为OS API), 在SDK有更好的兼容性,所以SDK中大量采用了这类API;另一种为POSIX Threads(这里简称为pthread api),(具体请参考 PTHREAD API );

7.8.1. DEMO

使用工程: 示例代码见 apps/common/example/system/os/os_api/main.c,测试时需要在 apps/demo/demo_DevKitBoard/include/demo_config.h ,开启宏 USE_OS_API_TEST

示例说明

展示了OS API基本使用方法,包括任务创建(动态任务创建和静态任务创建)、信号量、互斥量的使用和消息队列的使用等,主要示例包括:

  • mutex_test(); 互斥量使用示例

  • queue_test(); 消息队列使用示例

  • sem_test(); 信号量使用示例

  • static_task_test(); 静态任务创建示例

  • thread_can_not_kill_test(); 模拟线程无法杀死示例


7.8.2. 线程(Task)

任务创建

函数

int thread_fork(const char *thread_name, int prio, int stk_size, u32 q_size, int *pid, void (*func)(void *), void *parm);

描述

创建线程

参数

thread_name:标识此线程的字符串 prio:优先级 stk_size:堆栈空间的大小 q_size: 消息队列空间的大小 pid: 线程号 func: 线程入口函数地址 parm: 传递给线程入口函数的参数

返回值

0:成功 其他:失败

例子

#include "os_api.h"
#define TASK_STK_SIZE 256
#define TASK_Q_SIZE 0
#define TASK_PRIO 12

static int task_pid;

static void task_entry(void *p)
{
  //获取当前线程
  printf("task_entry (%s) task\n", os_current_task());

  while(1)
  {
    printf("running...\n");
    os_time_dly(50);
  }
}

void task_test(void)
{
  thread_fork("task_entry", TASK_PRIO, TASK_STK_SIZE, TASK_Q_SIZE, &task_pid, task_entry, NULL);
}

任务列表使用

务列表的作用可以对任务进行统一管理,方便对任务的优先级(优先级范围为0~31,数值越大优先级越高)、任务堆栈大小和消息队列大小进行调整,同时支持动态任务注册和静态任务注册,例如:

例子

/***********************************静态任务创建步骤********************************************
*1.创建使用  thread_fork 接口的 静态任务堆栈
*  (1)在app_main.c中创建静态任务堆栈:
*      #define STATIC_TASK_CREATE_STK_SIZE 256
*      #define STATIC_TASK_CREATE_Q_SIZE 0
*      #static u8 test_stk_q[sizeof(struct thread_parm) + STATIC_TASK_CREATE_STK_SIZE * 4 + \
*                                            (STATIC_TASK_CREATE_Q_SIZE ? (sizeof(struct task_queue) + APP_CORE_Q_SIZE) : 0 )] ALIGNE(4);
*
*  (2)在app_main.c中将静态任务加入任务列表const struct task_info task_info_table[]:
*      {任务名,        任务优先级,      任务堆栈大小,   任务消息队列大小,  任务堆栈},
*      {"task_create_static_test", STATIC_TASK_CREATE_PRIO, STATIC_TASK_CREATE_STK_SIZE, STATIC_TASK_CREATE_Q_SIZE, test_stk_q},
*********************************************************************************************/
#include "os_test.h"
#define STATIC_TASK_CREATE_STK_SIZE 256
#define STATIC_TASK_CREATE_Q_SIZE 0
#define STATIC_TASK_CREATE_PRIO 12

static int task_pid;
static int kill_req = 0;

static void task_create_static_test(void *p)
{
  //获取当前线程
  printf("task_create_static_test in (%s) task\n", os_current_task());

  while(1)
  {
    printf("Use static task stack to create task test!");
    os_time_dly(50);

    if(kill_req)
    {
      //退出任务前必须释放占用的资源
      os_time_dly(1000);
      break;
    }
  }
}

void static_task_test(void)
{
  thread_fork("task_create_static_test", STATIC_TASK_CREATE_PRIO, STATIC_TASK_CREATE_STK_SIZE, STATIC_TASK_CREATE_Q_SIZE, &task_pid, task_create_static_test, NULL);

  os_time_dly(50);

    puts("Exiting the task_create_static_test thread!\n");

  //退出线程请求
  kill_req = 1;

  //阻塞等待线程退出
    thread_kill(&task_pid, KILL_WAIT);
  puts("Exit the task_create_static_test thread successfully!");
}

7.8.3. 消息队列(Queue)

消息队列创建

函数

int os_taskq_post_type(const char *name, int type, int argc, int *argv);

描述

创建消息队列

参数

name:消息接收方的线程名称 type:消息类型 argc:消息个数 argv: 指向要发送的消息的指针

返回值

0:成功 ;OS_TASK_NOT_EXIST: 任务不存在; OS_ERR_POST_NULL_PTR: 任务消息队列不存在; OS_Q_FULL: 任务消息队列已满

例子

/***********************************消息队列测试说明********************************************
*说明:
*     设置queue_task任务和task3_task任务为同等优先级,queue_task任务阻塞等到消息,当收到task3_task
*   任务的消息后,向task3_task发送接收到消息通知。
*********************************************************************************************/

#include "os_test.h"

#define QUEUE_TASK_PRIO 10        //任务优先级大小
#define QUEUE_STACK_SIZE 512      //任务堆栈大小
#define QUEUE_QUEUE_SIZE 256      //消息队列大小,注意任务间需要通过消息队列通讯时必须分配足够的消息队列大小,否则接收不到消息。
static int queue_pid;

#define TASK3_TASK_PRIO 10
#define TASK3_STACK_SIZE 512
#define TASK3_QUEUE_SIZE 256
static int task3_pid;

//消息类型
enum {
    MESSAGE_1     = 0x01,
    MESSAGE_2     = 0x02,
    MESSAGE_3     = 0x03,
};

enum {
    GET_MESSAGE_1     = 0x01,
    GET_MESSAGE_2     = 0x02,
    GET_MESSAGE_3     = 0x03,
};

static char *message1 = "Message1 received!";
static char *message2 = "Message2 received!";
static char *message3 = "Message3 received!";

//等待消息队列任务
static void queue_task(void *priv)
{
  int argc = 2;  //消息个数
  int argv[4];
    int msg[32];   //接收消息队列buf
    int err;
  char *ptr = NULL;

  //获取当前线程
  printf("queue_task in (%s) task\n", os_current_task());

    while (1) {
    //阻塞等待消息
        err = os_taskq_pend("taskq", msg, ARRAY_SIZE(msg));
        if (err != OS_TASKQ || msg[0] != Q_USER) {
            continue;
        }

        switch (msg[1]) {
        case MESSAGE_1:
      printf("get MESSAGE_1, data : %d\n", msg[2]);
      ptr = message1;
            break;

        case MESSAGE_2:
      printf("get MESSAGE_2, data : %d\n", msg[2]);
      ptr = message2;
            break;

        case MESSAGE_3:
      printf("get MESSAGE_3, data : %d\n", msg[2]);
      ptr = message3;
            break;

            default:
                break;
        }

    argv[0] = msg[1];
    argv[1] = (int)ptr;

_retry1:
    //向任务task3_task发送接收到消息通知
    err = os_taskq_post_type("task3_task", Q_USER, argc, argv);
    //err = os_taskq_post("task3_task", argc, argv[0], argv[1]);//采用该接口发送信息时可变参数个数不能超过8个
    if(err == OS_Q_FULL)
    {
      os_time_dly(10);
      goto _retry1;
    }
    }
}

static void task3_task(void *priv)
{
  int err;
  int argc = 2;  //消息个数
  int argv[4];
    int msg[32];   //接收消息队列buf
  char *ptr = NULL;

  //获取当前线程
  printf("task3_task in (%s) task\n", os_current_task());

    //发送的消息内容
  argv[0] = MESSAGE_1;
  argv[1] = 12;

  while(1)
  {
    //向任务queue_task发送消息
    err = os_taskq_post_type("queue_task", Q_USER, argc, argv);
    //err = os_taskq_post("queue_task", argc, argv[0], argv[1]);//采用该接口发送信息时可变参数个数不能超过8个
    if(err == OS_Q_FULL)
    {
      os_time_dly(10);
      continue;
    }

    os_time_dly(20);

_retry2:
    //等待queue_task任务回复
        err = os_taskq_pend("taskq", msg, ARRAY_SIZE(msg));
        if (err != OS_TASKQ || msg[0] != Q_USER) {
            goto _retry2;
        }

        switch (msg[1]) {
        case GET_MESSAGE_1:
      ptr = (char *)msg[2];
      printf("%s\n", ptr);

      argv[0] = MESSAGE_2;
      argv[1] = 10;
            break;

        case GET_MESSAGE_2:
      ptr = (char *)msg[2];
      printf("%s\n", ptr);

      argv[0] = MESSAGE_3;
      argv[1] = 11;
            break;

        case GET_MESSAGE_3:
      ptr = (char *)msg[2];
      printf("%s\n", ptr);

      argv[0] = MESSAGE_1;
      argv[1] = 12;
            break;

            default:
                break;
        }

    os_time_dly(100);
  }
}

//队列测试
void queue_test(void)
{
    if (thread_fork("queue_task", QUEUE_TASK_PRIO,  QUEUE_STACK_SIZE, QUEUE_QUEUE_SIZE, &queue_pid, queue_task, NULL) != OS_NO_ERR) {
        printf("thread fork fail\n");
    }

  //创建任务2
    if (thread_fork("task3_task", TASK3_TASK_PRIO, TASK3_STACK_SIZE, TASK3_QUEUE_SIZE, &task3_pid, task3_task, NULL) != OS_NO_ERR) {
        printf("thread fork fail\n");
    }
}

7.8.4. 信号量(Semaphore)

信号量创建

函数

int os_sem_create(OS_SEM *sem, int cnt);

描述

创建信号量

参数

sem:信号量 cnt: 初始计数值

返回值

0:成功 ;其他:失败

例子

#include "os_test.h"

static OS_SEM psem;

static void thread_pend_sem(void *priv)
{
  //获取当前线程
  printf("thread_pend_sem in (%s) task\n", os_current_task());

    while (1) {
    puts(">>>>>>>[0]thread_pend_sem : wait sem!");

        os_sem_pend(&psem, 0); //获取信号量

    puts(">>>>>>>[2]thread_pend_sem : get sem!");
    }
}

static void thread_post_sem(void *priv)
{
  //获取当前线程
  printf("thread_post_sem in (%s) task\n", os_current_task());

    while (1) {
        os_time_dly(1000);  //延时模拟任务执行一段时间后释放信号量

        os_sem_post(&psem); //释放信号量

    puts(">>>>>>>[1]thread_post_sem : post sem!");
    }
}

void sem_test(void)
{
    os_sem_create(&psem, 0);

    if (thread_fork("thread_pend_sem", 10,  256, 0, NULL, thread_pend_sem, NULL) != OS_NO_ERR) {
        printf("thread fork fail\n");
    }

    if (thread_fork("thread_post_sem", 10, 256, 0, NULL, thread_post_sem, NULL) != OS_NO_ERR) {
        printf("thread fork fail\n");
    }

}

7.8.5. 互斥量(Mutex)

互斥量创建

例子

#include "os_test.h"

#define TASK1_TASK_PRIO 10     //任务优先级
#define TASK1_STACK_SIZE 512   //任务栈大小
#define TASK1_QUEUE_SIZE 0     //消息队列大小
static int task1_pid = 0;      //任务pid

#define TASK2_TASK_PRIO 10
#define TASK2_STACK_SIZE 512
#define TASK2_QUEUE_SIZE 0
static int task2_pid = 0;

static OS_MUTEX mutex;
static int value = 0;

char *str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *str2 = "abcdefghijklmnopqrstuvwxyz";

#if 0
/***********************************互斥量测试说明********************************************
*说明:
*     设置task1_task任务和task2_task任务为同等优先级,获取到互斥量的任务拥有该互斥量的使用权,
*其他任务想获取该互斥量必须等获取到互斥量的任务完成其工作并释放该互斥量才行。
*********************************************************************************************/
static void task1_task(void *priv)
{
    char *str = (char *)str1;

    os_mutex_pend(&mutex, 0);

    while (*str != '\0') {
        printf("%c\n", *str);
        str++;
    }
    puts("\n");

  os_mutex_post(&mutex);
}

static void task2_task(void *priv)
{
    char *str = (char *)str2;

    os_mutex_pend(&mutex, 0);

    while (*str != '\0') {
        printf("%c\n", *str);
        str++;
    }
    puts("\n");

  os_mutex_post(&mutex);
}
#else
/***********************************互斥量测试说明********************************************
*说明:
*     设置task1_task任务和task2_task任务为同等优先级,某个任务在执行期间对value的值进行修改
*  只有获取到互斥量的任务能获得value的使用权,其他任务需要等待该互斥量释放并获取到互斥量才
*   能对value进行修改, 从而可以通过互斥量来处理共享资源,防止多线程重入。
*********************************************************************************************/
static void task1_task(void *priv)
{
  //获取当前线程
  printf("task1_task in (%s) task\n", os_current_task());
  printf("task1_task pid : 0x%x\n", task1_pid);

  while(1)
  {
    os_mutex_pend(&mutex, 0);
    value = 100;
    printf("==========>Task1 gets the mutex!");

    for(int i = 0; i < 8; i++)
    {
      printf("task1 is running...\n");
      printf("value : (%d)\n", value);
      os_time_dly(20);
    }

    printf("==========>Task1 post the mutex!");
    os_mutex_post(&mutex);
    os_time_dly(100);
  }
}

void task2_task(void *priv)
{
  //获取当前线程
  printf("task2_task in (%s) task\n", os_current_task());
  printf("task2_task pid : 0x%x\n", task2_pid);

  while(1)
  {
    os_mutex_pend(&mutex, 0);
    value = 200;
    printf("==========>Task2 gets the mutex!");
    for(int i = 0; i < 8; i++)
    {
      printf("task2 is running...\n");
      printf("value : (%d)\n", value);
      os_time_dly(20);
    }

    printf("==========>Task2 post the mutex!");
    os_mutex_post(&mutex);
    os_time_dly(100);
  }
}
#endif

void mutex_test(void)
{
  os_mutex_create(&mutex);

  //创建任务1
    if (thread_fork("task1_task", TASK1_TASK_PRIO, TASK1_STACK_SIZE, TASK1_QUEUE_SIZE, &task1_pid, task1_task, NULL) != OS_NO_ERR) {
        printf("thread fork fail\n");
    }

  //创建任务2
    if (thread_fork("task2_task", TASK1_TASK_PRIO, TASK1_STACK_SIZE, TASK1_QUEUE_SIZE, &task2_pid, task2_task, NULL) != OS_NO_ERR) {
        printf("thread fork fail\n");
    }
}

7.8.6. 常见问题

  • 创建静态任务和创建动态任务有什么区别,该如何选择?

答:静态任务创建时采用的是静态内存,而动态任务创建时采用的动态内存。采用静态任务创建可以减小内存碎片;动态任务创建由于会频繁分配和释放内存,容易产生内存碎片。因此系统运行期间都必须存在的任务可采用静态任务创建,而运行周期较短的任务采用动态任务创建,这样一定程度上可以减小内存碎片和内存开销。

  • task_createthread_forkos_task_create 有什么区别,使用场合有哪些不同?

答:task_create创建线程到指定的任务列表的任务中。thread_fork创建的线程如果没有死循环执行完成后就会自动kill。os_task_create创建的线程一定要有死循环,不然概率触发死机重启。

  • 程序运行时出现thread can’t kill! pid : 0x400ce5c,rets_addr = 0x20110e6,怎么解决?如何正确退出线程?

答:出现这个打印是因为对应的线程无法退出导致的,thread_kill会阻塞等待线程退出,通过pid可找到对应的线程,或通过rets_addr地址找到阻塞的位置。需要退出线程时可通过设置标志位的方法,可参考 static_task_test.c 例程,或通过消息队列给对应线程发送特定消息,线程收到该消息后进行退出操作。

7.8.7. API Reference

任务消息类型

Q_MSG

普通消息

Q_EVENT

事件消息

Q_CALLBACK

回调消息

Q_USER

用户消息

信号量、互斥量和队列消息的是否强制删除操作标志

OS_DEL_NO_PEND
OS_DEL_ALWAYS

任务删除标志

OS_TASK_DEL_REQ
OS_TASK_DEL_RES
OS_TASK_DEL_OK

任务归属标志

OS_TASK_SELF
OS_TASK_FATHER
enum kill_mode

enum kill_mode used by thread_kill

Values:

enumerator KILL_WAIT

WAIT

enumerator KILL_REQ

REQUEST

enumerator KILL_FORCE

FORCE ON

void os_init(void)

初始化操作系统

void os_init_tick(int)

初始化操作系统的时钟节拍

void os_start(void)

操作系统开始调度

int os_task_create(void (*func)(void *parm), void *parm, u8 prio, u32 stk_size, int q_size, const char *name)

创建一个任务,任务栈使用动态分配

Parameters
  • func[in] 入口功能函数

  • parm[in] 入口函数的私有指针

  • prio[in] 优先级

  • stk_size[in] 堆栈空间的大小(以四个字节为一个单位)

  • q_size[in] 消息队列空间的大小(以四个字节为一个单位)

  • name[in] 任务名

Returns

0: 成功

Returns

-1: 失败

int os_task_create_static(void (*func)(void *parm), void *parm, u8 prio, u32 stk_size, int q_size, const char *name, u8 *tcb_stk_q)

创建一个任务,任务栈使用静态分配

Parameters
  • func[in] 入口功能函数

  • parm[in] 入口函数的私有指针

  • prio[in] 优先级

  • stk_size[in] 堆栈空间的大小(以四个字节为一个单位)

  • q_size[in] 消息队列空间的大小(以四个字节为一个单位)

  • name[in] 任务名

  • tcb_stk_q[in] 静态内存块(包括任务控制块空间+任务栈空间+消息队列空间)

Returns

0: 成功

Returns

-1: 失败

const char *os_current_task(void)

获取当前任务名

Returns

当前任务名

void os_task_set_priority(const char *task_name, u8 new_priority)

动态调整任务的优先级

Parameters
  • task_name[in] 需要调整的任务名

  • new_priority[in] 调整后的任务优先级

unsigned int os_current_task_prio(void)

获取当前任务的优先级

Returns

当前任务的优先级

unsigned int os_current_task_stask_size(void)

获取当前任务的任务栈大小

Returns

当前任务的任务栈大小

unsigned int os_time_get(void)

获取当前时钟节拍数

Returns

当前时钟节拍数

int os_task_del_req(const char *name)

请求删除任务

Parameters

name[in] 需要删除的任务名

Returns

删除标志tag

int os_task_del_res(const char *name)

响应任务删除请求,标记资源已经释放,可以删除当前任务

Parameters

name[in] 需要删除的任务名,当前任务可以用OS_TASK_SELF

Returns

0: 成功

Returns

-1: 失败

int os_task_del(const char *name)

强制删除任务

Note

任务不能删除自己,需要在其他任务中调用

Parameters

name[in] 需要删除的任务名

Returns

0: 成功

Returns

-1: 失败

void os_time_dly(int time_tick)

延时

Note

不可在中断函数或者临界区调用

Parameters

time_tick[in] 延时节拍,一个tick等于10ms

int __os_taskq_post(const char *name, int type, int argc, int *argv)

发送任务队列消息

Parameters
  • name[in] 消息队列所属任务名

  • type[in] 消息类型

  • argc[in] 消息个数

  • argv[in] 消息数组

Returns

0: 成功

Returns

OS_TASK_NOT_EXIST: 任务不存在

Returns

OS_ERR_POST_NULL_PTR: 任务消息队列不存在

Returns

OS_Q_FULL: 任务消息队列已满

int __os_taskq_pend(int *argv, int argc, int tick)

接收任务队列消息

Parameters
  • tick[in] 等待超时,时钟节拍为单位,取0不等待马上返回

  • argv[in] 可用消息数组

  • argc[in] 可用消息个数

Returns

OS_TASKQ: 成功

Returns

OS_Q_EMPTY: 任务消息队列为空

int __os_taskq_del(const char *name, int type, int argc, int *msg)

删除任务队列的指定某个消息

Parameters
  • name[in] 消息队列所属任务名

  • type[in] 消息类型

  • argv[in] 之前发送的消息个数

  • msg[in] 之前发送的消息

Returns

0: 成功

Returns

OS_TASK_NOT_EXIST: 任务不存在

Returns

OS_ERR_POST_NULL_PTR: 任务消息队列不存在

int os_taskq_pend(const char *fmt, int *argv, int argc)

接收任务队列消息,无限等待

Parameters
  • fmt[in] “taskq”

  • argv[in] 可用消息数组

  • argc[in] 可用消息个数

Returns

OS_TASKQ: 成功

Returns

OS_Q_EMPTY: 任务消息队列为空

int os_taskq_pend_timeout(const char *fmt, int *argv, int argc, int tick)

接收任务队列消息,无限等待

Parameters
  • fmt[in] “taskq”

  • argv[in] 可用消息数组

  • argc[in] 可用消息个数

  • tick[in] 超时tick个数

Returns

OS_TASKQ: 成功

Returns

OS_Q_EMPTY: 任务消息队列为空

int os_taskq_post(const char *name, int argc, ...)

发送任务队列普通消息

Parameters
  • name[in] 消息队列所属任务名

  • argc[in] 消息个数

  • ...[in] 消息可变参数

Returns

0: 成功

Returns

OS_TASK_NOT_EXIST: 任务不存在

Returns

OS_ERR_POST_NULL_PTR: 任务消息队列不存在

Returns

OS_Q_FULL: 任务消息队列已满

int os_taskq_del(const char *name, int type)

删除任务队列的某种类型的所有消息

Parameters
  • name[in] 消息队列所属任务名

  • type[in] 消息类型

Returns

0: 成功

Returns

OS_TASK_NOT_EXIST: 任务不存在

Returns

OS_ERR_POST_NULL_PTR: 任务消息队列不存在

int os_taskq_post_type(const char *name, int type, int argc, int *argv)

发送任务队列消息

Parameters
  • name[in] 消息队列所属任务名

  • type[in] 消息类型

  • argc[in] 消息个数

  • argv[in] 消息数组

Returns

0: 成功

Returns

OS_TASK_NOT_EXIST: 任务不存在

Returns

OS_ERR_POST_NULL_PTR: 任务消息队列不存在

Returns

OS_Q_FULL: 任务消息队列已满

int os_taskq_post_msg(const char *name, int argc, ...)

发送任务队列的普通消息

Parameters
  • name[in] 消息队列所属任务名

  • argc[in] 消息个数

  • ...[in] 消息可变参数

Returns

0: 成功

Returns

OS_TASK_NOT_EXIST: 任务不存在

Returns

OS_ERR_POST_NULL_PTR: 任务消息队列不存在

Returns

OS_Q_FULL: 任务消息队列已满

int os_taskq_flush(void)

重置当前任务的消息队列

Note

需要在当前任务中调用

Returns

0: 成功

Returns

-1: 失败

int os_sem_create(OS_SEM *sem, int cnt)

创建信号量

Parameters
  • sem[in] 信号量

  • cnt[in] 初始计数值

Returns

0: 成功

Returns

-1: 失败

int os_sem_pend(OS_SEM *sem, int timeout)

等待信号量

Note

不可在中断函数或者临界区调用

Parameters
  • sem[in] 信号量

  • timeout[in] 等待超时(时钟节拍),取0时无限等待,不堵塞请使用os_sem_accept

Returns

0: 成功

Returns

OS_TIMEOUT: 等待超时

int os_sem_accept(OS_SEM *sem)

获取信号量(非堵塞)

Note

不可在中断函数或者临界区调用

Parameters

sem[in] 信号量

Returns

0: 成功

Returns

OS_TIMEOUT: 获取失败

int os_sem_post(OS_SEM *sem)

发送信号量

Parameters

sem[in] 信号量

Returns

0: 成功

Returns

-EFAULT: 失败

int os_sem_del(OS_SEM *sem, int force)

删除信号量

Parameters
  • sem[in] 信号量

  • force[in] 是否强制删除

Returns

0: 成功

Returns

-1: 失败

int os_sem_set(OS_SEM *sem, u16 cnt)

设置信号量的计数值

Parameters
  • sem[in] 信号量

  • cnt[in] 计数值

Returns

0: 成功

Returns

-1: 失败

int os_sem_valid(OS_SEM *sem)

检查信号量是否合法

Parameters

sem[in] 信号量

Returns

1: 有效

Returns

0: 非法

int os_sem_query(OS_SEM *sem)

检查信号量是否空闲

Parameters

sem[in] 信号量

Returns

1: 没有其他线程在等待此信号量

Returns

0: 其他线程在等待此信号量

int os_mutex_create(OS_MUTEX *mutex)

创建互斥量

Parameters

mutex[in] 互斥量

Returns

0: 成功

Returns

-1: 失败

int os_mutex_pend(OS_MUTEX *mutex, int timeout)

等待互斥量

Note

不可在中断函数或者临界区调用

Parameters
  • mutex[in] 互斥量

  • timeout[in] 等待超时(时钟节拍),取0时无限等待,非堵塞请使用os_mutex_accept

Returns

0: 成功

Returns

OS_TIMEOUT: 等待超时

int os_mutex_accept(OS_MUTEX *mutex)

获取互斥量(非堵塞)

Note

不可在中断函数或者临界区调用

Parameters

mutex[in] 互斥量

Returns

0: 成功

Returns

OS_TIMEOUT: 获取失败

int os_mutex_post(OS_MUTEX *mutex)

释放互斥量

Note

不可在中断函数或者临界区调用

Parameters

mutex[in] 互斥量

Returns

0: 成功

Returns

-EFAULT: 失败

int os_mutex_del(OS_MUTEX *mutex, int force)

删除互斥量

Note

不可在中断函数或者临界区调用

Parameters
  • mutex[in] 互斥量

  • force[in] 是否强制删除

Returns

0: 成功

Returns

-1: 失败

int os_mutex_valid(OS_MUTEX *mutex)

检查互斥量是否合法

Parameters

mutex[in] 互斥量

Returns

1: 有效

Returns

0: 非法

int os_q_create(OS_QUEUE *pevent, QS size)

创建消息队列,内存采用动态分配

Parameters
  • pevent[in] 消息队列

  • size[in] 消息队列大小,以word为单位

Returns

0: 成功

Returns

-1: 失败

int os_q_create_static(OS_QUEUE *pevent, void *storage, QS size)

创建消息队列,内存采用静态分配

Parameters
  • pevent[in] 消息队列

  • storage[in] 队列消息内存块

  • size[in] 消息队列大小,以word为单位

Returns

0: 成功

Returns

-1: 失败

int os_q_del_static(OS_QUEUE *pevent, u8 force)

删除消息队列

Note

与os_q_create_static搭配使用

Parameters
  • pevent[in] 消息队列

  • force[in] 是否强制删除

Returns

0: 成功

Returns

-1: 失败

int os_q_del(OS_QUEUE *pevent, u8 force)

删除消息队列

Note

与os_q_create搭配使用

Parameters
  • pevent[in] 消息队列

  • force[in] 是否强制删除

Returns

0: 成功

Returns

-1: 失败

int os_q_flush(OS_QUEUE *pevent)

重置消息队列

Parameters

pevent[in] 消息队列

Returns

0: 成功

Returns

-1: 失败

int os_q_pend(OS_QUEUE *pevent, int timeout, void *msg)

接收队列消息

Note

不可在中断函数或者临界区调用

Parameters
  • pevent[in] 消息队列

  • timeout[in] 等待超时(时钟节拍),取0时无限等待,非堵塞请使用os_q_accept

  • msg[out] 接收到的消息

Returns

0: 成功

Returns

OS_TIMEOUT: 等待超时

int os_q_accept(OS_QUEUE *pevent, void *msg)

获取队列消息(非堵塞)

Note

不可在中断函数或者临界区调用

Parameters
  • pevent[in] 消息队列

  • msg[out] 接收到的消息

Returns

0: 成功

Returns

OS_TIMEOUT: 获取失败

int os_q_post(OS_QUEUE *pevent, void *msg)

发送队列消息

Note

不可在中断函数或者临界区调用

Parameters
  • pevent[in] 消息队列

  • msg[in] 要发送的消息

Returns

0: 成功

Returns

OS_Q_FULL: 消息队列已满

int os_q_peek(OS_QUEUE *pevent, void *msg, int timeout_ms)

查看队列消息,不取出来

Parameters
  • pevent[in] 消息队列

  • msg[out] 接收到的消息

  • timeout[in] 等待超时(单位是毫秒),取-1时无限等待,取0时不等待

Returns

0: 成功

Returns

OS_TIMEOUT: 等待超时

int os_q_recv(OS_QUEUE *pevent, void *msg, int timeout_ms)

接收队列消息

Parameters
  • pevent[in] 消息队列

  • msg[out] 接收到的消息

  • timeout[in] 等待超时(单位是毫秒),取-1时无限等待,取0时不等待

Returns

0: 成功

Returns

OS_TIMEOUT: 等待超时

int os_q_post_to_back(OS_QUEUE *pevent, void *msg, int timeout_ms)

发送队列消息到队列最后面

Parameters
  • pevent[in] 消息队列

  • msg[in] 要发送的消息

  • timeout[in] 等待超时(单位是毫秒),取-1时无限等待,取0时不等待

Returns

0: 成功

Returns

OS_Q_FULL: 消息队列已满

int os_q_post_to_front(OS_QUEUE *pevent, void *msg, int timeout_ms)

发送队列消息到队列最前面

Parameters
  • pevent[in] 消息队列

  • msg[in] 要发送的消息

  • timeout[in] 等待超时(单位是毫秒),取-1时无限等待,取0时不等待

Returns

0: 成功

Returns

OS_Q_FULL: 消息队列已满

int os_q_query(OS_QUEUE *pevent)

查询消息列是否空闲

Parameters

pevent[in] 消息队列

Returns

1: 没有其他线程在等待此消息队列

Returns

0: 其他线程在等待此消息队列

int os_q_valid(OS_QUEUE *pevent)

检查消息队列是否合法

Parameters

pevent[in] 互斥量

Returns

1: 有效

Returns

0: 非法

int os_q_is_full(OS_QUEUE *pevent)

检查消息队列是否已满

Parameters

pevent[in] 互斥量

Returns

1: 消息队列已满

Returns

0: 消息队列未满

int os_eventgroup_create(OS_EVENT_GRP **event, u32 flags)

创建事件组

Parameters
  • event[in] 保存创建成功后的事件组指针

  • flags[in] 事件标志

Returns

0: 成功

Returns

-1: 失败

int os_eventgroup_delete(OS_EVENT_GRP *event, u8 force)

删除事件组

Parameters
  • event[in] 事件组指针

  • force[in] 是否强制删除

Returns

0: 成功

Returns

-1: 失败

int os_eventgroup_set_bits(OS_EVENT_GRP *event, int bits)

事件组置位

Parameters
  • event[in] 事件组指针

  • bits[in] 事件标志

Returns

当前事件标志位

int os_eventgroup_clear_bits(OS_EVENT_GRP *event, int bits)

清除事件组标志位

Parameters
  • event[in] 事件组指针

  • bits[in] 事件标志

Returns

当前事件标志位

int os_eventgroup_wait_bits(OS_EVENT_GRP *event, int bits, int isClearOnExit, int isWaitForAllBits, int waitms)

等待事件组标志位

Parameters
  • event[in] 事件组指针

  • bits[in] 等待的事件标志

  • isClearOnExit[in] 是否清掉等待成功的标志

  • isWaitForAllBits[in] 是否等待指定的所有标志位

  • waitms[in] 等待延时,毫秒

Returns

当前事件标志位

int os_tasks_num_query(void)

当前操作系统的任务总数

Returns

任务个数

void os_task_suspend_all(const char (*Otherwise)[64], int array_num)

挂起所有任务,某些任务除外

Note

不可在中断函数或者临界区调用

Parameters
  • Otherwise[in] 不需要挂起的任务名(数组实现多个)

  • array_num[in] 除外的任务个数

void os_task_resume_all(void)

恢复所有任务

Note

不可在中断函数或者临界区调用

void os_task_resume(const char *name)

恢复任务

Note

不可在中断函数或者临界区调用

Parameters

name[in] 需要恢复的任务名

void os_task_suspend(const char *name)

挂起任务

Note

不可在中断函数或者临界区调用

Parameters

name[in] 需要挂起的任务名

int thread_fork_init(void)

创建thread_fork_kill线程

Note

该线程用来Kill掉其他线程,其任务优先级最高

Returns

0: 成功

Returns

other: enum OS_ERROR_CODES

int thread_rpc(int (*condition)(void), const char *thread_name, int prio, int stk_size, u32 q_size, int *pid, void (*func)(void*), void *parm, void (*thread_complete_cb)(void*), void *thread_complete_cb_parm)

创建一个线程(扩展接口)

Note

由于系统靠thread_name区分不同任务,所以请保证thread_name的唯一

Note

replace pthread_create function

Parameters
  • condition[in] 线程开始运行的前提条件(条件回调返回非0值开始运行)

  • thread_name[in] 标识此线程的字符串

  • prio[in] 优先级

  • stk_size[in] 堆栈空间的大小(以四个字节为一个单位)

  • q_size[in] 消息队列空间的大小(以四个字节为一个单位)

  • pid[out] 保存新线程的pid

  • func[in] 入口功能函数

  • parm[in] 入口函数的传入参数

  • thread_complete_cb[in] 线程结束回调

  • thread_complete_cb_parm[in] 线程结束回调的传入参数

Returns

0: 成功

Returns

-1: 参数错误

Returns

other: enum OS_ERROR_CODES

int thread_fork(const char *thread_name, int prio, int stk_size, u32 q_size, int *pid, void (*func)(void*), void *parm)

创建一个线程

Note

由于系统靠thread_name区分不同任务,所以请保证thread_name的唯一

Note

replace pthread_create function

Parameters
  • thread_name[in] 标识此线程的字符串

  • prio[in] 优先级

  • stk_size[in] 堆栈空间的大小(以四个字节为一个单位)

  • q_size[in] 消息队列空间的大小(以四个字节为一个单位)

  • pid[out] 保存新线程的pid

  • func[in] 入口功能函数

  • parm[in] 入口函数的传入参数

Returns

0: 成功

Returns

-1: 参数错误

Returns

other: enum OS_ERROR_CODES

void thread_kill(volatile int *pid, enum kill_mode mode)

杀死一个线程

Note

推荐使用KILL_WAIT

Note

replace pthread_kill function

Parameters
  • pid[in] 指向需要杀死的pid号的指针

  • mode[in] enum kill_mode

Returns

0: 成功

Returns

-1: 参数错误

Returns

other: enum OS_ERROR_CODES

int thread_kill_req(void)

获取正在运行的线程是否有其他线程请求自己杀死

Note

Returns

0: 没有杀死请求

Returns

1: 有杀死请求

int *get_cur_thread_pid(void)

获取指向当前线程pid的指针

Note

Returns

指向当前线程pid的指针

void udelay(unsigned int t)

微秒级延时函数

Note

TODO

Parameters

t[in] us

void mdelay(unsigned int ms)

毫秒级延时函数

Note

不可在中断函数或者临界区调用

Parameters

ms[in] ms

void msleep(unsigned int ms)

毫秒级延时函数

Note

不可在中断函数或者临界区调用

Parameters

ms[in] ms

int sema_init(int *sem, int cnt)

初始化信号量

Note

Parameters
  • sem[out] 保存新建信号量的信息

  • cnt[in] 计数器的初始值

Returns

enum OS_ERROR_CODES

int sem_pend(int *sem, unsigned int timeout)

等待信号量

Note

不可在中断函数或者临界区调用

Parameters
  • sem[in] 指向需要等待的信号量的指针

  • timeout[in] 等待超时(时钟节拍),取0时无限等待,取-1时不等待

Returns

enum OS_ERROR_CODES

int sema_post(int *sem)

发送信号量

Parameters

sem[in] 指向需要发送的信号量的指针

Returns

enum OS_ERROR_CODES

int sem_set(int *sem, int init_val)

设置信号量的计数器的值

Parameters
  • sem[in] 指向需要设置的信号量的指针

  • init_val[in] 计数器的设置值

Returns

enum OS_ERROR_CODES

int sem_del(int *sem)

销毁信号量

Note

不可在中断函数或者临界区调用

Parameters

sem[in] 指向需要销毁的信号量的指针

Returns

enum OS_ERROR_CODES

int sem_query(int *sem)

查询信号量计数值

Parameters

sem[in] 指向需要查询的信号量的指针

Returns

enum OS_ERROR_CODES

int sem_valid(int *sem)

检测信号量是否有效

Parameters

sem[in] 指向需要查询的信号量的指针

Returns

1: 有效

Returns

0: 非法