/**
 * @file hv_vos_Task.c
 * @brief vos task source file.
 * @details This file provides the following functions: \n
 *          (1) Initialization and de-initialization functions \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-25
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author                        <th>Date         <th>Change Description
 * <tr><td>HiView SoC Software Team      <td>2022-08-25   <td>init
 * </table>
*/


#include "hv_vos_Comm.h"
#include "FreeRTOS.h"
#include "task.h"
#include "hv_vos_Log.h"
#include "hv_comm_Define.h"

static BOOL s_schedulerStarted = HV_FALSE;

struct _HV_VOS_TASK_S{
    TaskHandle_t handle;
};

HV_VOS_TASK_S *Hv_Vos_TaskInit(Hv_Vos_TASK_INIT_PARAMS *param)
{    
    HV_VOS_TASK_S *self = NULL;
    TaskStatus_t xTaskDetails;
    BaseType_t ret;
    HV_ASSERT(param);
    self = HV_MALLOC_OBJECT(HV_VOS_TASK_S);
    const char *taskName = param->name ? param->name : "NoNameTask";
    self->handle = NULL;
    ret = xTaskCreate(param->entry, 
            taskName,
            ((param->stackSize > configMINIMAL_STACK_SIZE) ? param->stackSize : configMINIMAL_STACK_SIZE),
            param->arg,
            tskIDLE_PRIORITY + param->priority,
            &self->handle);
    /*
    vTaskGetInfo(self->handle, &xTaskDetails, pdHV_FALSE, eRunning);
    HV_LOGW("Create Task <%-16s>, ID:%02d\n", xTaskDetails.pcTaskName, xTaskDetails.xTaskNumber);
    */
    if (ret != pdPASS){
        HV_FREE_OBJECT(self);
        self = NULL;
    }
    return self;
}

void Hv_Vos_TaskCleanup(HV_VOS_TASK_S *self)
{   
    if (self == NULL){
        vTaskDelete(NULL);     
    } else {
        vTaskDelete(self->handle);
    }
    HV_FREE_OBJECT(self);
}

void Hv_Vos_TaskStart(void)
{
    s_schedulerStarted = HV_TRUE;
    vTaskStartScheduler();
}

void Hv_Vos_TaskYield(void)
{
    taskYIELD();
}

UINT32 Hv_Vos_TASK_CurrentTaskId(void)
{
    if (s_schedulerStarted){
        TaskStatus_t xTaskDetails;
        vTaskGetInfo(NULL, &xTaskDetails, pdHV_FALSE, eRunning);
        return xTaskDetails.xTaskNumber;
    } else {
        return 0xFFFFFFFF;
    }
}

UINT32 Hv_Vos_TASK_NotifyWait(UINT32* puiValue)
{
    uint32_t uiVlaue = 0;
    BaseType_t xReturn = xTaskNotifyWait(0xffffffffUL, 0xffffffffUL, &uiVlaue, portMAX_DELAY);
    *puiValue = uiVlaue;
    return xReturn == pdHV_TRUE;
}

BOOL Hv_Vos_TaskNotifyFromISR(HV_VOS_TASK_S *self)
{
   BaseType_t ret = 0;
   BaseType_t xHigherPriorityTaskWoken = pdHV_TRUE;
   ret = xTaskNotifyFromISR(self->handle, 0, eNoAction, &xHigherPriorityTaskWoken);
   portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
   return ret == pdPASS;
}

VOID Hv_Vos_TaskEnterCritical()
{
    taskENTER_CRITICAL();
}

VOID Hv_Vos_TaskExitCritical()
{
    taskEXIT_CRITICAL();
}
