Cart Contact NSDSP Home

Debugging multi-core devices

dsPIC33CH microcontrollers contain two separate cores known as master core and slave core. Each core is a separate microcontroller. Both cores can be debugged simultaneously, or separately.

The master core usually contains one or more images of the slave core, which are designed to be programmed by built-in program_secondary() function provided by the XC16 compiler. NSDSP uses the format required by program_secondary() to retrieve information about code being programmed onto the slave core.

Assisted Setup for Master Core

For assisted debugging, you need to use different set of macros to tell NSDSP debugger where to find the slave cores instead of the NSDSP_DBG_ENTRY macros. The NSDSP_DBG_ENTRY_MULTI_CORE specifies the number of slave images and must be followed by one or more of NSDSP_DBG_SLAVE_IMAGE macros each specifying a single slave image. The first parameter to NSDSP_DBG_SLAVE_IMAGE is an image id and the second is the pointer to the image. The number of NSDSP_DBG_SLAVE_IMAGE macros must match the number of images specified in the NSDSP_DBG_ENTRY_MULTI_CORE macro. For example:

  _program_secondary(1,0,active_img);
  _program_inactive_secondary(1,0,inactive_img);   _start_secondary();

  NSDSP_DBG_ENTRY_MULTI_CORE(2);
  NSDSP_DBG_SLAVE_IMAGE(4,active_img);
  NSDSP_DBG_SLAVE_IMAGE(7,inactive_img);

In this example, the entry macro specifies two slave images, one with id 4 and the other with id 7. These ids will be used for debugging the slave core.

There are many reasons you may have multiple slave images, for example because you have partitioned the slave core and it can hold two images, or because you load different images at different times, however most of the time, there will be only one slave image. In this case, you can use a simplified macro:

  _program_secondary(1,0,slave_img);
  _start_secondary();

  NSDSP_DBG_ENTRY_DUAL_CORE(slave_img);

In this case, you do not need to specify an id, it will be set to 1.

Assisted Setup for Slave Core

Assisted setup for a slave core is not any different from the setup for a regular chip. If you have used NSDSP debugging macros in one of the slave images, you must use them in all other slave images as well.

Since NSDSP cannot predict which core is going to be debugged, they all have to use the same location for the software breakpoint status word. The easiest way to accomplish this is to allocate the status word at a fixed address. It must be in the Near RAM. You may use the last location of Near RAM at 0x1ffe. Edit the nsdsp_dbg.S file to specify the addresses. For example change this section header:

  .section nsdsp_dbg_bp,bss,near

to this:

  .section nsdsp_dbg_bp,bss,near,address(0x1ffe)

If you used assisted setup in slave images, you must use assisted setup in master as well.

Manual Setup

Manual setup does not require any preparations. NSDSP Interface library will try to find slave images on its own. If it finds multiple images they will be given consecutive ids starting from 1 in the order images are positioned within the Hex file.

Debugging Master Core Only

To debug master core only, use the same procedures as for a single-core device. The only difference is that the assisted setup must enumerate slave images as explained above. This is necessary even if slave core is not being debugged.

Debugging Slave Core Only

There are two methods to debug slave cores. One method uses slave images programmed by the master core which is typically done by program_secondary() or program_inactive_secondary() functions provided by XC16 compiler. The other method involves programming slave images from HEX files through the NSDSP programmer.

If you want to debug slave images programmed by the master code, you need to program the master and then obtain Debug Info for debugging the slave core. The pseudo-code may look like this:

  NSDSP.create(serial)

  NSDSP.setDebugCores(cores = slave) 

  Session = NSDSP.startProgSession(mcu, readOnly = false)
  Session.checkId(adjustRate = true)
  debugSession = Session.programForDebug(hexMap, tcy)

  debugInfo = debugSession.getSlaveInfo(core = 1, imageA = 4, imageB = 7, tcy)
  NSDSP.endSession

  debugSession = NSDSP.startDebugSession(debugInfo)

  // Debugging the slave core here

  NSDSP.endSession
  NSDSP.free

To get Debug Info for the slave, you must know the ids of the images programmed by the master. In the example above you assume that the master programmed images with id 4 and 7 (see Assisted Setup for Master Core above). If the images actually programmed by the master are different from what you have specified, the debugging will fail.

If the slave core is not partitioned ( S1NOBTSWP configuration bit is set to OFF), you will need to specify only one image id. In this case set the second one to 0.

When you want to program the slave image by yourself, first make sure that the master does not program anything on the slave - functions like wape_secondary(), program_secondary(), or program_inactive_secondary() are not called by the master. Second, make sure that the slave core is not held in reset by the master core. The best way to accomplish this is to set S1ISOLAT configuration bit is set to ON. Then, you need to program master core, which is necessary for the configuration bits to take effect:

  NSDSP.create(serial)

  NSDSP.setDebugCores(cores = slave) 

  Session = NSDSP.startProgSession(mcu, readOnly = false)
  Session.checkId(adjustRate = true)
  debugSession = Session.programForDebug(hexMap, tcy)

  NSDSP.endSession
  NSDSP.free

After programming, the slave core can be programmed and debugged. When programming you need to use a HEX file built for the slave core (which has no relation to the HEX file you have used to program the master core). Also, you need to use a special MCU object:

  NSDSP.create(serial)

  slaveMCU = mcu.getSlaveCore(1); // Special MCU object

  Session = NSDSP.startProgSession(slaveMCU, readOnly = false)
  Session.checkId(adjustRate = true)
  debugSession = Session.programForDebug(hexMap, tcy)

  // Debugging here

  NSDSP.endSession
  NSDSP.free

Debugging Both Cores Simultaneously

To debug the slave and master cores simultaneously, you will need two NSDSP programmers. One programmer is connected in a regular way and is used to program and debug master core. The other is connected to a different pair of PGCx/PGDx pins, uses a special S1MCLRx pin, and is used to debug slave core.

The ICS and S1ICS configuration bits must select the correct PGCx/PGDx for master and slave cores respectively, and must differ from each other. The pseudo-code for simultaneous debugging may look like this:

  masterNSDSP.create(masterSerial)
  slaveNSDSP.create(slaveSerial)

  masterNSDSP.setDebugCores(cores = slave or master) 

  Session = masterNSDSP.startProgSession(mcu, readOnly = false)
  Session.checkId(adjustRate = true)
  masterDebugSession = Session.programForDebug(hexMap, masterTCY)

  debugInfo = masterDebugSession.getSlaveInfo(core = 1, imageA = 1, slaveTCY)

  slaveDebugSession = slaveNSDSP.startDebugSession(debugInfo)

  // Can debug both cores simultaneously
  // masterDebugSession is used to debug master core
  // slaveDebugSession is used to debug slave core

  slaveNSDSP.endSession
  slaveNSDSP.free

  masterNSDSP.endSession
  masterNSDSP.free

Northern Software Home NSDSP Contact Us Purchase/View Cart

© 2007-2025 Northern Software Inc. All Rights Reserved.