Debugging the DSP side of a CE application using CCS

From Texas Instruments Wiki
Jump to: navigation, search

Debugging the DSP using CCS for a CE application

This topic discusses how to debug the DSP using CCS on an ARM + DSP device (e.g. DM644x, OMAP3, OMAP-L13x, etc.) that's running Codec Engine.

There are two common scenarios when debugging the DSP that require slightly different approaches to setting up the debug environment:

  • Algorithm-level debugging: for example, a new or modified algorithm is being used inside the CE framework.
  • Arbitrary DSP code: code that is invoked directly from main() or via DSP/BIOS static objects.

In both cases, the assumption is that the user has a working system - DSP/BIOS, Link, and Codec Engine are already working - so there is no need to debug these fundamental components.

Algorithm Debugging

In this scenario, you do not need to modify the DSP code to enable debugging. Build the DSP application (possibly with a debug profile) as usual. On the ARM side, the application will load and start the DSP when the Engine_open() method of CE is called. After Engine_open(), the DSP is running and waiting for requests from the ARM. To debug your codec, now is the time to attach CCS to the DSP and set breakpoints.

You can ensure that the DSP side waits by putting a "prompt" after Engine_open() in the ARM-side application code. For example:

Engine_open( .... );
printf("Hit enter to continue:");
getchar();

Alternatively, you could use gdb to set a breakpoint in the ARM application somewhere after Engine_open() but before any VISA calls.

Once the DSP is loaded and running, you follow the same basic steps in either scenario:

On CCS v3

  1. Start CCS.
  2. Select Debug->connect
  3. Select File->load symbols->load symbols only, and choose your DSP server executable as input file (typically a .x64P or .x674 file extension).
  4. Set your breakpoints. Open other source files in CCS as needed to accomplish this.
  5. Run the DSP (Press F5) to continue execution. Happy debugging!

On CCS v5

  1. Start CCS. Launch the Debug configuration for your platform.
  2. Right-click on the DSP core in the Debug Window. Select Connect target
  3. Select Run->Load->Load symbols, and choose your DSP server executable as input file (typically a .x64P or .x674 file extension).
  4. Set your breakpoints. Open other source files in CCS as needed to accomplish this.
  5. Run the DSP (Press F8) to continue execution. Happy debugging!

Once the DSP debugging is running again, return to the ARM side to either "Hit enter" or continue in gdb.

Note! Step 3 can be circumvented during subsequent runs by using the reload symbols feature of CCS.

Arbitrary DSP Code Debugging

The biggest difference for when we are debugging arbitrary DSP code is that we need to get access of the DSP early while it is booting. We do this by using the global user init feature of DSP/BIOS. This means that we are "injecting" our own function, which in our case is a simple spin loop, in to the DSP/BIOS initialization procedure. This will halt the DSP before most of the DSP/BIOS initialization has been done.

You will then have to "release" the DSP by toggling the variable which the while loop is blocking on. You can either do this manually by halting CCS, examining the variable in the watch window and then changing the value before continuing execution on the DSP, or you can use a GEL script like described below.

The below has been tested out on the DM6446 EVM, and was added to the all_codecs example server that comes with CE (use the same procedure for your own codec server). Below are the changes needed.

Add the loop to main.c:

volatile int CE_exitSpinLock = 0;
 
void CE_spinLock(void)
{
    while (CE_exitSpinLock == 0) { }
}

Add this to all.tcf to make DSP/BIOS call the above loop early when initializing:

<syntaxhighlightlang='javascript'> bios.GBL.CALLUSERINITFXN = true; bios.GBL.USERINITFXN = prog.extern("CE_spinLock"); </syntaxhighlight>

Create a new file CE.gel which will be used for releasing the loop, and put the following code in here:

menuitem "Codec Engine GEL"

hotmenu Release_Dsp() { GEL_MemoryFill(&CE_exitSpinLock, 0, 1, 1); }

First compile the new server with the above changes and copy the server executable all.x64P or all.x674 to your target file system along with the audio_copy app.out ARM application which launches this server (as well as the in.dat file that the ARM app needs). Then:

On CCS v3

  1. Start CCS (with a proper configuration for your device) and open the DSP side of CCS.
  2. Execute app.out on your Linux target.
  3. Select Debug->connect.
  4. Select File->load symbols->load symbols only, and choose your DSP server executable as input file.
  5. Load the CE.gel file into CCS.
  6. Set your breakpoints. Open other source files in CCS as needed to accomplish this.
  7. Select the "Release DSP" menu item from the CCS GEL menu.
  8. Run the DSP (Press F5) to continue execution.

On CCS v5

  1. Start CCS (with a proper configuration for your device) and open the DSP side of CCS.
  2. Execute app.out on your Linux target.
  3. Right-click on the DSP core in the Debug Window. Select Connect target
  4. Select Run->Load->Load symbols, and choose your DSP server executable as input file.
  5. Load the CE.gel file into CCS. (Select Tools->GEL Files from the menu, then right click on the GEL files window and select Load GEL. Then open the gel file.)
  6. Set your breakpoints. Open other source files in CCS as needed to accomplish this.
  7. Select the "Release DSP" menu item from the Scripts menu.
  8. Run the DSP (Press F8) to continue execution.

Note! The ARM-side app.out may time out during the above process due to CE using a timeout in DSP Link PROC_start(). We are halting the DSP so early during initialization that the DSP Link "handshake" after loading a DSP image doesn't take place. This means you only have a limited time to do the steps above, and is one reason why using a GEL file is a good idea (you can add the addition of your breakpoints in to this same GEL file to speed up the process further).

Note!If you are using CE 2.00 or later, you can set an ARM-side environment variable CE_DSPDEBUG=1 before running the ARM app. That will 1) configure the Link "handshake" timeout to "forever", and 2) prompt the user to press Enter to continue. This way, you can leisurely connect to the DSP via CCS.

These steps above just have to be done one time. Due to the "new" connect/disconnect features in CCS only steps 3, 7 and 8 needs to be done next debugging session as long as CCS isn't closed (and step 4 if the DSP image is changed, but there is a reload symbols option in CCS).

The above solution has been implemented in the debugutil module which is part of the Servertools (available at https://www-a.ti.com/downloads/sds_support/applications_packages/index.htm). See the module's documentation for more details.

If you know that you don't need to debug the initialization of device drivers, DSP Link or other OS components, you can call CE_spinLock() manually in your Server's main() function. This way DSP Link gets to do it's handshake and you shouldn't receive any timeouts.

Additional Troubleshooting tips

  • If you get a message like this...
@1,146,919us: [+6 T:0x40018528] OC - Comm_locate> Attempt 20 of 20 to locate DSP
's MSGQ 'rmsq' failed. Retrying...
@1,147,172us: [+7 T:0x40018528] OC - Comm_locate> Error: could not locate DSP se
rver's MSGQ 'rmsq' in 20 retries. Check if you have the correct DSP image, or in
crease the number of retries (see ti.sdo.ce.osal.Global's commLocateRetries conf
ig param.
...then sure enough, you'd better bump up the value of commLocateRetries. Do this via: -
/* Load support for the Codec Engine */
var osalGlobal = xdc.useModule( 'ti.sdo.ce.osal.Global' );
osalGlobal.commLocateRetries = 100000; // CE OSAL default is 20

This config param (commLocateRetries) is the number of times to retry Comm_locate() to find DSP server's MSGQ before giving up.

This should give ample time to connect CCS, Load Symbols, set Breakpoints etc.