NOTICE: The Processors Wiki will End-of-Life on January 15, 2021. It is recommended to download any files or other content you may need that are hosted on processors.wiki.ti.com. The site is now set to read only.
System Analyzer Tutorial 8A
Contents
Tutorial 8A: Using UIA to Monitor EDMA3 Transactions[edit]
References
- Keystone Architecture: Enhanced Direct Memory Access (EDMA3) Controller - User's Guide
- EDMA Low Level Driver documentation (this ships as part of the EDMA LLD package. See the release_notes_edma3_lld.html file in the root directory of this package for links.)
Prerequisites for this tutorial:
- A board with a C66XX device (e.g. TMDXEVM6670L, TMDXEVM6678L or TMDXEVM6614LE)
- CCSv5.2 or later
- System Analyzer 1.1 or later
- Target content package uia_1_01_01_14 or later
- MCSDK 2.1.2 or later
Tested configuration
- C6000 Compiler v7.4.0
- UIA 1.2.1.8_eng
- C6678 EVM
- CCSv5.2.1.00018
- Packages that ship with MCSDK 2.1.2
- XDC 3.23.4.60
- EDMA3 Low Level Driver 2.11.5 (the folder for the package is named edma3_lld_02_11_05_02)
- Sys/BIOS 6.33.6.50
- MCSDK PDK TMS320C6678 1.1.2.5
Overview[edit]
This tutorial is based on the example projects that ship with the EDMA Low Level Driver (LLD) package, which is installed as part of the MCSDK. The original example source code is located in C:\ti\edma3_lld_02_11_05_02\examples\edma3_driver\src, and individual projects are provided in the parent folder for a wide range of devices. This tutorial is based on the C:\ti\edma3_lld_02_11_05_02\examples\edma3_driver\evm6678 project. In order to simplify things, the tutorial project is structured so that it contains the .cfg file (as opposed to the EDMA LLD project which splits out the .cfg file into a separate 'configuration only' project that the 'sample_app' project depends on).
The example consists of a number of tests that demonstrate different ways to configure and use the DMA engines that are provided by Keystone devices. We will be looking in detail at the code changes that were applied to one of these test cases in order to instrument it.
Building the Tutorial Project[edit]
Unzip the attached project File:Tutorial8A MonitorEDMA3WithUIA.zip into a folder and import it into CCS (File /Import), copying it into your workspace. Build the project.
Porting the tutorial to run on a different device
In order to modify the tutorial project to run on a device other than the C6678, you will need to change the libraries and library file paths used by the project to match those of the EDMA LLD example project for the device you wish to use.
Here is a screenshot of the libraries used for the C6678 target:
You will also need to change the Platform selected in the Build Settings / CCS General / RTSC tab to one appropriate for your device.
Running the Tutorial Project[edit]
- Launch a debug session for your target device:
- connect to the first C66XX CPU on the device
- do a system reset (Run / Reset / System Reset)
- run the Global Default Initialization GEL script for the EVM
- For the C6678: Scripts / EVMC6678L Init Functions / Global_Default_Setup
- Load the project. It should halt at main.
- Start System Analyzer (Tools / System Analyzer / Live -> Start
- Click on the Analyze button in the Live Session: Logs view and select Duration
- Click on the Analyze button in the Live Session: Logs view and select Execution
- Run the target. You should see a lot of text being output to the console.
- The following text will be displayed when the tests have completed:
- [C66xx_0] End -> EDMA3 Test memory to memory copy
- [C66xx_0]
- [C66xx_0] edma3deinit() Passed
- [C66xx_0] edma3deinit() Passed
- [C66xx_0] edma3deinit() Passed
Analysis Views[edit]
Here are screenshots of the Duration view and a zoomed in region of the Execution graph after the tests have completed:
Duration Summary view
This view shows the count, minimum, maximum, average, and total time measured between the starting time when the EDMA transfer was initiated and the stop time recorded in the callback function handling the EDMA completion notification.
Execution Graph view
Each of the benchmark start/stop events is shown on a separate row in the graph, and is positioned on a timeline to show when it occurred.
How It Works[edit]
For information on how the underlying DMA engines operate and details about how to configure them using the EDMA LLD software, please refer to the references at the top of this tutorial. Here, we'll instead focus on how the code is instrumented using UIA in order to log the benchmark start / stop events that drive the analysis views shown above.
Let's look at how one of the tests, dma_test.c, was modified in detail:
- the following #include files were added:
- #include <xdc/runtime/Log.h>
- #include <ti/uia/events/UIABenchmark.h>
- a unique string identifier was specified. This is used in System Analyzer to pair up the corresponding start and stop events.
- void *appData = (void*)__FILE__; // pass in the address of the string with the filename as appData for the ISR completion callback
- the appData was passed in as the 'application data' parameter to the EDMA LLD API used to configure the EDMA transaction. This value is passed to the callback function that is specified in the API upon completion of the event.
- result = EDMA3_DRV_requestChannel (hEdma, &chId, &tcc,(EDMA3_RM_EventQueue)0, &callback1, appData);
- A UIABenchmark_startInstanceWithStr event was logged just before the transaction was initiated. As there are two different callback functions provided in the example code, the event uses an integer specifying which callback is registered to receive notification of the transaction completion (in this case, 1 to indicate callback1). The unique string identifier that was passed in as application data to the LLD configuration API is used as the string parameter in the event.
- Log_write3(UIABenchmark_startInstanceWithStr,(IArg)"EDMA3 RM XFER callback%d, %s",(IArg)1,(IArg)appData);
- result = EDMA3_DRV_enableTransfer (hEdma, chId, EDMA3_DRV_TRIG_MODE_MANUAL);
The callback functions for all of the tests are provided in common.c. The following line was added to the callback1 function in order to log a 'stop' event for the various transactions initiated in each of the tests:
- Log_write3(UIABenchmark_stopInstanceWithStr,(IArg)"EDMA3 RM XFER callback%d, %s",(IArg)1,(IArg)appData);
System Analyzer will thus receive two events for each DMA transaction: a start event logged in the test code when the transaction has been initiated, and a stop event logged by the callback function that is called when the transaction is complete. The string that is passed in the appData parameter is used to 'name' the start / stop duration value in both the Duration Summary view and the Execution Graph view. The callback 'instance id' (1 in this case) is appended to this string in these names. For this test case, the results are displayed with the name dmatest.c.1 .
Each of the tests in the original EDMA LLD example code has been modified in a similar manner. A good way to understand the changes that were made to the other test cases in order to add UIA instrumentation is to use a program such as BeyondCompare to show the differences between the original example code and the modified code for the tutorial.
In order for these events to get logged, a logger needs to be configured for the project. This is done by adding the following lines to the .cfg file:
/*
* The xdc.runtime.Log module provides APIs to log prioritized events (errors,
* warnings, and info) as well as generic APIs to log events (Log_writeN,
* Log_printN)
*/
var Log = xdc.useModule('xdc.runtime.Log');
/*
* The following module from the ti.uia.events package contains predefined
* events that can be logged using the Log_write APIs
*/
var UIABenchmark = xdc.useModule('ti.uia.events.UIABenchmark');
/*
* Configure UIA to upload events via JTAG while the target is running.
* Disable loadLogging to reduce the number of events that are being logged.
*/
var LoggingSetup = xdc.useModule('ti.uia.sysbios.LoggingSetup');
LoggingSetup.eventUploadMode = LoggingSetup.UploadMode_JTAGRUNMODE;
LoggingSetup.sysbiosTaskLogging = true;
LoggingSetup.loadLogging = false;
LoggingSetup.mainLoggerSize = 0x8000;
LoggingSetup.sysbiosLoggerSize = 0x8000;
This configures an instance of the LoggerCircBuf module to log all of the events from the 'Main' module (i.e. all of the application code). If you need to reduce the CPU overhead associated with logging events, you can configure a more efficient logger such as LoggerStreamer as the logger (see http://processors.wiki.ti.com/index.php/SystemAnalyzerTutorial5 for more info on this).
If you wish to turn off logging of events from your application code entirely, add the line LoggingSetup.mainLogging = false; Please see http://processors.wiki.ti.com/index.php/SystemAnalyzerTutorial1 for more information on how to control which events are logged, both via the .cfg file and during runtime.
Next:Tutorial 8B: Periodically Logging Performance Monitoring Counters.