/*---------------------------------------------------------------------------- * Copyright (c) TJD Technologies Co., Ltd. 2020. All rights reserved. * * Description: task_service_timer.c * * Author: saimen * * Create: 2024-4-23 *--------------------------------------------------------------------------*/ //lib #include #include #include //os #include "securec.h" #include "common_def.h" #include "debug_print.h" #include "soc_osal.h" #include "cmsis_os2.h" //sdk //drv //user #include "sys_typedef.h" #include "sys_config.h" #include "sys_dlist.h" #include "task_service_timer.h" /********************************************************************************************************************** * DEFINE */ #define ENABLE_STATIC_PRINT_INFO false #define ENABLE_STATIC_PRINT_WARN true #define ENABLE_STATIC_PRINT_ERROR true #if ENABLE_STATIC_PRINT_INFO #define static_print_debug(...) sys_common_printf(__VA_ARGS__) #else #define static_print_debug(...) #endif #if ENABLE_STATIC_PRINT_WARN #define static_print_warn(...) sys_common_printf(__VA_ARGS__) #else #define static_print_warn(...) #endif #if ENABLE_STATIC_PRINT_ERROR #define static_print_error(...) sys_common_printf(__VA_ARGS__) #else #define static_print_error(...) #endif #define QUEUE_SERVICE_TIMER_COUNT 16 #define LIST_SERVICE_TIMER_COUNT 16 #define OSAL_MSGQ_WAIT_MIN_MS (9) #define OSAL_MSGQ_WAIT_MAX_MS (9000) typedef struct { tjd_sys_dlist_t dlist; queue_default_info_t queue_handler; unsigned int last_time; } service_timer_dlist_t; typedef struct { unsigned int *task_handle; unsigned long queue; unsigned int queue_wait; unsigned int min_interval; } model_service_timer_info_t; /********************************************************************************************************************** * VARIABLES */ model_service_timer_info_t g_model_service_timer_info = {0}; service_timer_dlist_t g_service_timer_list = {0}; /********************************************************************************************************************** * LOCAL FUNCTIONS */ static int function_dlist_cmpr_handle(const tjd_sys_dlist_item_t *item_a, const tjd_sys_dlist_item_t *item_b) { service_timer_dlist_t *temp_item_a = (service_timer_dlist_t *) item_a; service_timer_dlist_t *temp_item_b = (service_timer_dlist_t *) item_b; if(temp_item_a == NULL || temp_item_b == NULL) { return RET_ERROR; } if(temp_item_a->queue_handler.func_event_handler == temp_item_b->queue_handler.func_event_handler && temp_item_a->queue_handler.param == temp_item_b->queue_handler.param) { return RET_SUCCESS; } return RET_FAIL_BASE; } static int function_dlist_find_run(tjd_sys_dlist_t *dlist, unsigned int cur_sys_tick) { tjd_sys_dlist_t *curr_item = NULL; tjd_sys_dlist_t *next_item = NULL; service_timer_dlist_t *curr_node = NULL; unsigned int node_count = 0; g_model_service_timer_info.min_interval = OSAL_MSGQ_WAIT_MAX_MS; if (dlist == NULL) { return RET_ERROR; } TJD_SYS_DLIST_FOR_EACH(curr_item, next_item, dlist) { curr_node = (service_timer_dlist_t *)curr_item; node_count++; if (cur_sys_tick - curr_node->last_time >= curr_node->queue_handler.value) { if(curr_node->queue_handler.func_event_handler) { curr_node->last_time += curr_node->queue_handler.value; //curr_node->last_time = cur_sys_tick; curr_node->queue_handler.value = curr_node->queue_handler.func_event_handler(curr_node->queue_handler.param); static_print_debug("function_dlist_find_run()1:node=%d-%p-%d,time=%d-%d\r\n", node_count, curr_node->queue_handler.func_event_handler, curr_node->queue_handler.value, cur_sys_tick, curr_node->last_time); } if(curr_node->queue_handler.value <= 0) { tjd_sys_dlist_remove(curr_item); osal_kfree(curr_item); } } if (cur_sys_tick - curr_node->last_time >= curr_node->queue_handler.value) { g_model_service_timer_info.min_interval = OSAL_MSGQ_WAIT_MIN_MS; } else { unsigned int temp_interval = curr_node->queue_handler.value - (cur_sys_tick - curr_node->last_time); g_model_service_timer_info.min_interval = (g_model_service_timer_info.min_interval > temp_interval)? temp_interval:g_model_service_timer_info.min_interval; } } if(node_count == 0){ g_model_service_timer_info.queue_wait = OSAL_MSGQ_WAIT_MAX_MS; } else { g_model_service_timer_info.queue_wait = (g_model_service_timer_info.min_intervalqueue_handler.value = node_count; static_print_debug("function_dlist_find_run() END:node=%d-%d-%d\r\n", node_count, g_model_service_timer_info.min_interval, g_model_service_timer_info.queue_wait); return RET_SUCCESS; } /********************************************************************************************************************** * PUBLIC FUNCTIONS */ unsigned int *tjd_task_service_timer_get_task_handle(void) { return g_model_service_timer_info.task_handle; } unsigned long tjd_task_service_timer_get_queue_id(void) { return g_model_service_timer_info.queue; } void tjd_task_service_timer_entry(void *param) { unused(param); int32_t ret = OSAL_FAILURE; unsigned int msg_size = sizeof(queue_default_info_t); unsigned int cur_sys_tick = 0; unsigned int max_interval = 0; service_timer_dlist_t *cur_service_node = NULL; service_timer_dlist_t *find_service_node = NULL; tjd_sys_dlist_create(&g_service_timer_list.dlist); while (1) { if(cur_service_node == NULL) { cur_service_node = (service_timer_dlist_t *)osal_kmalloc(sizeof(service_timer_dlist_t), OSAL_GFP_KERNEL); if(cur_service_node == NULL) { osDelay(5000); continue; } memset_s(&cur_service_node->queue_handler, sizeof(queue_default_info_t), 0, sizeof(queue_default_info_t)); } ret = osal_msg_queue_read_copy(g_model_service_timer_info.queue, &cur_service_node->queue_handler, &msg_size, g_model_service_timer_info.queue_wait); cur_sys_tick = osKernelGetTickCount(); if (ret == OSAL_SUCCESS) { static_print_debug("queue_service_timer_default_info_t: service_node:0x%X-0x%X-%d\r\n", cur_service_node, cur_service_node->queue_handler.func_event_handler, cur_service_node->queue_handler.value); find_service_node = (service_timer_dlist_t *)tjd_sys_dlist_find(&g_service_timer_list.dlist, &cur_service_node->dlist, function_dlist_cmpr_handle); if(find_service_node == NULL) { if(cur_service_node->queue_handler.value <= 0) { static_print_debug("service_timer delete list: NOT FIND\r\n"); memset_s(&cur_service_node->queue_handler, sizeof(queue_default_info_t), 0, sizeof(queue_default_info_t)); } else { cur_service_node->last_time = cur_sys_tick; if(cur_service_node->queue_handler.value <= 2 )//注释本行代表:所有服务首次都是立即执行。 { cur_service_node->last_time = cur_sys_tick - cur_service_node->queue_handler.value; } tjd_sys_dlist_append(&g_service_timer_list.dlist, &cur_service_node->dlist); static_print_debug("service_timer add list: service_node:0x%X-0x%X-%d\r\n", find_service_node, &cur_service_node->dlist, g_service_timer_list.queue_handler.value); cur_service_node = NULL; } }else{ if(cur_service_node->queue_handler.value <= 0) { static_print_debug("service_timer delete list: service_node:0x%X\r\n", find_service_node); tjd_sys_dlist_remove(&find_service_node->dlist); osal_kfree(find_service_node); } static_print_debug("service_timer in list: service_node:0x%X-0x%X-%d\r\n", find_service_node, &cur_service_node->dlist, find_service_node->queue_handler.value); memset_s(&cur_service_node->queue_handler, sizeof(queue_default_info_t), 0, sizeof(queue_default_info_t)); } } function_dlist_find_run(&g_service_timer_list.dlist, cur_sys_tick); } } void tjd_task_service_timer_init(unsigned short stack_depth, unsigned short priority) { osal_msg_queue_create("tjd_q_service_timer", QUEUE_SERVICE_TIMER_COUNT, &g_model_service_timer_info.queue, 0, sizeof(queue_default_info_t)); #define APP_MAIN_STACK_SIZE 0x1000 #define TASK_PRIORITY_APP (osPriority_t)(17) osThreadAttr_t task_attr = { "tjd_t_service_timer", 0, NULL, 0, NULL, APP_MAIN_STACK_SIZE, TASK_PRIORITY_APP, 0, 0 }; if(stack_depth>APP_MAIN_STACK_SIZE){ task_attr.stack_size = stack_depth; } if(priority>TASK_PRIORITY_APP){ //task_attr.priority = priority; } task_attr.stack_mem = memalign(16, task_attr.stack_size);//add g_model_service_timer_info.task_handle = osThreadNew(tjd_task_service_timer_entry, NULL, &task_attr); g_model_service_timer_info.queue_wait = OSAL_MSGQ_WAIT_MAX_MS; static_print_warn("tjd_task_service_timer_init() END: task-0x%X queue-0x%X-%d\r\n", g_model_service_timer_info.task_handle, g_model_service_timer_info.queue, sizeof(queue_default_info_t)); } /********************************************************************************************************************** * TEST FUNCTIONS */ static unsigned long s_test_param; signed int tjd_task_service_timer_test_handle(void *param) { unsigned long *p_param = (unsigned long *)param; static_print_debug("tjd_task_service_timer_test_handle(): param=%d\r\n", *p_param); s_test_param++; return 1000; //定时执行间隔单位为ms } void tjd_task_service_timer_test_send(void) { queue_default_info_t msg_data = { tjd_task_service_timer_test_handle, &s_test_param, 500, NULL };//500ms首次执行的等待时间。 osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data, sizeof(queue_default_info_t), 0); }