/*
 * SHMDataSynchInit.c
 *
 *  Created on: Dec 5, 2024
 *      Author: tummalanr
 */



#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdarg.h>

#include <drivers/spinlock.h>
#include <kernel/dpl/EventP.h>
#include <kernel/dpl/SemaphoreP.h>
#include <kernel/dpl/TaskP.h>
#include <cslr_soc_baseaddress.h>
#include <kernel/dpl/AddrTranslateP.h>


#include    "AppSharedMemory.h"
#include    "SystemStsConfig.h"
#include    "MainCoreGlobal.h"
#include "SharedMemoryGlobalObjs.h"
#include    "SharedMemoryExterns.h"
#include "InterfaceHeader.h"



//System Status Config*********************************
//System Discovery Info Details shared Memory Lock
SemaphoreP_Object   System_Info_mutexObj;

static uint32_t
APP_aShmSysConfigStsRDTaskStack_g[APP_SHM_TASK_STACK_SIZE/sizeof(uint32_t)] __attribute__((aligned(32), section(".threadstack"))) = {0};

static TaskP_Object APP_ShmSysConfigStsRdTaskObj_g = { 0 };


EventP_Object       gSysConfigSts_DataRDWRSynchEvent;           // System Configuration/ Status Data Read /Write Event.

//IO Modules***************************

static uint32_t
APP_aShmIOCyclicRDTaskStack_g[APP_SHM_TASK_STACK_SIZE/sizeof(uint32_t)] __attribute__((aligned(32), section(".threadstack"))) = {0};

static TaskP_Object APP_ShmIOCyclicRdTaskObj_g = { 0 };

SemaphoreP_Object   Cyclic_IOModules_mutexObj;

SemaphoreP_Object gSemCyclic_IOModule_RDSynch;          // Read  Semaphore for synch for IO Modules Cyclic Data


//IO / PZx Modules  Cyclic Write
static uint32_t
APP_aShmIOPZCyclicWRTaskStack_g[APP_SHM_TASK_STACK_SIZE/sizeof(uint32_t)] __attribute__((aligned(32), section(".threadstack"))) = {0};

static TaskP_Object APP_ShmIOPZCyclicWrTaskObj_g = { 0 };
SemaphoreP_Object gSemCyclic_IOPZModule_WRSynch;


static uint32_t
APP_aShmIOACyclicWRTaskStack_g[APP_SHM_TASK_STACK_SIZE/sizeof(uint32_t)] __attribute__((aligned(32), section(".threadstack"))) = {0};

static TaskP_Object APP_ShmAIOACyclicWrTaskObj_g = { 0 };

static uint32_t
APP_aShmIOACyclicUpdateTaskStack_g[APP_SHM_TASK_STACK_SIZE/sizeof(uint32_t)] __attribute__((aligned(32), section(".threadstack"))) = {0};

static TaskP_Object APP_ShmIOACyclicUpdateTaskObj_g = { 0 };


SemaphoreP_Object   ACyclic_IOModules_mutexObj;
SemaphoreP_Object   ACyclic_PZx_mutexObj;


EventP_Object   gACyclic_IOModule_SynchEvent;           // Update / Read  Event for synch for IO Modules ACyclic Data
EventP_Object   gACyclic_IOModule_RDRespEvent;           // Update / Read Resp  Event for synch for IO Modules ACyclic Data

SemaphoreP_Object   Cyclic_PZx_mutexObj;


static uint32_t
APP_aShmPZxACyclicUpdateTaskStack_g[APP_SHM_TASK_STACK_SIZE/sizeof(uint32_t)] __attribute__((aligned(32), section(".threadstack"))) = {0};

static TaskP_Object APP_ShmPZxACyclicUpdateTaskObj_g = { 0 };

EventP_Object   gACyclic_PZxModule_SynchEvent;           // Update / Read  Event for synch for PZx Modules ACyclic Data
EventP_Object   gACyclic_PZxModule_RDRespEvent;           // Update / Read  Resp Event for synch for PZx Modules ACyclic Data

static uint32_t
APP_ShmPZxACyclicWRTaskStack_g[APP_SHM_TASK_STACK_SIZE/sizeof(uint32_t)] __attribute__((aligned(32), section(".threadstack"))) = {0};

