/*
*
* Copyright (c) 2024-2020 Texas Instruments Incorporated
*
* All rights reserved not granted herein.
*
* Limited License.
*
* Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
* license under copyrights and patents it now or hereafter owns or controls to make,
* have made, use, import, offer to sell and sell ("Utilize") this software subject to the
* terms herein.  With respect to the foregoing patent license, such license is granted
* solely to the extent that any such patent is necessary to Utilize the software alone.
* The patent license shall not apply to any combinations which include this software,
* other than combinations with devices manufactured by or for TI ("TI Devices").
* No hardware patent is licensed hereunder.
*
* Redistributions must preserve existing copyright notices and reproduce this license
* (including the above copyright notice and the disclaimer and (if applicable) source
* code license limitations below) in the documentation and/or other materials provided
* with the distribution
*
* Redistribution and use in binary form, without modification, are permitted provided
* that the following conditions are met:
*
* *       No reverse engineering, decompilation, or disassembly of this software is
* permitted with respect to any software provided in binary form.
*
* *       any redistribution and use are licensed by TI for use only with TI Devices.
*
* *       Nothing shall obligate TI to provide you with source code for the software
* licensed and provided to you in object code.
*
* If software source code is provided to you, modification and redistribution of the
* source code are permitted provided that the following conditions are met:
*
* *       any redistribution and use of the source code, including any resulting derivative
* works, are licensed by TI for use only with TI Devices.
*
* *       any redistribution and use of any object code compiled from the source code
* and any resulting derivative works, are licensed by TI for use only with TI Devices.
*
* Neither the name of Texas Instruments Incorporated nor the names of its suppliers
*
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* DISCLAIMER.
*
* THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TI AND TI'S LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

/**
 *  \file can_profile.h.c
 *
 *  \brief Main file for TI-RTOS build
 */

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */

#include <ti/csl/arch/csl_arch.h>
#include <ti/csl/soc.h>
#include <ti/csl/cslr.h>

#include <ti/osal/osal.h>
#include <ti/osal/TaskP.h>

#include "CanApp_Startup.h"
#include "can_profile.h"
#include "CanIf.h"
#if (defined (BUILD_MCU1_0) && (defined (SOC_J721E) || defined (SOC_J7200) || defined (SOC_J784S4) || defined (SOC_J721S2) || defined (SOC_J742S2)))
#include <ti/drv/sciclient/sciserver_tirtos.h>
#endif
#include <ti/drv/ipc/include/ipc_rsctypes.h>
#include <ti/drv/sciclient/sciclient.h>
#include <ti/drv/pm/examples/utils/app_utils.h>
/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */

/* Test application stack size */
#define APP_TASK_STACK                  (10U * 1024U)
/**< Stack required for the stack */
#define CAN_PROFILE_DEMO_TASK_NAME      ("CAN PROFILE")
/**< Task name */
#define APP_TSK_STACK_MAIN              (32U * 1024U)
/**< Test application stack size */
#define IPC_INIT_SCISERVER_TASK_PRI         (6)
#define APP_SCISERVER_INIT_TSK_STACK        (32U * 1024U)
/* High Priority for SCI Server - must be higher than Low priority task */
#define IPC_SETUP_SCISERVER_TASK_PRI_HIGH   (5)
/*
 * Low Priority for SCI Server - must be higher than IPC echo test tasks
 * to prevent delay in handling Sciserver requests when test is performing
 * multicore ping/pong.
 */
#define IPC_SETUP_SCISERVER_TASK_PRI_LOW    (4)
/* ========================================================================== */
/*                         Structure Declarations                             */
/* ========================================================================== */

/* None */

/* ==========================================================================*/
/*                          Function Declarations                             */
/* ========================================================================== */

