#include "drv_wdog.h"

#include "bsp_task.h"

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

#include "os.h"

#define TASK_RUNNING_TIME_CHECK  true
typedef struct
{  
    UintArgCall reset_call;
    TaskArray *task_array[OS_MAX_TASKS];
    uint16_t   max_wdog_tick[OS_MAX_TASKS];
}TaskItem;

TaskItem task_item;


static void task_template(void *item)
{    
    TaskArray *_item;
    uint32_t start_tick = 0;
	
    KIT_ASSERT_PARAM(item != NULL);  
		
    if(item != NULL)
    {
        _item = item;
        if(_item->init != NULL)
        {
            _item->init();
        }

        for (;;)
        {           
    #if (TASK_RUNNING_TIME_CHECK == true)        
            KIT_DEBUG_PRINTF("task:%d period:%d\r\n", _item->task_id, kit_time_get_tick() - start_tick);  
    #endif                
            start_tick = kit_time_get_tick();
            //清除看门狗时间
            _item->wdog_tick = 0;
            _item->task(_item->task_period);

            kit_time_dly_by_fix_period(start_tick, _item->task_period);
        }
    }
}

void bsp_task_beat_wdog(void)
{
    uint32_t i;
    TaskArray *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->wdog_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.max_wdog_tick[cur_task->task_id] < cur_task->wdog_tick)
            {
                task_item.max_wdog_tick[cur_task->task_id] = cur_task->wdog_tick;
            }  
        }
    }

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

KitResult bsp_task_creat(TaskArray* task, uint8_t * name)
{
    uint8_t res;
    KIT_ASSERT_PARAM(task != NULL);
    
    if((task != NULL) && (task->task_id < OS_MAX_TASKS))
    {
        OS_ERR err;
        //CPU_STK *Task2Task_STK = (CPU_STK *)mymalloc(SRAMIN, task->stk_size * sizeof(CPU_STK));
        OSTaskCreate((OS_TCB       *)task->task_tcb,
                    (CPU_CHAR      *)name,
                    (OS_TASK_PTR    )task_template, 
                    (void          *)task,
                    (OS_PRIO        )task->task_prio,
                    (CPU_STK       *)task->stk_array,
                    (CPU_STK_SIZE   )task->stk_size/10,
                    (CPU_STK_SIZE   )task->stk_size,
                    (OS_MSG_QTY     )0,
                    (OS_TICK        )0,
                    (void          *)0,
                    (OS_OPT         )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                    (OS_ERR        *)&err);  

        task_item.task_array[task->task_id] = task;
    }
    
    return (KitResult)res;
}



void bsp_task_feed_wdog(uint32_t tick)
{
    TaskArray *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;
        }
    }
}

uint32_t bsp_task_delay_ms(uint32_t dly)
{
		OS_ERR err;
    bsp_task_feed_wdog(dly);
		OSTimeDly(dly, OS_OPT_TIME_DLY, &err);
    return dly;
}


void bsp_task_set_timeout_call(UintArgCall call)
{
    if(call != NULL)
    {
        task_item.reset_call = call;
    }
}


uint16_t bsp_task_get_max_wdog_tick(uint8_t task_id)
{
    uint16_t tmp = 0;
    if(task_id < OS_MAX_TASKS)
    {
        tmp = task_item.max_wdog_tick[task_id];
    }
    return tmp;
}