Migrating DCI Applications to CToolsLib/CodeExample

From Texas Instruments Wiki
Jump to: navigation, search

Code Example

Overview

This example details the migration of an Application using DCI to an equivalent application using the CToolsLib family of libraries. In both cases, the application is attempting to capture trace data into the Embedded Trace Buffer while the Program Counter is within a specified range. Once the data is captured, the application will read it out of the Embedded trace buffer and store it in a binary file on the host in the same directory as the .out file. The same flow executes two times and generates two .bin files which can then be translated into human readable trace output by using a utility called bin2tdf supplied with Code Composer Studio.

Header Section

Note the removal of the DCI header file, and the inclusions of the header files of the CToolsLib libraries that we will need for this specific task.

DCI CToolsLib
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dci.h>
#include <c6x.h>
#include <tistdtypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <c6x.h>
#include <tistdtypes.h>
#include <aet.h>
#include "DSPTraceExport.h"
#include "ETBInterface.h"

Parameter Structures And Variables

It up to the user to decide how to allocate these variables, as global or local. With CToolsLib, there are parameters structures for each of the libraries used.

DCI CToolsLib
/* ======== DCI command structure ======== */
DCI_Command dciCmd;
/* Trace Configuration Parameters */
DCI_TraceConfig trcCfg;
 
DCI_Config dciCfg = DCI_CONFIG_DEFAULT;  /* Initialize to defaults */
DCI_ActionRange parTrcRange;  /*
/* ======== AETLib Related Variables ======== */
AET_jobParams traceRangeParams = AET_JOBPARAMS;
    /* Parameters Structure Initialized to defaults */
 
AET_jobIndex traceRangeJob;                   
    /* Job Index Variable */
 
AET_error aetRet;                             
    /* Function Return Status */
 
 
/* ======== ETBLib Related Variables ======== */
eETB_Error  etbRet;                           
    /* ETBLib Error Code */
 
ETB_errorCallback pETBErrCallBack =0;         
    /* Pointer to Error Callback Function */
 
ETBHandle* pETBHandle[NUM_CORES];             
    /* Array of pointers to ETB Interface
       Handle (one per core) */
 
/* ======== DSPTraceLib Related Variables ======== */
eDSPTrace_Error dspRet;                       
    /* DSPTraceLib Error Code */
 
DSPTrace_errorCallback pDSPErrorCallBack=0;   
    /* Pointer to Error Callback Function */
 
DSPTraceHandle* pDSPHandle=0;                 
    /* DSPTraceLib Interface Handle */


DoTest Function