static void CanApp_TaskFxn(void* a0, void* a1);
static void CanApp_Shutdown(void);
//sint32 SetupSciServer(void);
static void taskFxn(void* a0, void* a1);
void CanProfile_setupSciServer(void);
void ipc_initSciclient(void);
void Ipc_setupSciServer(void* a0, void* a1);
/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */
/* application stack */
static uint8_t CanApp_TaskStack[APP_TASK_STACK] __attribute__((aligned(32)));
//static uint8_t SciServer_TaskStack[APP_TASK_STACK] __attribute__((aligned(32)));
static uint8_t  gAppTskStackMain[APP_TSK_STACK_MAIN] __attribute__ ((aligned(8192)));
static uint8_t  gSciserverInitTskStack[APP_SCISERVER_INIT_TSK_STACK] __attribute__ ((aligned(8192)));
/**< Stack for the task */
static canAppTaskObj_t  CanApp_TestPrms;
/**< Test parameters */
static HwiP_Handle      CanApp_IsrHndls[CAN_MAX_CONTROLLER];
/**< Stores the ISR handles */
extern SemaphoreP_Handle CanIf_TxConfirmationSemaphore;
/**< TX Confirmation semaphore, would be posted when TX completes */
extern SemaphoreP_Handle CanIf_RxConfirmationSemaphore;
/**< Rx Confirmation semaphore, would be posted when TX completes */
/* ========================================================================== */
/*                            External Variables                              */
/* ========================================================================== */
extern uint32 CanIf_DrvStatus;
/**< CAN IF Driver Status, defined in CanIf.c */

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */
const Ipc_ResourceTable ti_ipc_remoteproc_ResourceTable __attribute__ ((section (".resource_table"), aligned (4096))) = 
{
    {
        1U,                   /* we're the first version that implements this */
        2U,         /* number of entries in the table */
        {
            0U, 
            0U,                /* reserved, must be zero */
        }
    },
};

int main(void)
{
    TaskP_Handle task;
    TaskP_Params taskParams;
    //sint32 ret = CSL_PASS;


    /* Relocate FreeRTOS Reset Vectors from BTCM*/
    void _freertosresetvectors (void);  
    memcpy((void *)0x0, (void *)_freertosresetvectors, 0x40);

    OS_init();
    /* Initialize the task params */
    TaskP_Params_init(&taskParams);
    /* Set the task priority higher than the default priority (1) */
    taskParams.priority = 2;
    taskParams.stack        = gAppTskStackMain;
    taskParams.stacksize    = sizeof (gAppTskStackMain);

    task = TaskP_create(taskFxn, &taskParams);
    if(NULL == task)
    {
        OS_stop();
    }
    OS_start();    /* does not return */

}
static void taskFxn(void* a0, void* a1)
{
#ifdef UART_ENABLED
    AppUtils_Init();
#endif
    /* Initialize SCI Client - It must be called before board init */
    ipc_initSciclient();

    TaskP_Handle sciserverInitTask;
    TaskP_Params sciserverInitTaskParams;
    /* Initialize SCI Client Server */
//    ret = SetupSciServer();
//    if(ret != CSL_PASS)
    TaskP_Params_init(&sciserverInitTaskParams);
    sciserverInitTaskParams.priority     = IPC_INIT_SCISERVER_TASK_PRI;
    sciserverInitTaskParams.stack        = gSciserverInitTskStack;
    sciserverInitTaskParams.stacksize    = sizeof (gSciserverInitTskStack);

    sciserverInitTask = TaskP_create(Ipc_setupSciServer, &sciserverInitTaskParams);
    if(NULL == sciserverInitTask)
    
    {
        OS_stop();
    }
    CanApp_Startup();
    CanApp_PowerAndClkSrc();

    /* Initialize dummy CAN IF */
    CanIf_Init(NULL);
     TaskP_Handle task;
     TaskP_Params taskParams;

    if (CANIF_DRV_INITIALIZED == CanIf_DrvStatus)
    {
        /* Initialize the task params */
        TaskP_Params_init(&taskParams);
        //taskParams.instance->name = CAN_PROFILE_DEMO_TASK_NAME;
        /* Set the task priority higher than the default priority (1) */
        taskParams.priority     = 2;
        taskParams.stack        = CanApp_TaskStack;
        taskParams.stacksize    = sizeof (CanApp_TaskStack);

        task = TaskP_create(&CanApp_TaskFxn, &taskParams);
        if(NULL == task)
        {
            OS_stop();
        }
        //OS_start();    /* does not return */
    }
    else
    {
        AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME
                " Error : CAN IF not initialized !!!\n");
    }

    //return(0);
}
void ipc_initSciclient(void)
{
    int32_t ret = CSL_PASS;
    Sciclient_ConfigPrms_t        config;

    /* Now reinitialize it as default parameter */
    ret = Sciclient_configPrmsInit(&config);
    if (ret != CSL_PASS)
    {
        AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME "Sciclient_configPrmsInit Failed\n");
    }

