
#include <stdio.h>
#include <ti/csl/src/intc/csl_intc.h>
#include <ti/csl/src/intc/csl_intcAux.h>
#include <ti/csl/src/intc/cslr_intc.h>
#include <ti/csl/src/intc/_csl_intc.h>
#include <ti/csl/cslr_chip.h>
#include <ti/csl/soc.h>
#include <ti/csl/csl_sem.h>
#include <ti/csl/csl_semAux.h>
#include <ti/csl/cslr_sem.h>
#include <ti/csl/cslr_device.h>
#include <ti/csl/csl_cache.h>
#include <ti/csl/csl_cacheAux.h>
#include <c6x.h>

#define TEST_SEMAPHORE_NUM  10

#pragma DATA_SECTION (timeSyncMark, ".sync");
Uint32                      timeSyncMark = 0;

CSL_IntcHandle              intcHandle;
Uint32                      flag;
Uint32                      isrFinished = 0;

/* INTC Parameter */
CSL_IntcContext 			intcContext;
CSL_IntcEventHandlerRecord	EventHandler[30];
CSL_Status					intStat;
CSL_IntcObj 				intcObj;
CSL_IntcHandle				hnd;
CSL_IntcEventHandlerRecord	EventRecord;	
CSL_IntcGlobalEnableState	state;	
CSL_IntcParam				vecId;
CSL_IntcEventId 			evtId;

static void interruptISR ()
{

    flag = CSL_semGetFlags(DNUM);

    CSL_semClearFlags(DNUM, flag);

    CSL_semSetEoi(TEST_SEMAPHORE_NUM);
    
    /**************************************************************/

    /* Disable the interrupts. */    
    CSL_intcHwControl(intcHandle, CSL_INTC_CMD_EVTDISABLE, NULL);
      
    /* Close the Interrupt Handles. */
    CSL_intcClose(intcHandle);    

    isrFinished = 1;

}

static Uint32 configInterrupt (CSL_IntcEventHandler isr, CSL_IntcParam vectId, CSL_IntcEventId eventId)
{

   /************************************************
     ****************** INTC Configuration **************** 
     ************************************************/
    
    printf("Core %d Debug: INTC initialization start ...\n", DNUM);
    
    /* INTC module initialization */
    intcContext.eventhandlerRecord = EventHandler;
    intcContext.numEvtEntries      = 10;
    
    if (CSL_intcInit(&intcContext) != CSL_SOK) 
    {
        printf("Core %d Error: GEM-INTC initialization failed\n", DNUM);
        return -1;
    }    

    /* Enable NMIs */
    if (CSL_intcGlobalNmiEnable() != CSL_SOK) 
    {
        printf("Core %d Error: GEM-INTC global NMI enable failed\n", DNUM);
        return -1;
    }

    /* Enable global interrupts */
    if ((intStat = CSL_intcGlobalEnable(&state)) != CSL_SOK) 
    {
        printf ("Core %d Error: GEM-INTC global enable failed\n", DNUM);
        return -1;
    }

    /* Open the INTC Module for Vector ID and Event ID 
      *Refer to the interrupt architecture and mapping document for the Event ID */

    hnd = CSL_intcOpen (&intcObj, eventId, &vectId, &intStat);
    if (hnd == NULL) 
    {
        printf("Core %d Error: GEM-INTC Open failed\n", DNUM);
        return -1;
    }

    /* Register an call-back handler which is invoked when the event occurs. */
    EventRecord.handler = isr;
    EventRecord.arg = (void *)vectId;
    
    if (CSL_intcPlugEventHandler(hnd,&EventRecord) != CSL_SOK) 
    {
        printf("Core %d Error: GEM-INTC Plug event handler failed\n", DNUM);
        return -1;
    }

    /* Clear the before event */
    if (CSL_intcHwControl(hnd, CSL_INTC_CMD_EVTCLEAR, NULL) != CSL_SOK) 
	{
		printf("Core %d Error: GEM-INTC CSL_INTC_CMD_EVTCLEAR command failed\n", DNUM);
		return -1;
	}

	/* Enable the event */
	if (CSL_intcHwControl(hnd, CSL_INTC_CMD_EVTENABLE, NULL) != CSL_SOK) 
	{
		printf("Core %d Error: GEM-INTC CSL_INTC_CMD_EVTENABLE command failed\n", DNUM);
		return -1;
	}
    
    printf("Core %d Debug: INTC initialization finished ...\n", DNUM);

    return 0;

}


