/******************************************************************************
 * @file     	bsp_task.h
 * @brief     任务组件框架
 * @version   V1
 * @copyright    
 ******************************************************************************/
 
#include "drv_wdog.h"
#include "drv_misc.h"
#include "drv_flash.h"

#include "bsp_task.h"
#include "bsp_task.h"

#include "eeprom_manager.h"

#include "kit_time.h"
#include "kit_debug.h"

#include "ucos_ii.h"

typedef struct
{  
    UintArgFunCall reset_call;
    task_array_t *task_array[OS_MAX_TASKS];
    uint16_t   wdog_timeout_tick[OS_MAX_TASKS];
}task_monitor_t;

task_monitor_t task_item;


/*****************************************************************************
 * @brief       任务模板
 * @param[in]   void: 无
 * @return      void
 *****************************************************************************/
static void _task_template(void *item)
{    
    task_array_t *_item;
   
    KIT_ASSERT_PARAM(item != NULL);    
    
    if(item != NULL)
    {
        _item = item;
        if(_item->init_func != NULL)
        {
            _item->init_func();
        }

        while(1)
        {                          
            //清除看门狗时间
            _item->wdog_tick = 0;
            _item->handler_func(_item->interval);
						
			//时间延时
			OSTimeDly(_item->interval);
        }
    }
}

/*****************************************************************************
 * @brief       看门狗函数
 * @param[in]   void: 无
 * @return      void
 *****************************************************************************/
void bsp_task_beat_wdog(void)
{
    uint32_t i;
    task_array_t *cur_task;
	bool is_timeout = false;
    static uint32_t wdog_tick;

    for(i = 0; i < OS_MAX_TASKS; i++ )
    {
        cur_task = task_item.task_array[i];
        if(cur_task != NULL)
        {
            if ((cur_task->wdog_tick++ > cur_task->timeout))
            {
                if((cur_task->is_time_out == false) && (task_item.reset_call != NULL))
                {
										//task_item.reset_call(i);
                    cur_task->is_time_out = true;
                    KIT_DEBUG_PRINTF("wdog timeout task id %d \r\n", cur_task->task_id);
                }
               // is_timeout = true;
            }
            if(task_item.wdog_timeout_tick[cur_task->task_id] < cur_task->wdog_tick)
            {
                task_item.wdog_timeout_tick[cur_task->task_id] = cur_task->wdog_tick;
            }  
        }
    }

    if(is_timeout == false)
    {
        wdog_tick = 0;
        drv_wdog_feed();
    }
    else if(wdog_tick++ >= 5000)
    {
        bms_soft_reset_save(kSoftReset_Wdog, NULL, 0);
        drv_misc_reset_mcu();
    }
}

/*****************************************************************************
 * @brief       任务创建
 * @param[in]   void: 无
 * @return      void
 *****************************************************************************/
kit_ret_e bsp_create_task(task_array_t* task, uint8_t * name)
{
    uint8_t res;
    KIT_ASSERT_PARAM(task != NULL);
    
    if((task != NULL) && (task->task_id < OS_MAX_TASKS))
    {
        res = OS_ERR_NONE;
#if (TRACE_PROBE | TRACE_SYSTEM_VIEW)
        res = OSTaskCreateExt(task_template,
                        (void *)task,
                        &task->stk_array[task->stk_size - 1],
                        task->task_id,
                        task->task_id,
                        task->stk_array,
                        task->stk_size,
                        (void *)0,
                        OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
                        
        OSTaskNameSet(task->task_id, name, &res);
        KIT_DEBUG_PRINTF("task creat %s \r\n", name);
#else
        res = OSTaskCreate(_task_template, (void *)task, &task->stk_array[task->stk_size - 1], task->task_id);
#endif      
        task_item.task_array[task->task_id] = task;
    }
    
    return (kit_ret_e)res;
}


/*****************************************************************************
 * @brief       喂狗函数
 * @param[in]   void: 无
 * @return      void
 *****************************************************************************/
void bsp_task_feed_wdog(uint32_t tick)
{
    task_array_t *cur_task;
    if(OSPrioCur < OS_MAX_TASKS)
    {
        cur_task = task_item.task_array[OSPrioCur];
        if(cur_task != NULL)
        {
            cur_task->wdog_tick = (cur_task->wdog_tick > tick) ? (cur_task->wdog_tick - tick) : 0;
        }
    }
}

/*****************************************************************************
 * @brief       任务延时函数
 * @param[in]   void: 无
 * @return      void
 *****************************************************************************/
uint32_t bsp_task_delay_ms(uint32_t dly)
{
    bsp_task_feed_wdog(dly);
    OSTimeDly(dly);
    return dly;
}

/*****************************************************************************
 * @brief       设置任务回调
 * @param[in]   void: 无
 * @return      void
 *****************************************************************************/
void bsp_task_set_timeout_call(UintArgFunCall call)
{
    if(call != NULL)
    {
        task_item.reset_call = call;
    }
}

/*****************************************************************************
 * @brief       看门狗超时的任务获取
 * @param[in]   void: 无
 * @return      void
 *****************************************************************************/
uint16_t bsp_task_get_wdog_timeout_tick(uint8_t task_id)
{
    uint16_t tmp = 0;
    if(task_id < OS_MAX_TASKS)
    {
        tmp = task_item.wdog_timeout_tick[task_id];
    }
    return tmp;
}
