AM62P: [AM62P][CCS v10] Code Coverage Analysis

Part Number: AM62P

Hi Team,

I am capturing the Trace data for Coverage analysis using Code Coverage tool supported by CCS. Currently experiementing with "DDR PERF" example given in TI SDK -> examples/drivers/ddr/ddr_perf. I am running on A53 core and trigger for DDR region. 

Queries :

  1. How to analyse the data ?
  2. ddr_perf_main.c shows 0% coverage, is this expected ?
  3. How to download the data . 

Thanks,

ShriyaScreenshot 2026-09-17 153256.png

  • Under coverage section -> If I click "Filename" it does not expand the code . What could be the reason ?

    THanks,

    Shriya

  • Hi ,

    AM62P does not support CCS v10. Additionally, the Code Coverage feature available in CCS v10 is supported only for MSP430 devices. You can verify the CCS version support details in the corresponding SDK release notes
    Code coverage document for V10

    https://software-dl.ti.com/ccs/esd/documents/application_notes/appnote-code_coverage_compiler.html

    Thanks,

    JOMY 

  • Hi JOMY,

    Sorry my mistake, the CCS version here is -> 12.8 for AM62P.

    Please share me the details on this.

    Thanks,

    Shriya

  • Hi ,

    Could you please let me know which version of the AM62Px SDK you are currently using?

    Thanks,

    JOMY

  • Hi Jomy,

    Currently we are using AM62P SDK -> 10.0.0

    Thanks,

    Shriya

  • Hi ,

    For AM62Px MCU+ SDK 10.0.0, please use CCS 12.7.0+ and TI ARM Clang 3.2.2 LTS. For more details, please refer to the relevant release documentation.

    https://software-dl.ti.com/mcu-plus-sdk/esd/AM62PX/10_00_00_14/exports/docs/api_guide_am62px/RELEASE_NOTES_10_00_00_PAGE.html

    For code coverage, you can refer to the information provided below. and its support 1.1.x later

    https://software-dl.ti.com/ccs/esd/documents/application_notes/appnote-code_coverage_clang.html 

    Thanks,

    JOMY

  • Hi Jomy, 

    Thanks for the information. But I am currently work on Eclipse pluggin for CCS , so how to go about it here ? I am looking for coverage analysis under Tools .

    Thanks,

    Shriya

  • Hi ,

    The document I shared is specifically related to the CCSv12+

    code coverage section : ://software-dl.ti.com/ccs/esd/documents/application_notes/appnote-code_coverage_clang.html#analyzing-the-data

    Before starting the coverage analysis, there are several prerequisite steps that must be completed. Please follow the guide carefully and ensure all the required setup steps are performed before proceeding with the analysis. The document provides detailed instructions on configuring, collecting, and analyzing code coverage data.
    Thanks,
    JOMY
  • Hi Jomy,

    Yes thanks for the info. Currently we add compiler flags in makefile and build it. 

    For MCU R5 -

    I added the flags ->  -fcoverage-mapping , -fprofile-instr-generate , -fmcdc . 

    Yes this helped me to collect the profile data. 

    For A53 - 

    These flags are not recognisible by makefile.  So could you let me know suitable compiler flags here ?

    Thanks,

    Shriya

  • Hi Jomy,

    Another query - generating  *.profraw.

    I have added a call to the main.c ->  __llvm_profile_write_file() followed by a breakpoint . And also updated linker file and printf also works.

    But now it needs to copy that file to host machine but enable to find it.

     I am not follwing the doc as mentioned -> COllect, analyze as we have following setup -

    Linux machine connected to AM62 PTI SDK , baremetal . 

    Compiling on host and then loading via CCS.  

    Please let me know if I have missed out any.

    Thanks,

    Shriya

  • Hi 

    Have you already checked the directory where the .out file was generated (typically the output directory of the active build configuration), or do you have a specific Working Directory configured in your Run/Debug Configuration?

    Also, after hitting the breakpoint, could you try searching the entire host file system for the generated default.profraw file? For example:

    find / -name "default.profraw"

    After locating the default.profraw file, please identify the compiler installation used by the project. You can verify this in Properties → Build → General → Compiler Version. Then run the following commands:
    <ccs_install>/tools/compiler/ti-cgt-armllvm_<version>/bin/tiarmprofdata merge -sparse \
      -obj-file=<path_to>/empty.release.out \
      <path_to>/default.profraw \
      -o coverage.profdata
    Next, generate the coverage report:
    <ccs_install>/tools/compiler/ti-cgt-armllvm_<version>/bin/tiarmcov show --format=html \
      --show-instantiations \
      --show-branches=count \
      --object=<path_to>/empty.release.out \
      -instr-profile=coverage.profdata \
      --output-dir=coverage_report

    Once the report is generated, open:
    coverage_report/index.html
    Thanks,
    JOMY

  • Thanks a ton !! Jomy. This really helps .

    I could get the default.profraw . But I stuck into another issue following this.

    Generated file is corrupted or header is missing. When I tried the first command mentioned above -

    /bin/tiarmprofdata merge -sparse   : Error observed - default.profraw: unrecognized instrumentation profile encoding format.

    So i took hexdump -

    hexdump -C default.profraw | head -n 4
    00000000 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
    *
    00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
    *

    =================

    Analysis - 

    Is it issue with linked.cmd ? 

    Added these points in linker.cmd for MCU R5->

    GROUP {
    .bss: {} palign(8) /* This is where uninitialized globals go */
    __llvm_prf_cnts : {} align(8)
    __llvm_prf_bits : {} align(8)
     RUN_START(__BSS_START)

    And main.c

    Board_driversClose();
    /* Close drivers */
    Drivers_close();
    printf("Before log generation\n");
    __llvm_profile_write_file();
    printf("After log generation\n");

    Thanks,

    Shriya

  • I also tried updating this file -> but issue still exists.

    And main.c

    printf("Before log generation\n");
    __llvm_profile_write_file();
    printf("After log generation\n");

    Board_driversClose();
    /* Close drivers */
    Drivers_close(); 

    Regards,

    Shriya

  • Hi Jomy ,

    Tried again with this modification ->

    printf("Before log generation\n");
    __llvm_profile_write_file();
    printf("After log generation\n");

    Board_driversClose();
    /* Close drivers */
    Drivers_close();

    Issue still exists. 

  • And linker.cmd -

    GROUP {
    .bss: {} palign(8) /* This is where uninitialized globals go */
    __llvm_prf_cnts : {} align(8)
    __llvm_prf_bits : {} align(8)
    __llvm_prf_data : {} align(8)
    __llvm_prf_names : {} align(8)
    RUN_START(__BSS_START)
    RUN_END(__BSS_END)
    .sysmem: {} palign(8) /* This is where the malloc heap goes */
    .stack: {} palign(8) /* This is where the main() stack goes */
    } > MSRAM

    With these changes, the issue still persists.

    Kindly let me know if I need to correct here

    THanks,

    Shriya

  • Hi Shriya,

    Could you share the linker script you are using? It would help me debug and analyze the issue further.

    Thanks,

    JOMY

  • Hi Jomy,

    Sharing the linker.cmd for MCU R5 core.

    /* This is the stack that is used by code running within main()
     * In case of NORTOS,
     * - This means all the code outside of ISR uses this stack
     * In case of FreeRTOS
     * - This means all the code until vTaskStartScheduler() is called in main()
     *   uses this stack.
     * - After vTaskStartScheduler() each task created in FreeRTOS has its own stack
     */
    --stack_size=16384
    /* This is the heap size for malloc() API in NORTOS and FreeRTOS
     * This is also the heap used by pvPortMalloc in FreeRTOS
     */
    --heap_size=32768
    -e_vectors  /* This is the entry of the application, _vector MUST be plabed starting address 0x0 */
    
    /* This is the size of stack when R5 is in IRQ mode
     * In NORTOS,
     * - Here interrupt nesting is enabled
     * - This is the stack used by ISRs registered as type IRQ
     * In FreeRTOS,
     * - Here interrupt nesting is disabled
     * - This is stack that is used initally when a IRQ is received
     * - But then the mode is switched to SVC mode and SVC stack is used for all user ISR callbacks
     * - Hence in FreeRTOS, IRQ stack size is less and SVC stack size is more
     */
    __IRQ_STACK_SIZE = 256;
    /* This is the size of stack when R5 is in IRQ mode
     * - In both NORTOS and FreeRTOS nesting is disabled for FIQ
     */
    __FIQ_STACK_SIZE = 256;
    __SVC_STACK_SIZE = 4096; /* This is the size of stack when R5 is in SVC mode */
    __ABORT_STACK_SIZE = 256;  /* This is the size of stack when R5 is in ABORT mode */
    __UNDEFINED_STACK_SIZE = 256;  /* This is the size of stack when R5 is in UNDEF mode */
    
    SECTIONS
    {
        /* This has the R5F entry point and vector table, this MUST be at 0x0 */
        .vectors:{} palign(8) > R5F_VECS
    
        /* This has the R5F boot code until MPU is enabled,  this MUST be at a address < 0x80000000
         * i.e this cannot be placed in DDR
         */
        GROUP {
            .text.hwi: palign(8)
            .text.cache: palign(8)
            .text.mpu: palign(8)
            .text.boot: palign(8)
            .text:abort: palign(8) /* this helps in loading symbols when using XIP mode */
        } > MSRAM
    
        /* This is rest of code. This can be placed in DDR if DDR is available and needed */
        GROUP {
            .text:   {} palign(8)   /* This is where code resides */
            .rodata: {} palign(8)   /* This is where const's go */
        } > MSRAM
    
        /* This is rest of initialized data. This can be placed in DDR if DDR is available and needed */
        GROUP {
            .data:   {} palign(8)   /* This is where initialized globals and static go */
        } > MSRAM
    
        /* This is rest of uninitialized data. This can be placed in DDR if DDR is available and needed */
        GROUP {
            .bss:    {} palign(8)   /* This is where uninitialized globals go */
            RUN_START(__BSS_START)
            RUN_END(__BSS_END)
    	__llvm_prf_cnts : {} align(8)
        	__llvm_prf_bits : {} align(8)
    	__llvm_prf_data  : {} align(8)
        	__llvm_prf_names : {} align(8)
            .sysmem: {} palign(8)   /* This is where the malloc heap goes */
            .stack:  {} palign(8)   /* This is where the main() stack goes */
        } > MSRAM
    
    
    
    
        /* This is where the stacks for different R5F modes go */
        GROUP {
            .irqstack: {. = . + __IRQ_STACK_SIZE;} align(8)
            RUN_START(__IRQ_STACK_START)
            RUN_END(__IRQ_STACK_END)
            .fiqstack: {. = . + __FIQ_STACK_SIZE;} align(8)
            RUN_START(__FIQ_STACK_START)
            RUN_END(__FIQ_STACK_END)
            .svcstack: {. = . + __SVC_STACK_SIZE;} align(8)
            RUN_START(__SVC_STACK_START)
            RUN_END(__SVC_STACK_END)
            .abortstack: {. = . + __ABORT_STACK_SIZE;} align(8)
            RUN_START(__ABORT_STACK_START)
            RUN_END(__ABORT_STACK_END)
            .undefinedstack: {. = . + __UNDEFINED_STACK_SIZE;} align(8)
            RUN_START(__UNDEFINED_STACK_START)
            RUN_END(__UNDEFINED_STACK_END)
        } > MSRAM
    
        /* Sections needed for C++ projects */
        GROUP {
            .ARM.exidx:  {} palign(8)   /* Needed for C++ exception handling */
            .init_array: {} palign(8)   /* Contains function pointers called before main */
            .fini_array: {} palign(8)   /* Contains function pointers called after main */
        } > MSRAM
    
    }
    
    MEMORY
    {
        R5F_VECS  : ORIGIN = 0x00000000 , LENGTH = 0x00000040
        R5F_TCMA  : ORIGIN = 0x00000040 , LENGTH = 0x00007FC0
        R5F_TCMB0 : ORIGIN = 0x41010000 , LENGTH = 0x00004000
    
        MSRAM     : ORIGIN = 0x79100000 , LENGTH = 0x80000
    
        DDR_CODE_DATA                 : ORIGIN = 0x9BA00000, LENGTH = 0xE00000   /* Code/Data            */
    }
    

  • your __llvm_prf_cnts and __llvm_prf_bits sections have no RUN_START/RUN_END attached, so the runtime falls back to a zero-length default, which is why the file comes out empty.

    Replace your GROUP block with:

    GROUP {
    .bss: {} palign(8)
    RUN_START(__BSS_START)
    RUN_END(__BSS_END)

    __llvm_prf_cnts: {} align(8)
    RUN_START(__start___llvm_prf_cnts)
    RUN_END(__stop___llvm_prf_cnts)

    __llvm_prf_bits: {} align(8)
    RUN_START(__start___llvm_prf_bits)
    RUN_END(__stop___llvm_prf_bits)

    __llvm_prf_data: {} align(8)
    __llvm_prf_names: {} align(8)

    .sysmem: {} palign(8)
    .stack: {} palign(8)
    } > MSRAM

    Clean, rebuild, then check default.profraw — it should no longer be all zeros. If the build log shows #10190-D warnings for the four new symbols, the fix took effect.

     

  • Steps followed to achieve this.

    1. Update makefile with these parameters -

    -fcoverage-mapping \
    -fprofile-instr-generate \
    -fmcdc \

    2. Linker.cmd - Updated with  the changes as mentioned above.

    3. main.c

    Its the PMIC example given in TI SDK

    extern void __llvm_profile_write_file(void);
    void pmic_user_reg_cfg_main(void *args);

    void freertos_main(void *args)
    {
    int32_t status = SystemP_SUCCESS;
    //__llvm_profile_write_file();
    /* Open drivers */
    Drivers_open();
    /* Open flash and board drivers */
    status = Board_driversOpen();
    DebugP_assert(status==SystemP_SUCCESS);

    pmic_user_reg_cfg_main(NULL);
    printf("Before log generation\n");
    __llvm_profile_write_file();
    printf("After log\r\n");
    /* Close board and flash drivers */
    Board_driversClose();
    /* Close drivers */
    Drivers_close();

    vTaskDelete(NULL);
    }

    4. Build using make PROFILE=debug. 

    5. CCS steps

    Connect the target for the core MCU R5

    Load the debug.out file.

    Set the breakpoint at the highlighted line above

    6. Run the application

    ===========

    Regards,

    Shriya.

  • Hi Jomy,

    Just now tried by editing makefile. Removed MC/DC coverage support (-fmcdc) . Now using  -> __llvm_profile_write_file() .

    Hitting new issue ->

    ./tiarmprofdata merge -sparse -obj-file=/home/ubuntu24/shriya/ti_am62p_sdk/examples/drivers/pmic/pmic_user_reg_cfg/am62px-sk/mcu-r5fss0-0_freertos/ti-arm-clang/pmic_user_reg_cfg.debug.out /home/ubuntu24/shriya/ti_am62p_sdk/examples/drivers/pmic/pmic_user_reg_cfg/am62px-sk/mcu-r5fss0-0_freertos/ti-arm-clang/default.profraw -o coverage.profdata
    LLVM ERROR: out of memory
    Allocation failed
    PLEASE submit a bug report to github.com/.../ and include the crash backtrace.
    Stack dump:
    0. Program arguments: ./tiarmprofdata "tiarmprofdata merge" -sparse -obj-file=pmic_user_reg_cfg.debug.out default.profraw -o coverage.profdata
    Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
    ./tiarmprofdata[0x6731d3]
    ./tiarmprofdata[0x67154e]
    ./tiarmprofdata[0x673676]
    /lib/x86_64-linux-gnu/libc.so.6(+0x45330)[0x7bbc0e045330]
    /lib/x86_64-linux-gnu/libc.so.6(pthread_kill+0x11c)[0x7bbc0e09ec0c]
    /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x1e)[0x7bbc0e04527e]
    /lib/x86_64-linux-gnu/libc.so.6(abort+0xdf)[0x7bbc0e0288ff]
    ./tiarmprofdata[0x607cd9]
    ./tiarmprofdata[0x607d12]
    ./tiarmprofdata[0x78dadc]
    ./tiarmprofdata[0x4e2b8b]
    ./tiarmprofdata[0x4dc54c]
    ./tiarmprofdata[0x4da944]
    ./tiarmprofdata[0x4da655]
    ./tiarmprofdata[0x422e9b]
    ./tiarmprofdata[0x40ed2f]
    ./tiarmprofdata[0x40aa48]
    /lib/x86_64-linux-gnu/libc.so.6(+0x2a1ca)[0x7bbc0e02a1ca]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x8b)[0x7bbc0e02a28b]
    ./tiarmprofdata[0x406b35]
    Aborted (core dumped)

    Please help me here with your inputs. 

    Thanks,

    Shriya

  • Hi Shriya,

    Let me test this using one of the SDK examples, and I'll get back to you with an update.

    Thanks,
    JOMY
  • Hi Jomy,

    The issue is resolved. !!  Finally its a relief. I removed  sections from linker.cmd ->

    __llvm_prf_data: {} align(8)
    __llvm_prf_names: {} align(8)

    Then it worked. Able to see index.html.

    So to conclude here ->

    1. Is this parameters very important -> 

    __llvm_prf_data: {} align(8)
    __llvm_prf_names: {} align(8) ? If yes, then how to go about the crash occured in the above post.

    Thanks,

    Shriya

  • Hi Jomy,

    That shall help , kindly test with these parameters ->

    __llvm_prf_data: {} align(8)
    __llvm_prf_names: {} align(8)  and if possible for A53 core.

    Thanks,

    Shriya