static Uint32 test_hardware_semaphore ()
{

    Uint32                      timeLoad = 100000;
    Uint32                      result;
    
    printf ("**************************************************\n");
    printf ("************* Hardware Semaphore tset ************\n");
    printf ("**************************************************\n");
    
    /**************************************************************
     ********************** hardware demaphore related code ***************
     **************************************************************/
   
    if (DNUM == 0)
    {

        /* Lock Core 1 before Core 0 finished the operation */
        timeSyncMark = 1;
        
        CACHE_wbL1d(&timeSyncMark, 4, CACHE_WAIT);

        /* Check for the semaphore you want to use is available or not */
        if (CSL_semIsFree(TEST_SEMAPHORE_NUM) != 1)
        {
            printf("Core %d Error: The Semaphore %d is not free\n", DNUM, TEST_SEMAPHORE_NUM);
            return -1;
        }

        /* Start request for a direct hardware semaphore */        
        if (CSL_semAcquireDirect(TEST_SEMAPHORE_NUM) != 1)
        {
            printf("Core %d Error: The Semaphore %d is not available\n", DNUM, TEST_SEMAPHORE_NUM);
            return -1;
        }
        else
        {
            printf("Core %d Debug: The Semaphore %d is requested in direct mode\n", DNUM, TEST_SEMAPHORE_NUM);
        }

        result = CSL_semGetResourceOwner(TEST_SEMAPHORE_NUM);
        
        printf("Core %d Debug: The Semaphore %d is now requested by master %d\n", DNUM, TEST_SEMAPHORE_NUM, result);
        
        /* Core 0 finished the operation and Core 1 can continue*/
        timeSyncMark = 0;
        
        CACHE_wbL1d(&timeSyncMark, 4, CACHE_WAIT);

        /* Wait a long time to let Core1 pend semaphore then Core 0 release this semaphore to generate Core1's event*/
        while(timeLoad)
        {
            timeLoad--;
        }

        CSL_semReleaseSemaphore(TEST_SEMAPHORE_NUM);
        
        if(CSL_semIsFree(TEST_SEMAPHORE_NUM) == 0) 
        {
            printf("Core %d Debug: The Semaphore %d is not free\n", DNUM, TEST_SEMAPHORE_NUM);
        }
        else
        {
            printf("Core %d Debug: The Semaphore %d is free\n", DNUM, TEST_SEMAPHORE_NUM);
        }
        
        result = CSL_semGetResourceOwner(TEST_SEMAPHORE_NUM);
        
        printf("Core %d Debug: The Semaphore %d is now requested by master %d\n", DNUM, TEST_SEMAPHORE_NUM, result);
        
    }

    if (DNUM == 1)
    {
        
        /* Hardware semaphore output core event 16 */
        evtId = CSL_GEM_SEMINTN;
        
        /* Pick a interrupt vector id to use */
        vecId = CSL_INTC_VECTID_12;

        result = configInterrupt((CSL_IntcEventHandler)&interruptISR, (CSL_IntcParam)vecId, (CSL_IntcEventId)evtId);

        if(result < 0)
        {
            printf("Core %d Error: TINTC initialization FAILED\n", DNUM);
            return -1;
        }
        else
        {
            printf("Core %d Debug: TINTC initialization PASSED\n", DNUM);
        }
        
        /* Wait for Core 0 finished */
        while(timeSyncMark)
        {
            CACHE_invL1d(&timeSyncMark, 4, CACHE_WAIT);
        };

        /* Core 1 can continue running */
        if(CSL_semIsFree(TEST_SEMAPHORE_NUM) == 0) 
        {
            printf("Core %d Debug: The Semaphore %d is not free\n", DNUM, TEST_SEMAPHORE_NUM);
        }
        else
        {
            printf("Core %d Debug: The Semaphore %d is free\n", DNUM, TEST_SEMAPHORE_NUM);
        }

        result = CSL_semGetResourceOwner(TEST_SEMAPHORE_NUM);
        
        printf("Core %d Debug: The Semaphore %d is now requested by master %d\n", DNUM, TEST_SEMAPHORE_NUM, result);

        /* Start request for a indirect hardware semaphore */
        CSL_semAcquireIndirect(TEST_SEMAPHORE_NUM);
        
        printf("Core %d Debug: The Semaphore %d is requested in indirect mode\n", DNUM, TEST_SEMAPHORE_NUM);

        while(1)
        {
            if(isrFinished == 1)
                break;
        }
        
    }

    /* Test has been completed successfully. */
    return 0;

}


/**
 *  @b Description
 *  @n  
 *      The main code.
 *
 *  @retval
 *      Not Applicable.
 */
void main (void)
{    


    /* Start the test */
    if (test_hardware_semaphore() < 0)
    {
        printf("Core %d Error: Testing hardware semaphore FAILED\n", DNUM);
        return;
    }
    printf("Core %d Debug: Testing hardware semaphore Passed\n", DNUM);

   
    /* All the tests have passed. */
    printf ("**************************************************\n");
    printf ("******** Hardware Semaphore tset finished ********\n");
    printf ("**************************************************\n");

    return; 
    
}


