/**
 * \file    sys_task.h
 * \brief   System task definition, simple implementation
 * 
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-03-30
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-03-30  Original Creation
 * 
 */
 
#ifndef __SYS_TASK_H_
#define __SYS_TASK_H_


#include "types.h"

typedef int                     sys_tid_t;

#define SYS_TASK_ID_MAX         (8)
#define SYS_TASK_ID_INVALID     (-1)

#if (!SYS_FREERTOS_ENABLED)

#include "msq.h"

/** \brief System task initialization
 *
 */
void sys_task_init(void);

/** \brief System task start scheduler
 *
 */
void sys_task_start_scheduler(void);

/** \brief Create system task 
 *
 * \param intr_func     Task handler
 * \param arg           Task argument
 * \return              Task ID
 */
sys_tid_t sys_task_create(v_func_ptr_t intr_func, u32_t arg);


/** \brief Delete system task 
 *
 * \param id            Task ID
 */
void sys_task_delete(sys_tid_t id);

#define sys_task_enter_critical()

#define sys_task_exit_critical()

#else  /* SYS_FREERTOS_ENABLED */

#include "types.h"
#include "drv_interrupt.h"

/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"


/* Application task priorities. */
#define SYS_INIT_TASK_PRIORITY              ( tskIDLE_PRIORITY + 4 )
#define SYS_USBPD_TASK_PRIORITY             ( tskIDLE_PRIORITY + 3 )
#define SYS_INTF_TASK_PRIORITY              ( tskIDLE_PRIORITY + 2 )
#define SYS_UART_TASK_PRIORITY              ( tskIDLE_PRIORITY + 1 )


/* Application task stack size, only for -O2 option */
#define SYS_INIT_TASK_STACK_SIZE            ( ( unsigned short ) 128 )
#define SYS_USBPD_TASK_STACK_SIZE           ( ( unsigned short ) 216 )
#define SYS_INTF_TASK_STACK_SIZE            ( ( unsigned short ) 128 )
#define SYS_UART_TASK_STACK_SIZE            ( ( unsigned short ) 216 )


#define SYS_INTF_QUEUE_LENGTH               ( 4 )
#define SYS_INTF_QUEUE_SIZE                 ( 4 )


/* The period after which the check timer will expire provided no errors have
been reported by any of the standard demo tasks.  ms are converted to the
equivalent in ticks using the portTICK_PERIOD_MS constant. */
#define mainCHECK_TIMER_PERIOD_MS			( 10000UL / portTICK_PERIOD_MS )

/* A block time of zero simply means "don't block". */
#define mainDONT_BLOCK						( 0UL )

/** Define a empty macro */
#define sys_task_init()

/** \brief System task start scheduler
 *
 */
void sys_task_start_scheduler(void);

/** \brief Create system task 
 *
 * \param intr_func     Task handler
 * \param arg           Task argument
 * \return              Task ID
 */
sys_tid_t sys_task_create(v_func_ptr_t intr_func, u32_t arg);


/** \brief Delete system task 
 *
 * \param id            Task ID
 */
void sys_task_delete(sys_tid_t id);


#define sys_task_enter_critical() \
    UBaseType_t uxSavedInterruptStatus = 0; \
    if (DRV_INTR_IS_PENDING()) { \
        uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); \
    } \
    else { \
        taskENTER_CRITICAL(); \
    }

#define sys_task_exit_critical() \
    if (DRV_INTR_IS_PENDING()) { \
        taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); \
    } \
    else { \
        taskEXIT_CRITICAL(); \
    }


#endif /* if (!SYS_FREERTOS_ENABLED) */

extern volatile v_func_ptr_t g_sys_task_uart0_handler;

#define sys_task_uart0_handler_is_null() \
    (NULL == g_sys_task_uart0_handler)

#define sys_task_uart0_handler_set(func) \
    do { \
        g_sys_task_uart0_handler = (v_func_ptr_t)(func); \
    } while(0)

#define sys_task_uart0_handler(arg) \
    do { \
        if (NULL != g_sys_task_uart0_handler) {\
            g_sys_task_uart0_handler(arg); \
        } \
    } while(0)

extern volatile v_func_ptr_t g_sys_task_uart1_handler;

#define sys_task_uart1_handler_is_null() \
    (NULL == g_sys_task_uart1_handler)

#define sys_task_uart1_handler_set(func) \
    do { \
        g_sys_task_uart1_handler = (v_func_ptr_t)(func); \
    } while(0)

#define sys_task_uart1_handler(arg) \
    do { \
        if (NULL != g_sys_task_uart1_handler) {\
            g_sys_task_uart1_handler(arg); \
        } \
    } while(0)


#endif /* #ifndef __SYS_TASK_H_ */


