Spectrum Digital Target
Interface
Document Revision 0.2
April 23, 2001
1.1 Who
Should Use This Product
4.4 GetOptions()
NOT supported in version 1
4.8 GetErrorString()
Not supported in version 1
11.2 C54x
Extended Address Support
This document covers the specification for the Spectrum Digital Target Interface. A simple C based interface to basic emulation and debug capabilities of various DSP and microprocessor devices.
This product is aimed at the test engineer wanting to automate production test of an end product. To use this product you should be proficient in the following:
1. Structured C programming.
2. Use of Microsoft Visual Studio 6.0.
3. Use of hardware and software development tools for the intended processor.
4. Use of dynamic link libraries and their nuances in a Win32 environment.
The following block diagram shows a typical use of the target interface when used in the Spectrum Digital Flash Programmer application. When used in conjunction with a TI DSP the target interface sits on top of the standard sdgoxxx.dvr driver used with Code Composer. The sdgoxxx.dvr files will load the appropriate emulation drivers based on the emulator address and type specified in the sdopts.cfg file.
The interface is generic in nature and designed to support a wide range of processors without compile time dependencies. This allows an application like a Flash Programmer to support a wide range of devices without being recompiled or reconfigured for each device type supported. When used with a TI processor the interface becomes a thin layer that maps generic functions into specifics of a proprietary interface. This has the advantage of reusing existing well known drivers from Code Composer products but supplementing them with a more generic non- proprietary documented interface.
A working example of the interface can be found in the Spectrum Digital Perl utility. In this example Perl is used for writing test scripts. These scripts are then converted from Perl functions to target function calls via the Spectrum Digital Target Interface, or SDTI. The SDTI consists of 5 major functional interfaces:
1. Configuration: For configuring the interface and specifying operating
modes.
2. Register: For accessing target registers.
3. Memory: For
accessing target memory.
4. Events: For
managing events, i.e. breakpoints
5. Execution: For run control
When connecting to the SDTI driver “sdtsrv.dll” you make one function call to get all the methods for the interface then use the above interfaces. Example:
SD_TARGET_INTERFACE *pSd;
SDTI_GetInterface( &pSd, FAMILY_TMS320C2XX);
pSd->pCfg->CreateHndl(…); // Create a handle for an instance of the C2xx
pSD->pCfg->Connect(…); // Make a physical connection to the C2xx
pSd->pExe->Reset(…); // Reset the C2xx DSP
All interfaces contain version information for compatibility checking. SDTI uses one interface header file named sdti.h which is included by the application. This file also contains interface details for the various types used by SDTI.
All functions in the interface return TRUE (1) or FALSE (0). A return value of TRUE indicates success. A return value of FALSE indicates failure. When an error does occur it is queued in the event queue.
SDTI treats errors, status changes, target events (breakpoints) as events and queues them into the event queue. The application can periodically check the event queue to dequeue the events. The event queue is built as a FIFO.
The user application links to the SDSTRV.DLL file. This dll will likewise make runtime linkage to other Spectrum Digital drivers and support files. These will be the same files as used in a typical Code Composer emulator driver install when used with a TI processor. Following is a list of required files for the C2xx:
Sdtsrv.dll - Top level dll
Sdtsrv.lib - MSVC generated library file that allows implicit linkage by the application
Sdgo2xx.dvr - The standard C2xx Code Composer emulation driver
Sddllmgt.dll - The Spectrum Digital DLL manager/loader
Sdspi515.dll - The XDS510PP_PLUS and SPI515 emulation driver
Sdiont.sys - The WinNT driver required for WinNT4/5 installs
Sdopts.cfg - The standard Spectrum Digital configuration file.
If you have used Code Composer or the SDFlash programming utility you should be familiar with most of the files and file structure.
The remainder of this document covers the interface details for the SDTI interface. A working example of the interface is provided with the SDPerl project for both the C2xx and C54x devices. The header file sdti.h also contains a number of comments on the interface and the associated data types.
See the SDPerl documentation for install and build details. The currently supported SDTI interface runs on Win98, WinNT4, and Win2K. Win95 is not supported or tested.
The configuration interface is defined as:
typedef struct sdf_cfg
{
int
StructSz; // Size of
this structure
int
Version; // Interface
major version
int
Revision; // Interface
minor revision
// Create/Free handle for debug instance
BOOL
(*CreateHndl) ( SDTI_HNDL
*pHndl, char *pLibPath, char *pLibName,
char *pFamily );
BOOL
(*FreeHndl) ( SDTI_HNDL Hndl
);
// Option setup prior to connecting to the
target
BOOL
(*SetOptions) ( SDTI_HNDL Hndl,
char *pOptsString );
BOOL
(*GetOptions) ( SDTI_HNDL Hndl,
int MaxString,
char
*pOptsString );
BOOL
(*FreeOptions) ( SDTI_HNDL Hndl
);
// Connect/Disconnect from the target
BOOL
(*Connect) ( SDTI_HNDL
Hndl );
BOOL
(*Disconnect) ( SDTI_HNDL
Hndl );
// Get an error string based on the error
code
BOOL
(*GetErrorString) ( SDTI_HNDL Hndl, int Error, int MaxString,
char *pErrString );
} SDF_CFG, *PSDF_CFG;
CreateHndl will create an instance for the specified processor but will not make a connection to the processor. This must be the first function called, as it will return a handle that is required by all other functions. The specified driver/dll pointed to by pLibPath\pLibName will be loaded and verified for the proper interface and processor family. Call CreateHndl for each processor you wish to access. You do not have to call CreateHndl processors that you are not accessing, i.e. in bypass.
SDTI_HNDL *pHndl Pointer to return handle
char *pLibPath Path to low level driver,
“c:\ti\drivers”
char *pLibName Name of the low level driver,
“sdgoxxx.dvr”
char *pFamily Processor family, used for interface
verification
Returns TRUE or FALSE.
Notes
The sdgoxxxx.dvr drivers require a specific interface be exposed for sdtsrv.dll. If you are using an older sdgoxxx.dvr this interface may not be exposed. In this case CreatHndl will return FALSE. The sdgoxxxx.dvr files shipped in the SDPerl and SDFlash utilities have the proper interface exposed.
The following code fragment gets the SDTI interface and then attempts to create a handle for one instance.
SDTI_GetInterface( (void **)&pIntf, (char
*)(m_sDspFamily.c_str()) );
if( pIntf != NULL )
{
m_pIntf = (void
*)pIntf;
if(
pIntf->pCfg != NULL )
{
if( pIntf->pCfg->CreateHndl != NULL)
Success = pIntf->pCfg->CreateHndl( &SdTiHndl,
(driver_path[0] == '\0')
? NULL :
driver_path,
(driver_name[0] == '\0')
? NULL : driver_name,
(char
*)(m_sDspFamily.c_str()) );
//
If we failed then return error. If we
got a handle go
//
ahead and free it for safety.
if(
Success == FALSE )
{
if(
SdTiHndl != NULL )
{
if(
pIntf->pCfg->FreeHndl != NULL)
pIntf->pCfg->FreeHndl(
m_SdTiHndl );
}
return(
-1 );
}
}
}
FreeHndl will free the resources created by CreatHndl including the associated instance of the driver/dll specified in CreateHndl. If still connected to the target then FreeHndl will disconnect from the target before freeing. Once the handle is freed no more calls can be made to that processor until a new handle is created.
SDTI_HNDL Hndl Handle created by CreateHndl()
Returns TRUE or FALSE.
SetOptions provides a means to set target specific options prior to making a connection to the target. Once a target is connected many of the options cannot be modified unless you disconnect from the target. For example you cannot change the port address of the attached emulator after you have connected. You can make multiple calls to SetOptions or a single call with multiple options. When passing multiple options each option is comma delimited with no spaces. Example:
Char MyOptions[] = “EmuPortAddr=0x378,DevBoardName=\\ti\\cc\\bin\\brd\\ccBrd0.dat,DevProdName=cpu_0”
SDTI_HNDL Hndl Handle created by CreateHndl()
char *pOptsString Pointer to a comma delimited set of options
Returns TRUE or FALSE.
Supported Options
EmuPortAddr
Emulator port address, to match sdopts.cfg
EmulatorId
Emulator port ID, to match sdopts.cfg
DevBoardName
Path\name of the board file.
DevProcName
Name of the cpu that you want to attach to. Must match the name in your board file.
DevConnectRealtime
Start the emulation session in realtime mode if supported by the processor.
DevRunOnDisconnect
Let the processor run in native non-emulation mode when disconnected.
The following options are set to defaults internally by Spectrum Digital. The user should not modify these. They are included here for completeness
DevEnableMemoryMapChecking
Disable memory map checking. Set to disabled as memory map checking is not supported.
DevMaxMemoryBlockSize
Set the maximum memory block size in target words that can be accesses in one call.
DevForceStatusCheck
When the processor is halted full status checking is not performed. Enable this to force a full status check. Safe but slow.
The following example sets up the EmuPortAddr, DevBoardName, and DevProcName if the user has provided valid input to the application.
if(
pIntf->pCfg->SetOptions != NULL )
{
//
Set the emulator port address
::memset(
opts, 0,MAX_NAME_SIZE);
::strcpy(
opts, "EmuPortAddr=0x" );
if(
!m_sEmulatorAddress.empty() )
::strcat(opts,m_sEmulatorAddress.c_str());
else
::strcat(opts,"378");
pIntf->pCfg->SetOptions(
m_SdTiHndl, opts );
//
Set the board file path
::memset(
opts, 0,MAX_NAME_SIZE);
::strcpy(
opts, "DevBoardName=" );
if(
!m_sBoardFile.empty() )
{
::strncat(opts,m_sBoardFile.c_str(),
MAX_NAME_SIZE-14 );
pIntf->pCfg->SetOptions(
m_SdTiHndl, opts );
}
//
Set the processor name. The name is max
of 8 characters
//
per TI name spec.
::memset(
opts, 0,MAX_NAME_SIZE);
::strcpy(
opts, "DevProcName=" );
if(
!m_sProcessorName.empty() )
{
::strncat(opts,m_sProcessorName.c_str(),8
);
pIntf->pCfg->SetOptions(
m_SdTiHndl, opts );
}
}
Will be supported in a future version.
FreeOptions will free the current options and return to the default state. FreeOptions can only be called with in the disconnected state.
SDTI_HNDL Hndl Handle created by CreateHndl()
Returns TRUE or FALSE.
Connect will attempt to make a physical connection to the target processor. When used with a Spectrum Digital emulator this will include loading low level emulation drivers as required, initializing the drivers then making the target connection. The target connection will be made using the default options or those setup with the SetOptions function. Following a call to Connect, you can then check to see if the target processor is running or halted and retrieve any errors that may have occurred.
SDTI_HNDL Hndl Handle created by CreateHndl()
Returns TRUE or FALSE.
Disconnect will make a physical disconnection from the connected target processor. When disconnected no emulation accesses are allowed.
SDTI_HNDL Hndl Handle created by CreateHndl()
Returns TRUE or FALSE.
Notes
When disconnected the user may cycle power on the target(s). When a subsequent Connect is made the emulation drivers will be reinitialized. In a multiprocessor environment ALL processors have to be disconnected before power is removed.
Will be supported in a future version. You can still get an error number from the event queue for all errors. If the error is generated in the SDTI interface then an SDTI interface error will be queued. If the error originates is a lower layer of software then that lower level error will be queued. See the sdti.h file for SDTI error codes.
The register interface is defined as:
typedef struct sdf_reg
{
int
StructSz; // Size of
this structure
int
Version; // Interface
major version
int
Revision; // Interface
minor revision
BOOL
(*ReadByName) ( SDTI_HNDL Hndl, char *pRegName, TREG *pReg );
BOOL
(*WriteByName)( SDTI_HNDL Hndl, char *pRegName, TREG *pReg );
}SDF_REG, *PSDF_REG;
All processor registers are accessed using a name string. The register name corresponds to the data book name for the register. For each processor a file named stdi_regxxx.c is provided which contains all the registers and their access size used by SDTI. The user can include this C file in the application or simply use the data contained in this file for register accesses.
Read ONE register by name.
SDTI_HNDL Hndl Handle created by CreateHndl()
char *pRegName Register name string
TREG *pReg Pointer to structure to hold the
returned register data.
Returns TRUE or FALSE.
Notes
TREG is a union of all registers sizes so use the proper access type for each register based on the support file sdti_regxxx.c.
Write ONE register by name.
SDTI_HNDL Hndl Handle created by CreateHndl()
char *pRegName Register name string
TREG *pReg Pointer to structure to hold the
input register data.
Returns TRUE or FALSE.
Notes
TREG is a union of all registers sizes so use the proper access type for each register based on the support file sdti_regxxx.c.
The following example shows a 16-bit and 32-bit register write. The C54x example is using the extended PC model, which requires special handling.
BOOL CFixedPointDSP::RunFromSymbol(char * name)
{
struct
SYMBOL * s;
TREG
Pc;
SD_TARGET_INTERFACE
* pIntf = (SD_TARGET_INTERFACE *)m_pIntf;
if(!( ( pIntf != NULL )
&&
( m_SdTiHndl != NULL )
&&
(m_isConnected == TRUE )))
return(
FALSE );
s =
find_sym(name);
if (s
== (struct SYMBOL *)NULL )
return( FALSE );
if(
pIntf->pReg->WriteByName != NULL)
{
if(
m_dsp == DSP_C54X )
{
Pc.Reg32
= s->symaddr >> 16;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "PMR_VAL", &Pc )==FALSE
)
return(
FALSE );
Pc.Reg32
= s->symaddr;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "EXT_PC", &Pc
)==FALSE )
return(
FALSE );
}
else
{
Pc.Reg32
= s->symaddr;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "PC", &Pc ) == FALSE
)
return(
FALSE );
}
}
return(
TRUE );
}
The memory interface is defined as:
typedef struct sdf_mem
{
int
StructSz; // Size of
this structure
int
Version; // Interface
major version
int
Revision; // Interface
minor revision
BOOL
(*Read) ( SDTI_HNDL Hndl,
TMEM_DESC *pMem );
BOOL
(*Write) ( SDTI_HNDL Hndl,
TMEM_DESC *pMem );
BOOL
(*Fill) ( SDTI_HNDL Hndl,
TMEM_DESC *pMem );
}SDF_MEM, *PSDF_MEM;
To support a wide range of memory types and processors a generic method of specifying memory is used. This is a combination of both DSP and non-DSP memory types.
MEM_SPACE tells SDTI which memory bus or space to use for the access.
typedef enum mem_space
{
M_NATURAL = 0, // Natural space for processor, !Harvard
M_PROGRAM, // Program space
M_DATA, // Data space
M_IO // I/O space
}MEM_SPACE, *
PMEM_SPACE;
MEM_ACCESS_SIZE tells SDTI what type of memory access to make for the associated memory space. In general the M_SIZE_NATURAL should be used for non-DSP processors. However on some processors a smaller access size must be made to certain memory ranges. When loading a TI COFF file the type M_COFF should be used for dual endian processors. This preserves the special handling of COFF for those TI processors.
typedef enum
mem_access_size
{
M_SIZE_NATURAL = 0, // Natural size of processor memory bus
M_SIZE8, // 8-Bit
M_SIZE16, // 16-Bit
M_SIZE32, // 32-Bit
M_SIZE64, // 64-Bit
M_COFF // Preserve TI-COFF accesses
}MEM_ACCESS_SIZE, *
PMEM_ACCESS_SIZE;
M_SIZE_NATURAL is defined as the natural access size for the attached processor. For each processor supported this corresponds to the following:
Processor M_SIZE_NATURAL
(native type) M_COFF Needed
C2xx M_SIZE16 No
C54x M_SIZE16 No
C27x M_SIZE16 No
C55x M_SIZE8 No
ARM7 M_SIZE32 Yes
SDTI uses an unsigned long for all memory addresses.
typedef unsigned
long MEM_TADDR; // 32 Bit memory address
For version 1 of the memory interface the Asize and Bsize must be the same. In future versions a variable Bsize will be supported. This will allow SDTI to insert/extract target data into an application specified data format. Memory functions pass the following descriptor:
typedef struct tmem
{
MEM_TADDR Taddr; //
Target address
MEM_SPACE Space; //
Target memory space
MEM_ACCESS_SIZE Asize; // Target
memory access size
MEM_ACCESS_SIZE Bsize; // Host
memory buffer access size
unsigned long Length; // Number
of elements in ACCESS_SIZE
void * pData; // Src/Dst data
} TMEM_DESC,
*PTMEM_DESC;
Access a block of target memory.
SDTI_HNDL Hndl Handle created by CreateHndl()
TMEM_DESC *pMem Pointer to memory access descriptor
pMem->Taddr
Starting target address.
pMem->Space
Memory space to access.
pMem->Asize
Access size for the memory.
pMem->Bsize
Buffer size for the memory access. Must be set to Asize for version 1 of the SDTI.
pMem->Length
Number of Asize elements to access.
pMem->pData
Pointer to the input/output data buffer. The buffer type should match the size in bits of Asize. For example for MSIZE_16 the buffer should be defined as unsigned short, or short.
Returns TRUE or FALSE.
The following code fragment is reading COFF data and writing to the target. This fragment shows support for a program and data space write as well as an 8-bit and 16-bit write. The 16-bit write is for the C54x/C2xx while the 8 bit is for the C55xx. Neither of these processors requires special handling of COFF data.
for( i=1; i<= NumSections; i++ )
{
if
( COFFR_IsLoadSection( pCoffHndl,
(short)i )
!= COFF_NOLOADSECT_ERR )
{
COFFR_GetSectData(
pCoffHndl,
(short)i,
RetBuffer,
0,
LOCTOBYTE(pCoffHndl,
pSectionHdr->s_size),
&ActualBytesRead );
TempSection
= *pSectionHdr;
Tmem.Taddr = pSectionHdr->s_vaddr;
Tmem.Space = (pSectionHdr->s_page == 0) ?
M_PROGRAM : M_DATA;
Tmem.Asize = (m_BytesPerWord == 1) ? M_SIZE8 :
M_SIZE16;
Tmem.Bsize = (m_BytesPerWord == 1) ? M_SIZE8 :
M_SIZE16;
Tmem.Length = ActualBytesRead/m_BytesPerWord;
Tmem.pData = (void *)(RetBuffer);
if(
pIntf->pMem->Write( m_SdTiHndl, &Tmem ) == FALSE )
{
Success
= FALSE;
break;
}
}/*
End of COFFR_IsLoadSection */
pSectionHdr++;
}
The user can set conditions on the target to generate events. Many events are generated by the emulation software or target automatically however other events like software breakpoints need user-defined conditions to cause an event. The event interface is defined as follows:
typedef struct sdf_evt
{
int StructSz;
// Size of this structure
int Version;
// Interface major version
int Revision;
// Interface minor revision
BOOL
(*Add) ( SDTI_HNDL Hndl,
TEVT_DESC *pEvt );
BOOL
(*Delete) ( SDTI_HNDL Hndl,
unsigned EvtId );
}SDF_EVT, *PSDF_EVT;
The EVT_TYPE specifies the type of event that has been queued. To set up a software breakpoint condition you must Add an event of type EVT_SWBP.
typedef enum evt_type
{
EVT_NONE = 0, // No
event
EVT_HALT, // Target halted, by user or non-brkpoint
EVT_SWBP, // Software
EVT_HWIAQ, // Hardware break, Instruction
EVT_HWDATA //
Hardware break, Data access
}EVT_TYPE, * PEVT_TYPE;
typedef struct tevt
{
unsigned EvtId; //
The event Id
MEM_TADDR Taddr; //
Target address
MEM_SPACE Space; //
Target memory space
EVT_TYPE Type; //
Type of breakpoint
} TEVT_DESC,
*PTEVT_DESC;
Add a breakpoint event condition.
SDTI_HNDL Hndl Handle created by CreateHndl()
TEVT_DESC *pEvt Pointer to the event descriptor
PEvt->Taddr
Target address to add the event.
PEvt->Space
Target memory space to add the event.
PEvt->Type
Type of event.
Returns TRUE or FALSE.
pEvt->EvtId
An id number used to identify the event for use by Delete.
Notes
Version 1 of SDTI limits events that can be added to software breakpoints (EVT_SWBP) in program memory (M_PROGRAM).
Delete an event that was set with event Add.
SDTI_HNDL Hndl Handle created by CreateHndl()
unsigned EvtId The event id returned from Add()
Returns TRUE or FALSE.
typedef struct sdf_exe
{
int StructSz;
// Size of this structure
int Version;
// Interface major version
int Revision;
// Interface minor revision
BOOL
(*Reset) ( SDTI_HNDL Hndl );
BOOL
(*Continue) ( SDTI_HNDL Hndl );
BOOL
(*Suspend) ( SDTI_HNDL Hndl );
BOOL
(*Step) ( SDTI_HNDL Hndl,
unsigned long Count );
BOOL
(*UserMode) ( SDTI_HNDL Hndl );
BOOL
(*IsRunning) ( SDTI_HNDL Hndl );
BOOL
(*IsEvent) ( SDTI_HNDL Hndl,
TEVT_STAT_DESC *pEvtStat );
}SDF_EXE, *PSDF_EXE;
Perform target processor reset. Following a Reset the target processor should be in a suspend state. However you should make a call to IsRunning to verify this condition.
SDTI_HNDL Hndl Handle created by CreateHndl()
Returns TRUE or FALSE.
Continue target processor execution from its current state. If a breakpoint is pending then step over the breakpoint and continue. Following a Continue the target processor should be in a non-suspend state until it is stopped by the user or executes and event condition that would suspend execution. Interrupts are active during Continue if enabled by the target application.
SDTI_HNDL Hndl Handle created by CreateHndl()
Returns TRUE or FALSE.
Suspend target processor execution. Following a Suspend the target processor should be in a suspend state. However you should make a call to IsRunning to verify this condition.
SDTI_HNDL Hndl Handle created by CreateHndl()
Returns TRUE or FALSE.
Step the target processor Count instructions or until an event occurs, with interrupts disabled. Following a Step the target processor should be in a suspend state. However you should make a call to IsRunning to verify this condition.
SDTI_HNDL Hndl Handle created by CreateHndl()
Unsigned long Count
Returns TRUE or FALSE.
Return the target processor to user mode and continue execution. The caller must remove breakpoints prior to calling UserMode.
SDTI_HNDL Hndl Handle created by CreateHndl()
Returns TRUE or FALSE.
Is the processor running or not suspended? The target is considered to be running until it is successfully suspended.
SDTI_HNDL Hndl Handle created by CreateHndl()
Returns TRUE or FALSE.
Is there an event in the event queue?
SDTI_HNDL Hndl Handle created by
CreateHndl()
TEVT_STAT_DESC
*pEvtStat Pointer to return a pending
event
Returns TRUE or FALSE.
EvtStat. If pEvtStat is not NULL and an event is pending then the top pending event is returned.
pEvtStat->EvtId
Queued event Id. This
Id is an incrementing number which corresponds to the Nth event queued. This is
NOT the event Id that was returned from Evt->Add().
pEvtStat->Taddr
An address associated with the event/error if applicable, else
0.
pEvtStat->Space
The space associated with the event/error if applicable, else
0.
pEvtStat->Type
The type of non-system event if applicable else, 0.
pEvtStat->System
The type of system event if applicable else, 0.
pEvtStat->Error
The associated error if applicable else, 0.
Notes
All events are returned via IsEvent. If you simply want to know if an event is pending then call IsEvent with pEvtStat=NULL. This allows the application to test for the occurrence of an event but defer processing to later. IsEvent will return TRUE as long as 1 or more events remain in the queue. To dequeue an event you have to call IsEvent with pEvtStat as non-NULL. The event queue includes both target events as well at target/system errors. So while processing events you have to distinguish between events and errors.
Processing Error Events
The following code fragment is an example of error event processing. If a valid error event occurs then a message is printed to let the user know if this is an SDTI error or OTIS driver error. OTIS errors come from the sdgoxxx.dvr and lower level drivers.
BOOL CFixedPointDSP::CheckEvents( void )
{
TEVT_STAT_DESC StatEvt;
BOOL isEvt;
SD_TARGET_INTERFACE * pIntf = (SD_TARGET_INTERFACE *)m_pIntf;
if( (
pIntf == NULL)
|| (
m_SdTiHndl == NULL ))
return(
FALSE );
// Get
the target event if there is one
isEvt
= pIntf->pExe->IsEvent( m_SdTiHndl, &StatEvt );
if(
isEvt )
{
if(
StatEvt.System == EVT_SYS_NONE )
{
//
This should not occur but here for safety
if(
StatEvt.Error )
{
//If
we have a DISCONNECTED error then return isEvt==FALSE.
//If
you are disconnected you will always get a disconnected
//error,
i.e. an endless loop
//
if(
StatEvt.Error == CFG_ERR_DISCONNECTED )
return(
FALSE );
else
OutputMessage(0,"MSG:
Execution event detected\n");
}
}
else
{
//
If system warning event then do not send error message.
//
These are for internal processing.
Return that we saw
//
an event so that caller can continue processing other
//
events as required.
if(
StatEvt.System == EVT_SYS_WARN )
return(
isEvt );
else
{
//If
we have a DISCONNECTED error then return isEvt==FALSE.
//If
you are disconnected you will always get a disconnected
//error,
i.e. an endless loop
//
if(
StatEvt.Error == CFG_ERR_DISCONNECTED )
return(
FALSE );
//
Real errors in SDTI or OTIS
if(
StatEvt.Error > (CFG_ERR_GENERIC -1 ) )
::sprintf(
m_ErrMsg,"ERR: SDTI error,
Error = %d\n",StatEvt.Error);
else
if ( StatEvt.Error < 0 )
::sprintf( m_ErrMsg,"ERR: OTIS error,
Error =
%d\n",StatEvt.Error);
OutputMessage(0, m_ErrMsg );
}
}
}
return(
isEvt );
The following code fragment shows the use of pExe->Continue followed by a wait for breakpoint loop.
// Clear the event queue before starting new execution.
while(
CheckEvents() );
if(
pIntf->pExe->Continue != NULL)
if(
pIntf->pExe->Continue( m_SdTiHndl ) == FALSE )
goto
EXIT_TARG_EXECUTE;
//
Set the timeout and loop looking for an error or breakpoint event
timeout
= m_nEraseTimeout*TIMEOUT;
do
{
TEVT_STAT_DESC StatEvt;
BOOL isEvt;
isEvt
= pIntf->pExe->IsEvent( m_SdTiHndl, &StatEvt );
if(
isEvt )
{
if(
StatEvt.System )
goto
EXIT_TARG_EXECUTE;
if(
StatEvt.Type == EVT_SWBP )
break;
}
else
Sleep(1);
}while(
timeout-- );
if (
timeout < 0 )
{
OutputMessage(0,"ERR:
Exceeded algorithm initialization timeout.\n");
goto
EXIT_TARG_EXECUTE;
}
/*H***************************************************************************
*
* $Archive::
/TI/product/sdtsrv/user/Sdti.h
$
* $Revision:: 3 $
* $Date:: 11/30/00
8:44a $
* $Author:: Tonyc $
*
* DESCRIPTION:
*
* USAGE/LIMITATIONS:
*
* NOTES:
*
* (C) Copyright 2000 by
Spectrum Digital Incorporated
* All rights reserved
*
*H***************************************************************************/
#ifndef sdti_h
#define sdti_h
/*---- compilation
control switches ----------------------------------------*/
/*****************************************************************************
* INCLUDE FILES
(minimize nesting of header files)
*****************************************************************************/
#if defined( _WIN32 )
#if (_MSC_VER >= 900 )
#define WIN32_LEAN_AND_MEAN
#define INC_OLE2
#define NOSERVICE
#endif
#include <windows.h>
#else
#include <stdlib.h>
#include <string.h>
#include <file.h>
// Define BOOL if not in a WIN32 environment
#define BOOL int
#endif
/*---- system and
platform files -------------------------------------------*/
/*---- program files
-------------------------------------------------------*/
/*****************************************************************************
* FILE CONTENT
*****************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/*****************************************************************************
* FUNCTIONAL AREA
DETAIL
*****************************************************************************/
//----------------------------------------------------------------------------
// Interface
Version/Revision
//
#define
SDTI_VERSION 1
#define
SDTI_REVISION 1
//----------------------------------------------------------------------------
// Sub-Interface
Version/Revision
//
#define
SDTI_CFG_VERSION 1
#define
SDTI_CFG_REVISION 1
#define SDTI_REG_VERSION 1
#define
SDTI_REG_REVISION 1
#define
SDTI_MEM_VERSION 1
#define
SDTI_MEM_REVISION 1
#define
SDTI_EVT_VERSION 1
#define
SDTI_EVT_REVISION 1
#define
SDTI_EXE_VERSION 1
#define
SDTI_EXE_REVISION 1
//----------------------------------------------------------------------------
// Interface handle
//
typedef void *
SDTI_HNDL;
//----------------------------------------------------------------------------
// Target register
types
//
typedef unsigned
char TREG_8; // 8-bit register
typedef unsigned short
TREG_16; // 16-bit
register
typedef unsigned
long TREG_32; // 32-bit register
typedef struct treg_64 // 33-64 bit
register
{
unsigned long RegL;
unsigned long RegH;
}TREG_64, *PTREG_64;
typedef union treg
{
TREG_8
Reg8;
TREG_16
Reg16;
TREG_32
Reg32;
TREG_64
Reg64;
}TREG, * PTREG;
// TREG_DESC is used by
sdti_regXXX.c to describe each target register
//
typedef struct
treg_desc
{
char
*pRegName; // Register
name, hopefully match the data book
int
RegSize; // Read/Write size
of the register
int
RegId; // An Id for
the register, not really used
} TREG_DESC, *
PTREG_DESC;
//----------------------------------------------------------------------------
// Target memory types
//
// For Harvard devices
the memory space can be Program or Data.
For
// compatibility with
TI DSP there is also an I/O space.
// If the processor is
not Harvard then use the default of M_NATURAL.
//
// MEM_ACCESS_SIZE
provides a way to force target processor accesses
// to a certain access
boundary. This is generally required by
byte
// addressable
processors with I/O device access size restrictions.
// Some common rules to
apply:
//
// 1) If your processor
is a 16 bit fixed point DSP that can only
// perform 16 bit read/writes then use
M_SIZE16 or M_SIZE_NATURAL.
//
// 2) If your processor
is a 32 bit fixed point DSP that can only
// perform 32 bit read/writes then use
M_SIZE32 or M_SIZE_NATURAL.
//
// 3) If you processor
is a byte addressable machine and you are
// fetching program or data memory then
M_SIZE_NATURAL is recommended.
// Else, use the size that matches your
processor bus width.
//
// 4) For other cases
use the size that matches the access restrictions
// of your I/O or memory devices.
//
// The arguments in
TMEM_DESC are pretty obvious with exception
// of Asize and
Bsize. Asize is the access size of the
processor
// memory read/write
operation, see rules above. Bsize is
the
// size of an element
in the read/write buffer. By having the
// Bsize option the
user can pass in a pointer to a 32 bit buffer
// that only has 16
bits of valid data in each 32 bit element.
// Example:
// unsigned long *pD32;
// unsigned short *pD16;
//
// *pD32++ = (unsigned long)(*pD16++) &
0x0000FFFFL;
//
// Another example is
when the buffer size is smaller then the
// target processor
access size. This is generally the case
// on a fixed point DSP
where you want "char" data that is
// 8 bit instead of the
16 bit DSP "char".
// Example:
// unsigned char *pD8; // Host 8 bit char data
// unsigned char *pD16; // DSP 16 bit data
//
// *pD8++ = (unsigned char)(*pD16++);
//
// When the Asize and
Bsize do not match the unused data bits
// are set to zero.
//
typedef enum mem_space
{
M_NATURAL = 0, // Natural space for processor, !Harvard
M_PROGRAM, // Program space
M_DATA, // Data space
M_IO // I/O space
}MEM_SPACE, *
PMEM_SPACE;
typedef enum
mem_access_size
{
M_SIZE_NATURAL = 0, // Natural size of processor memory bus
M_SIZE8, // 8-Bit
M_SIZE16, // 16-Bit
M_SIZE32, // 32-Bit
M_SIZE64, // 64-Bit
M_COFF // Preserve TI-COFF accesses
}MEM_ACCESS_SIZE, *
PMEM_ACCESS_SIZE;
typedef unsigned
long MEM_TADDR; // 32 Bit memory address
typedef struct tmem
{
MEM_TADDR Taddr; //
Target address
MEM_SPACE Space; //
Target memory space
MEM_ACCESS_SIZE Asize; // Target
memory access size
MEM_ACCESS_SIZE Bsize; // Host
memory buffer access size
unsigned long Length; // Number
of elements in ACCESS_SIZE
void * pData; // Src/Dst data
} TMEM_DESC,
*PTMEM_DESC;
//----------------------------------------------------------------------------
// Target event types
//
typedef enum evt_type
{
EVT_NONE = 0, //
No event
EVT_HALT,
// Target halted, by user or non-brkpoint
EVT_SWBP, // Software
EVT_HWIAQ, // Hardware break, Instruction
EVT_HWDATA // Hardware break, Data access
}EVT_TYPE, * PEVT_TYPE;
typedef enum evt_system
{
EVT_SYS_NONE = 0, // No
event
EVT_SYS_WARN, // Generic warning, not an error
EVT_SYS_ERROR, // Generic non-target error
EVT_SYS_TARGET, // Generic
target error
EVT_SYS_TARGET_DISCONNECT, // Target is disconnected
EVT_SYS_TARGET_LOSSPOWER, // Target lost power
EVT_SYS_TARGET_TIMED_OUT, // Target operation timed out
EVT_SYS_TARGET_IN_RESET, // Target is being held in reset
EVT_SYS_TARGET_NOT_READY, // Target is being held not ready
EVT_SYS_TARGET_BUS_FAULT, // Target performed a bus fault
}EVT_SYSTEM, *
PEVT_SYSTEM;
typedef struct tevt
{
unsigned EvtId; //
The event Id
MEM_TADDR Taddr; //
Target address
MEM_SPACE Space; //
Target memory space
EVT_TYPE Type; //
Type of breakpoint
} TEVT_DESC,
*PTEVT_DESC;
typedef struct
tevt_stat
{
// Event information that pertains to
breakpoint type events
unsigned EvtId; //
The event Id
MEM_TADDR Taddr; //
Target address
MEM_SPACE Space; //
Target memory space
EVT_TYPE Type; // Type of breakpoint
// Event information that pertains to
error type events
EVT_SYSTEM System; //
System events
int Error;
}TEVT_STAT_DESC,
*PTEVT__STAT_DESC;
/*A***************************************************************************
* NAME: Spectrum Digital Target Interface
*
* USAGE: Interface that
can sit on top of GTI, OTI or others.
The
* interface is processor independent and
you can specify your
* "cpu" family during initialization. Further, argument options that
* do not cleanly fit into generic data
types are passed in as
* strings. This allows any number of options to be supported without
* continually changing the interface.
*
* CONNECTION:
* The interface has only 1 external function
"SDTI_GetInterface. The
* user calls this functions to get a
pointer to the "Interface" which
* contains configuration information
plus all the functions (methods)
* for the interface. You then access
functions as follows:
*
* pIntf->pCfg->Init(...);
* pIntf->pCfg->Open(...);
*
* The function SDTI_GetInterface
includes a parameter pTargetFamily.
* This parameter specifies which target
processor you are targeting.
* If the requested target family is not
supported then NULL is
* returned for the interface.
*
* This style of interface is most
significant when built as
* a DLL and explicitly loaded by the
caller. In this case you only
* have to get a reference to one function
"SDTI_GetInterface" then
* call it to get everything you need to
know about the interface.
*
* VERSION/REVISION:
* The interface provides a
version/revision. The caller should
* always check for interface
version/revision compatibility.
* "Version" changes when a
significant change to the interface
* occurs that would effect backward
compatibility. "Revision"
* changes when a minor change occurs
that would not affect backward
* compatibility. You can also use sizeof( SD_TARGET_INTERFACE
)
* and compare to "StructSz"
for another level of checking.
*
* RETURN :
* Return types follow the Microsoft
convention
* 1 - True/Success. The function completed without error.
* 0 - False/Failure. The function did
not complete without error.
* The error will be queued into the
event queue.
*
* POINTERS :
* Again following the Microsoft
convention all pointer arguments
* are checked for NULL. If a pointer is NULL then input arguments
* are not used and return arguments are
not returned. Example,
* if you call GetLastError and set
pErrString to NULL then no
* error string is returned.
*A***************************************************************************/
//----------------------------------------------------------------------------
// Interface config
functions
//
// CreateHndl : Create
a handle for this debug instance. If pLibPath
and
// pLibName are not NULL then use
the specified debug library.
// Else, pDevName must hold the
name of the processor family
// to connect to. If all three parameters are provided then
// pFamily will be used to validate
the loaded lib..
// A valid handle is returned
except in the rare case of
// insufficent host memory. Thus you can call GetLastError
// if there is an error during
CreateHndl.
//
// FreeHndl : Free the handle from CreateHndl. Closes the open
// debug session if required. You MUST always call
// this to release resources if
CreateHndl returns
// a valid handle. FreeHndl will
automaticly "Disconnect"
// if the debug session is still
"Connected".
//
// SetOptions : Set the
options for this debug session. Options are
// generally setup prior to
connecting to a target.
// Options are in the form of
"EmulatorId=378,...",
// using a comma seperator and null
terminator. Once
// connected some options cannot be
changed until you
// disconnect, for example your
EmulatorId.
//
// GetOptions : Return
the current options. MaxString is the
maximum
// size of the return string.
//
// FreeOptions : Free
the current options and return to the default
// state. FreeOptions can only be
called when in the
// disconnected state. You can change current options
// by calling SetOptions with the
restriction that not
// all options can be changed
while in the connected
// state.
//
// Connect : Make a debug connection to the
target. Once connected the
// target is ready for a debug
session.
//
// Disconnect :
Disconnect from the debug session. Once disconnected no
// more target accesses are
allowed.
//
// GetErrorString : Get
an error string based on the error number
//
//
//----------------------------------------------------------------------------
// Valid device
families for the function CreatHndl
#define
FAMILY_TMS320C5X
"TMS320C5X"
#define
FAMILY_TMS320C3X
"TMS320C3X"
#define FAMILY_TMS320VC3X "TMS320VC3X"
#define
FAMILY_TMS320C4X
"TMS320C4X"
#define
FAMILY_TMS320C2XX
"TMS320C2XX"
#define
FAMILY_TMS320C54X
"TMS320C54X"
#define
FAMILY_TMS320C6XX
"TMS320C6XX"
#define FAMILY_TMS320C55XX "TMS320C55XX"
#define
FAMILY_TMSR470
"TMSR470"
#define
FAMILY_TMS320C27XX
"TMS320C27XX"
typedef struct sdf_cfg
{
int
StructSz; // Size of
this structure
int
Version; // Interface major version
int
Revision; // Interface
minor revision
// Create/Free handle for debug instance
BOOL
(*CreateHndl) ( SDTI_HNDL
*pHndl, char *pLibPath, char *pLibName,
char *pFamily );
BOOL
(*FreeHndl) ( SDTI_HNDL Hndl
);
// Option setup prior to connecting to the
target
BOOL
(*SetOptions) ( SDTI_HNDL Hndl,
char *pOptsString );
BOOL
(*GetOptions) ( SDTI_HNDL Hndl, int MaxString,
char
*pOptsString );
BOOL
(*FreeOptions) ( SDTI_HNDL Hndl
);
// Connect/Disconnect from the target
BOOL
(*Connect) ( SDTI_HNDL
Hndl );
BOOL (*Disconnect) ( SDTI_HNDL Hndl );
// Get an error string based on the error
code
BOOL
(*GetErrorString) ( SDTI_HNDL Hndl, int Error, int MaxString,
char *pErrString );
} SDF_CFG, *PSDF_CFG;
//----------------------------------------------------------------------------
// Register functions
//
// ReadByName : Read a target register using the
"common" register name as
// the identifier.
// WriteByName : Write
a target register using the "common" register name as
// the identifier.
//
// Each processor has a
register mapping file named "sdti_regCPU.c" where
// CPU is a processor
identifier. Each register is defined
as:
// { "Name", Size, Id }
// C54x Example:
// {"IMR", sizeof(TREG_16), 0 },
// {"IFR", sizeof(TREG_16), 1 },
//
typedef struct sdf_reg
{
int
StructSz; // Size of
this structure
int
Version; // Interface major version
int
Revision; // Interface
minor revision
BOOL
(*ReadByName) ( SDTI_HNDL Hndl, char *pRegName, TREG *pReg );
BOOL
(*WriteByName)( SDTI_HNDL Hndl, char *pRegName, TREG *pReg );
}SDF_REG, *PSDF_REG;
//----------------------------------------------------------------------------
// Memory functions
//
// Read : Read a block of memory.
// Write : Write a
block of memory.
// Fill : Fill a block of memory.
//
// The user can specify
a memory type, i.e. program, data, i/o for Harvard(TI),
// or natural for
others.
// The user then
specifies if the access size is to be 8,16,32,64 bit.
// The length of the
block is in "access size" elements.
//
// Data in the memory
buffer is passed in host endianess format for the
// specified access
size.
//
typedef struct sdf_mem
{
int
StructSz; // Size of
this structure
int
Version; // Interface
major version
int
Revision; // Interface
minor revision
BOOL
(*Read) ( SDTI_HNDL Hndl,
TMEM_DESC *pMem );
BOOL
(*Write) ( SDTI_HNDL Hndl,
TMEM_DESC *pMem );
BOOL
(*Fill) ( SDTI_HNDL Hndl,
TMEM_DESC *pMem );
}SDF_MEM, *PSDF_MEM;
//----------------------------------------------------------------------------
// Event functions
//
// Add : Add an event. An event Id is returned.
// Delete : Delete an
event based on EvtId.
//
typedef struct sdf_evt
{
int StructSz; // Size of this structure
int Version;
// Interface major version
int Revision;
// Interface minor revision
BOOL
(*Add) ( SDTI_HNDL Hndl,
TEVT_DESC *pEvt );
BOOL
(*Delete) ( SDTI_HNDL Hndl,
unsigned EvtId );
}SDF_EVT,
*PSDF_EVT;
//----------------------------------------------------------------------------
// Execution functions
//
// Reset : Do a
hardware or software reset on the connected target.
// Continue : Continue
target execution from the current program address.
// Suspend : Suspend target execution.
// Step : Step "Count" assembly
instructions with interrupts off.
// UserMode : Continue
target execution in user mode, i.e. connected but
// debug disabled.
// IsRunning : Is the
target processor running or suspended.
The
// target is considered
"running" until it is SUCCESSFULLY
// suspended.
// IsEvent : Is an
event pending. If pEvtStat is not NULL then return the
// pending event.
//
// IsEvent returns all
events, i.e. breakpoints, errors, status, etc..
// As long as events
are in the queue IsEvent will return "TRUE".
//
typedef struct sdf_exe
{
int StructSz;
// Size of this structure
int Version;
// Interface major version
int Revision;
// Interface minor revision
BOOL
(*Reset) ( SDTI_HNDL Hndl );
BOOL
(*Continue) ( SDTI_HNDL Hndl );
BOOL
(*Suspend) ( SDTI_HNDL Hndl );
BOOL
(*Step) ( SDTI_HNDL Hndl,
unsigned long Count );
BOOL
(*UserMode) ( SDTI_HNDL Hndl );
BOOL
(*IsRunning) ( SDTI_HNDL Hndl );
BOOL
(*IsEvent) ( SDTI_HNDL Hndl,
TEVT_STAT_DESC *pEvtStat );
}SDF_EXE, *PSDF_EXE;
typedef struct
sd_target_interface
{
int StructSz;
// Size of this structure
int Version; // Interface major version
int Revision;
// Interface minor revision
int Type;
// Interface type
int isInitalized;
// True if intf. autoinit
char
* Name; // Interface name, will contain
the
//
target family name
unsigned long Flags; //
Operation flags
SDF_CFG * pCfg; // Interface config functions
SDF_REG * pReg;
// Register functions
SDF_MEM * pMem;
// Memory functions
SDF_EVT * pEvt;
// Event functions
SDF_EXE * pExe; // Execution functions
}SD_TARGET_INTERFACE,
*PSD_TARGET_INTERFACE ;
typedef enum
sdti_errors
{
ERR_NONE = 0,
// Config errors
CFG_ERR_GENERIC = 4000,
GFG_ERR_HOST_MALLOC, // Fail host memory malloc
CFG_ERR_LIB_HANDLE, // Could not get targ lib
handle
CFG_ERR_LIB_INTERFACE, // Invalid lib interface
CFG_ERR_LIB_VERSION, // Invalid lib version
CFG_ERR_FAMILY, // Invalid processor family
CFG_ERR_UNKNOWN_OPTION, // Unknown/unsupported option
CFG_ERR_HANDLE, // Passed handle is invalid
CFG_ERR_DISCONNECTED, // Invalid action when targ
disconnected
// Register errors
REG_ERR_GENERIC = 5000,
REG_ERR_NAME, // Invalid register name
// Memory errors
MEM_ERR_GENERIC = 6000,
MEM_ERR_SPACE, // Invalid memory space
MEM_ERR_ACCESS_SIZE, // Access size not supported
MEM_ERR_ADDRESS, // Invalid or out of range address
// Event errors
EVT_ERR_GENERIC = 7000,
EVT_ERR_ADDRESS, // Invalid or out of range address
EVT_ERR_SPACE, //
Invalid memory space
EVT_ERR_TYPE, // Unsupported event type
// Execution errors
EXE_ERR_GENERIC = 8000,
EXE_ERR_TARGET_RUNNING // Invalid action while running
}SDTI_ERRORS, *
PSDTI_ERRORS;
/*---- global data
declarations --------------------------------------------*/
/*---- global function
prototypes ------------------------------------------*/
#ifdef GLOBAL
#undef GLOBAL
#endif
#ifdef sdti_c
#define GLOBAL
#else
#define GLOBAL extern
#endif
GLOBAL int
SDTI_GetInterface( void
** pInterface, char *pFamily );
#ifdef __cplusplus
}
#endif
#endif /* inf_h -------
END OF FILE ----------------------------------------*/
The C2xx supports the following register names and sizes. This is extracted from sdti_reg2xx.c.
#define NOT_USED 0
TREG_DESC
SDTI_RegDef_2xx[] =
{
{"PC", sizeof(TREG_16),
NOT_USED}, // PC
{"AR0", sizeof(TREG_16), NOT_USED}, // FP
{"AR1", sizeof(TREG_16), NOT_USED}, // SP
{"AR2", sizeof(TREG_16), NOT_USED},
{"AR3", sizeof(TREG_16), NOT_USED},
{"AR4", sizeof(TREG_16), NOT_USED},
{"AR5", sizeof(TREG_16), NOT_USED},
{"AR6", sizeof(TREG_16), NOT_USED},
{"AR7", sizeof(TREG_16), NOT_USED},
{"ACC", sizeof(TREG_32), NOT_USED},
{"ACCH", sizeof(TREG_16), NOT_USED},
{"ACCL", sizeof(TREG_16), NOT_USED},
{"PR",
sizeof(TREG_32),
NOT_USED},
{"PRH", sizeof(TREG_16), NOT_USED},
{"PRL", sizeof(TREG_16), NOT_USED},
{"TR", sizeof(TREG_16),
NOT_USED},
{"GREG", sizeof(TREG_16), NOT_USED},
{"IFR", sizeof(TREG_16), NOT_USED},
{"IMR", sizeof(TREG_16), NOT_USED},
{"ST0", sizeof(TREG_16), NOT_USED},
{"ST1", sizeof(TREG_16), NOT_USED},
{"TOS", sizeof(TREG_16), NOT_USED},
{"RPTC", sizeof(TREG_16), NOT_USED},
{(char *)NULL, 0,
NOT_USED}
};
The C54x supports the following register names and sizes. This is extracted from sdti_reg54x.c.
#define NOT_USED
0
TREG_DESC SDTI_RegDef_54x[] =
{
{"PC",
sizeof(TREG_16),
NOT_USED}, // PC
{"SP",
sizeof(TREG_16),
NOT_USED}, // SP
{"AR0",
sizeof(TREG_16),
NOT_USED}, //
{"AR1",
sizeof(TREG_16), NOT_USED},
{"AR2",
sizeof(TREG_16),
NOT_USED},
{"AR3",
sizeof(TREG_16),
NOT_USED},
{"AR4",
sizeof(TREG_16),
NOT_USED},
{"AR5",
sizeof(TREG_16),
NOT_USED},
{"AR6",
sizeof(TREG_16), NOT_USED},
{"AR7",
sizeof(TREG_16),
NOT_USED},
{"A",
sizeof(TREG_32),
NOT_USED},
{"AL",
sizeof(TREG_16),
NOT_USED},
{"AH",
sizeof(TREG_16),
NOT_USED},
{"AG",
sizeof(TREG_16),
NOT_USED},
{"B",
sizeof(TREG_32),
NOT_USED},
{"BL",
sizeof(TREG_16),
NOT_USED},
{"BH",
sizeof(TREG_16),
NOT_USED},
{"BG",
sizeof(TREG_16),
NOT_USED},
{"IMR", sizeof(TREG_16), NOT_USED},
{"IFR",
sizeof(TREG_16),
NOT_USED},
{"ST0",
sizeof(TREG_16),
NOT_USED},
{"ST1",
sizeof(TREG_16)
NOT_USED},
{"TREG",
sizeof(TREG_16),
NOT_USED},
{"TRN", sizeof(TREG_16), NOT_USED},
{"BK",
sizeof(TREG_16),
NOT_USED},
{"BRC",
sizeof(TREG_16),
NOT_USED},
{"RSA",
sizeof(TREG_16),
NOT_USED},
{"REA",
sizeof(TREG_16),
NOT_USED},
{"PMST", sizeof(TREG_16), NOT_USED},
{"EXT_PC",
sizeof(TREG_32),
NOT_USED},
{"PMR_ADDR", sizeof(TREG_16), NOT_USED},
{"PMR_PAGE", sizeof(TREG_16), NOT_USED},
{"PMR_MASK", sizeof(TREG_16), NOT_USED},
{"PMR_RANGE",sizeof(TREG_16), NOT_USED},
{"PMR_VAL",
sizeof(TREG_16),
NOT_USED},
{"PMR_ACTIVE",sizeof(TREG_16), NOT_USED},
{(char
*)NULL, 0, NOT_USED}
};
The C54x supports extended addressing but does require some setup. The following code example shows how to setup the C54x for extended addressing.
BOOL CFixedPointDSP::SetupExtendedAddressing(
void )
{
TREG
Reg;
SD_TARGET_INTERFACE
* pIntf = (SD_TARGET_INTERFACE *)m_pIntf;
if(!( (
pIntf != NULL)
&&
( m_SdTiHndl != NULL )
&&
(m_isConnected == TRUE )))
return(
FALSE );
if( (
m_dsp == DSP_C54X )
&& ( pIntf->pReg->WriteByName != NULL ))
{
//PMR_ADDR
= 0x001E
Reg.Reg32
= 0x001E;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "PMR_ADDR", &Reg ) ==
FALSE )
return(
FALSE );
//PMR_PAGE = 1
Reg.Reg32
= 1;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "PMR_PAGE", &Reg ) ==
FALSE )
return(
FALSE );
//PMR_MASK = 0x007F
Reg.Reg32
= 0x007F;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "PMR_MASK", &Reg ) ==
FALSE )
return(
FALSE );
//PMR_RANGE = 0x8000
Reg.Reg32
= 0x8000;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "PMR_RANGE", &Reg )
== FALSE )
return(
FALSE );
//PMR_VAL = 0
Reg.Reg32
= 0;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "PMR_VAL", &Reg ) ==
FALSE )
return(
FALSE );
//PMR_ACTIVE = 1 to enable, 0 to disable
Reg.Reg32
= 1;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "PMR_ACTIVE", &Reg ) ==
FALSE )
return(
FALSE );
}
return(
TRUE );
}
To set the PC on the C54x requires that you first
write the PMR_VAL with the upper byte of the extended address then write the
entire 32bit extended PC value to EXT_PC. The following code example is setting
the C54x PC when passed the name of a function.
BOOL CFixedPointDSP::RunFromSymbol(char * name)
{
struct
SYMBOL * s;
TREG
Pc;
SD_TARGET_INTERFACE
* pIntf = (SD_TARGET_INTERFACE *)m_pIntf;
if(!( ( pIntf != NULL )
&&
( m_SdTiHndl != NULL )
&&
(m_isConnected == TRUE )))
return(
FALSE );
s =
find_sym(name);
if (s
== (struct SYMBOL *)NULL )
return( FALSE );
if(
pIntf->pReg->WriteByName != NULL)
{
if(
m_dsp == DSP_C54X )
{
Pc.Reg32
= s->symaddr >> 16;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "PMR_VAL", &Pc
)==FALSE )
return(
FALSE );
Pc.Reg32
= s->symaddr;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "EXT_PC", &Pc
)==FALSE )
return(
FALSE );
}
else
{
Pc.Reg32
= s->symaddr;
if(
pIntf->pReg->WriteByName( m_SdTiHndl, "PC", &Pc ) == FALSE
)
return(
FALSE );
}
}
return(
TRUE );
}