Please note as of Wednesday, August 15th, 2018 this wiki has been set to read only. If you are a TI Employee and require Edit ability please contact x0211426 from the company directory.

Using a PSP Driver in DSP/BIOS

From Texas Instruments Wiki
Jump to: navigation, search

This topic details the steps necessary to initialize and use a Platform Support Package (PSP) driver on a DSP-only device. The PSP is included with a standard DVSDK installation, and it allows high-level operation of peripheral devices such as I2C, UART, or video ports using the standard DSP/BIOS GIO or SIO APIs. The PSP for each device provides a full set of IOM-compliant minidrivers for this purpose.

Please note that PSP only exists on recent chips such as the DM6437 or DM648. Older devices, such as the DM642, rely upon functional CSL and/or custom minidrivers (created via DDK) to operate peripheral devices.

Initializing the Peripheral Device

The heart of each PSP driver is an IOM-compliant minidriver. IOM requires that the peripheral device be declared and initialized in the project's textual configuration file (TCF). The following code initializes an I2C device on the DM6437.

bios.UDEV.create("I2C0");
bios.UDEV.instance("I2C0").fxnTableType = "IOM_Fxns";
bios.UDEV.instance("I2C0").initFxn = prog.extern("I2C_INIT");
bios.UDEV.instance("I2C0").params = prog.extern("I2C_devParams");
bios.UDEV.instance("I2C0").fxnTable = prog.extern("I2CMD_FXNS");

Place the above code in a file with a TCI (textual configuration include) extension, such as i2c0.tci. Then add the following line to your project's main TCF:

utils.importFile("i2c0.tci");

The TCI contents may also be placed directly in the TCF, but using TCI files allows many projects to share a single configuration.

Adding a device to TCF using the graphical editor

Alternatively, the TCF graphical configuration tool in Code Composer Studio can be used to automatically generate the above lines in the project’s TCF file. Simply insert a new "User-Defined Device" in the Input/Output category. This will not neatly encapsulate each device in a reusable TCI file, but it allows the user to perform all configuration in the CCS GUI. Note that, in the GUI, references to C objects must be prefixed with the underscore symbol "_" to avoid errors.

The parameters set in the TCI above are, in order, the function table type, initialization function, device parameters data structure, and the function table. If the DSP had more than one I2C peripheral, the TCF would also require a device ID parameter to choose which would be serviced by the PSP driver. Some of the parameters may be included in the driver library (above: fxnTable), while others are furnished in your own source code (above: initFxn, params). The specifics vary with individual drivers; refer to a driver's sample application and user's guide to determine the appropriate TCF entries. If you’re new to DSP/BIOS 5 and/or TCF, these sample TCF files may also help with general system setup: memory segment usage, TSK scheduling, interrupt routines, ECM, and more.

Summary

  • Declare and initialize peripheral device in project's TCF.
  • Device parameters include function tables in the driver library.
  • Device parameters select between peripheral instances if necessary (i.e. UART0, UART1).
  • Device parameters may reference functions or structs furnished in your C source code.
  • Refer to individual driver's sample application and user's guide for details.

Linking the Driver Library

Some PSP deliverables (specifically, releases with version 1.10.xx.xx) are packaged according to the RTSC package standard. Others (version 1.00.xx.xx) are not. This section describes how to integrate either flavor of PSP driver into a project.

Linking PSP 1.10.xx.xx Drivers with XDCTOOLS

Newer PSP releases are packaged as RTSC packages to speed integration. To add a driver library to your project, simply add a single line to XDC configuration script (*.cfg):

xdc.loadPackage('ti.sdo.pspdrivers.drivers.i2c');

Individual drivers may also require additional inclusions: PAL libraries, the EDMA3 LLD, etc. Check the driver's sample application and see which packages are included in its XDC configuration script. If your project doesn’t already contain an XDC configuration script, the sample project’s script is a good starting point. You will also need to properly configure the XDC tab in the project's build options. Fully explaining the XDC build tools falls outside the scope of this document, but some key steps are listed below.

  1. Settings for XDC tab in project build options:
    • Set target: ti.targets.C64P
    • Set platform (ex. ti.platforms.evmDM648)
    • Check box to include TCF in build (or add --tcf)
    • Set XDC search path. One way to do this is simply include the DVSDK’s top-level XDC paths file: --xdcpathsfile="%BIOSDVSDK_INSTALL_DIR%/xdcpaths_evmDM648.dat"
  2. Settings for compiler tab in project build options:
    • Include the automatically generated compiler directives (default: xdcconfig/compiler.opt), which tell CCS where to look for the PSP driver header files. -@"=$(Proj_dir)/xdcconfig/compiler.opt"
  3. Exclude TCF from normal (non-XDC) build.
    • Right click TCF in project view and select "File Specific Options..." In the General tab, check the box marked "Exclude file from build."