static TaskP_Object APP_ShmPZxACyclicWrTaskObj_g = { 0 };



SemaphoreP_Object   mbn_mutexObj;
static uint32_t
APP_ShmMBNTaskStack_g[(APP_SHM_TASK_STACK_SIZE) /sizeof(uint32_t)] __attribute__((aligned(32), section(".threadstack"))) = {0};

static TaskP_Object APP_ShmMBNTaskObj_g = { 0 };

SemaphoreP_Object   mbn_datasyncObj;

uint32_t            spinlockBaseAddr;

/* Event objects, typically these are global's */
EventP_Object gCAN_ModuleStatusSynchEvent;


//Event group for IO modules Acyclic write Event group
EventP_Object gIOModuleAcyclicWriteEvent;


//Event group for PZx modules Acyclic write Event group
EventP_Object gPZxModuleAcyclicWriteEvent;



ecat_runstateinfo curecatstate = {0u};
ecat_runstateinfo prevecatstate = {0xffu};



void memset_volatile(volatile void *s, char c, uint32_t n) {
  volatile char *p = s;
  while (n-- > 0) {
    *p++ = c;
  }
}

/*!
 *  <!-- Description: -->
 *
 *  \brief
 *
 *   Application Shared Memory RD/WR Process Initialization.
 *
 *  <!-- Parameters and return values: -->
 *  \param[in]  :   None
 *  \return     :   AppRET_T   on success AppRET_OK otherwise Error.
 */
