使用os定时器实现实现异步通知(RTOS)

2023-05-16

方法一:通过回调方式,开启,销毁定时器

os time创建:

int arch_os_timer_create(arch_os_timer_handle_t* ptimer, const char *name, uint32_t ms,
		    void (*call_back)(arch_os_timer_handle_t), void *context,
		    arch_os_timer_reload_t reload,
		    arch_os_timer_activate_t activate)
{
	int auto_reload = (reload == ARCH_OS_TIMER_ONE_SHOT) ? pdFALSE : pdTRUE;
	uint32_t ticks = ARCH_OS_WAIT_MS2TICK(ms);

	*ptimer = xTimerCreate((const char * const)name, ticks,
				      auto_reload, context, call_back);
	if (*ptimer == NULL)
		return MIIO_ERROR;

	if (activate == ARCH_OS_TIMER_AUTO_ACTIVATE){
		if(pdTRUE != xTimerStart(*ptimer, ticks)){
			xTimerDelete(*ptimer, ARCH_OS_MS2TICK(ARCH_OS_TIMER_OPT_BLOCK_MS_MAX));
			*ptimer = NULL;
			return MIIO_ERROR;
		}
	}

	return MIIO_OK;
}

*定义定时器回调变量:

typedef struct{
	void (*cb)(void* cb_arg);    //定时任务回调函数
	void *cb_arg;        //回调函数参数
	int delay_ms;        //定时器时长
}async_call_s;

应用层异步定时器实现函数:

int arch_os_async_call(void (*cb)(void* cb_arg), void *cb_arg, int delay_ms)
{
	if(NULL == cb)
		return MIIO_ERROR_PARAM;

	async_call_s *async_ctx = malloc(2*sizeof(void *) + sizeof(int));

	async_ctx->cb = cb;
	async_ctx->cb_arg = cb_arg;
	async_ctx->delay_ms = delay_ms;

	int ret;
	if(async_ctx->delay_ms > 0){
		arch_os_timer_handle_t async_timer;
		ret = arch_os_timer_create(&async_timer, "asyncCallTimer", async_ctx->delay_ms, aysnc_timer_callback, async_ctx, ARCH_OS_TIMER_ONE_SHOT, ARCH_OS_TIMER_AUTO_ACTIVATE);
	}
	else{
		arch_os_thread_handle_t async_callTask;
		ret = arch_os_thread_create(&async_callTask, "asyncCallTask", aysnc_task_callback, 4096, async_ctx, ARCH_OS_PRIORITY_DEFAULT);
	}
	
	if(MIIO_OK != ret){
		LOG_ERROR_TAG(MIIO_LOG_TAG, "==>[%s] arch_os_async_call error !", __func__);
		free(async_ctx);
	}

	return ret;
}

定时器定回调函数:

1.到时去执行async_ctx->cb = cb的回调任务

2.销毁定时器

static void aysnc_timer_callback(arch_os_timer_handle_t timer)
{
	async_call_s *async_ctx = (async_call_s *)arch_os_timer_get_context(timer);

	if(async_ctx){
		async_ctx->cb(async_ctx->cb_arg);
		free(async_ctx);
	}

	arch_os_timer_delete(timer);
}

方法二:通过os周期定时器,时间递减,通过消息队列通知回调执行实现

创建循环定时器,并定义超时时间

static int start_video_upload_ack_timer(void) {
    int ret = 0;
    tag_CAT_CONTEXT* catCtx = get_cat_context();

    if (!catCtx->netState || catCtx->isSDCardMounted) {
        return 0;
    }

    if (upload_ack_timer_id == 0) {
        uint32_t ticks = LOS_MS2Tick(UPLOAD_ACK_TIMER_PERIOD);
        ret = LOS_SwtmrCreate(ticks, LOS_SWTMR_MODE_PERIOD, on_video_upload_ack_timer_cb,
                              &upload_ack_timer_id, NULL);
        if (ret != 0) {
            return -1;
        }
        ret = LOS_SwtmrStart(upload_ack_timer_id);
        if (ret != 0) {
            return -1;
        }
    }

    miot_video_upload_ack_timeout = MIOT_VIDEO_UPLOAD_ACK_TIMEOUT;

    return ret;
}

定时器回调函数

static void on_video_upload_ack_timer_cb(uint32_t param) {
    int ret = 0;
    tag_CAT_CONTEXT* catCtx = get_cat_context();

    if ((upload_ack_timer_id == 0) || (miot_video_upload_ack_timeout <= 0)) {
        return;
    }

    miot_video_upload_ack_timeout -= UPLOAD_ACK_TIMER_PERIOD;
    if (miot_video_upload_ack_timeout <= 0) {
        ret = send_async_task(catCtx->uwMsgQueueID, stop_video_upload_ack_timer,
                              (void*)&upload_ack_timer_id);
    }
}

发送同步任务函数:

1.绑定定时器到时要执行的回调函数

2.传入回调变量,变量定义如下

typedef int (*async_task)(void* param);
typedef struct async_task_s {
    async_task task_impl;
    void* param;
} async_task_t;
int send_async_task(int msg_queque, async_task task_impl, void* param) {
    int ret = 0;
    async_task_t* task_p = NULL;

    task_p = calloc(sizeof(async_task_t), 1);
    if (task_p == NULL) {
        return ERROR_OUT_OF_MEMORY;
    }

    task_p->task_impl = task_impl;
    task_p->param = param;

    ret = send_message3(msg_queque, MSG_RUN_ASYNC_TASK, (void*)task_p, 0, 0);
    if (ret != LOS_OK) {
        printf("send_async_task err:%x\n", ret);
    }

    return ret;
}

在消息队列接收处接收async_task_t的值(绑定的回调函数去执行)

while(1) {
    LOS_QueueRead(ctx>uwMsgQueueID,&uwReadbuf,sizeof(tag_CAT_MESSAGE),LOS_WAIT_FOREVER);        
    if (uwRet != LOS_OK) {
        log_e("recv message failure,error:0x%x\n", uwRet);
        continue;
    }
  if (pMsg->param1) {
     async_task_t* task_p = (async_task_t*)pMsg->param1;
     if (task_p->task_impl) {
            task_p->task_impl(task_p->param);
        }
     }
....
    }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用os定时器实现实现异步通知(RTOS) 的相关文章

随机推荐