Linking the driver library is only half of the story. Any C source file that uses the PSP driver's data types or macros will need the appropriate header file. Under RTSC-packaged PSP, the header file is listed relative to the packages folder of the PSP directory. (The compiler.opt file, generated at build time by XDC, tells CCS to look for header files in all folders defined in your XDC paths file.) For the I2C driver, the relevant include line may look like this:

#include <ti/sdo/pspdrivers/drivers/i2c/psp_i2c.h>

Summary

  • Add package to the project's XDC configuration script.
  • If creating a new XDC config script (*.cfg): add script to project and configure XDC using project build options.
  • Include header file with path relative to XDCTOOLS search path.

Linking PSP 1.00.xx.xx Drivers without XDCTOOLS

Integrating an older, non-RTSC packaged PSP driver is straightforward if less automated. The following instructions refer to menus in Code Composer Studio (CCS), but the process should be virtually identical in other development environments.

Like any other library, the PSP driver may be linked into the project in two different ways. First, it can simply be added to the project as a library file by right clicking on the project's "Libraries" folder and selecting "Add files to project...". Alternatively, the following items can be added on the project's Build Options window, under the Linker tab:

-i"%PSP_INSTALL_DIR%\pspdrivers\lib\" -l"DM6437\Debug\i2c_bios_drv.lib"

In the above, PSP_INSTALL_DIR is a windows environment variable that points to the base PSP directory. The details in the second command (-l"...") depend on the device and the project configuration (debug vs. release; instrumented vs. non-instrumented).

The driver's header file may be referenced directly, but the common PSP include folder must be "included" in the Compiler tab of the Build Options window:

<syntaxhighlightlang='c'>#include <psp_i2c.h></syntaxhighlight> -i"%PSP_INSTALL_DIR%\pspdrivers\inc"

Summary

  • Link in appropriate library file from %PSP_INSTALL_DIR%\pspdrivers\lib\... Navigate further subfolders by device name and project configuration.
  • Include header file in C source with no path.
  • Add PSP include folder to build search path (Build Options, Compiler Tab).

Linking PSP 1.10.xx.xx Drivers without XDCTOOLS

Even with RTSC-packaged PSP, it is possible to bypass XDCTOOLS and integrate drivers directly. To avoid editing PSP header files, simply include the PSP packages subfolder in the compiler's search path.

-i"%PSP_INSTALL_DIR%\packages"

You will need to include the path to each header file relative to this folder in your C source:

<syntaxhighlightlang='c'>#include <ti/sdo/pspdrivers/drivers/i2c/psp_i2c.h></syntaxhighlight>

Library files may be referenced in a similar way. In the Linker tab, "include" the packages folder of the PSP installation, then link libraries relative to that folder:

-i"%PSP_INSTALL_DIR%\packages" -l"ti\sdo\pspdrivers\drivers\i2c\lib\dm6437\Debug\i2c_bios_drv.lib"

Creating and Using a Driver Handle

PSP drivers are typically accessed at runtime via calls to the GIO API (some drivers also implement SIO). A driver handle is created by a call to GIO_create/SIO_create, and the peripheral device is ready for I/O transactions immediately afterward. The parameters required by these functions vary for each driver. Refer to a driver's sample application or user's guide to determine its requirements. The following code block demonstrates the use of GIO_create with an I2C device. GIO_create/SIO_create typically must be called from the TSK context, but PSP 1.10.00.09 or greater allows these functions to be called from main(). (Note: if using EDMA, the EDMA LLD must be version 1.05.xx or greater.)

GIO_Attrs gioAttrs = GIO_ATTRS;
GIO_Handle i2cHandle;
 
i2cHandle = GIO_create("/I2C0", IOM_INOUT, NULL, NULL, &gioAttrs);

Calling GIO_submit with the driver handle and an appropriate command (i.e. read, write) initiates an I/O transaction through the peripheral device. (SIO_issue and SIO_reclaim replace this function when working with the SIO API.) A call to GIO_submit also requires transfer parameters, which vary per driver. Common parameters include a data buffer address, the size of the transaction in bytes, timeout, and a callback function for asynchronous operation. Refer to a driver's sample application and user's guide to determine what parameters it expects in a call to GIO_submit.

The GIO API allows high-level operation of the peripheral device. The PSP driver handles low-level tasks such as timing, start and stop conditions, and byte-by-byte data handling. The user simply provides a buffer and certain transfer parameters, and control passes to the driver. For synchronous operation, GIO_submit does not return until the transaction is complete (or a critical error is encountered). Asynchronous operation requires an application-layer callback function that the driver may call when the transaction is complete. Individual drivers may support synchronous operation, asynchronous operation, or both; refer to a driver's datasheet for details. The following code block uses GIO_read, a standard macro from gio.h that wraps GIO_submit, to read one byte through the I2C handle initialized in the previous code block.

PSP_I2cRequest  readBuf;
size_t          size;
char		buffer;
int		status;
 