AppRET_T App_ShrdMem_Init(void)
{
    int32_t             status;
    bool result = true;
    int32_t taskErr = SystemP_SUCCESS;
    TaskP_Params appshrdmemTaskParam = { 0u };


    #ifdef Debug_Verbose2
        App_Struct_Union_Size();
    #endif

    //Init Shared memory variables later before usage

    memset_volatile(&system_discovery_status, 0x00u, sizeof(system_discovery_status));
    system_discovery_status.ModuleDiscoveryStatus = 0x01;;

    #ifdef Debug_Verbose2
        DebugP_log("[[CIP]%s  system_discovery_status.ModuleDiscoveryStatus : %#x / app_sys_discvrystsinfo.ModuleDiscoveryStatus : %#x[%" PRId64 " ms]\r\n",__func__, system_discovery_status.ModuleDiscoveryStatus,app_sys_discvrystsinfo.ModuleDiscoveryStatus,(ClockP_getTimeUsec()/1000u));
    #endif



    // Get address after translation translate *********************************************************
    spinlockBaseAddr = (uint32_t) AddrTranslateP_getLocalAddr(SPINLOCK_BASE_ADDR);

    //Event for local thread safe operation.

    status = EventP_construct(&gCAN_ModuleStatusSynchEvent);
    DebugP_assert(SystemP_SUCCESS == status);

//    /* Clearing the CANDiscoveryComplete_EVENT_BIT bits */
//    status = EventP_clearBits(&gCAN_ModuleStatusSynchEvent, (CANDiscoveryComplete_EVENT_BIT ));//| EVENT_BIT_PONG
//    DebugP_assert(SystemP_SUCCESS == status);


    status = EventP_construct(&gIOModuleAcyclicWriteEvent);
    DebugP_assert(SystemP_SUCCESS == status);

    status = EventP_construct(&gPZxModuleAcyclicWriteEvent);
    DebugP_assert(SystemP_SUCCESS == status);

    //For System Info**************************************************

    //Mutex for Accessing  Modules System Info/Config in Shared Memory
    status = SemaphoreP_constructMutex(&System_Info_mutexObj);
    DebugP_assert(status==SystemP_SUCCESS);

    // Read / Write Event for synch for SysConfigSts messages
    status = EventP_construct(&gSysConfigSts_DataRDWRSynchEvent);
    DebugP_assert(SystemP_SUCCESS == status);

    //create SystemConfig RD/WR task for Reading SystemConfigs Data from SHM
    TaskP_Params_init (&appshrdmemTaskParam);
    appshrdmemTaskParam.name        = "shm_sysconfigsts_rdtask";
    appshrdmemTaskParam.stackSize   = sizeof(APP_aShmSysConfigStsRDTaskStack_g);
    appshrdmemTaskParam.stack       = (uint8_t*)APP_aShmSysConfigStsRDTaskStack_g;
    appshrdmemTaskParam.priority    = OSAL_TASK_Prio_17;
    appshrdmemTaskParam.taskMain    = (TaskP_FxnMain)APP_SHM_SysConfigStsRDWRTask;
    appshrdmemTaskParam.args        = NULL;

    taskErr = TaskP_construct(&APP_ShmSysConfigStsRdTaskObj_g, &appshrdmemTaskParam);
    if (taskErr != SystemP_SUCCESS)
    {
        #ifdef Debug_Verbose
            DebugP_log("[APP] ERROR: Failed to create task %s (%ld)\r\n",appshrdmemTaskParam.name, taskErr);
        #endif
        TaskP_destruct(&APP_ShmSysConfigStsRdTaskObj_g);
        result = false;
    }

    //For IO Modules**************************************************

    //IO Modules Cyclic Data Process

    //Mutex for Accessing IO Modules Shared Memory
    status = SemaphoreP_constructMutex(&Cyclic_IOModules_mutexObj);
    DebugP_assert(status==SystemP_SUCCESS);
    //SemaphoreP_post(&Cyclic_IOModules_mutexObj);



    // Write semaphore for synch for IO / PZx Modules Cyclic Write messages
    SemaphoreP_constructBinary(&gSemCyclic_IOPZModule_WRSynch, 0);
    // Read semaphore for synch for IO Cyclic messages
    SemaphoreP_constructBinary(&gSemCyclic_IOModule_RDSynch, 0);

    //IO Modules ACyclic Data Process

    status = SemaphoreP_constructMutex(&ACyclic_IOModules_mutexObj);
    DebugP_assert(status==SystemP_SUCCESS);

    // Update Event for synch for ACyclic messages
    status = EventP_construct(&gACyclic_IOModule_SynchEvent);
    DebugP_assert(SystemP_SUCCESS == status);

    //Read Resp Event
    status = EventP_construct(&gACyclic_IOModule_RDRespEvent);
    DebugP_assert(SystemP_SUCCESS == status);


    //create IO Modules WR task for Writing ACyclic Messages to SHM
    TaskP_Params_init (&appshrdmemTaskParam);
    appshrdmemTaskParam.name        = "shm_iomodules_acyclicwrtask";
    appshrdmemTaskParam.stackSize   = sizeof(APP_aShmIOACyclicWRTaskStack_g);
    appshrdmemTaskParam.stack       = (uint8_t*)APP_aShmIOACyclicWRTaskStack_g;
    appshrdmemTaskParam.priority    = OSAL_TASK_Prio_12;
    appshrdmemTaskParam.taskMain    = (TaskP_FxnMain)APP_SHM_IOACyclicWRTask;
    appshrdmemTaskParam.args        = NULL;

    taskErr = TaskP_construct(&APP_ShmAIOACyclicWrTaskObj_g, &appshrdmemTaskParam);
    if (taskErr != SystemP_SUCCESS)
    {
        #ifdef Debug_Verbose
            DebugP_log("[APP] ERROR: Failed to create task %s (%ld)\r\n",appshrdmemTaskParam.name, taskErr);
        #endif
        TaskP_destruct(&APP_ShmAIOACyclicWrTaskObj_g);
        result = false;
    }

    //create IO Modules RD task For Reading ACyclic Messages from SHM

    //create IO Modules ParamUpdate task For Updating ACyclic Parameters from SHM
    TaskP_Params_init (&appshrdmemTaskParam);
    appshrdmemTaskParam.name        = "shm_iomodules_acyclicupdttask";
    appshrdmemTaskParam.stackSize   = sizeof(APP_aShmIOACyclicUpdateTaskStack_g);
    appshrdmemTaskParam.stack       = (uint8_t*)APP_aShmIOACyclicUpdateTaskStack_g;
    appshrdmemTaskParam.priority    = OSAL_TASK_Prio_13;
    appshrdmemTaskParam.taskMain    = (TaskP_FxnMain)APP_SHM_IOACyclicUpdateTask;
    appshrdmemTaskParam.args        = NULL;

    taskErr = TaskP_construct(&APP_ShmIOACyclicUpdateTaskObj_g, &appshrdmemTaskParam);
    if (taskErr != SystemP_SUCCESS)
    {
        #ifdef Debug_Verbose
            DebugP_log("[APP] ERROR: Failed to create task %s (%ld)\r\n",appshrdmemTaskParam.name, taskErr);
        #endif
        TaskP_destruct(&APP_ShmIOACyclicUpdateTaskObj_g);
        result = false;
    }

    //(void)result;
    //For IO Modules**************************************************

    //DebugP_log("[[CIP] IOCyclic_Inst_x : %#x \r\n",&IOCyclic_Inst_x);


    //For PZx STND-VAL/ISEM-DIAG/DIAGVALVE/INTRPROP/EXTRPROP**************************************************

       status = SemaphoreP_constructMutex(&Cyclic_PZx_mutexObj);
       DebugP_assert(status==SystemP_SUCCESS);

       status = SemaphoreP_constructMutex(&ACyclic_PZx_mutexObj);
       DebugP_assert(status==SystemP_SUCCESS);

    //Mutex for local thread safe operation on spinlock*************************************************

    status = EventP_construct(&gACyclic_PZxModule_SynchEvent);
    DebugP_assert(SystemP_SUCCESS == status);

    status = EventP_construct(&gACyclic_PZxModule_RDRespEvent);
    DebugP_assert(SystemP_SUCCESS == status);


    //create IO Modules ParamUpdate task For Updating ACyclic Parameters from SHM
    TaskP_Params_init (&appshrdmemTaskParam);
    appshrdmemTaskParam.name        = "shm_pzxmodules_acyclicupdttask";
    appshrdmemTaskParam.stackSize   = sizeof(APP_aShmPZxACyclicUpdateTaskStack_g);
    appshrdmemTaskParam.stack       = (uint8_t*)APP_aShmPZxACyclicUpdateTaskStack_g;
    appshrdmemTaskParam.priority    = OSAL_TASK_Prio_13;
    appshrdmemTaskParam.taskMain    = (TaskP_FxnMain)APP_SHM_PZxACyclicUpdateTask;
    appshrdmemTaskParam.args        = NULL;

    taskErr = TaskP_construct(&APP_ShmPZxACyclicUpdateTaskObj_g, &appshrdmemTaskParam);
    if (taskErr != SystemP_SUCCESS)
    {
        #ifdef Debug_Verbose
            DebugP_log("[APP] ERROR: Failed to create task %s (%ld)\r\n",appshrdmemTaskParam.name, taskErr);
        #endif
       TaskP_destruct(&APP_ShmPZxACyclicUpdateTaskObj_g);
       result = false;
    }

    TaskP_Params_init (&appshrdmemTaskParam);
    appshrdmemTaskParam.name        = "shm_pzxmodules_acyclicwrtask";
    appshrdmemTaskParam.stackSize   = sizeof(APP_ShmPZxACyclicWRTaskStack_g);
    appshrdmemTaskParam.stack       = (uint8_t*)APP_ShmPZxACyclicWRTaskStack_g;
    appshrdmemTaskParam.priority    = OSAL_TASK_Prio_12;
    appshrdmemTaskParam.taskMain    = (TaskP_FxnMain)APP_SHM_PZxACyclicWRTask;
    appshrdmemTaskParam.args        = NULL;

    taskErr = TaskP_construct(&APP_ShmPZxACyclicWrTaskObj_g, &appshrdmemTaskParam);
    if (taskErr != SystemP_SUCCESS)
    {
        #ifdef Debug_Verbose
            DebugP_log("[APP] ERROR: Failed to create task %s (%ld)\r\n",appshrdmemTaskParam.name, taskErr);
        #endif
        TaskP_destruct(&APP_ShmPZxACyclicWrTaskObj_g);
        result = false;
    }

    //MBN related
    status = SemaphoreP_constructMutex(&mbn_mutexObj);
    DebugP_assert(status==SystemP_SUCCESS);

    SemaphoreP_constructBinary(&mbn_datasyncObj, 0);
    DebugP_assert(status==SystemP_SUCCESS);



    #ifdef Debug_Verbose
        DebugP_log("[[CIP] Exit %s \r\n",__func__);
    #endif

    if(result == false) {
        return  AppSharedMem_InitErr;
    }

    return AppRET_OK;

}