DCI CToolsLib
Uint32 doTest()
{
  Uint32 callCnt, dNum;
 
    /* DCI config structure */
    DCI_Config dciCfg = DCI_CONFIG_DEFAULT;
 
    /* Trigger Event Parameters */
    DCI_ActionRange parTrcRange;
    Uint32 iter;
 
    /* ======== Initialize the Trace PLL ======== */
  trace_pll_init(PLL_DIV_VALUE);
 
 
  /* ======== Configure ETB Parameters ======== */
 
  dciCfg.etbDrainBuffer = drainBuffer;
      /* Set the location where the ETB data
         will be drained to */
 
  dciCfg.etbDrainBufferSize = DRAINBUF_SIZE;
        /* Set the size of the ETB drain buffer.
           This should be at least the size of
           the ETB which is device dependent. */
 
  dciCfg.etbDrainNumWords = 1023;
      /* Set the number of words in the ETB drain
         again, this is device dependent.  For the
         TMS320C6474, this is 1023.  For the
         TMS320C6472, this is 511.  */
 
 
  /* ======== Initialize DCI =======*/
  if (DCI_open(&dciCfg)!=DCI_STATUS_OK)
  {
      printf ("Could not open DCI.\n");
      return 1;
  }
 
 
  /* ======== Configrue Trace Params ========*/
  trcCfg.cpuStallEnable         = 0;
  trcCfg.cpuStallDbgmEnable     = 0;
  trcCfg.cpuStallHpiEnable     = 0;
  trcCfg.mode                 = DCI_TRCMODE_NORMAL;
  trcCfg.timingStreamEnable     = timingStream;
  trcCfg.pcStreamEnable         = pcStream;
  trcCfg.readStreamEnable     = readStream;
  trcCfg.writeStreamEnable     = writeStream;
 
  /* ======== Enable ETB ======== */
    dciCmd.command = DCI_CMD_ETB_ENABLE;
    DCI_control(&dciCmd, &trcCfg);
    if (dciCmd.status!=DCI_STATUS_OK)
    {
        printf ("Could not enable ETB (status = 0x%x).\n",dciCmd.status);
        return 1;
    }
 
    /* Do two trials */
    for(iter=0; iter<2; iter++)
    {
        /* Initialize output buffers */
      initBuffers();
 
        /* Reset ETB */
        dciCmd.command = DCI_CMD_ETB_RESET;
        DCI_control(&dciCmd, &dNum);
        if (dciCmd.status!=DCI_STATUS_OK)
        {
            printf ("Could not reset ETB (status = 0x%x).\n",dciCmd.status);
            return 1;
        }
 
        /* ======== Claim the AET resource ======== */
        dciCmd.command = DCI_CMD_AET_CLAIM;
        DCI_control(&dciCmd, NULL);
        if (dciCmd.status!=DCI_STATUS_OK)
        {
            printf ("Could not claim AET (status = 0x%x).\n",dciCmd.status);
            return 1;
        }
 
      /* ======== Set the trigger parameters ========*/
        parTrcRange.triggerType = DCI_TRIG_TRCA;
        parTrcRange.startAddr = (Uint32)&func_dummy;
        parTrcRange.endAddr = (Uint32)&func_dummy + (Uint32)&func_dummy_size;
        parTrcRange.trig.pc=pcStream;
        parTrcRange.trig.timing=timingStream;
        parTrcRange.trig.rAddr=readStream;
        parTrcRange.trig.wAddr=writeStream;
        parTrcRange.trig.rData=readStream;
        parTrcRange.trig.wData=writeStream;
        parTrcRange.trig.pcTag=(readStream&pcStream)|(writeStream&pcStream);
 
        /* Adjust to last non-zero instruction */
        /* Note we use -ml3 and --no_compress to get
          rid of trampolines and fp headers */
        while (!*(Uint8*)(parTrcRange.endAddr-=4));
 
        /* ======== Program the action range ======== */
        dciCmd.command = DCI_CMD_AET_PAR;
 
        DCI_control(&dciCmd, &parTrcRange);
 
        if (dciCmd.status!=DCI_STATUS_OK)
        {
            printf ("Could not configure program action range (status = 0x%x).\n",dciCmd.status);
            return 1;
        }
 
        /* ======== Enable AET ======== */
      dciCmd.command = DCI_CMD_AET_ENABLE;
        DCI_control(&dciCmd, NULL);
        if (dciCmd.status!=DCI_STATUS_OK)
        {
            printf ("Could not enable AET (status = 0x%x).\n",dciCmd.status);
            return 1;
        }
 
        /* Loop for NUM_CALLS iterations */
        for(callCnt=0;callCnt<NUM_CALLS;callCnt++)
        {
            func_dummy();
 
            /* Read all trace data from ETB */
            if (drainEtb()) return 1;
        }
 
        /* Send the rest of traced data into output buffer */
        sendBuffer(nDrainedWords);
 
        /* Dump drain buffer to file */
        dumpTraceToFile(iter+1);
 
      /* ======== Clear AET jobs ======== */
        dciCmd.command = DCI_CMD_AET_CLEAR_JOB;
        DCI_control(&dciCmd, &parTrcRange);
        if (dciCmd.status!=DCI_STATUS_OK)
        {
            printf ("Could not clear program action range (status = 0x%x).\n",dciCmd.status);
            return 1;
        }
 
        /* ======== Release AET ======== */
        dciCmd.command = DCI_CMD_AET_RELEASE;
        DCI_control(&dciCmd, NULL);
        if (dciCmd.status!=DCI_STATUS_OK)
        {
            printf ("Could not release AET (status = 0x%x).\n",dciCmd.status);
            return 1;
        }     
 
    }
 
  /* ======== Disable ETB ======== */
    dciCmd.command = DCI_CMD_ETB_DISABLE;
    DCI_control(&dciCmd, NULL);
    if (dciCmd.status!=DCI_STATUS_OK)
    {
      printf ("Could not disable ETB (status = 0x%x).\n",dciCmd.status);
      return 1;
    }
 
    /* ======== Close DCI ======== */
    if (DCI_close()!=DCI_STATUS_OK)
    {
      printf ("Could not close DCI (status = 0x%x).\n",dciCmd.status);
      return 1;
    }
Uint32 callCnt, dNum, i;
 
    ETB_errorCallback pETBErrCallBack =0;
 
    Uint32 etbWidth;
 
    eDSPTrace_Error dspRet;
    DSPTrace_errorCallback pDSPErrorCallBack=0;
    DSPTraceHandle* pDSPHandle=0;
 
    /* jobParams Structure for the Trace in range job */
    AET_jobParams traceRangeParams = AET_JOBPARAMS;
 
    /* jobIndex holders for the Trace in range job */
    AET_jobIndex traceRangeJob;
    AET_error aetRet;
 
    Uint32 iter;
 
    dNum = DNUM;
 
    setMPAX();
  syncPtr = (Uint32*)(0xD0000000 + (Uint32)&syncPoint - 0x0C000000);
 
  /* Initialize trace word counters */
  for (i=0; i<NUM_CORES; i++) nTotalTraceWords[i] = 0;
 
  /* ======== Initialize the Trace PLL ======== */
  /* In CToolsLib, this functionality comes from
     DSPTraceLib.  This PLL will get initialized
     later, when we call DSPTrace_setClock() */
 
  /* ======== Configure ETB Parameters ======== */
  /* Since we're using ETBLib, we don't need to
     specify the drain buffer location and size
     ahead of time.  This can be done later.
     What we will do here is to initialize  and
     enable all of the libraries that we are
     using.   */
 
    /*** Setup ETB receiver ***/
    /* Open the ETB Interface on each core */
    for (i=0; i<NUM_CORES; i++)
    {
        etbRet = ETB_open(pETBErrCallBack, eETB_Circular, (Uint8)i, &pETBHandle[i], &etbWidth);
        if(etbRet != eETB_Success)
        {
            printf("Error opening ETB%d (status = 0x%x).\n",i,etbRet);
            return 1;
        }
    }
 
    /* Enable ETB receiver On This Core */
    etbRet = ETB_enable(pETBHandle[dNum], 0);
    if(etbRet != eETB_Success)
    {
        printf("Error enabling ETB (status = 0x%x).\n",etbRet);
        return 1;
    }
 
    /*** Setup Trace Export ***/
 
    /* Open DSP Trace export module */
    dspRet = DSPTrace_open( pDSPErrorCallBack, &pDSPHandle);
    if(dspRet != eDSPTrace_Success)
    {
        printf("Error opening DSP Trace Export block (status = 0x%x).\n",dspRet);
        return 1;
    }
    /* Setup trace export clock to FCLK/3 */
    dspRet= DSPTrace_setClock(pDSPHandle, PLL_DIV_VALUE);
    if(dspRet != eDSPTrace_Success)
    {
        printf("Error setting up DSP trace export clock (status = 0x%x).\n",dspRet);
        return 1;
    }
 
    dspRet= DSPTrace_enable(pDSPHandle, 0, 0);
 
    if(dspRet != eDSPTrace_Success)
    {
        printf("Error enabling DSP trace export (status = 0x%x).\n",dspRet);
        return 1;
    }
 
    /* Init the AET resource */
    AET_init();
 
 
    /* Sync the cores */
    if (dNum == 0)
    {
        *syncPtr = 1;
        while(*syncPtr<NUM_CORES);
    }   
    else if (dNum == 1)
    {
        while (*syncPtr<1);
        *syncPtr = 2;
        while(*syncPtr<NUM_CORES);
    }   
    else if (dNum == 2)
    {
        while (*syncPtr<2);
        *syncPtr = 3;
        while (*syncPtr<NUM_CORES);
    }   
    else if (dNum == 3)
    {
        while (*syncPtr<3);
        *syncPtr = 4;
        while (*syncPtr<NUM_CORES);
    }   
 
    /* Do one trial.  At this point, nothing will
       be traced because we haven't yet configured
       AET to generate any triggers. So, while the
       ETB is listening, and Trace is configured
       to output to the ETB, there are no triggers
       to start/stop trace */
 
    for(iter=0; iter<1; iter++)
    {
      printf("Test iteration started on core %d\n",dNum);
 
        /* Initialize output buffers */
        if (dNum==0) initBuffers();
 
        /* Reset ETB (disable --> enable ETB receiver */
        etbRet = ETB_disable(pETBHandle[dNum]);
        if(etbRet != eETB_Success)
        {
            printf("Error disabling ETB 1 (status = 0x%x).\n",etbRet);
            return 1;
        }
        etbRet = ETB_enable(pETBHandle[dNum],0);
        if(etbRet != eETB_Success)
        {
            printf("Error enabling ETB (status = 0x%x).\n",etbRet);
            return 1;
        }
 
 
        /* Claim the AET resource */
        if (aetRet = AET_claim())
        {
            printf("Error claiming AET resources (status = 0x%x).\n",aetRet);
            return 1;
        }
 
        /* Set the trigger parameters */
      traceRangeParams.traceActive = AET_TRACE_ACTIVE;
        traceRangeParams.traceStartAddress = (Uint32)&func_dummy;
      traceRangeParams.traceEndAddress = (Uint32)&dummyfunc;
        /* Adjust to last non-zero instruction */
        /* Note we use -ml3 and --no_compress
            to get rid of trampolines and fp headers */
        while (!*(Uint8*)(traceRangeParams.traceEndAddress-=4));
 
        traceRangeParams.traceTriggers = timingStream*AET_TRACE_TIMING |
                                         pcStream*AET_TRACE_PA |
                                         readStream*AET_TRACE_RA |
                                         readStream*AET_TRACE_RD |
                                         writeStream*AET_TRACE_WA |
                                         writeStream*AET_TRACE_WD |
                                         readStream*AET_TRACE_RA |
                                         ((readStream&pcStream)|(writeStream&pcStream))*AET_TRACE_PCTAG;
 
        /* Set up the Trace Start job */
        if (aetRet = AET_setupJob(
                     AET_JOB_TRACE_IN_PC_RANGE,
                     &traceRangeParams))
        {
            printf("Error: could not setup AET job (status = 0x%x).\n",aetRet);
            return 1;
        }
 
        /* Remember the Number of the Trace Job */
        traceRangeJob = traceRangeParams.jobIndex;
 
        printf("The Trace in Range Job index is %d\n", traceRangeJob);
 
        /* Enable AET */
        if (aetRet = AET_enable())
        {
            printf("Error: could not enable AET (status = 0x%x).\n",aetRet);
            return 1;
        }
 
        /* Loop for NUM_CALLS iterations */
        for(callCnt=0;callCnt<NUM_CALLS;callCnt++)
        {
            func_dummy();
 
        }
 
        /* Sync the cores */
        if (dNum == 0)
        {
            *syncPtr = NUM_CORES+1;
            while(*syncPtr<2*NUM_CORES);
        }   
        else if (dNum == 1)
        {
            while (*syncPtr<NUM_CORES+1);
            *syncPtr = NUM_CORES+2;
            while(*syncPtr<2*NUM_CORES+1);
        }   
        else if (dNum == 2)
        {
            while (*syncPtr<NUM_CORES+2);
            *syncPtr = NUM_CORES+3;
            while (*syncPtr<2*NUM_CORES+1);
        }   
        else if (dNum == 3)
        {
            while (*syncPtr<NUM_CORES+3);
            *syncPtr = NUM_CORES+4;
            while (*syncPtr<2*NUM_CORES+1);
        }   
 
        if (dNum==0)
        {
            /* Drain the ETBs of other cores*/
          /* Read all trace data from ETB */
            for (i=0; i < NUM_CORES; i++)
               if (drainEtb(i)) return 1;
 
            /* Dump drain buffer to file */
            for (i=0; i < NUM_CORES; i++)
                dumpTraceToFile(iter+1,i);
 
            *syncPtr = 2*NUM_CORES+1;
        }
 
        /* Clear AET jobs */
        AET_releaseJob(traceRangeJob);
        /* Release AET */
        AET_release();   
    }
 
    etbRet = ETB_disable(pETBHandle[dNum]);
    if(etbRet != eETB_Success)
    {
        printf("Error disabling ETB 3 (status = 0x%x).\n",etbRet);
        return 1;
    }
 
    /* Disable DSP Trace Export */
    dspRet= DSPTrace_disable(pDSPHandle);
    if(dspRet != eDSPTrace_Success)
    {
        printf("Error disabling DSP trace export (status = 0x%x).\n",dspRet);
        return 1;
    }
 
    /*** Now we are done and close all the handles **/
    etbRet  = ETB_close(pETBHandle[dNum]);
    if(etbRet != eETB_Success)
    {
        printf("Error closing ETB (status = 0x%x).\n",etbRet);
        return 1;
    }
 
 
    dspRet= DSPTrace_close(pDSPHandle);
    if(dspRet != eDSPTrace_Success)
    {
        printf("Error closing DSP trace export module (status = 0x%x).\n",dspRet);
        return 1;
    }
 
    AET_releaseJob(traceRangeJob);
    AET_release();   
 
    return 0;

Auxilliary Functions

DCI CToolsLib
void trace_pll_init (
    Uint32 div_val
)
{
    /* turn on trace clock from PLL here. */
    volatile Uint32 *pllcmd_addr = (volatile Uint32 *)0x029A0138;
    volatile Uint32 *pllstat_addr = (volatile Uint32 *)0x029A013C;
    volatile Uint32 *plldiv_addr = (volatile Uint32 *)0x029A0184;
 
    /* Wait for any concurrent GOSET to complete */
    while (*pllstat_addr&0x1);
 
    /* PLLDIV register value:
    bit 4:0 -- ratio = 00011b (/4), 11111b (/32)
    bit 15 -- DnEn = 1 */
    /* PLL divider value could be from 1 to 32. */
 
    *plldiv_addr = (1<<15) | (div_val-1);
 
    /* PLLCMD register value:
    bit 1 -- GOSET */
    *(unsigned int*)pllcmd_addr = 0x1;
 
    return;
}
 
void func_dummy()
{
  Uint32 i;
 
  for (i=0;i<ARRAY_SIZE;i++)
  {
    array1[i] = rand();
  }
 
  for (i=0;i<ARRAY_SIZE-1;i++)
  {
    array2[i] = array1[i+1]/3 + array1[i]/5;
  }
}
 
void func_dummy_kick()
{
  return;
}
 
 
void dumpTraceToFile(Uint32 testNum)
{
    Uint32 *p, i;
    char filename[20];
    sprintf(filename,"myfile%d.bin\0",testNum);
 
    fid = fopen(filename,"wb");
    /* Dump drain buffer to file */
    p=traceOutputBuffer;
    for (i=0;i<nTotalTraceWords;i++)
        fwrite32(*(p++),fid); //fwrite(p++,4,1,fid);
    fflush(fid);
    fclose(fid);
}
 
void sendBuffer(Uint32 nWords)
{
    memcpy(&traceOutputBuffer[nTotalTraceWords],&drainBuffer,nWords*4);
    nTotalTraceWords+=nWords;       
}
 
Uint32 drainEtb()
{
    drainParams.etbInstanceNumber = DNUM;
    dciCmd.command = DCI_CMD_ETB_DRAIN;
    do{
        DCI_control(&dciCmd, &drainParams);
        if (dciCmd.status != DCI_STATUS_OK)
        {
            printf ("Drain ETB failed (status = 0x%x).\n",dciCmd.status);
            return 1;
        }
        nDrainedWords += drainParams.nWordsRead;
        if (drainParams.etbDrainBufferFull)
        {
            sendBuffer(nDrainedWords);
            nDrainedWords = 0;
        }
    } while(!drainParams.etbEmpty);
 
 
    return 0;
}
 
void initBuffers()
{
    memset(drainBuffer,0,2*DRAINBUF_SIZE);
    memset(traceOutputBuffer,0,2*DRAINBUF_SIZE*4);
    nTotalTraceWords = 0;
    nDrainedWords = 0;
}
void func_dummy()
{
  Uint32 i, dnum;
 
 dnum=DNUM;
 
  for (i=0;i<ARRAY_SIZE;i++)
  {
    if (dnum==0)
       array1[i]=rand();
    else if (dnum==1)
       array1[i]=i*i;
    else if (dnum==2)
       array1[i]=i^0xFFFF;
    else if (dnum==3)
       array1[i]=_lmbd(1,i);
  }
 
  for (i=0;i<ARRAY_SIZE-1;i++)
  {
    array2[i] = array1[i+1]/3 + array1[i]/5;
  }
#if defined(__TI_ELFABI__)
  asm ("dummyfunc:");  /* This label marks the end of func1(); */
#else // COFF ABI
  asm ("_dummyfunc:");  /* This label marks the end of func1(); */
#endif
}
 
void dumpTraceToFile(Uint32 testNum, Uint32 etbNum)
{
    Uint32 *p, i;
    char filename[20];
    sprintf(filename,"etb%d_test%d.bin\0",etbNum,testNum);
 
    fid = fopen(filename,"wb");
    /* Dump drain buffer to file */
    p=&traceOutputBuffer[0][etbNum];
    for (i=0;i<nTotalTraceWords[etbNum];i++)
        fwrite32(*(p++),fid); //fwrite(p++,4,1,fid);
    fflush(fid);
    fclose(fid);
}
 
void sendBuffer(Uint32 nWords, Uint32 etbNum)
{
    memcpy(&traceOutputBuffer[nTotalTraceWords[etbNum]][etbNum],drainBuffer,nWords*4);
    nTotalTraceWords[etbNum]+=nWords;       
}
 
Uint32 drainEtb(Uint32 etbNum)
{
    ETBStatus etbStatus;
  Uint32 retSize=0;
 
/* Now disable trace capture - ETB receiver */
    etbRet = ETB_disable(pETBHandle[etbNum]);
    if(etbRet != eETB_Success)
    {
        printf("Error disabling ETB 2 (status = 0x%x).\n",etbRet);
        return 1;
    }
 
    /*** Get ETB data ***/
    /* Check the ETB status */
    etbRet= ETB_status(pETBHandle[etbNum], &etbStatus);
    if(etbRet != eETB_Success)
    {
        printf("Error getting ETB status (status = 0x%x).\n",etbRet);
        return 1;
    }
 
    if(etbStatus.canRead == 1)
    {
        if(etbStatus.isWrapped == 1)
            printf ("ETB is wrapped; ETB words = %d\n", etbStatus.availableWords);
        else
            printf ("ETB is not wrapped; ETB words = %d\n", etbStatus.availableWords);
 
        etbRet = ETB_read(pETBHandle[etbNum], drainBuffer, etbStatus.availableWords, 0, etbStatus.availableWords, &retSize);
        if(etbRet != eETB_Success)
        {
            printf("Error reading ETB data (status = 0x%x).\n",etbRet);
            return 1;
        }
        sendBuffer(etbStatus.availableWords,etbNum);
    }
    else
    {
        printf("Error reading ETB: ETB status was not readable\n");
        return 1;
    }
 
/* Now re-enable trace capture - ETB receiver */
    etbRet = ETB_enable(pETBHandle[etbNum],0);
    if(etbRet != eETB_Success)
    {
        printf("Error enabling ETB (status = 0x%x).\n",etbRet);
        return 1;
    }
 
    return 0;
}
 
void initBuffers()
{
    int i;
    memset(drainBuffer,0,2*DRAINBUF_SIZE);
    memset(traceOutputBuffer,0,2*DRAINBUF_SIZE*4*NUM_CORES);
    for (i=0;i<NUM_CORES;i++) nTotalTraceWords[i] = 0;
}
 
void coreSync()
{
}
 
#define XMC_CFG_BASE          0x08000000
 
void setMPAX()
{
   /* Mapping for non-cached view for MSMC*/
   *(unsigned int *)(XMC_CFG_BASE+0x18) = 0x00C0003F; /* replacement addr + perm */
   *(unsigned int *)(XMC_CFG_BASE+0x1C) = 0xD0000014; /* base addr + seg size (2MB) */
 
}