readBuf.i2cTrans.buffer		= (Uint8 *)&buffer;
readBuf.i2cTrans.bufLen    	= 1;
readBuf.i2cTrans.flags     	= PSP_I2C_DEFAULT_READ;
readBuf.i2cTrans.param     	= NULL;
readBuf.i2cTrans.slaveAddr 	= 0x50;
readBuf.timeout			= SYS_FOREVER;
size				= 1;
 
status = GIO_read(i2cHandle, &readBuf, &size);

Device parameters are initialized during system startup according to the data structure referenced by the TCF, but certain parameters may be modified at run-time through GIO_control. For instance, UART baud may be changed from 256 kbps to 512 kbps. GIO_control can also issue commands to the driver, such as flushing all pending I/O or retrieving parameters without changing them. Naturally, the functionality of GIO_control varies widely per driver. Refer to a driver's user's guide to find a list of all commands (or IO_CTLs) that it services and what parameters are required for each. The following code block configures an I2C handle to use a bus frequency of 200 kHz.

int i2cBitRate = 200000;
int status = GIO_control(i2cHandle, PSP_I2C_IOCTL_SET_BIT_RATE, &i2cBitRate);

While using a PSP driver, you should avoid modifying the peripheral device's behavior via direct access to its registers. Changes made in this way will not propagate into the PSP driver's internal data structures, which can cause your application to fail.

Summary

  1. Create driver handle in C program using GIO_create or SIO_create.
  2. Device is ready for high-level operation immediately.
  3. Initiate transactions using GIO_submit (GIO_read, GIO_write wrap this function) or SIO_submit/SIO_reclaim.
    • Driver may offer synchronous and/or asynchronous operation.
  4. Modify device status and parameters using GIO_control.
    • Submit device handle, driver-specific IO_CTL, and any additional parameters.
    • Avoid modifying device registers directly: these changes may not propagate properly into the driver’s data structures

Advanced: Beyond PSP

You may find that a PSP driver is not well suited for your application. For instance, the McBSP driver included with the DM6437 PSP is intended solely for audio applications, and it cannot be used for McBSP-as-SPI even though the McBSP peripheral supports this mode of operation. In this situation, there are two options:

  1. Write a low-level program using register-layer CSL (RCSL).
    • RCSL consists of header files containing macros that allow register-level control of the DSP.
    • RCSL is included with the PSP in the soc folder.
  2. Modify the PSP driver.
    • Full source code for all drivers is included with the PSP.
    • TI may provide limited support in the form of tips and/or advice on where to begin and what to change.
    • Typically, a good starting point is the driver's DDC (device driver core) source file.
    • While using the debug driver library, it is possible to set break points in the driver source while running your application. This is a helpful way to observe the driver's behavior.

The first option can be thought of as replacing PSP, while the second modifies or extends it. Be sure to save the original driver library and source code before you begin; you may wish to revert to the original driver functionality without reinstalling the PSP. Refer to PSP Overview to learn more about the structure of a PSP driver and its source code.

Advanced: Decoupling from DSP/BIOS

You may wish to use a PSP driver, or at least some part of it, in an application that does not use DSP/BIOS. This is a tough proposition since most PSP drivers rely on basic OS functions, such as semaphores and registered interrupts, at all layers to function. Other PSP drivers may use the EDMA3 low-level driver (LLD), which is itself coupled to DSP/BIOS. Decoupling a PSP driver from DSP/BIOS requires extensive modification to the driver source code, and will almost certainly result in some loss of functionality.

It's important to understand the structure of a PSP driver before attempting to modify its source code. Refer to PSP Overview for a more complete description of a PSP driver's layers: DDA, DDC, and LLC. The high-level DDA layer, which implements the DSP/BIOS-specific IOM standard, will need to be removed or replaced entirely. The DDC layer will likely require extensive modification to remove or replace OS dependencies: semaphore pends, interrupt registering, calls to the EDMA3 LLD, etc. OS functions in this layer are typically abstracted by calls to the PAL_OS API; calls to this library will need to be removed or replaced. The low-level LLC layer, which is not formally separate from DDC in every PSP driver, should require no modification.

Decoupling a PSP driver from DSP/BIOS is a complicated task that does not lend itself to a simple, step-by-step summary. You should be certain that removing DSP/BIOS from your application is absolutely necessary before attempting this modification.

Miscellaneous Tips

  • Some PSP drivers require the use of PAL_sys and/or PAL_os libraries, which are included with the PSP installation. These must be linked into the project.
  • Similarly, some PSP drivers require the use of an EDMA library (either from PSP or the stand-alone EDMA3 LLD). The appropriate libraries must be linked into the project.
  • Some PSP drivers require a DSP/BIOS LOG object named "trace". Create this in the project's TCF. Refer to the driver's sample application for help.

See Also

PSP Overview

Software Migration: DM642 to DM648/DM6437