更新时间:2024-11-20 02:14:51下载pdf
教程主要介绍和 Tuya IoT OS API 相关的函数接口,内容主要包括:
Log 打印和错误码介绍
线程
软件定时器
内存管理
信号量
互斥量
队列
本文 Github 仓库地址:https://github.com/Tuya-Community/tuya-os-api-examples
如何编译这些 examples 呢?
下面以编译 log_print_demo 为例进行演示。
错误码的作用:当在 SDK 开发过程中遇到程序执行错误的时,可以根据返回的错误码判断程序出现的问题。
错误码的位置:在 tuya_iot_sdk 下的 /sdk/include/tuya_error_code.h
中找到对应的 error code。
log 日志存放位置:在 tuya iot sdk 中和日志相关的文件为 uni_log.h
,该文件位置通常在 tuya_iot_sdk 下的 /sdk/include/uni_log.h
。
日志打印接口和日志等级接口: log 打印中常用到的函数接口为日志打印接口和日志等级接口。日志打印接口可以根据输出信息的等级不同选择不同的打印接口,还可以通过修改 log 输出等级从而控制不同等级信息的输出;同时可以用日志等级接口设置调整打印输出等级,SDK 中默认的日志等级为 DEBUG
,打印输出的东西越多系统占用的资源也就越多,会拖慢系统运行的速度和占用更多的内存,所以在功能开发完成后的正式版本中建议将日志等级设置为 NOTICE
。
日志打印接口如下:
函数接口 | 函数说明 |
---|---|
PR_ERR(fmt, ...) |
用于打印错误信息,程序正常运行不应发生的信息 |
PR_WARN(fmt, ...) |
用于打印警告信息 |
PR_NOTICE(fmt, ...) |
用于打印需要注意的信息 |
PR_INFO(fmt, ...) |
用于打印通知信息 |
PR_DEBUG(fmt, ...) |
用于打印程序运行调试信息 |
PR_TRACE(fmt, ...) |
用于打印程序运行路径信息 |
日志等级接口如下:
OPERATE_RET SetLogManageAttr(IN CONST LOG_LEVEL curLogLevel);
设置 log 日志输出等级,等级越高输出信息越多。也就是说如果日志等级设置为
TY_LOG_LEVEL_TRACE
就会打印所有信息,设置为TY_LOG_LEVEL_NOTICE
则只会打印NOTICE
,WARN
,ERR
三种日志信息。
Parameters:
curLogLevel
: 设置的 log 等级。可设置值为:
#define TY_LOG_LEVEL_ERR 0
#define TY_LOG_LEVEL_WARN 1
#define TY_LOG_LEVEL_NOTICE 2
#define TY_LOG_LEVEL_INFO 3
#define TY_LOG_LEVEL_DEBUG 4
#define TY_LOG_LEVEL_TRACE 5
Return:
OPRT_OK
: 函数执行成功other
: 函数执行失败日志打印和设置不同日志等级的输出情况示例:根据执行的日志截图可以发现,当把日志等级设置为 TY_LOG_LEVEL_NOTICE
时,只有PR_NOTICE
, PR_WARN
和 PR_ERR
可以打印出来,而其他三个无法输出;当把日志等级设置为 TY_LOG_LEVEL_DEBUG
时,只有 PR_DEBUG
, PR_INFO
, PR_NOTICE
, PR_WARN
和 PR_ERR
可以打印出来,而PR_TRACE
无法输出。
void log_printf_demo(void)
{
PR_NOTICE("*************************************************");
SetLogManageAttr(TY_LOG_LEVEL_NOTICE);
PR_NOTICE("log level is NOTICE");
PR_ERR("This is error log");
PR_WARN("This is warn log");
PR_NOTICE("This is notice log");
PR_INFO("This is info log");
PR_DEBUG("This is debug log");
PR_TRACE("This is trace log");
PR_NOTICE("*************************************************");
SetLogManageAttr(TY_LOG_LEVEL_DEBUG);
PR_NOTICE("log level is DEBUG");
PR_ERR("This is error log");
PR_WARN("This is warn log");
PR_NOTICE("This is notice log");
PR_INFO("This is info log");
PR_DEBUG("This is debug log");
PR_TRACE("This is trace log");
PR_NOTICE("*************************************************");
}
线程的文件位置:在 tuya_iot_sdk 下的 /sdk/include/tuya_hal_thread.h
。
在 TuyaOS 中与线程相关的函数主要有四个接口可用,创建线程
tuya_hal_thread_create()
,释放线程 tuya_hal_thread_release()
,检查线程是否是本身 tuya_hal_thread_is_self()
和设置自身线程名称
tuya_hal_thread_set_self_name()
。
int tuya_hal_thread_create(THREAD_HANDLE* thread,
const char* name,
uint32_t stack_size,
uint32_t priority,
THREAD_FUNC_T func,
void* const arg);
在 TuyaOS 中最常使用的便是该函数了,该函数的功能是用来创建一个线程。
Parameters:
thread
: [out]线程句柄。
name
: 线程的名字。
stack_size
: 线程的栈大小,单位:bit。
priority
: 线程的优先级。
/* 这些关于优先级的宏定义在 /sdk/include/uni_thread.h 中,所以使用它们的时候,注意添加 uni_thread.h 的头文件 */
#define TRD_PRIO_0 5 /* High */
#define TRD_PRIO_1 4
#define TRD_PRIO_2 3
#define TRD_PRIO_3 2
#define TRD_PRIO_4 1
#define TRD_PRIO_5 0
#define TRD_PRIO_6 0 /* low */
func
: 线程入口函数。
arg
: 线程入口函数的参数,可以为NULL
。
Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。int tuya_hal_thread_release(THREAD_HANDLE thread);
释放创建的线程。
Parameters:
thread
: 线程句柄。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。int tuya_hal_thread_is_self(THREAD_HANDLE thread, BOOL_T* is_self);
用于判断当前执行线程是否为
thread
线程。
Parameters:
thread
: 线程句柄。is_self
: [out] is_self == 1
当前执行的线程是 thread
(这里的 thread 是指调用该函数时具体输入的线程句柄,而并非真的就是 thread
);is_self == 0
当前执行的线程不是 thread
。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。int tuya_hal_thread_set_self_name(const char* name);
更改自身线程的名字。
Parameters:
name
: 该线程要设置的名字。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。实际开发中创建线程和释放线程函数比较常用,检查线程是否是本身和设置自身线程名称函数使用较少。下面 Demo 主要演示如何创建和释放线程:
在 Demo 中创建了名叫 thread demo
的线程,该线程的作用是打印运行提示和线程运行的计数值 thread_demo_count
,当计数大于10的时会将 thread demo
线程释放掉,不会再打印。
#include "uni_log.h"
#include "uni_thread.h"
#include "tuya_error_code.h"
#include "tuya_hal_system.h"
#include "thread_demo.h"
THREAD_HANDLE thread_demo_handle = NULL;
static thread_demo_count = 0;
void thread_demo_task_func(void)
{
OPERATE_RET op_ret = OPRT_OK;
for (;;) {
PR_NOTICE("thread demo is running, count: %d", thread_demo_count);
if (thread_demo_count >= 10) {
break;
}
thread_demo_count++;
tuya_hal_system_sleep(1000);
}
PR_NOTICE("thread demo task will release");
op_ret = tuya_hal_thread_release(thread_demo_handle);
if (OPRT_OK != op_ret) {
PR_ERR("release thread demo task failed, err_num:%d", op_ret);
return;
}
}
void thread_demo_init(void)
{
OPERATE_RET op_ret = OPRT_OK;
op_ret = tuya_hal_thread_create(&thread_demo_handle, "thread demo", 64*8, TRD_PRIO_4, thread_demo_task_func, NULL);
if (op_ret != OPRT_OK) {
PR_ERR("creat thread demo task failed, err_num:%d", op_ret);
return;
}
}
软件定时器的文件位置:在 tuya_iot_sdk 下的 /sdk/include/sys_timer.h
。
在 TuyaOS 中与软件定时器相关的接口一共有 12 个,下面对其进行简单的分类介绍。
第一部分:软件定时器的初始化和释放。
第二部分:软件定时器的常用功能。如软件定时器的添加、启动、停止、删除和判断软件定时器是否在运行。
第三部分: TuyaOS 软件定时器的其他功能。如触发一个软件定时器、得到软件定时器的个数、得到和设置软件定时器的休眠间隔和设置软件定时器的栈大小。
软件定时器的初始化在 SDK 中就已经完成,后续建议不要再对软件定时器进行初始化和释放,以下两个函数在开发过程中一般无需调用。
system_timer_init()
OPERATE_RET system_timer_init(void);
软件定时器初始化。 SDK 启动过程中已经完成初始化,用户在使用过程中不用再次进行初始化。
Parameters:
Return:
OPRT_OK
: 函数执行成功。
other
: 函数执行失败。
system_timer_release()
OPERATE_RET system_timer_release(void);
释放软件定时器的资源。该接口与
system_timer_init
相对应的。
Parameters:
Return:
OPRT_OK
: 函数执行成功。
other
: 函数执行失败。
以下函数接口在实际开发中使用频率较高。
sys_add_timer()
OPERATE_RET sys_add_timer(IN CONST P_TIMER_FUNC pTimerFunc,\
IN CONST PVOID_T pTimerArg,\
OUT TIMER_ID *p_timerID);
添加一个软件定时器。
Parameters:
pTimerFunc
: 回调函数。pTimerArg
: 回调函数参数。p_timerID
: [OUT]软件定时器ID。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。sys_start_timer()
OPERATE_RET sys_start_timer(IN CONST TIMER_ID timerID,\
IN CONST TIME_MS timeCycle,\
IN CONST TIMER_TYPE timer_type);
启动一个软件定时器。
Parameters:
timerID
: 软件定时器 ID。timeCycle
: 定时时间,单位:MS。timer_type
: 定时器类型,可通过这里配置定时器是单次模式 TIMER_ONCE
,还是循环模式 TIMER_CYCLE
。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。sys_stop_timer()
OPERATE_RET sys_stop_timer(IN CONST TIMER_ID timerID);
停止一个定时器。与删除不同的是,定时器停止后可以使用
sys_start_timer()
而不用添加定时器就再次启动该定时器,当然相关资源的占用依然存在。
Parameters:
timerID
: 软件定时器ID。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。sys_delete_timer()
OPERATE_RET sys_delete_timer(IN CONST TIMER_ID timerID);
删除一个定时器。删除后,如果想要再次启动该定时器,需要先使用
sys_add_timer()
成功添加定时器,才能再次启动。
Parameters:
timerID
: 软件定时器 ID 。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。IsThisSysTimerRun()
BOOL_T IsThisSysTimerRun(IN CONST TIMER_ID timer_id);
判断一个定时器是否在运行。
Parameters:
timer_id
: 软件定时器 ID 。Return:
TRUE
: 定时器在运行。FAIL
: 定时器没有在运行。应用示例功能说明:添加并启动一个软件定时器,等到软件定时器执行10次后,关闭软件定时器。
#include "software_timer.h"
#include "uni_log.h"
#include "uni_thread.h"
#include "sys_timer.h"
TIMER_ID my_timer_id;
static int sw_run_count = 0;
void my_timer_cb(UINT_T timerID, PVOID_T pTimerArg)
{
OPERATE_RET op_ret = OPRT_OK;
PR_NOTICE("------this is timer %d callback, count: %d", timerID, sw_run_count);
sw_run_count++;
if (sw_run_count >= 10) {
if (IsThisSysTimerRun(my_timer_id)) {
op_ret = sys_stop_timer(my_timer_id);
if (OPRT_OK != op_ret) {
PR_ERR("sys stop timer failed, error code %d", op_ret);
return;
}
PR_NOTICE("timer %d is stop.", my_timer_id);
}
}
}
void sw_timer_task(void)
{
OPERATE_RET op_ret = OPRT_OK;
op_ret = sys_add_timer(my_timer_cb, NULL, &my_timer_id);
if (OPRT_OK != op_ret) {
PR_ERR("sys add timer failed, error code %d", op_ret);
return;
}
PR_NOTICE("timer add success, timer id: %d.", my_timer_id);
op_ret = sys_start_timer(my_timer_id, 2000, TIMER_CYCLE);
if (OPRT_OK != op_ret) {
PR_ERR("sys start timer failed, error code %d", op_ret);
return;
}
PR_NOTICE("timer %d start success.", my_timer_id);
}
以下函数接口使用频率较低,可做了解。
sys_trigger_timer()
OPERATE_RET sys_trigger_timer(IN CONST TIMER_ID timerID);
立刻触发该定时器。
Parameters:
timerID
: 软件定时器 ID 。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。sys_get_timer_num()
INT_T sys_get_timer_num(void);
得到当前活跃的软件定时器个数(启动的定时器个数,停止和删除的定时器不算)。
Parameters:
Return:
system_timer_get_sleep_interval()
ULONG_T system_timer_get_sleep_interval(VOID);
获取定时器的最小间隔。
Parameters:
Return:
system_timer_set_sleep_interval()
VOID system_timer_set_sleep_interval(ULONG_T interval);
设置定时的最小休眠间隔。
Parameters:
interval
: 要设置的最小睡眠间隔。Return:
system_timer_cfg_stack_size()
OPERATE_RET system_timer_cfg_stack_size(UINT_T stack_size);
设置软件定时器的栈大小。一般默认即可,非必要不要进行修改。
Parameters:
stack_size
: 配置软件定时器的栈大小。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。内存管理的文件位置:在 tuya_iot_sdk 下的
/sdk/include/tuya_hal_memory.h
。
TuyaOS 中关于内存管理的 API 特别简单,只有申请和释放两个。
VOID_T *tuya_hal_system_malloc(CONST SIZE_T size);
用于分配内存。
Parameters:
size
: 要申请的栈空间大小。Return:
NULL
: 内存申请失败。other
: 内存成功申请到的地址。VOID_T tuya_hal_system_free(VOID_T* ptr);
释放申请到的内存。
Parameters:
ptr
: 需要释放的内存指针。Return:
NULL
应用示例说明:演示内存申请和释放函数的使用方法。在 Demo 中会申请3个 int 的内存大小,然后把前两个进行赋值,打印申请到的地址和内存中存的数据。
OPERATE_RET device_init(VOID)
{
int *str;
PR_NOTICE("******************** memory demo begin ********************");
str = tuya_hal_system_malloc(5*sizeof(int));
if (NULL == str) {
PR_ERR("tuya_hal_system_malloc is error");
return;
}
PR_NOTICE("memset");
memset(str, 0, 5*sizeof(int));
str[0] = 300;
str[1] = 200;
PR_NOTICE("str address: %x", str);
PR_NOTICE("str[0]:%d, str[1]:%d, str[2]:%d", str[0], str[1], str[2]);
if (NULL != str) {
PR_NOTICE("memory will free");
tuya_hal_system_free(str);
str = NULL;
PR_NOTICE("******************** memory demo end ********************");
}
return OPRT_OK;
}
信号量的文件位置:在 tuya_iot_sdk 下的 /sdk/include/tuya_hal_semaphore.h
。
信号量常用于对共享资源的访问控制和任务同步。
INT_T tuya_hal_semaphore_create_init(SEM_HANDLE *pHandle, CONST UINT_T semCnt, CONST UINT_T sem_max);
创建并初始化一个信号量。
Parameters:
pHandle
: [OUT] 信号量句柄。semCnt
: 开始时的信号量个数。sem_max
: 信号量的最大个数。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。INT_T tuya_hal_semaphore_release(CONST SEM_HANDLE semHandle);
释放一个信号量的资源,与
tuya_hal_semaphore_create_init()
函数相对应。
Parameters:
semHandle
: 要释放资源的信号量句柄。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。INT_T tuya_hal_semaphore_wait(CONST SEM_HANDLE semHandle);
等待一个信号量。调用该函数会消耗一个信号量(信号量-1),如果信号量为 0 时调用就会阻塞信号量(信号量不能为负的)。
Parameters:
semHandle
: 信号量句柄。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。INT_T tuya_hal_semaphore_waittimeout(CONST SEM_HANDLE semHandle, unsigned int timeout);
等待一个信号量,带有超时功能。和其它函数不同的是,此函数多一个超时设定,当函数发生阻塞时不会等待信号量到达,超过时间就不再阻塞等待。
Parameters:
semHandle
: 信号量句柄。timeout
: 等待超时时间。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。INT_T tuya_hal_semaphore_post(CONST SEM_HANDLE semHandle);
放入一个信号量。(信号量+1)
Parameters:
semHandle
: 信号量句柄。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。需要关注的是 tuya_hal_semaphore_create_init( )
和
tuya_hal_semaphore_release()
两个函数。 creat 函数创建信号量, release 函数则是在信号量使用完成后释放信号量,进行删除。
应用示例说明:创建两个任务,分别为创建一个信号量并每 5s post 一个信号量;和等待信号量,并在接收到信号量后打印 hello 字样。
#include "sem.h"
#include "uni_log.h"
#include "uni_thread.h"
#include "tuya_hal_system.h"
#include "tuya_hal_semaphore.h"
SEM_HANDLE my_sem;
void sem_wait_task_handle(void)
{
for (;;) {
tuya_hal_semaphore_wait(my_sem);
PR_NOTICE("HELLO");
}
}
void sem_release_task_handle(void)
{
tuya_hal_semaphore_create_init(&my_sem, 0, 1);
for (;;) {
tuya_hal_semaphore_post(my_sem);
PR_NOTICE("sem is posted.");
tuya_hal_system_sleep(5000);
}
}
void sem_task_init(void)
{
tuya_hal_thread_create(NULL, "sem release", 64*8, TRD_PRIO_5, sem_release_task_handle, NULL);
tuya_hal_thread_create(NULL, "sem wait", 64*8, TRD_PRIO_5, sem_wait_task_handle, NULL);
}
互斥量的文件位置:在 tuya_iot_sdk 下的 /sdk/include/tuya_hal_mutex.h
。
互斥量也叫互斥型信号量,和二值型信号量类似,但互斥型信号量用于资源保护,能避免出现优先级反转现象。
OPERATE_RET tuya_hal_mutex_create_init(MUTEX_HANDLE *pMutexHandle);
创造并初始化一个互斥量。
Parameters:
pMutexHandle
: [OUT] 互斥量句柄。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。OPERATE_RET tuya_hal_mutex_release(const MUTEX_HANDLE mutexHandle);
释放一个信号量的资源(与
tuya_hal_mutex_create_init()
相对应)。
Parameters:
mutexHandle
: 信号量句柄。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。OPERATE_RET tuya_hal_mutex_lock(const MUTEX_HANDLE mutexHandle);
互斥量上锁。
Parameters:
mutexHandle
: 信号量句柄。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。OPERATE_RET tuya_hal_mutex_unlock(const MUTEX_HANDLE mutexHandle);
互斥量解锁。
Parameters:
mutexHandle
: 信号量句柄。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。应用示例说明:创建两个任务,使两个使用互斥量进行一些打印输出。
#include "mutex.h"
#include "uni_log.h"
#include "tuya_hal_mutex.h"
#include "uni_thread.h"
#include "tuya_hal_system.h"
#include "tuya_hal_thread.h"
MUTEX_HANDLE my_mutex;
int demo_value = 0;
void task_1_handle(void)
{
for (;;) {
PR_NOTICE("task 1 wait unlock");
tuya_hal_mutex_lock(my_mutex);
PR_NOTICE("task 1 lock");
demo_value = demo_value + 2;
PR_NOTICE("task 1 demo value:%d", demo_value);
tuya_hal_system_sleep(3000);
tuya_hal_mutex_unlock(my_mutex);
PR_NOTICE("task 1 unlock");
tuya_hal_system_sleep(100);
}
}
void task_2_handle(void)
{
for (;;) {
PR_NOTICE("task 2 wait unlock");
tuya_hal_mutex_lock(my_mutex);
PR_NOTICE("task 2 lock");
demo_value--;
PR_NOTICE("task 2 demo value:%d", demo_value);
tuya_hal_system_sleep(5000);
tuya_hal_mutex_unlock(my_mutex);
PR_NOTICE("task 2 unlock");
tuya_hal_system_sleep(100);
}
}
void mutex_task_init(void)
{
tuya_hal_mutex_create_init(&my_mutex);
tuya_hal_thread_create(NULL, "task 1", 64*8, TRD_PRIO_5, task_1_handle, NULL);
tuya_hal_thread_create(NULL, "task 2", 64*8, TRD_PRIO_5, task_2_handle, NULL);
}
通过下面的日志可以发现,在 task 2 上锁的时候, task 1 会先等待互斥量解锁,等 task 1 一解锁便马上开始下面的操作。
队列的文件位置:在 tuya_iot_sdk 下的 /sdk/include/uni_queue.h
。
创建队列时需要设定队列深度(队列可以保存的最大单元数目)和每个单元的大小,队列的规则是先进先出。
下面将对 TuyaOS 中和队列功能相关的 API 函数接口进行分类介绍:
第一部分:队列的创建和释放(去初始化)。
第二部分:队列的最基本的功能,入队列和出队列。
第三部分:其他一些函数功能的介绍。如得到队列的剩余空间、得到当前队列中的入列数、清空队列和删除队列中的部分数。
CreateQueueObj()
P_QUEUE_CLASS CreateQueueObj(const unsigned int queTolNum, const unsigned int queUnitSize);
创建一个队列。
Parameters:
queTolNum
: 队列的个数。queUnitSize
:队列中单个数占用的内存大小。Return:
NULL
: 队列创建失败。other
: 队列创建成功,返回创建的队列的地址。** ReleaseQueueObj()**
void ReleaseQueueObj(P_QUEUE_CLASS pQueObj);
释放一个队列,和
CreateQueueObj
相对应。
Parameters:
pQueObj
: 要释放队列。Return:
NULL
队列的基本功能
** InQueue()**
unsigned char InQueue(P_QUEUE_CLASS pQueObj, const unsigned char *pQueUnit, const unsigned int queNum);
数据入队。
Parameters:
pQueObj
: 要入队的目标队列。pQueUnit
: 要入队的数据首地址。queNum
: 要入队数据个数。Return:
1
: 函数执行成功。other
: 函数执行失败。OutQueue()
unsigned char OutQueue(P_QUEUE_CLASS pQueObj,unsigned char *pQueUnit, const unsigned int queNum);
数据出队。
Parameters:
pQueObj
: 要出队的队列。pQueUnit
: 出队数据存放的空间地址。queNum
: 要出队的数据个数。Return:
1
: 函数执行成功。other
: 函数执行失败。GetQueueMember()
unsigned char GetQueueMember(P_QUEUE_CLASS pQueObj, const unsigned int start, unsigned char *pQueUnit, const unsigned int queNum);
得到队列中的数据。该函数和出队不同的是可以从任何位置开始获取指定长度的数据,获取完成后并不会导致获取到的数据丢失。
Parameters:
pQueObj
: 要操作的队列。start
: 获取数据的开始。从首个数据开始的话就填1。pQueUnit
: 获取到的数据存放的buffer地址。queNum
: 获取数据的个数。Return:
1
: 函数执行成功。other
: 函数执行失败。unsigned int GetCurQueNum(P_QUEUE_CLASS pQueObj);
得到当前队列中数据的个数。
Parameters:
pQueObj
: 要操作的队列。Return:
1
: 函数执行成功。other
: 函数执行失败。GetCurFreeQueNum()
unsigned int GetCurFreeQueNum(P_QUEUE_CLASS pQueObj);
得到当前队列中空闲个数。
Parameters:
pQueObj
: 要操作的队列。Return:
1
: 函数执行成功。other
: 函数执行失败。unsigned char DelQueueMember(P_QUEUE_CLASS pQueObj, const unsigned int queNum);
删除队列中指定数目的数据。
Parameters:
pQueObj
: 要操作的队列。queNum
: 删除的数据个数Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。ClearQueue()
unsigned char ClearQueue(P_QUEUE_CLASS pQueObj);
清空队列中的数据。
Parameters:
pQueObj
: 要操作的队列。Return:
OPRT_OK
: 函数执行成功。other
: 函数执行失败。队列一般用在进程间通信,为了方便我们将所有队列的功能放在一个线程进行演示。
Demo 创建了有 5 个单元,每个单元大小为 int 的队列,打印当前队列已经使用的单元个数和未使用的单元个数。随后队列入了8个数,并打印出队列当前剩余(未使用)的单元个数。队列出一个数,打印输出数的值和剩余单元个数。得到队列从第一个单元开始的4个单元的数值,输出这4个单元的数值和剩余单元的个数,可以发现的是通过
GetQueueMember()
和出列不同的是使用出列输出数值后,对应的剩余单元也会增加,而调用 GetQueueMember()
拿到的数值不会改变剩余的单元个数。随后又从队列中删掉了一个单元,输出剩余单元个数,清除该队列,输出单元个数,可以发现清除后,所以单元都是可以的。最后释放了该队列。
#include "queue_demo.h"
#include "uni_log.h"
#include "tuya_hal_thread.h"
#include "uni_queue.h"
#include "uni_thread.h"
P_QUEUE_CLASS my_queue;
int in_number[] = {31, 32, 33, 5, 7};
int out_number[5];
void queue_task(void)
{
unsigned char ret;
int i;
/* create queue */
my_queue = CreateQueueObj(5, SIZEOF(int));
if (NULL == my_queue) {
PR_ERR("creat queue failed.");
return;
}
PR_NOTICE("create queue success.");
PR_NOTICE("cur queue num: %d", GetCurQueNum(my_queue));
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* in queue */
ret = InQueue(my_queue, in_number, 5);
if (1 != ret) {
PR_ERR("in queue failed.");
} else {
PR_NOTICE("queue input 5 numbers success.");
}
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* out queue */
ret = OutQueue(my_queue, out_number, 1);
if (1 != ret) {
PR_ERR("out queue failed.");
} else {
PR_NOTICE("queue out 1 number success.");
}
PR_NOTICE("out_number[0]: %d", out_number[0]);
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* GetQueueMember */
ret = GetQueueMember(my_queue, 1, out_number, 4);
if (1 != ret) {
PR_ERR("queue get member failed.");
} else {
PR_NOTICE("GetQueueMember success.");
}
for (i=0; i<4; i++) {
PR_NOTICE("out_number[%d]:%d", i, out_number[i]);
}
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* delete 1 queue number */
ret = DelQueueMember(my_queue, 1);
if (1 != ret) {
PR_ERR("delete queue number error.");
} else {
PR_NOTICE("delete queue number success.");
}
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* clean queue */
ret = ClearQueue(my_queue);
if (1 != ret) {
PR_ERR("clean queue failed.");
} else {
PR_NOTICE("clean queue success.");
}
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* release queue */
ReleaseQueueObj(my_queue);
PR_NOTICE("queue is release.");
}
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