mcu_hi3321_watch/tjd/task/task_service_timer.c
2025-05-26 20:15:20 +08:00

243 lines
11 KiB
C

/*----------------------------------------------------------------------------
* Copyright (c) TJD Technologies Co., Ltd. 2020. All rights reserved.
*
* Description: task_service_timer.c
*
* Author: saimen
*
* Create: 2024-4-23
*--------------------------------------------------------------------------*/
//lib
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
//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_interval<OSAL_MSGQ_WAIT_MIN_MS)? OSAL_MSGQ_WAIT_MIN_MS:g_model_service_timer_info.min_interval;
}
curr_node = (service_timer_dlist_t *)dlist;//get head point, head list node no used.
curr_node->queue_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);
}