#if (defined (BUILD_MCU1_0) && (defined (SOC_J721E) || defined (SOC_J7200) || defined (SOC_J721S2)))
    if (ret == CSL_PASS)
    {
        ret = Sciclient_boardCfgParseHeader(
            (uint8_t *)SCISERVER_COMMON_X509_HEADER_ADDR,
            &config.inPmPrms, &config.inRmPrms);
        if (ret != CSL_PASS)
        {
            AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME "Sciclient_boardCfgParseHeader Failed\n");
        }
    }
#endif

    //return(0);
    if (ret == CSL_PASS)
    {
        ret = Sciclient_init(&config);
        if (ret != CSL_PASS)
        {
            AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME "Sciclient_init Failed\n");
        }
    }

    /* DEBUG: Print PLL/Clock related info to compare before/after Linux boots */
    AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME "ipc_initSciclient done\n");
}

void Ipc_setupSciServer(void* a0, void* a1)
{

    Sciserver_TirtosCfgPrms_t appPrms;
    int32_t ret = CSL_PASS;
    char *version_str = NULL;
    char *rmpmhal_version_str = NULL;

    ret = Sciserver_tirtosInitPrms_Init(&appPrms);

    appPrms.taskPriority[SCISERVER_TASK_USER_LO] =
                                            IPC_SETUP_SCISERVER_TASK_PRI_LOW;
    appPrms.taskPriority[SCISERVER_TASK_USER_HI] =
                                            IPC_SETUP_SCISERVER_TASK_PRI_HIGH;

    if (ret == CSL_PASS)
    {
        ret = Sciserver_tirtosInit(&appPrms);
    }

    version_str = Sciserver_getVersionStr();
    rmpmhal_version_str = Sciserver_getRmPmHalVersionStr();
    AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME "DM Built On: %s %s\n", __DATE__, __TIME__);
    AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME "Sciserver Version: %s\n", version_str);
    AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME "RM_PM_HAL Version: %s\n", rmpmhal_version_str);

    if (ret == CSL_PASS)
    {
        AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME "Starting Sciserver..... PASSED\n");
    }
    else
    {
        AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME "Starting Sciserver..... FAILED\n");
    }

    return;
}
static void CanApp_TaskFxn(void* a0, void* a1)
{
    CanApp_PlatformInit();
    Utils_prfInit();

    Utils_prfLoadRegister (TaskP_self(), CAN_PROFILE_DEMO_TASK_NAME);

    CanApp_TestPrms.numTxPackets = APP_NUM_MSG_PER_ITERATION;
    CanApp_TestPrms.numIterations = APP_NUM_ITERATION;

    TaskP_yield();

    CanApp_ProfileTest(&CanApp_TestPrms);

    while (1)
    {
        can_send_data();
        //AppUtils_delay(1000);
        TaskP_sleep(100);
    }
        

    CanApp_Shutdown();

    Utils_prfLoadUnRegister (TaskP_self());
    Utils_prfDeInit();
    return;
}

/** \brief Application tear down functions */
static void CanApp_Shutdown(void)
{
    uint32 idx;

    for (idx = 0U; idx < CAN_MAX_CONTROLLER; idx++)
    {
        if (NULL != CanApp_IsrHndls[idx])
        {
            if (HwiP_OK != HwiP_delete(CanApp_IsrHndls[idx]))
            {
                AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME
                                " Error!!! Could not De register"
                                " the ISR for instance %d!!!\n", idx);
                break;
            }
        }
    }

    if (NULL != CanIf_TxConfirmationSemaphore)
    {
        SemaphoreP_delete(CanIf_TxConfirmationSemaphore);
        if (NULL != CanIf_RxConfirmationSemaphore)
        {
            SemaphoreP_delete(CanIf_RxConfirmationSemaphore);
        }
    }
    return;
}
