This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Count Event Question



Hello,


I'm trying to determine if I can use the Count Event hardware "breakpoint" to determine the number of times a particular piece of code is executed. I'm trying not to add extra lines of code to my program.

I'm essentially looking for if PC == X, increment count.

I'm running on a C6472.

Thanks!

  • Hello,

    There isn't quite a default event counter that will do exactly what you ask. But you can easily find an alternative.

    What I would recommend is to set a breakpoint at the location and for the 'Debug Response -> Action' (in the Breakpoint Properties, set it to execute a GEL expression which simply increments a GEL global variable counter to keep track of the count.

    Thanks

    ki

  • Is the lack of such a counter due to AET? or Code Composer? It looks like something AET should be able to do.

    Does your recommendation interfere with run time? I'm looking to count events in a pretty critical HWI in our data path.

  • It would be an AET limitation I suppose. They just didn't create that specific event to count.

    If you use a hardware breakpoint, that would not interfere with runtime.

  • Interesting. I guess this page is not a full set of the AET features:

    http://processors.wiki.ti.com/index.php/C6000_AET_Logic

    it seems like on a PC compare the counters should be able to be advanced.

    Of course it looks like those counters only decrement, where as the one in Code Composer increments?

    Finding detailed docs on AET is extremely difficult, which is unfortunate since it looks like an exceptional debugging tool for complex issues. Especially the build in state machine capability.

  • Oh yeah, I'm sure that the AET hw logic itself easily has the capability to support a simple counter to keep track of the number of times a program location was reached. It can keep track of much more. However there is no implementation in the driver/sw (that I can find) that supports this via the standard interface (breakpoints view).

  • Now I have to ask the question: Is there a non-standard way to configure some of the more complicated features of AET?

  • AETLib comes to mind but you mentioned you don't want to add any extra lines of code to you application. You may be able to use the ctools scripting APIs, i'll need to check with some folks here. What exactly are you looking to do? Is it simply counting the number of times a program address was reached? Or are you looking to do something more?

  • My immediate concern is to count the number of times a program address was reached.

    But if the hardware has the capability to help with more complex issues in the future, learning how to implement this counter with AET can be helpful.

  • I have been playing around with AET for a bit and it looks like my original solution is not the best because the target *is* halted when evaluating the GEL expression (even though no target access is needed to evaluate the expression). This violates your requirement of non-intrsiveness.

    There may be some other tricks you can do with asserting emu pins and then counting the assertions. But I will forward this thread to the AET experts and defer to their wisdom.

    Thanks

    ki

  • Any updates in this arena?

  • Sorry for the delay. let me ping the Emulation folks again.

  • I don't think CCS exposes any particular breakpoint option to non-intrusively counting the number of times a particular PC is executed. The closest that I think of here is using skip count along with a HW breakpoint. Skip count can be configured by right clicking on the breakpoint and then breakpoint options. Basically, say if skip count of a HW breakpoint job is configured as 10, the CPU will halt whenever the breakpoint is hit the 11th time.

    However, it is possible to realize this use-case using AETLib. Briefly, AETLib is an embedded C library, which exposes APIs for setting up AET related trace and trigger jobs from the application SW. For more details, please refer to:

    http://processors.wiki.ti.com/index.php/AETLIB

    http://processors.wiki.ti.com/index.php/CToolsLib

    The AETLib source and examples are available at:

    https://gforge.ti.com/gf/project/ctoolslib/frs/?action=FrsReleaseBrowse&frs_package_id=82

    I got to modify an existing AETLib example (halt_on_watchpoint) to realize this use-case. The modified source file is attached. In this modified example, I am using AET counter 0 to count the number of times test_func2 is called.

    I hope this helps.

    Thanks,

    Karthik.

    /*
     * halt_on_watchpoint.c
     *
     * AET Library public API Definitions 
     *
     * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ 
     * 
     * 
     *  Redistribution and use in source and binary forms, with or without 
     *  modification, are permitted provided that the following conditions 
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright 
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the 
     *    documentation and/or other materials provided with the   
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
     *  "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 THE COPYRIGHT 
     *  OWNER OR CONTRIBUTORS 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.
     *
    
     *  =============================halt_on_watchpoint.c==========================
     *  Revision Information
     *   Changed: $LastChangedDate: 2013-01-18 15:47:09 -0600 (Fri, 18 Jan 2013) $
     *   Revision: $LastChangedRevision: 10598 $
     */
    
    
    /*  ===========================================================================
     *  ==                              OVERVIEW                                 ==
     *  ===========================================================================
     *
     *  This application demonstrates the functionality of a the Halt on Program 
     *  Watchpoint of the AET Target Library.  The watchpoint is triggered on 
     *  encountering a specific PC value.  In this example, the PC value is the 
     *  the address of the test_func2() function.  Encountering this address in the 
     *  PC will cause the watchpoint to be triggered.  AET breakpoints are
     *  always imprecise because they execute when the instruction is retired from 
     *  the CPU pipeline.The delay should be in the neighborhood of 6-9 cycles. 
     ******************************************************************************/
    
    #include <aet.h>
    #include <stdio.h>
    
    /* Function Prototypes */
    void test_func1();
    void test_func2();
    
    void main()
    {
    	AET_jobParams params; /* AET parameters */
    	AET_jobIndex jobNumber;				/* Index in job table */
    
    	/* Counter 0 Configuration Parameters */
    	AET_counterConfigParams counter0 = AET_COUNTERCONFIGPARAMS;
    
    	/* Value read from the counter */
    	Uint32 counterValue;
    
    	/* Initialize AET */
    	AET_init();
    
    	/* Claim the AET resource */
    	if (AET_claim())
    		return;
    
    	/* Use Counter 0 */
    	counterValue = AET_readCounter(AET_CNT_0);
    	printf ("The initial value of the counter is 0x%x\n", counterValue);
    
    	/* Set the configuration parameters */
    	counter0.configMode = AET_COUNTER_TRAD_COUNTER;
    	counter0.counterNumber = AET_CNT_0;
    	counter0.reloadValue = 0xFFFFFFFF; 	/* This is not really necessary in this
    											mode.  Reload has no meaning in
    											traditional mode
    										 */
    
    	/* Configure the counter */
    	AET_configCounter(&counter0);
    
    	/* 
    	 Set the Watchpoint to halt when it encounters 
    	 test_func2.  There can be a few cycles of delay
    	 when using a watchpoint of this kind.  But it 
    	 should halt within the test_func2 scope.
    	 */
    	params = AET_JOBPARAMS; /* Initialize Job Parameter Structure */
    
    	params.programAddress = (Uint32) &test_func2;
    	params.triggerType = AET_TRIG_CNT0_START;
    
    	/* Setup the AET job */
    	if (AET_setupJob(AET_JOB_TRIG_ON_PC, &params))
    		return;
    	
    	/* Remember the index of this job */
    	jobNumber = params.jobIndex;
    
    	printf("The index is %d\n", jobNumber);
    
    	/* Enable AET */
    	if (AET_enable())
    		return;
    
    	/* Call test_func1, and we should halt in test_func2() */
    	test_func1();
    
    	/* Clear the job that we've programmed */
    	AET_releaseJob(jobNumber);
    
    	return;
    
    
    }
    
    void test_func1()
    {
    	Uint32 counterValue,i;
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	for(i=0;i<25000;i++)
    	{
    		test_func2();
    	}
    
    	counterValue = AET_readCounter(AET_CNT_0);
    	printf ("The value of the counter0 is 0x%x\n", counterValue);
    
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    
    }
    
    void test_func2()
    {
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    	asm(" nop");
    }