TMS320 DSP/BIOS User’s Guide Literature Number: SPRU423B November 2002
IMPORTANT NOTICE Texas Instruments Incorporated and its subsidiaries (TI) reserve the right to make corrections, modifications, enhancements, improvements, and other changes to its products and services at any time and to discontinue any product or service without notice. Customers should obtain the latest relevant information before placing orders and should verify that such information is current and complete.
Preface Read This First About This Manual DSP/BIOS gives developers of mainstream applications on Texas Instruments TMS320 DSP devices the ability to develop embedded real-time software. DSP/BIOS provides a small firmware real-time library and easy-touse tools for real-time tracing and analysis. You should read and become familiar with the TMS320 DSP/BIOS API Reference Guide for your platform. The API reference guide is a companion volume to this user’s guide.
Related Documentation From Texas Instruments ❏ Square brackets ( [ and ] ) identify an optional parameter. If you use an optional parameter, you specify the information within the brackets. Unless the square brackets are in a bold typeface, do not enter the brackets themselves. ❏ Throughout this manual, 54 can represent the two-digit numeric appropriate to your specific DSP platform. If your DSP platform is C62x based, substitute 62 each time you see the designation 54.
Related Documentation From Texas Instruments TMS320C54x Assembly Language Tools User’s Guide (literature number SPRU102) describes the assembly language tools (assembler, linker, and other tools used to develop assembly language code), assembler directives, macros, common object file format, and symbolic debugging directives for the C5000 generation of devices.
Related Documentation From Texas Instruments TMS320C55x Programmer's Guide (literature number SPRU376) describes ways to optimize C and assembly code for the TMS320C55x DSPs and includes application program examples. TMS320C6000 Programmer's Guide (literature number SPRU189) describes the C6000 CPU architecture, instruction set, pipeline, and interrupts for these digital signal processors.
Related Documentation TMS320C55x Code Composer Studio Tutorial Online Help (literature number SPRH097) introduces the Code Composer Studio integrated development environment and software tools. Of special interest to DSP/BIOS users are the Using DSP/BIOS lessons. TMS320C6000 Code Composer Studio Tutorial Online Help (literature number SPRH125) introduces the Code Composer Studio integrated development environment and software tools. Of special interest to DSP/BIOS users are the Using DSP/BIOS lessons.
Trademarks Principles of Concurrent and Distributed Programming (Prentice Hall International Series in Computer Science), by M. Ben-Ari, published by Prentice Hall; ISBN: 013711821X, May 1990 American National Standard for Information Systems-Programming Language C X3.159-1989, American National Standards Institute (ANSI standard for C); (out of print) Trademarks MS-DOS, Windows, and Windows NT are trademarks of Microsoft Corporation.
Contents 1 About DSP/BIOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1-1 DSP/BIOS is a scalable real-time kernel. It is designed for applications that require real-time scheduling and synchronization, host-to-target communication, or real-time instrumentation. DSP/ BIOS provides preemptive multi-threading, hardware abstraction, real-time analysis, and configuration tools. 1.1 DSP/BIOS Features and Benefits . . . . . . . . . . . . .
Contents 4 Thread Scheduling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-1 This chapter describes the types of threads a DSP/BIOS program can use, their behavior, and their priorities during program execution. 4.1 Overview of Thread Scheduling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2 4.2 Hardware Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Contents 7.13 7.14 7.15 7.16 7.17 Real-Time I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-38 Closing Devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-41 Device Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7-43 Device Ready . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Figures Figures 1-1 1-2 1-3 1-4 1-5 2-1 2-2 2-3 2-4 3-1 3-2 3-3 3-4 3-5 3-6 3-7 3-8 3-9 3-10 3-11 3-12 3-13 3-14 3-15 3-16 3-17 3-18 3-19 3-20 3-21 xii DSP/BIOS Components .................................................................................................1-4 Configuration Tool Interface.............................................................................................1-7 The DSP/BIOS Menu ............................................................................................
Figures 3-22 3-23 3-24 4-1 4-2 4-3 4-4 4-5 4-6 4-7 4-8 4-9 4-10 4-11 4-12 4-13 4-14 4-15 4-16 4-17 4-18 4-19 4-20 4-21 4-22 4-23 5-1 5-2 5-3 6-1 6-2 6-3 6-4 7-1 7-2 7-3 7-4 7-5 7-6 The Memory Page Dialog Box ...................................................................................... 3-35 The Software Interrupts Page Dialog Box..................................................................... 3-36 RTDX Data Flow between Host and Target .........................................................
Figures 7-7 7-8 7-9 7-10 7-11 7-12 7-13 7-14 7-15 xiv inStreamSrc Properties Dialog Box ...............................................................................7-18 Sine Wave Output for Example 7-9 ...............................................................................7-22 Flow of DEV_STANDARD Streaming Model ................................................................7-38 Placing a Data Buffer to a Stream ................................................................................
Tables Tables 1-1 1-2 1-3 1-4 2-1 2-2 2-3 3-1 3-2 3-3 3-4 4-1 4-2 4-3 4-4 7-1 DSP/BIOS Modules ........................................................................................................ 1-5 DSP/BIOS Standard Data Types: ................................................................................. 1-12 Memory Segment Names ............................................................................................. 1-13 Standard Memory Segments ...........................................
Examples Examples 2-1 2-2 2-3 2-4 2-5 2-6 3-1 3-2 3-3 4-1 4-2 4-3 4-4 4-5 4-6 4-7 4-8 4-9 4-10 4-11 4-12 4-13 4-14 4-15 4-16 4-17 5-1 5-2 5-3 5-4 xvi Creating and Referencing Dynamic Objects ................................................................ 2-11 Deleting a Dynamic Object .......................................................................................... 2-11 Sample Makefile for a DSP/BIOS Program ..................................................................
Examples 5-5 5-6 5-7 5-8 5-9 5-10 5-11 5-12 5-13 5-14 5-15 5-16 5-17 5-18 7-1 7-2 7-3 7-4 7-5 7-6 7-7 7-8 7-9 7-10 7-11 7-12 7-13 7-14 7-15 7-16 7-17 7-18 7-19 7-20 7-21 7-22 7-23 7-24 7-25 Using MEM_free to Free Memory .................................................................................. 5-6 Freeing an Array of Objects ........................................................................................... 5-6 Memory Allocation (C5000 and C28x Platforms)...................................
Examples 7-26 7-27 7-28 7-29 7-30 7-31 7-32 7-33 xviii The Parameters of SIO_create..................................................................................... The Dxx_Obj Structure ................................................................................................. Typical Features for a Terminating Device ................................................................... Template for Dxx_issue for a Typical Terminating Device ...........................................
Chapter 1 About DSP/BIOS DSP/BIOS is a scalable real-time kernel. It is designed for applications that require real-time scheduling and synchronization, host-to-target communication, or real-time instrumentation. DSP/BIOS provides preemptive multi-threading, hardware abstraction, real-time analysis, and configuration tools. Topic Page 1.1 DSP/BIOS Features and Benefits . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2 1.2 DSP/BIOS Components . . . . . . . . . . . . . . . . . . . . . . . . .
DSP/BIOS Features and Benefits 1.1 DSP/BIOS Features and Benefits DSP/BIOS and its Analysis Tool for Code Composer Studio software are designed to minimize memory and CPU requirements on the target. This design goal is accomplished in the following ways: ❏ All DSP/BIOS objects can be created in the Configuration Tool and bound into an executable program image. This reduces code size and optimizes internal data structures. ❏ Instrumentation data (such as logs and traces) are formatted on the host.
DSP/BIOS Features and Benefits ❏ Low-level system primitives are provided to make it easier to handle errors, create common data structures, and manage memory usage. ❏ The Chip Support Library (CSL) is a component of DSP/BIOS and can be used within a DSP/BIOS application. The DSP/BIOS API standardizes DSP programming for a number of TI devices and provides easy-to-use powerful program development tools.
DSP/BIOS Components 1.2 DSP/BIOS Components Figure 1-1 shows the components of DSP/BIOS within the program generation and debugging environment of Code Composer Studio: Figure 1-1. DSP/BIOS Components Host Target Code Composer Studio source files .cdb (Config database) cfg.cmd cfg.s54 cfg.h54 cfg_c.c cfg.h OLE application using RTDX DSP Code Composer editor Configuration Tool .c .h .asm DSP/BIOS API Code Composer project Code generation tools Compiler, assembler, lnker...
DSP/BIOS Components 1.2.1 DSP/BIOS Real-Time Kernel and API DSP/BIOS is a scalable real-time kernel, designed for applications that require real-time scheduling and synchronization, host-to-target communication, or real-time instrumentation. DSP/BIOS provides preemptive multi-threading, hardware abstraction, real-time analysis, and configuration tools. The DSP/BIOS API is divided into modules, however, the CSL is actually a sub-component of BIOS, with many sub-modules of its own.
DSP/BIOS Components 1.2.
DSP/BIOS Components Figure 1-2. Configuration Tool Interface Using the Configuration Tool, DSP/BIOS objects can be pre-configured and bound into an executable program image. Alternately, a DSP/BIOS program can create and delete objects at run time. In addition to minimizing the target memory footprint by eliminating run-time code and optimizing internal data structures, creating static objects with the Configuration Tool detects errors earlier by validating object properties before program compilation.
DSP/BIOS Components 1.2.3 The DSP/BIOS Analysis Tools The DSP/BIOS Analysis Tools complement the Code Composer Studio environment by enabling real-time program analysis of a DSP/BIOS application. You can visually monitor a DSP application as it runs with minimal impact on the application’s real-time performance. The DSP/BIOS Analysis Tools are found on their own menu, as shown in Figure 1-3. Figure 1-3.
DSP/BIOS Components Figure 1-4 illustrates several of the DSP/BIOS Analysis Tools panels. Figure 1-4. Code Composer Studio Analysis Tool Panels Figure 1-5 shows the DSP/BIOS Analysis Tools toolbar, which can be toggled on and off by choosing View→Plug-in Toolbars→DSP/BIOS. Figure 1-5.
Naming Conventions 1.3 Naming Conventions Each DSP/BIOS module has a unique name that is used as a prefix for operations (functions), header files, and objects for the module. This name is comprised of 3 or more uppercase alphanumerics. Throughout this manual, 54 represents the two-digit numeric appropriate to your specific DSP platform. If your DSP platform is C6200 based, substitute 62 each time you see the designation 54.
Naming Conventions DSP/BIOS includes a number of modules that are used internally. These modules are undocumented and subject to change at any time. Header files for these internal modules are distributed as part of DSP/BIOS and must be present on your system when compiling and linking DSP/BIOS programs. 1.3.2 Object Names System objects that are included in the configuration by default typically have names beginning with a 3- or 4-letter code for the module that defines or uses the object.
Naming Conventions ❏ LNK_F_dataPump. Run by the LNK_dataPump IDL object to manage the transfer of real-time analysis and HST channel data to the host. ❏ HWI_unused. Not actually a function name. This string is used in the Configuration Tool to mark unused HWI objects. Note: Your program code should not call any built-in functions whose names begin with MOD_F_. These functions are intended to be called only as function parameters specified within the Configuration Tool.
Naming Conventions In addition, the standard constant NULL (0) is used by DSP/BIOS to signify an empty pointer value. The constants TRUE (1) and FALSE (0) are used for values of type Bool. Object structures used by the DSP/BIOS API modules use a naming convention of MOD_Obj, where MOD is the letter code for the object’s module. If your program code uses any such objects created by the Configuration Tool, it should make an extern declaration for the object.
Naming Conventions Table 1.3 Memory Segment Names (continued) b. C55x Platform Segment Description IDATA Primary block of data memory DATA1 Secondary block of data memory (not contiguous with DATA) PROG Program memory VECT DSP Interrupt vector table memory segment c.
Naming Conventions 1.3.6 Standard Memory Sections The Configuration Tool defines standard memory sections and their default allocations as shown in Table 1-4. You can change these default allocations using the MEM Manager in the Configuration Tool. For more detail, see MEM Module in the TMS320 DSP/BIOS API Reference Guide for your platform. Table 1-4. Standard Memory Segments a. C54x Platform Sections Segment System stack Memory (.stack) IDATA Application Argument Memory (.
For More Information Table 1.4 Standard Memory Segments (continued) c. C6000 Platform Sections Segment System stack memory (.stack) IDRAM Application constants memory (.const) IDRAM Program memory (.text) IPRAM Data memory (.data) IDRAM Startup code memory (.sysinit) IPRAM C initialization records memory (.cinit) IDRAM Uninitialized variables memory (.bss) IDRAM c. C2800 Platform Sections Segment System stack memory (.stack) M1SARAM Program memory (.text) IPROG Data memory (.
Chapter 2 Program Generation This chapter describes the process of generating programs with DSP/BIOS. It also explains which files are generated by DSP/BIOS components and how they are used. Topic Page 2.1 Development Cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2 2.2 Using the Configuration Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3 2.3 Files Used to Create DSP/BIOS Programs. . . . . . . . . . . . . . . . . . . . 2-12 2.
Development Cycle 2.1 Development Cycle DSP/BIOS supports iterative program development cycles. You can create the basic framework for an application and test it with a simulated processing load before the DSP algorithms are in place. You can easily change the priorities and types of program threads that perform various functions.
Using the Configuration Tool 2.2 Using the Configuration Tool The Configuration Tool is a visual editor with an interface similar to the Windows Explorer. It allows you to initialize data structures and set various parameters used by DSP/BIOS. When you save a file, the Configuration Tool creates assembly source and header files and a linker command file to match your settings. When you build your application, these files are linked with your application programs.
Using the Configuration Tool 8) In the Save as type box choose Seed files (*.cdb) and click Save. 9) In the Set Description dialog type a description and click OK. 10) In the Configuration Tool, choose File→Exit. 2.2.3 Setting Global Properties for a Module 1) When you choose a module (by clicking on it), the right side of the window shows the current properties for the module. (If you see a list of priorities instead of a property list, right-click on the module and choose Property/value view.
Using the Configuration Tool Note: SYS_printf is probably the most memory intensive function in DSP/BIOS. Use the LOG functions instead of SYS_printf to make your application smaller. ❏ Improved run-time performance. In addition to saving code space, avoiding dynamic creation of objects reduces the time your program spends performing system setup. Creating objects with the Configuration Tool has the following limitations: ❏ Objects are created whether or not they are needed.
Using the Configuration Tool Note: When specifying C functions to be run by various objects, add an underscore before the C function name. For example, type _myfunc to run a C function called myfunc. The underscore prefix is necessary because the Configuration Tool creates assembly source, and C calling conventions require an underscore before C functions called from assembly. 2.2.
Using the Configuration Tool ❏ CLK - Clock Manager ❏ PRD - Periodic Function Manager ❏ SWI - Software Task Manager ❏ TSK - Task Manager ❏ IDL - Idle Function Manager The order of objects in the Ordered Collection View can be rearranged by dragging and dropping the object into its new position. For example, if you require the CLK0 object to execute immediately after the PRD_clock object, drag and drop CLK0 on top of the PRD_clock object.
Using the Configuration Tool The small model makes assumptions about the placement of global data in order to reduce the number of instruction cycles. If you are using the small model (the default compilation mode) to optimize global data access, your code can be modified to make sure that it references objects created with the Configuration Tool correctly. There are four methods for dealing with this issue.
Using the Configuration Tool Since objects created with the Configuration Tool are not placed in the .bss section, you must ensure that application code compiled with the small model references them correctly. There are three ways to do this: ❏ Declare static objects with the far keyword. The DSP/BIOS compiler supports this common extension to the C language. The far keyword in a data declaration indicates that the data is not in the .bss section.
Using the Configuration Tool You can guarantee this placement of objects by using the Configuration Tool as follows: a) Declare a new memory segment by inserting a MEM object with the MEM Manager and setting its properties (i.e., the base and length); or use one of the preexisting data memory MEM objects. b) Place all objects that are referenced by small model code in this memory segment. c) Place Uninitialized Variables Memory (.
Using the Configuration Tool Most XXX_create functions accept as their last parameter a pointer to a structure of type XXX_Attrs which is used to assign attributes to the newlycreated object. By convention, the object is assigned a set of default values if this parameter is NULL.
Files Used to Create DSP/BIOS Programs 2.3 Files Used to Create DSP/BIOS Programs When you save a configuration file for your program with the Configuration Tool, the following files are created. These files are described below. The numeric 62 is applicable to the C62x platform only. Replace the 62 in the extensions with 54, 55, or 64 depending on your platform. ❏ ❏ ❏ ❏ ❏ ❏ program.cdb programcfg.h54 programcfg.s54 programcfg.cmd programcfg.h programcfg_c.
Files Used to Create DSP/BIOS Programs 2.3.1 ❏ module.h. DSP/BIOS API header files for C or C++ programs. Your source files should include std.h and the header files for any modules the program uses. ❏ module.h54. DSP/BIOS API header files for assembly programs. Assembly source files should include the *.h54 header file for any module the assembly source uses. ❏ program.obj. Object file(s) compiled or assembled from your source file(s) ❏ *.obj.
Compiling and Linking Programs 2.4 Compiling and Linking Programs You can build your DSP/BIOS executables using a Code Composer Studio project or using your own makefile. The Code Composer Studio software includes gmake.exe, the GNU make utility, and sample makefiles for gmake to build the tutorial examples. 2.4.
Compiling and Linking Programs For details on how to create a Code Composer Studio project and build an executable from it, refer to the Code Composer Studio User’s Guide or the online help. For most DSP/BIOS applications the generated linker command file, programcfg.cmd, suffices to describe all memory segments and allocations. All DSP/BIOS memory segments and objects are handled by this linker command file. In addition, most commonly used sections (such as .text, .bss, .data, etc.
Compiling and Linking Programs Note: Code Composer Studio software allows only one linker command file per project. When both programcfg.cmd and app.cmd are required by the application, the project should use app.cmd (rather than programcfg.cmd) as the project's linker command file. To include programcfg.cmd in the linking process, you must add the following line to the beginning of app.cmd: -lprogramcfg.cmd (This line begins with a dash character and then a lower-case L character.
Compiling and Linking Programs Example 2-3. Sample Makefile for a DSP/BIOS Program # Makefile for creation of program named by the PROG variable # The following naming conventions are used by this makefile: # .asm - C54 assembly language source file # .obj - C54 object file (compiled/assembled source) # .out - C54 executable (fully linked program) # cfg.s54 - configuration assembly source file # generated by Configuration Tool # cfg.
Using DSP/BIOS with the Run-Time Support Library 2.5 Using DSP/BIOS with the Run-Time Support Library The linker command file generated by the Configuration Tool automatically includes directives to search the necessary libraries including a DSP/BIOS, RTDX, and a run-time support library. The run-time support library is created from rts.src, which contains the source code for the run-time support functions.
Using DSP/BIOS with the Run-Time Support Library Note: It is recommended to use the DSP/BIOS library version of malloc, free, memalign, calloc and realloc within DSP/BIOS applications. When you are not referencing these functions directly in your application but call another run-time support function which references one or more of them, add '-u _symbol', (for example, -u _malloc) to your linker options.
DSP/BIOS Startup Sequence 2.6 DSP/BIOS Startup Sequence When a DSP/BIOS application starts up, the calls or instructions in the boot.s54 (C54x platform), or autoinit.c and boot.snn (C6000 and C55x platforms) files determine the startup sequence. Compiled versions of these files are provided with the bios.ann and biosi.ann libraries and the source code is available on the distribution disks received with your product.
DSP/BIOS Startup Sequence Note: When configuring an interrupt with the Configuration Tool, DSP/BIOS plugs in the corresponding ISR (interrupt service routine) into the appropriate location of the interrupt service table. However, DSP/BIOS does not enable the interrupt bit in IER. It is your responsibility to do this at startup or whenever appropriate during the application execution. ■ HST_init initializes the host I/O channel interface.
DSP/BIOS Startup Sequence ■ CLK_startup sets up the PRD register, enables the bit in the IER (C6000 platform) or the IMR (C5400 platform) for the timer chosen in the CLK Manager, and finally starts the timer. (This macro is only expanded if you enable the CLK Manager in the Configuration Tool.) ■ PIP_startup calls the notifyWriter function for each created pipe object. ■ SWI_startup enables software interrupts.
DSP/BIOS Startup Sequence The C5500 platform also allows for three possible stack modes (see Table 2-3). To configure the processor in any of the non-default modes, the user is required to set bits 28 and 29 to the reset vector location appropriately using the Code Composer Studio debugger tool and then to apply a software reset. For more information, please see the TMS320C55x DSP CPU Reference Guide. Table 2-3.
Using C++ with DSP/BIOS 2.7 Using C++ with DSP/BIOS DSP/BIOS applications can be written in C++. An understanding of issues regarding C++ and DSP/BIOS can help to make C++ application development proceed smoothly. These issues concern memory management, name mangling, calling class methods from the Configuration Tool, and special considerations for class constructors and destructors. 2.7.1 Memory Management The functions new and delete are the C++ operators for dynamic memory allocation and deallocation.
Using C++ with DSP/BIOS Example 2-4. Declaring Functions in an Extern C Block extern "C" { Void function1(); Int function2(); } This allows you to refer to the functions within the Configuration Tool (preceded by an underscore, as with other C function names). For example, if you had an SWI object which should run function1() every time that the SWI posts, you would enter _function1 into the function property of that SWI object.
Using C++ with DSP/BIOS A wrapper function for a class method is shown in Example 2-6. Example 2-6. Wrapper Function for a Class Method Void wrapper (SampleClass myObject) { myObject->method(); } Any additional parameters that the class method requires can be passed to the wrapper function. 2.7.4 Class Constructors and Destructors Any time that a C++ class object is instantiated, the class constructor executes. Likewise, any time that a class object is deleted, the class destructor is called.
User Functions Called by DSP/BIOS 2.8 User Functions Called by DSP/BIOS User functions called by DSP/BIOS objects (IDL, TSK, SWI, PIP, PRD, and CLK objects) need to follow specific conventions in order to ensure that registers are used properly and that values are preserved across function calls. On the C6x and C55x platforms, all user functions called by DSP/BIOS objects need to conform to C compiler register conventions for their respective platforms.
Calling DSP/BIOS APIs from Main 2.9 Calling DSP/BIOS APIs from Main The main routine in a DSP/BIOS application is for user initialization purposes such as configuring a peripheral, or enabling individual hardware interrupts. It is important to recognize that main does not fall into any of the DSP/BIOS threads types (HWI, SWI, TSK, or IDL), and that when program execution reaches main, not all of the DSP/BIOS initialization is complete.
Chapter 3 Instrumentation DSP/BIOS provides both explicit and implicit ways to perform real-time program analysis. These mechanisms are designed to have minimal impact on the application’s real-time performance. Topic Page 3.1 Real-Time Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2 3.2 Instrumentation Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-4 3.3 Instrumentation APIs . . . . . . . . . . . . . . . . . . . . . . . . . .
Real-Time Analysis 3.1 Real-Time Analysis Real-time analysis is the analysis of data acquired during real-time operation of a system. The intent is to easily determine whether the system is operating within its design constraints, is meeting its performance targets, and has room for further development. Note: On platforms where RTDX is not updated only in stop mode. That is, host PC while the target program is reach a breakpoint, analysis data Composer Studio.
Real-Time Analysis a balance between program perturbation and recording sufficient information. Limited instrumentation provides inadequate detail, but excessive instrumentation perturbs the measured system to an unacceptable degree. DSP/BIOS provides a variety of mechanisms that allow you to control precisely the balance between intrusion and information gathered. In addition, the DSP/BIOS instrumentation operations all have fixed, short execution times.
Instrumentation Performance 3.2 Instrumentation Performance When all implicit DSP/BIOS instrumentation is enabled, the CPU load increases less than one percent in a typical application.
Instrumentation Performance 3.2.1 ❏ Statistics are accumulated in 32-bit variables on the target and in 64-bit variables on the host. When the host polls the target for real-time statistics, it resets the variables on the target. This minimizes space requirements on the target while allowing you to keep statistics for long test runs. ❏ You can specify the buffer size for LOG objects. The buffer size affects the program’s data size and the time required to upload log data.
Instrumentation Performance Table 3-1. Examples of Code-size Increases Due to an Instrumented Kernel a.
Instrumentation APIs 3.3 Instrumentation APIs Effective instrumentation requires both operations that gather data and operations that control the gathering of data in response to program events. DSP/BIOS provides the following three API modules for data gathering: ❏ LOG (Event Log Manager). Log objects capture information about events in real time. System events are captured in the system log. You can create additional logs using the Configuration Tool. Your program can add messages to any log.
Instrumentation APIs The LOG and STS APIs are also used internally by DSP/BIOS to collect information about program execution. These internal calls in DSP/BIOS routines provide implicit instrumentation support. As a result, even applications that do not contain any explicit calls to the DSP/BIOS instrumentation APIs can be monitored and analyzed using the DSP/BIOS Analysis Tools. For example, the execution of a software interrupt is recorded in a LOG object called LOG_system.
Instrumentation APIs ❏ Fixed. The log stores the first messages it receives and stops accepting messages when its message buffer is full. As a result, a fixed log stores the first events that occur since the log was enabled. ❏ Circular. The log automatically overwrites earlier messages when its buffer is full. As a result, a circular log stores the last events that occur.
Instrumentation APIs Using the RTA Control Panel Properties dialog box as shown in Figure 3-3, you can control how frequently the host polls the target for log information. To access the RTA Control Panel select DSP/BIOS→RTA Control Panel. Rightclick on the RTA Control Panel and choose the Property Page to set the refresh rate. If you set the refresh rate to 0, the host does not poll the target for log information unless you right-click on a log window and choose Refresh Window from the pop-up menu.
Instrumentation APIs 3.3.3 Statistics Object Manager (STS Module) This module manages statistics objects, which store key statistics while a program runs. You create individual statistics objects using the Configuration Tool. Each STS object accumulates the following statistical information about an arbitrary 32-bit wide data series: ❏ Count. The number of values on the target in an application-supplied data series ❏ Total.
Instrumentation APIs Although statistics are accumulated in 32-bit variables on the target, they are accumulated in 64-bit variables on the host. When the host polls the target for real-time statistics, it resets the variables on the target. This minimizes space requirements on the target while allowing you to keep statistics for long test runs. The Statistics View can optionally filter the data arithmetically before displaying it as shown in Figure 3-5. Figure 3-5.
Instrumentation APIs 3.3.3.1 Statistics About Varying Values STS objects can be used to accumulate statistical information about a time series of 32-bit data values. For example, let Pi be the pitch detected by an algorithm on the ith frame of audio data. An STS object can store summary information about the time series {Pi}.
Instrumentation APIs 3.3.3.3 Statistics About Value Differences Both STS_set and STS_delta update the contents of the previous value field in an STS object. Depending on the call sequence, you can measure specific value differences or the value difference since the last STS update. Example 3-1 shows code for gathering information about differences between specific values. Figure 3-6 shows current values when measuring differences from the base value. Example 3-1.
Instrumentation APIs Example 3-2 gathers information about a value’s difference from a base value. Figure 3-7 illustrates the current value when measuring differences from a base value. Example 3-2.
Instrumentation APIs 3.3.4 Trace Manager (TRC Module) The TRC module allows an application to enable and disable the acquisition of analysis data in real time. For example, the target can use the TRC module to stop or start the acquisition of data when it discovers an anomaly in the application’s behavior.
Instrumentation APIs DSP/BIOS defines constants for referencing specific trace bits as shown in Figure 3-2. The trace bits allow the target application to control when to start and stop gathering system information. This can be important when trying to capture information about a specific event or combination of events. Table 3-2.
Instrumentation APIs You can enable and disable these trace bits in the following ways: ❏ From the host, use the RTA Control Panel as shown in Figure 3-8. This panel allows you to adjust the balance between information gathering and time intrusion at run time. By disabling various implicit instrumentation types, you lose information but reduce the overhead of processing. You can control the refresh rate for trace state information by rightclicking on the Property Page of the RTA Control Panel.
Implicit DSP/BIOS Instrumentation 3.4 Implicit DSP/BIOS Instrumentation The instrumentation needed to allow the DSP/BIOS Analysis Tools to display the Execution Graph, system statistics, and CPU load are built automatically into a DSP/BIOS program to provide implicit instrumentation. You can enable different components of DSP/BIOS implicit instrumentation by using the RTA Control Panel Analysis Tool in Code Composer, as described in section 3.4.4.2, Control of Implicit Instrumentation, page 3-15.
Implicit DSP/BIOS Instrumentation CLK and PRD events are shown to provide a measure of time intervals within the Execution Graph. Rather than timestamping each log event, which is expensive (because of the time required to get the timestamp and the extra log space required), the Execution Graph simply records CLK events along with other system events. As a result, the time scale on the Execution Graph is not linear.
Implicit DSP/BIOS Instrumentation Figure 3-10. CPU Load Graph Window All CPU activity is divided into work time and idle time. To measure the CPU load over a time interval T, you need to know how much time during that interval was spent doing application work (tw) and how much of it was idle time (ti).
Implicit DSP/BIOS Instrumentation When the CPU is not performing any of those activities, it is going through the idle loop, executing the IDL_cpuLoad function, and calling the other DSP/ BIOS IDL objects. In other words, the CPU idle time in a DSP/BIOS application is the time that the CPU spends doing the routine in Example 3-3.
Implicit DSP/BIOS Instrumentation The host uploads the STS objects from the target at the polling rate set in the RTA Control Panel Property Page. The information contained in IDL_busyObj is used to calculate the CPU load. The IDL_busyObj count provides a measure of N (the number of times the idle loop ran). The IDL_busyObj maximum is not used in CPU load calculation. The IDL_busyObj total provides the value T in units of the high-resolution clock.
Implicit DSP/BIOS Instrumentation Figure 3-12. Monitoring Stack Pointers (C6000 platform) Default Configuration Monitoring isr1 IST IST 00 : b isr0 isr0 00 : b isr0 isr0 20 : b isr1 isr1 20 : b stub1 stub1 20n : b isrn isrn 20n : b isrn isrn isr1 For hardware interrupts that are not monitored, there is no overhead—control passes directly to the HWI function. For interrupts that are monitored, control first passes to a stub function generated by the Configuration Tool.
Implicit DSP/BIOS Instrumentation 3) Run your program and view the STS object that monitors the stack pointer for this HWI function in the Statistics View window. 4) Subtract the minimum value of the stack pointer (maximum field in the STS object) from the end of the system stack to find the maximum depth of the stack. The Kernel Object View displays stack information for all targets. (See section 3.5, Kernel/Object View Debugger) Figure 3-13.
Implicit DSP/BIOS Instrumentation To enable implicit HWI instrumentation: 1) Open the properties window for any HWI object and choose a register to monitor in the monitor field. You can monitor any variable shown in Table 3-3, or you can monitor nothing. When you choose to monitor a variable, the Configuration Tool automatically creates an STS object to store the statistics for the variable. Table 3-3.
Implicit DSP/BIOS Instrumentation Table 3-4. STS Operations and Their Results STS Operation Result STS_add( *addr ) Stores maximum and total for the data value or register value STS_delta( *addr ) Compares the data value or register value to the prev property of the STS object (or a value set consistently with STS_set) and stores the maximum and total differences. STS_add( -*addr ) Negates the data value or register value and stores the maximum and total.
Implicit DSP/BIOS Instrumentation 3) Load your program in Code Composer and use the Statistics View to view the STS object that monitors the stack pointer for this HWI function. 4) Run your program. Any change to the value at the top of the stack is seen as a non-zero total (or maximum) in the corresponding STS object. 3.4.5 Interrupt Latency Interrupt latency is the maximum time between the triggering of an interrupt and when the first instruction of the HWI executes.
Kernel/Object View Debugger 3.5 Kernel/Object View Debugger The Kernel/Object View debug tool allows a view into the current configuration, state, and status of the DSP/BIOS objects currently running on the target. To start Kernel/Object View in Code Composer Studio software, go to DSP/BIOS→Kernel/Object View as shown in Figure 3-14. Figure 3-14. Selecting The Kernel/Object View Debugger.
Kernel/Object View Debugger Figure 3-15. 3.5.1 The Disabled Message Kernel The kernel page (select the tab labeled KNL) shows system-wide information as shown in Figure 3-16. Figure 3-16. The Kernel Page Dialog Box The Kernel page fields and other information are as follows: ❏ 3-30 Mode. The value in this field indicates the current operating mode of the target.
Kernel/Object View Debugger 3.5.2 ❏ Target. The Target field indicates the target processor and whether it is an emulator or simulator. ❏ Time. This is the current value of the clock that is used for timer functions and alarms for tasks. The clock is set up during configuration (PRD_clk) in CLK - Clock Manager. This is only used when tasks are enabled in the Task Manager (TSK). When tasks are disabled, the time field remains zero. ❏ System Stack.
Kernel/Object View Debugger 3.5.3 ❏ Name (Handle). This is the task name and handle. The name is taken from the label for statically configured objects and is generated for dynamically created objects. The label matches the name in the task manager configuration. The handle is the address on the target. ❏ State. The current state of the task: Ready, Running, Blocked, or Terminated. ❏ Priority. This is the task’s priority as set in the configuration or as set by the API.
Kernel/Object View Debugger Figure 3-19. ❏ Name (Handle). This is the mailbox name and handle. The name is taken from the label for statically configured objects and is generated for dynamically created objects. The label matches the name in the MBX Manager configuration. The handle is the address on the target. ❏ Msgs/Max.The first number is the current number of messages that the mailbox contains. The second number is the maximum number of messages that the mailbox can hold.
Kernel/Object View Debugger 3.5.4 Semaphores The semaphores page (select the tab labeled SEM) shows all semaphore information as illustrated in Figure 3-20. Figure 3-20. The Semaphores Page Dialog Box The semaphores page fields and other information are as follows: 3-34 ❏ Semaphore(s). The value in this field indicates the number of semaphores present in the currently operating system. The number of lines of information in the main information field is equal to the value in this field.
Kernel/Object View Debugger Figure 3-21. 3.5.5 Viewing a List of Tasks Pending Memory The memory page (select the tab labeled MEM) shows all memory heap information as illustrated in Figure 3-22. Figure 3-22. The Memory Page Dialog Box The memory page fields and other information are as follows: ❏ Heap(s). The value in this field indicates the number of heaps present in the currently operating system.
Kernel/Object View Debugger 3.5.6 ❏ Max Contiguous. This is the maximum amount of contiguous memory that is free to allocate in the heap. ❏ Free. This is the total amount of memory that is free to allocate in the heap. If this value is zero a warning will be given. A warning is indicated when this field is red and the text is yellow. ❏ Size (Start/End). This is the heap size and the starting and ending locations in memory. ❏ Used. This is the amount of memory that is allocated from the heap.
Kernel/Object View Debugger in the SWI Manager configuration. The handle is the address on the target. ❏ State. This is the software interrupt’s current state. Valid states are Inactive, Ready, or Running. ❏ Priority. This is the software interrupt’s priority as set in the configuration or during creation. Valid priorities are 0 through 15. ❏ Mailbox. This is the software interrupt’s current mailbox value.
Instrumentation for Field Testing 3.6 Instrumentation for Field Testing The embedded DSP/BIOS run-time library and DSP/BIOS Analysis Tools support a new generation of testing and diagnostic tools that interact with programs running on production systems. Since DSP/BIOS instrumentation is so efficient, your production program can retain explicit instrumentation for use with manufacturing tests and field diagnostic tools, which can be designed to interact with both implicit and explicit instrumentation. 3.
Real-Time Data Exchange 3.7.1 RTDX Applications RTDX is well suited for a variety of control, servo, and audio applications. For example, wireless telecommunications manufacturers can capture the outputs of their vocoder algorithms to check the implementations of speech applications. Embedded control systems also benefit from RTDX. Hard disk drive designers can test their applications without crashing the drive with improper signals to the servo-motor.
Real-Time Data Exchange Figure 3-24. RTDX Data Flow between Host and Target Host OLE automation client OLE interface Target Code Composer RTDX host library JTAG interface User interface RTDX Target Library Target DSP application (optional) log file 3.7.3.1 Target to Host Data Flow To record data on the target, you must declare an output channel and write data to it using routines defined in the user interface.
Real-Time Data Exchange An OLE automation client can send data to the target using the OLE Interface. All data to be sent to the target is written to a memory buffer within the RTDX host library. When the RTDX host library receives a read request from the target application, the data in the host buffer is sent to the target via the JTAG interface. The data is written to the requested location on the target in real time. The host notifies the RTDX target library when the operation is complete. 3.7.3.
Real-Time Data Exchange 3.7.4 RTDX Modes The RTDX host library provides the following modes of receiving data from a target application: ❏ Non-continuous. The data is written to a log file on the host. Noncontinuous mode should be used when you want to capture a finite amount of data and record it in a log file. ❏ Continuous. The data is simply buffered by the RTDX host library; it is not written to a log file.
Real-Time Data Exchange 3.7.7 Sending Data From Target to Host or Host to Target The user library interface provides the data types and functions for: ❏ ❏ Sending data from the target to the host Sending data from the host to the target The following data types and functions are defined in the header file rtdx.h. They are available via DSP/BIOS or standalone.
Chapter 4 Thread Scheduling This chapter describes the types of threads a DSP/BIOS program can use, their behavior, and their priorities during program execution. Topic Page 4.1 Overview of Thread Scheduling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2 4.2 Hardware Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-11 4.3 Software Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-26 4.4 Tasks . . . . .
Overview of Thread Scheduling 4.1 Overview of Thread Scheduling Many real-time DSP applications must perform a number of seemingly unrelated functions at the same time, often in response to external events such as the availability of data or the presence of a control signal. Both the functions performed and when they are performed are important. These functions are called threads. Different systems define threads either narrowly or broadly.
Overview of Thread Scheduling ❏ Software interrupts (SWI). Patterned after hardware interrupt (HWIs). While HWIs are triggered by a hardware interrupt, software interrupts are triggered by calling SWI functions from the program. Software interrupts provide additional priority levels between hardware interrupts and TSKs. SWIs handle threads subject to time constraints that preclude them from being run as tasks, but whose deadlines are not as severe as those of hardware ISRs.
Overview of Thread Scheduling 4.1.2 Choosing Which Types of Threads to Use The type and priority level you choose for each thread in an application program has an impact on whether the threads are scheduled on time and executed correctly. The Configuration Tool makes it easy to change a thread from one type to another. Here are some rules for deciding which type of object to use for each task to be performed by a program: 4-4 ❏ SWI or TSK versus HWI.
Overview of Thread Scheduling ensures that the PRD_swi software interrupt can preempt those routines when the next system tick occurs and PRD_swi is posted again. 4.1.3 A Comparison of Thread Characteristics Table 4-1 provides a comparison of the thread types supported by DSP/BIOS. Table 4-1. Comparison of Thread Characteristics Characteristic HWI SWI TSK IDL Priority Highest 2nd highest 2nd lowest Lowest Number of priority levels DSP-dependent 15.
Overview of Thread Scheduling Table 4.1.
Overview of Thread Scheduling 4.1.4 Thread Priorities Within DSP/BIOS, hardware interrupts have the highest priority. The Configuration Tool lists HWI objects in order from highest to lowest priority as shown in Figure 4-1, but this priority is not maintained implicitly by DSP/BIOS. The priority only applies to the order in which multiple interrupts that are ready on a given CPU cycle are serviced by the CPU.
Overview of Thread Scheduling 4.1.5 Yielding and Preemption The DSP/BIOS schedulers run the highest-priority thread that is ready to run except in the following cases: ❏ The thread that is running disables some or all hardware interrupts temporarily (with HWI_disable or HWI_enter), preventing hardware ISRs from running. ❏ The thread that is running disables software interrupts temporarily (with SWI_disable). This prevents any higher-priority software interrupt from preempting the current thread.
Overview of Thread Scheduling Table 4-2.
Overview of Thread Scheduling Figure 4-2. Preemption Scenario In Figure 4-2, the low priority software interrupt is asynchronously preempted by the hardware interrupts. The first ISR posts a higher-priority software interrupt, which is executed after both hardware interrupt routines finish executing.
Hardware Interrupts 4.2 Hardware Interrupts Hardware interrupts handle critical processing that the application must perform in response to external asynchronous events. The DSP/BIOS HWI module is used to manage hardware interrupts. In a typical DSP system, hardware interrupts are triggered either by ondevice peripherals or by devices external to the DSP. In both cases, the interrupt causes the processor to vector to the ISR address.
Hardware Interrupts You need to enter only the name of the ISR that is called in response to a hardware interrupt in the Property Page of the corresponding HWI object in the Configuration Tool. DSP/BIOS takes care of setting up the interrupt table so that each hardware interrupt is handled by the appropriate ISR. The Configuration Tool also allows you to select the memory segment where the interrupt table is located. The online help in the Configuration Tool describes HWI objects and their parameters.
Hardware Interrupts In real-time mode, background codes are suspended at break events while continuing to execute the time-critical interrupt service routines (also referred to as foreground code.) 4.2.3.
Hardware Interrupts unhaltable region of code, in which case the halt will be delayed until DBGM is no longer set. This is just like an interrupt, which will be delayed until INTM is no longer set. As an example, assume there is a variable called Semaphore, which is incremented in an ISR, and decremented in the main loop. Because of the way interrupts and debug accesses are handled, neither can occur in the italicized regions below: Example 4-1.
Hardware Interrupts Figure 4-3.
Hardware Interrupts Single Instruction State: This state is entered when you tell the debugger to execute a single instruction by using RUN 1 or a STEP 1 command. The CPU executes the single instruction pointed to by PC and then returns to the debug halt state. If an interrupt occurs in this state and RUN 1 command was used to enter the state, CPU can service the interrupt. However, if STEP 1 was used to enter the state, CPU cannot service the interrupt. This is true for both stop mode and real-time mode.
Hardware Interrupts Run State: This state is entered when you use a run command from the debugger interface. CPU services all the interrupts, depending on the INTM bit and the IER register value. Figure 4-4.
Hardware Interrupts DSP/BIOS has some code segments that need to be protected from interrupts; these code sections are called critical sections. If these segments are interrupted, and interrupt calls some DSP/BIOS API, it is bound to corrupt the program results. Therefore, it is important to surround the code with SET INTM, DBGM and CLRC INTM, DBGM. Figure 4-2 shows two code examples of regions protected from all interrupts. Example 4-2. Code Regions That are Uninterruptible (a) Assembly Code .
Hardware Interrupts 4.2.4 Context and Interrupt Management Within Interrupts When a hardware interrupt preempts the function that is currently executing, the HWI function must save and restore any registers it uses or modifies. DSP/BIOS provides the HWI_enter assembly macro to save registers and the HWI_exit assembly macro to restore registers. Using these macros gives the function that was preempted the same context when it resumes running.
Hardware Interrupts Whether called explicitly, C55 or by the HWI dispatcher, the HWI_enter and HWI_exit macros prepare an ISR to call any C function. In particular, the ISR is prepared to call any DSP/BIOS API function that is allowed to be called from the context of an HWI. (See Functions Callable by Tasks, SWI Handlers, or Hardware ISRs in the TMS320 DSP/BIOS API Reference Guide for your platform for a complete list of these functions.
Hardware Interrupts When HWI_exit is called, you can also provide an IMRRESTOREMASK parameter. The bit pattern in the IMRRESTOREMASK determines what interrupts are restored by HWI_exit, by setting the corresponding bits in the IMR. Of the interrupts in IMRRESTOREMASK, HWI_exit restores only those that were disabled with HWI_enter. If upon exiting the ISR you do not wish to restore one of the interrupts that was disabled with HWI_enter, do not set that interrupt bit in IMRRESTOREMASK in HWI_exit.
Hardware Interrupts ❏ The fourth parameter on the C6000 platform, CCMASK, specifies the value to place in the cache control field of the CSR. This cache state remains in effect for the duration of code executed between the HWI_enter and HWI_exit calls. Some typical values for this mask are defined in c62.h62 (for example, C62_PCC_ENABLE). You can OR the PCC code and DCC code together to generate CCMASK. If you use 0 as CCMASK, a default value is used.
Hardware Interrupts ❏ The second parameter of HWI_enter and HWI_exit on the C28x platform, ACC_MASK, specifies the mask of ACC, p, and t registers to be stored and restored by the ISR. ❏ The third parameter, MISC_MASK, specifies the mask of registers ier, ifr, DBGIER, st0, st1, and dp. ❏ The fourth parameter, IERDISABLEMASK, specifies which bits in the IER are to be turned off.
Hardware Interrupts Example 4-3. Constructing a Minimal ISR on C6000 Platform ; ; ======== myclk.s62 ======== ; .include "hwi.h62" ; macro header file IEMASK .set 0 CCMASK .set c62_PCC_DISABLE .
Hardware Interrupts Example 4-5.
Software Interrupts 4.3 Software Interrupts Software interrupts are patterned after hardware ISRs. The SWI module in DSP/BIOS provides a software interrupt capability. Software interrupts are triggered programmatically, through a call to a DSP/BIOS API such as SWI_post. Software interrupts have priorities that are higher than tasks but lower than hardware interrupts. The SWI module should not be confused with the SWI instruction that exists on many processors.
Software Interrupts 4.3.1 Creating SWI Objects As with many other DSP/BIOS objects, you can create SWI objects either dynamically (with a call to SWI_create) or statically (with the Configuration Tool). Software interrupts you create dynamically can also be deleted during program execution. To add a new software interrupt with the Configuration Tool, create a new SWI object for the SWI Manager in the Configuration Tool.
Software Interrupts 4.3.2 Setting Software Interrupt Priorities in the Configuration Tool There are different priority levels among software interrupts. You can create as many software interrupts as your memory constraints allow for each priority level. You can choose a higher priority for a software interrupt that handles a thread with a shorter real-time deadline, and a lower priority for a software interrupt that handles a thread with a less critical execution deadline.
Software Interrupts 2) To change the priority of a SWI object, drag the software interrupt to the folder of the corresponding priority. For example, to change the priority of SWI0 to 3, select it with the mouse and drag it to the folder labeled Priority 3. Software interrupts can have up to 15 priority levels. The highest level is SWI_MAXPRI (14). The lowest is SWI_MINPRI (0). The priority level of 0 is reserved for the KNL_swi object, which runs the task scheduler. See section 4.3.
Software Interrupts You can have up to 15 software interrupt priority levels, but each level requires a larger system stack. If you see a pop-up message that says “the system stack size is too small to support a new software interrupt priority level,” increase the Application Stack Size property of the Memory Section Manager. Creating the first PRD object creates a new SWI object called PRD_swi (see section 4.9, Periodic Function Manager (PRD) and the System Clock, page 4-74, for more information on PRD).
Software Interrupts Note: Two things to remember about SWI: When an SWI starts executing it must run to completion without blocking. When called from within an HWI, the code sequence calling any of the SWI functions which can trigger or post a software interrupt must be either wrapped within an HWI_enter/HWI_exit pair or invoked by the HWI dispatcher. SWI functions can be preempted by threads of higher priority (such as an HWI or an SWI of higher priority). However, SWI functions cannot block.
Software Interrupts SWI_andn and SWI_dec post the SWI object only if the value of its mailbox becomes 0: ❏ SWI_andn clears the bits in the mailbox determined by a mask passed as a parameter. ❏ SWI_dec decreases the value of the mailbox by one. Table 4-3 summarizes the differences between these functions. Table 4-3.
Software Interrupts When an SWI has been posted using SWI_inc, once the SWI Manager calls the corresponding SWI function for execution, the SWI function can access the SWI object mailbox to know how many times it was posted before it was scheduled to run, and proceed to execute the same routine as many times as the value of the mailbox. Figure 4-7.
Software Interrupts If more than one event must always happen for a given software interrupt to be triggered, SWI_andn should be used to post the corresponding SWI object as shown in Figure 4-8. For example, if a software interrupt must wait for input data from two different devices before it can proceed, its mailbox should have two set bits when the SWI object was created with the Configuration Tool.
Software Interrupts Figure 4-9. Using SWI_or to Post an SWI. Program configuration Value returned by SWI_getmbox 0 ... 0 0 ... · Calls SWI_or(&myswi, 0x1) · myswi is posted 0 ... 0 1 ... · myswiFxn() is executed† 0 ... 0 0 · Calls SWI_or(&myswi, 0x2) · myswi is posted 0 ... 1 0 · myswiFxn() is executed 0 ... 0 0 SWI object myswi Function myswiFxn() Program execution Mailbox value 0 ... 0 1 ... 0 ... 1 0 myswiFxn() { ...
Software Interrupts Figure 4-10. Using SWI_dec to Post an SWI Program configuration SWI object myswi Function myswiFxn() Program execution 4.3.
Software Interrupts The second advantage is that an SWI handler can call some functions that cannot be called from an HWI, because an SWI handler is guaranteed not to run while DSP/BIOS is updating internal data structures.
Software Interrupts All registers listed in Table 4-4 are saved when a software interrupt preempts another thread. It is not necessary for a SWI handler written in either C or assembly to save any registers. However, if the SWI handler is written in assembly, it is safest to follow the register conventions and save the "save on entry" registers, since future DSP/BIOS implementations may not save these registers.
Software Interrupts When software interrupts are disabled, a posted software interrupt does not run at that time. The interrupt is “latched” in software and runs when software interrupts are enabled and it is the highest-priority thread that is read to run. Note: An important side effect of SWI_disable is that task preemption is also disabled. This is because DSP/BIOS uses software interrupts internally to manage semaphores and clock ticks.
Tasks 4.4 Tasks DSP/BIOS task objects are threads that are managed by the TSK module. Tasks have higher priority than the idle loop and lower priority than hardware and software interrupts. The TSK module dynamically schedules and preempts tasks based on the task’s priority level and the task’s current execution state. This ensures that the processor is always given to the highest priority thread that is ready to run. There are 15 priority levels available for tasks.
Tasks 4.4.1.1 Creating and Deleting Tasks Dynamically You can spawn DSP/BIOS tasks by calling the function TSK_create, whose parameters include the address of a C function in which the new task begins its execution. The value returned by TSK_create is a handle of type TSK_Handle, which you can then pass as an argument to other TSK functions. TSK_Handle TSK_create(fxn, attrs, [arg,] ...
Tasks 4.4.1.2 Creating Tasks with the Configuration Tool You can also create tasks using the Configuration Tool. The Configuration Tool allows you to set a number of properties for each task and for the TSK Manager itself. While it is running, a task that was created with the Configuration Tool behaves exactly the same as a task created with TSK_create. You cannot use the TSK_delete function to delete tasks created with the Configuration Tool. See section 2.2.
Tasks Figure 4-11. Right Side of Task Manager Display 3) To change the priority of a task object, drag the task to the folder of the corresponding priority. For example, to change the priority of TSK1 to 3, select it with the mouse and drag it to the folder labeled Priority 3.
Tasks Figure 4-12. 4.4.
Tasks Unlike many time-sharing operating systems that give each task its “fair share” of the processor, DSP/BIOS immediately preempts the current task whenever a task of higher priority becomes ready to run. The maximum priority level is TSK_MAXPRI (15); the minimum priority is TSK_MINPRI (1). If the priority is less than 0, the task is barred from further execution until its priority is raised at a later time by another task.
Tasks Note: Do not make blocking calls, such as SEM_pend or TSK_sleep, from within an IDL function. Doing so prevents DSP/BIOS Analysis Tools from gathering run-time information. When the TSK_RUNNING task transitions to any of the other three states, control switches to the highest-priority task that is ready to run (that is, whose mode is TSK_READY).
Tasks Two functions, TSK_checkstacks, and TSK_stat, can be used to watch stack size. The structure returned by TSK_stat contains both the size of its stack and the maximum number of MADUs ever used on its stack, so this code segment could be used to warn of a nearly full stack: TSK_Stat statbuf; /* declare buffer */ TSK_stat(TSK_self(), &statbuf); /* call func to get status */ if (statbuf.used > (statbuf.attrs.stacksize * 9 / 10)) { LOG_printf(&trace, "Over 90% of task's stack is in use.
Tasks 4.4.5 Task Hooks for Extra Context Consider, for example, a system that has special hardware registers (say, for extended addressing) that need to be preserved on a per task basis. In Example 4-7 the function doCreate is used to allocate a buffer to maintain these registers on a per task basis, doDelete is used to free this buffer, and doSwitch is used to save and restore these registers.
Tasks Example 4-7.
Tasks 4.4.6 Task Yielding for Time-Slice Scheduling Example 4-8 demonstrates an implementation of a time-slicing scheduling model that can be managed by a user. This model is preemptive and does not require any cooperation (which is, code) by the tasks. The tasks are programmed as if they were the only thread running. Although DSP/BIOS tasks of differing priorities can exist in any given application, the time-slicing model only applies to tasks of equal priority.
Tasks Example 4.8.
Tasks Figure 4-14. Trace Window Results from Example 4-8 Figure 4-15.
The Idle Loop 4.5 The Idle Loop The idle loop is the background thread of DSP/BIOS, which runs continuously when no hardware interrupt service routines, software interrupt, or tasks are running. Any other thread can preempt the idle loop at any point. The IDL Manager in the Configuration Tool allows you to insert functions that execute within the idle loop. The idle loop runs the IDL functions that you configured with the Configuration Tool.
The Idle Loop 4-54 ❏ RTA_dispatcher is a real-time analysis server on the target that accepts commands from DSP/BIOS Analysis Tools, gathers instrumentation information from the target, and uploads it at run time. RTA_dispatcher sits at the end of two dedicated HST channels; its commands/responses are routed from/to the host via LNK_dataPump. ❏ IDL_cpuLoad uses an STS object (IDL_busyObj) to calculate the target load.
Semaphores 4.6 Semaphores DSP/BIOS provides a fundamental set of functions for intertask synchronization and communication based upon semaphores. Semaphores are often used to coordinate access to a shared resource among a set of competing tasks. The SEM module provides functions that manipulate semaphore objects accessed through handles of type SEM_Handle. SEM objects are counting semaphores that can be used for both task synchronization and mutual exclusion.
Semaphores Example 4-10. Setting a Timeout with SEM_pend Bool SEM_pend(sem, timeout); SEM_Handle sem; Uns timeout; /* return after this many system clock ticks*/ Example 4-11 provides an example of SEM_post, which is used to signal a semaphore. If a task is waiting for the semaphore, SEM_post removes the task from the semaphore queue and puts it on the ready queue. If no tasks are waiting, SEM_post simply increments the semaphore count and returns. Example 4-11.
Semaphores Example 4-12. SEM Example Using Three Writer Tasks * /* ======== semtest.c ======== * * * * * * * * * * * * * * * * * * * * */ Use a QUE queue and SEM semaphore to send messages from multiple writer() tasks to a single reader() task. The reader task, the three writer tasks, queues, and semaphore are created by the Configuration Tool. The MsgObj’s are preallocated in main(), and put on the free queue.
Semaphores Example 4.12.
Semaphores Example 4.12. SEM Example Using Three Writer Tasks (continued) /* * ======== writer ======== */ Void writer(Int id) { Msg msg; Int i; for (i = 0; i < NUMMSGS; i++) { /* * Get msg from the free queue. Since reader is higher * priority and only blocks on sem, this queue is * never empty. */ if (QUE_empty(&freeQueue)) { SYS_abort(“Empty free queue!\n”); } msg = QUE_get(&freeQueue); /* fill in value */ msg->id = id; msg->val = (i & 0xf) + ‘a’; LOG_printf(&trace, “(%d) writing ‘%c’ ...
Semaphores Figure 4-16.
Mailboxes 4.7 Mailboxes The MBX module provides a set of functions to manage mailboxes. MBX mailboxes can be used to pass messages from one task to another on the same processor. An intertask synchronization enforced by a fixed length shared mailbox can be used to ensure that the flow of incoming messages does not exceed the ability of the system to process those messages. The examples given in this section illustrate just such a scheme.
Mailboxes Conversely, MBX_post is used to post a message to the mailbox as shown in Example 4-15. If no message slots are available (that is, the mailbox is full), MBX_post blocks. In this case, the timeout parameter allows the task to wait until a timeout, to wait indefinitely, or to not wait at all. Example 4-15. Posting a Message to a Mailbox Bool MBX_post(mbx, msg, timeout) MBX_Handle mbx; Void *msg; Uns timeout; /* return after this many */ /* system clock ticks */ 4.7.
Mailboxes Example 4-16. MBX Example With Two Types of Tasks /* * * * * * * * * * * * * */ ======== mbxtest.c ======== Use a MBX mailbox to send messages from multiple writer() tasks to a single reader() task. The mailbox, reader task, and 3 writer tasks are created by the Configuration Tool. This example is similar to semtest.c. The major differences are: - MBX is used in place of QUE and SEM. - the ‘elem’ field is removed from MsgObj. - reader() task is *not* higher priority than writer task.
Mailboxes Example 4.16. MBX Example With Two Types of Tasks (continued) /* * ======== reader ======== */ Void reader(Void) { MsgObj msg; Int i; for (i=0; ;i++) { /* wait for mailbox to be posted by writer() */ if (MBX_pend(&mbx, &msg, TIMEOUT) == 0) { LOG_printf(&trace, "timeout expired for MBX_pend()"); break; } /* print value */ LOG_printf(&trace, "read ’%c’ from (%d).", msg.val, msg.id); } LOG_printf(&trace, "reader done.
Mailboxes Figure 4-17. Trace Window Results from Example 4-16 Associated with the mailbox at creation time is a total number of available message slots, determined by the mailbox length you specify when you create the mailbox. In order to synchronize tasks writing to the mailbox, a counting semaphore is created and its count is set to the length of the mailbox. When a task does an MBX_post operation, this count is decremented.
Mailboxes At this point, the readers pend for a period of time according to the following formula, and then time out: TIMEOUT*1ms/(clock ticks per millisecond) After this timeout occurs, the pending reader task continues executing and then concludes.
Timers, Interrupts, and the System Clock 4.8 Timers, Interrupts, and the System Clock DSPs typically have one or more on-device timers which generate a hardware interrupt at periodic intervals. DSP/BIOS normally uses one of the available on-device timers as the source for its own system clock. Using the on-device timer hardware present on most TMS320 DSPs, the CLK module supports time resolutions close to the single instruction cycle.
Timers, Interrupts, and the System Clock 4.8.1 High- and Low-Resolution Clocks Using the CLK Manager in the Configuration Tool, you can disable or enable DSP/BIOS’ use of an on-device timer to drive high- and low-resolution times on the Clock Manager Properties dialog box as shown in Figure 4-19, which depicts the CLK Manager Properties dialog box for the C54x platform. The C6000 platform has multiple general-purpose timers, whereas, the C5400 platform has one general-purpose timer.
Timers, Interrupts, and the System Clock When the CLK Manager is enabled on the C6000 platform, the timer counter register is incremented every four CPU cycles. When the CLK Manager is enabled on the C5400 platform, the timer counter is decremented at the following rate, where CLKOUT is the DSP clock speed in MIPS (see the Global Settings Property dialog in the TMS320 DSP/BIOS API Reference Guide for your platform) and TDDR is the value of the timer divide-down register as shown in the following equation.
Timers, Interrupts, and the System Clock The high-resolution clock ticks at the same rate the timer counter register is incremented on the C6000 platform and decremented on the C5400 and C2800 platforms. Hence, the high-resolution time is the number of times the timer counter register has been incremented or decremented. On the C6000 platform, this is equivalent to the number of instruction cycles divided by 4.
Timers, Interrupts, and the System Clock To do the same thing on C5400 and C2800 platforms with a 40 MIPS processor using the CPU to drive the clock, the period register value is: Period = 0.001 sec * 40,000,000 cycles per second = 40,000 4.8.2 System Clock Many DSP/BIOS functions have a timeout parameter. DSP/BIOS uses a system clock to determine when these timeouts should expire. The system clock tick rate can be driven using either the low-resolution time or an external source.
Timers, Interrupts, and the System Clock 4.8.3 Example—System Clock Example 4-17, clktest.c, shows a simple use of the DSP/BIOS functions that use the system clock, TSK_time and TSK_sleep. The task, labeled task, in clktest.c sleeps for 1000 ticks before it is awakened by the task scheduler. Since no other tasks have been created, the program runs the idle functions while task is blocked. The program assumes that the system clock is configured and driven by PRD_clock.
Timers, Interrupts, and the System Clock Note: Non-pointer type function arguments to LOG_printf need explicit type casting to (Arg) as shown in the following code example: LOG_printf(&trace, "Task %d Done", (Arg)id); Figure 4-20.
Periodic Function Manager (PRD) and the System Clock 4.9 Periodic Function Manager (PRD) and the System Clock Many applications need to schedule functions based on I/O availability or some other programmed event. Other applications can schedule functions based on a real-time clock. The PRD Manager allows you to create objects that schedule periodic execution of program functions. To drive the PRD module, DSP/BIOS provides a system clock.
Periodic Function Manager (PRD) and the System Clock 4.9.1 Invoking Functions for PRD Objects When PRD_tick is called two things can occur: ❏ PRD_D_tick, the system clock counter, increases by one; that is, the system clock ticks. ❏ An SWI called PRD_swi is posted if the number of PRD_ticks that have elapsed is equal to a value that is the greatest power of two among the common denominators of the PRD function periods.
Periodic Function Manager (PRD) and the System Clock The maximum ready-to-complete time is a good measure of how close the system is to potential failure. The closer a software interrupt’s maximum ready-to-complete time is to its period, the more likely it is that the system cannot survive occasional bursts of activity or temporary data-dependent increases in computational requirements.
Periodic Function Manager (PRD) and the System Clock Figure 4-21.
Using the Execution Graph to View Program Execution 4.10 Using the Execution Graph to View Program Execution You can use the Code Composer Studio Execution Graph to see a visual display of thread activity by choosing DSP/BIOS→Execution Graph. 4.10.
Using the Execution Graph to View Program Execution 4.10.2 Threads in the Execution Graph Window The SWI and PRD functions listed in the left column are listed from highest to lowest priority. However, for performance reasons, there is no information in the Execution Graph about hardware interrupt and background threads (aside from the CLK ticks, which are normally performed by an interrupt).
Using the Execution Graph to View Program Execution 4.10.4 RTA Control Panel Settings for Use with the Execution Graph The TRC module allows you to control what events are recorded in the Execution Graph at any given time during the application execution.
Using the Execution Graph to View Program Execution If you plan to use the Execution Graph and your program has a complex execution sequence, you can increase the size of the Execution Graph in the Configuration Tool. Right-click on the LOG_system LOG object and select Properties to increase the buflen property. Each log message uses four words, so the buflen should be at least the number of events you want to store multiplied by 4.
Chapter 5 Memory and Low-level Functions This chapter describes the low-level functions found in the DSP/BIOS realtime multitasking kernel. These functions are embodied in three software modules: MEM, which manages allocation of memory; SYS, which provides miscellaneous system services; and QUE, which manages queues. This chapter also presents several simple example programs that use these modules.
Memory Management 5.1 Memory Management The Memory Section Manager (MEM module) manages named memory segments that correspond to physical ranges of memory. If you want more control over memory segments, you can create your own linker command file and include the linker command file created by the Configuration Tool. It also provides a set of functions that can be used to dynamically allocate and free variable-sized blocks of memory.
Memory Management ❏ Delete some MEM segments, particularly those that correspond to external memory locations. However, you must first change any references to that segment made in the properties of other objects and managers. To find dependencies on a particular MEM segment, rightclick on that segment and select Show Dependencies from the pop-up menu. Deleting or renaming the IPRAM and IDRAM (C6000 platform) or IPROG and IDATA (C5000 platform) segments is not recommended. ❏ Rename some MEM segments.
Memory Management You should then create your own linker command file that begins by including the linker command file created by the Configuration Tool. For example, your own linker command file might look like one of those shown in Example 5-1 or Example 5-2. Example 5-1. Linker Command File (C6000 Platform) /* First include DSP/BIOS generated cmd file. */ -l designcfg.cmd SECTIONS { /* place high-performance code in on-device ram */ .fast_text: { myfastcode.lib*(.text) myfastcode.lib*(.
Memory Management 5.1.4 Allocating Memory Dynamically Basic system-level storage allocation is handled by MEM_alloc, whose parameters specify a memory segment, a block size, and an alignment as shown in Example 5-3. If the memory request cannot be satisfied, MEM_alloc returns MEM_ILLEGAL. Example 5-3. Using MEM_alloc for System-Level Storage Ptr MEM_alloc(segid, size, align) Int segid; Uns size; Uns align; The segid parameter identifies the memory segment from which memory is to be allocated.
Memory Management If no alignment is necessary, align should be 0. MEM’s implementation aligns memory on a boundary equal to the number of words required to hold a MEM_Header structure, even if align has a value of 0. Other values of align cause the memory to be allocated on an align word boundary, where align is a power of 2. 5.1.5 Freeing Memory MEM_free frees memory obtained with a previous call to MEM_alloc, MEM_calloc, or MEM_valloc.
Memory Management To minimize memory fragmentation, you can use separate memory segments for allocations of different sizes as shown in Figure 5-1. Figure 5-1.
Memory Management Example 5-7. Memory Allocation (C5000 and C28x Platforms) /* ======== memtest.c ======== * This code allocates/frees memory from different memory segments. */ #include #include #include
Memory Management Note: Non-pointer type function arguments to LOG_printf need explicit type casting to (Arg) as shown in the following code example: LOG_printf(&trace, "Task %d Done", (Arg)id); Example 5-8. Memory Allocation (C6000 Platform) /* ======== memtest.c ======== * This program allocates and frees memory from * different memory segments. */ #include #include #include
Memory Management Figure 5-2. Memory Allocation Trace Window The program in Example 5-7 and Example 5-8 gives board-dependent results. O indicates the original amount of memory, U the amount of memory used, and A the length in MADUs of the largest contiguous free block of memory. The addresses you see are likely to differ from those shown in Example 5-2.
System Services 5.2 System Services The SYS module provides a basic set of system services patterned after similar functions normally found in the standard C run-time library. As a rule, DSP/BIOS software modules use the services provided by SYS in lieu of similar C library functions. Using the Configuration Tool, you can specify a customized routine that performs when the program calls one of these SYS functions.
System Services Example 5-10. Using SYS_abort with Optional Data Values (*(Abort_function)) (format, vargs) The single vargs parameter is of type va_list and represents the sequence of arg parameters originally passed to SYS_abort. The function specified for the Abort function property can pass the format and vargs parameters directly to SYS_vprintf or SYS_vsprintf prior to terminating program execution.
System Services 5.2.2 Handling Errors SYS_error is used to handle DSP/BIOS error conditions as shown in Example 5-13. Application programs as well as internal functions use SYS_error to handle program errors. Example 5-13. DSP/BIOS Error Handling Void SYS_error(s, errno, ...) String s; Uns errno; SYS_error uses whatever function is bound to the Error function property to handle error conditions. The default error function in the configuration template is _UTL_doError, which logs an error message.
Queues 5.3 Queues The QUE module provides a set of functions to manage a list of QUE elements. Though elements can be inserted or deleted anywhere within the list, the QUE module is most often used to implement a FIFO list—elements are inserted at the tail of the list and removed from the head of the list. QUE elements can be any structure whose first field is of type QUE_Elem.
Queues 5.3.2 Other QUE Functions Unlike QUE_get and QUE_put, there are a number of QUE functions that do not disable interrupts when updating the queue. These functions must be used in conjunction with some mutual exclusion mechanism if the queues being modified are shared by multiple threads. QUE_dequeue and QUE_enqueue are equivalent to QUE_get and QUE_put except that they do not disable interrupts when updating the queue.
Queues 5.3.3 QUE Example Example 5-18 uses a QUE queue to send five messages from a writer to a reader task. The functions MEM_alloc and MEM_free are used to allocate and free the MsgObj structures. The program in Example 5-18 yields the results shown in Figure 5-3. The writer task uses QUE_put to enqueue each of its five messages and then the reader task uses QUE_get to dequeue each message. Example 5-18. Using QUE to Send Messages /* * * * * * * * * * * * * * * * * * */ ======== quetest.
Queues Example 5.18. Using QUE to Send Messages (continued) /* ======== main ======== */ Void main() { /* * Writer must be called before reader to ensure that the * queue is non-empty for the reader. */ writer(); reader(); } /* ======== reader ======== */ Void reader() { Msg msg; Int i; for (i=0; i < NUMMSGS; i++) { /* The queue should never be empty */ if (QUE_empty(&queue)) { SYS_abort("queue error\n"); } /* dequeue message */ msg = QUE_get(&queue); /* print value */ LOG_printf(&trace, "read '%c'.
Queues Note: Non-pointer type function arguments to log_printf need explicit type casting to (Arg) as shown in the following code example: LOG_printf(&trace, "Task %d Done", (Arg)id); Figure 5-3.
Chapter 6 Input/Output Overview and Pipes This chapter provides an overview on data transfer methods, and discusses pipes in particular. Topic Page 6.1 I/O Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-2 6.2 Comparing Pipes and Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-5 6.3 Data Pipe Manager (PIP Module) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6 6.4 Host Channel Manager (HST Module) . . . . .
I/O Overview 6.1 I/O Overview Input and output for DSP/BIOS applications are handled by stream, pipe, and host channel objects. Each type of object has its own module for managing data input and output. Note: An alternative to pipes and streams is to use the GIO class driver to interface with IOM mini-drivers. The DSP/BIOS Driver Developer's Guide (SPRU616) describes the GIO class driver and the IOM mini-driver model.
I/O Overview Device drivers are software modules that manage a class of devices. For example, two common classes are serial ports and parallel ports. These modules follow a common interface (provided by DEV) so stream functions can make generic requests, the drivers execute in whatever manner is appropriate for the particular class of devices. Figure 6-2 depicts the interaction between streams and devices.
I/O Overview Separate pipes should be used for each data transfer thread, and a pipe should only have a single reader and a single writer, providing point to point communication. Often one end of a pipe is controlled by an HWI and the other end is controlled by an SWI function. Pipes can also transfer data between two application threads. Host channel objects allow an application to stream data between the target and the host. Host channels are statically configured for input or output.
Comparing Pipes and Streams 6.2 Comparing Pipes and Streams DSP/BIOS supports two different models for data transfer. The pipe model is used by the PIP and HST modules. The stream model is used by the SIO and DEV modules. Both models require that a pipe or stream have a single reader thread and a single writer thread. Both models transfer buffers within the pipe or stream by copying pointers rather than by copying data between buffers.
Data Pipe Manager (PIP Module) 6.3 Data Pipe Manager (PIP Module) Pipes are designed to manage block I/O (also called stream-based or asynchronous I/O). Each pipe object maintains a buffer divided into a fixed number of fixed length frames, specified by the numframes and framesize properties. All I/O operations on a pipe deal with one frame at a time. Although each frame has a fixed length, the application can put a variable amount of data in each frame (up to the length of the frame).
Data Pipe Manager (PIP Module) There are no special format or data type requirements for the data to be transferred by a pipe. The online help in the Configuration Tool describes data pipe objects and their parameters. See PIP Module in the TMS320 DSP/BIOS API Reference Guide for your platform for information on the PIP module API. 6.3.
Data Pipe Manager (PIP Module) Example 6-1 Writing Data to a Pipe extern far PIP_Obj writerPipe; /* pipe object created with*/ /* the Configuration Tool */ writer() { Uns size; Uns newsize; Ptr addr; if (PIP_getWriterNumFrames(&writerPipe) > 0) { PIP_alloc(&writerPipe); /* allocate an empty frame */ } else { return; /* There are no available empty frames */ } addr = PIP_getWriterAddr(&writerPipe); size = PIP_getWriterSize(&writerPipe); ' fill up the frame ' /* optional */ newsize = 'number of words writt
Data Pipe Manager (PIP Module) 5) When the application has finished reading all the data, the frame can be returned to the pipe by calling PIP_free. 6) Calling PIP_free causes the notifyWriter function to run. This enables the reader thread to notify the writer thread that there is a new empty frame available in the pipe. The code fragment in Example 6-2 demonstrates how to read data from a pipe.
Data Pipe Manager (PIP Module) When the HWI routine finishes filling up (reading) a frame and calls PIP_put (PIP_free), the pipe’s notify function can be used to automatically post a software interrupt. In this case, rather than polling the pipe for frame availability, the reader (writer) function runs only when the software interrupt is triggered; that is, when frames are available to be read (written).
Data Pipe Manager (PIP Module) Example 6-3 Using PIP_alloc /* correct */ PIP_alloc(); ... PIP_put(); ... PIP_alloc(); ... PIP_put(); /* error! */ PIP_alloc(); ... PIP_alloc(); ... PIP_put(); ... PIP_put(); Similarly when PIP_get is called, the reader counter is decreased by one. A full frame is removed from the reader list and the reader frame descriptor is updated with the information from this frame.
Data Pipe Manager (PIP Module) The pipe's reader function, the HWI routine, calls PIP_get to read data from the pipe. The pipe's writer function, the SWI routine, calls PIP_put. Since the call to the notifyReader happens within PIP_put in the context of the current routine, a call to PIP_get also happens from the SWI writer routine. Hence, in the example described two threads with different priorities call PIP_get for the same pipe.
Host Channel Manager (HST Module) 6.4 Host Channel Manager (HST Module) The HST module manages host channel objects, which allow an application to stream data between the target and the host. Host channels are configured for input or output. Input streams read data from the host to the target. Output streams transfer data from the target to the host. Note: HST channel names cannot start with a leading underscore ( _ ).
Host Channel Manager (HST Module) Example 6-5 Reading Data Through a Host Channel extern far HST_Obj input; readFromHost() { PIP_Obj *pipe; Uns size; Ptr addr; pipe = HST_getpipe(&input) /* get a pointer to the host channel's pipe object */ PIP_get(pipe); /* get a full frame from the host */ size = PIP_getReaderSize(pipe); addr = PIP_getReaderAddr(pipe); ' read data from frame ' PIP_free(pipe); /* release empty frame to the host */ } Each host channel can specify a data notification function to be per
I/O Performance Issues 6.4.1 Transfer of HST Data to the Host While the amount of usable bandwidth for real-time transfer of data streams to the host ultimately depends on the choice of physical data link, the HST Channel interface remains independent of the physical link. The HST Manager in the Configuration Tool allows you to choose among the physical connections available. The actual data transfer to the host occurs within the idle loop on the C54x platform, running at lowest priority.
Chapter 7 Streaming I/O and Device Drivers This chapter describes issues relating to writing and using device drivers, and gives several programming examples. Topic Page 7.1 Overview of Streaming I/O and Device Drivers . . . . . . . . . . . . . . . . . 7-2 7.2 Creating and Deleting Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-5 7.3 Stream I/O—Reading and Writing Streams. . . . . . . . . . . . . . . . . . . . . 7-7 7.4 Stackable Devices . . . . . . . . . . . . . . . . . .
Overview of Streaming I/O and Device Drivers 7.1 Overview of Streaming I/O and Device Drivers Note: This chapter describes devices the use the DEV_Fxns function table type. The DSP/BIOS Driver Developer's Guide (SPRU616) describes a newer device driver model—the IOM model, which uses a function table of type IOM_Fxns. See that document for a description of how to create IOM minidrivers and how to integrate IOM mini-drivers into your applications.
Overview of Streaming I/O and Device Drivers Unlike other modules, your application programs do not issue direct calls to driver functions that manipulate individual device objects managed by the SIO module. Instead, each driver module exports a specifically named structure of a specific type (DEV_Fxns), which in turn is used by the SIO module to route generic function calls to the proper driver function.
Overview of Streaming I/O and Device Drivers Figure 7-2 illustrates the relationship between the device, the Dxx device driver, and the stream accepting data from the device. SIO calls the Dxx functions listed in DEV_Fxns, the function table for the device. Both input and output streams exchange buffers with the device using the atomic queues device→todevice and device→fromdevice. Figure 7-2. Device, Driver, and Stream Relationship open ctrl issue reclaim . . .
Creating and Deleting Streams 7.2 Creating and Deleting Streams To enable your application to do streaming I/O with a device, the device must first be added with the Configuration Tool. You can add a device for any driver included in the product distribution or a user-supplied driver. To use a stream to perform I/O with a device, first configure the device in the Configuration Tool. Then, create the stream object in the Configuration Tool or at runtime with the SIO_create function. 7.2.
Creating and Deleting Streams If you open the stream with the streaming model (attrs→model) set to SIO_STANDARD (the default), buffers of the specified size are allocated and used to prime the stream. If you open the stream with the streaming model set to SIO_ISSUERECLAIM, no stream buffers are allocated, since the creator of the stream is expected to supply all necessary buffers. SIO_delete, shown in Example 7-2, closes the associated device(s) and frees the stream object.
Stream I/O—Reading and Writing Streams 7.3 Stream I/O—Reading and Writing Streams There are two models for streaming data in DSP/BIOS: the standard model and the Issue/Reclaim model. The standard model provides a simple method for using streams, while the Issue/Reclaim model provides more control over the stream operation. SIO_get and SIO_put implement the standard stream model as shown in Example 7-3. SIO_get is used to input the data buffers. SIO_get exchanges buffers with the stream.
Stream I/O—Reading and Writing Streams Example 7-4. Implementing the Issue/Reclaim Streaming Model Int SIO_issue(stream, pbuf, nbytes, arg) SIO_Handle stream; Ptr pbuf; Uns nbytes; Arg arg; Int SIO_reclaim(stream, bufp, parg) SIO_Handle stream; Ptr *bufp; Arg *parg; If no buffer is available, the stream will block the task until the buffer becomes available or the stream’s timeout has elapsed.
Stream I/O—Reading and Writing Streams Figure 7-3. How SIO_get Works Application Program Device Driver SIO_get (stream, &bufp) Exchange Free Buffer Full Buffer In Figure 7-3, the device driver associated with stream fills a buffer as data becomes available. At the same time, the application program is processing the current buffer. When the application uses SIO_get to get the next buffer, the new buffer that was filled by the input device is swapped for the buffer passed in.
Stream I/O—Reading and Writing Streams 7.3.2 Example - Reading Input Buffers from a DGN Device The program in Example 7-5 illustrates some of the basic SIO functions and provides a straightforward example of reading from a stream. For a complete description of the DGN software generator driver, see the DGN section in the TMS320 DSP/BIOS API Reference Guide for your platform. The configuration template for Example 7-5 can be found in the siotest directory of the DSP/BIOS distribution.
Stream I/O—Reading and Writing Streams Example 7.5. Basic SIO Function (continued) * ======== doStreaming ======== * This function is the body of the pre-created TSK thread * streamTask.
Stream I/O—Reading and Writing Streams Figure 7-4. 7.3.3 Output Trace for Example 7-5 Example - Reading and Writing to a DGN Device Example 7-6 adds new SIO operations to the previous one. An output stream, outputStream, has been added with the Configuration Tool. streamTask reads buffers from a DGN sine device as before, but now it sends the data buffers to outputStream rather than printing the contents to a log buffer. The stream outputStream sends the data to a DGN user device called printData.
Stream I/O—Reading and Writing Streams Example 7-6. Adding an Output Stream to Example 7-5 ======== Portion of siotest2.c ======== /* SIO objects created with conf tool */ extern far LOG_Obj trace; extern far SIO_Obj inputStream; extern far SIO_Obj outputStream; extern far TSK_Obj streamTask; SIO_Handle input = &inputStream; SIO_Handle output = &outputStream; ...
Stream I/O—Reading and Writing Streams The complete source code and configuration template for Example 7-6 can be found in the c:\ti\tutorial\target\siotest directory of the DSP/BIOS product distribution (siotest2.c, siotest2.cdb, dgn_print.c). For more details on how to add and configure a DGN device using the Configuration Tool, see the DGN section in the TMS320 DSP/BIOS API Reference Guide for your platform. In the output for this example, sine wave data appears in the myLog window display. Figure 7-5.
Stream I/O—Reading and Writing Streams Example 7-7.
Stackable Devices 7.4 Stackable Devices The capabilities of the SIO module play an important role in fostering deviceindependence within DSP/BIOS in that logical devices insulate your application programs from the details of designating a particular device. For example, /dac is a logical device name that does not imply any particular DAC hardware.
Stackable Devices In Example 7-8, the virtual input device, /scale2/a2d, actually comprises a stack of two devices, each named according to the prefix of the device name specified in your configuration file. ❏ /scale2 designates a device that transforms a fixed-point data stream produced by an underlying device (/a2d) into a stream of scaled fixedpoint values; and ❏ /a2d designates a device managed by the A/D-D/A device driver that produces a stream of fixed-point input from an A/D converter.
Stackable Devices The devices in Example 7-9 have been configured with the Configuration Tool. The complete source code and configuration template for Example 7-9 can be found in the c:\ti\tutorial\target\siotest directory of the DSP/BIOS product distribution (siotest5.c, siotest5.cdb, dgn_print.c). The devices sineWave and printDat are DGN devices. pip0 is a DPI device. scale is a DTR stacking device.
Stackable Devices When you add an SIO stream in the Configuration Tool that uses a stacking device, you must first enter a configured terminal device in the Device Control Parameter property box. The name of the terminal device must be preceded by a slash character ( / ). In the example we use /sineWave, where sineWave is the name of a configured DGN terminal device. Then select the stacking device (scale) from the dropdown list in the Device property.
Stackable Devices Example 7-9. /* * * * * * * * * * * * * */ Data Exchange Through a Pipe Device ======== siotest5.c ======== In this program two tasks are created that exchange data through a pipe device. The source task reads sine wave data from a DGN device through a DTR device stacked on the sine device, and then writes it to a pipe device. The sink task reads the data from the pipe device and writes it to the printData DGN device.
Stackable Devices Example 7.9. Data Exchange Through a Pipe Device (continued) * ======== main ======== */ Void main() { LOG_printf(&trace, "Start SIO example #5"); } /* * ======== source ======== * This function forms the body of the sourceTask TSK thread. */ Void source(Uns nloops) { SIO_Handle input = &inStreamSrc; SIO_Handle output = &outStreamSrc; /* Do I/O */ doStreaming(input, output, nloops); } /* * ======== sink ======== * This function forms the body of the sinkTask TSK thread.
Stackable Devices Figure 7-8. Sine Wave Output for Example 7-9 You can edit sioTest5.c and change the scaling factor of the DTR_PRMS, rebuild the executable and see the differences in the output to myLog. A version of Example 7-9, where the streams are created dynamically at runtime by calling SIO_create is available in the product distribution (siotest4.c, siotest4.cdb).
Controlling Streams 7.5 Controlling Streams A physical device typically requires one or more specialized control signals in order to operate as desired. SIO_ctrl makes it possible to communicate with the device, passing it commands and arguments. Since each device admits only specialized commands, you need to consult the documentation for each particular device. The general calling format is shown in Example 7-10. Example 7-10.
Selecting Among Multiple Streams 7.6 Selecting Among Multiple Streams The SIO_select function allows a single DSP/BIOS task to wait until an I/O operation can be performed on one or more of a set of SIO streams without blocking. For example, this mechanism is useful in the following applications: ❏ Non-blocking I/O. Real-time tasks that stream data to a slow device (for example, a disk file) must ensure that SIO_put does not block. ❏ Multitasking.
Streaming Data to Multiple Clients 7.7 Streaming Data to Multiple Clients A common problem in multiprocessing systems is the simultaneous transmission of a single data buffer to multiple tasks in the system. Such multi-cast transmission, or scattering of data, can be done easily with DSP/ BIOS SIO streams. Consider the situation in which a single processor sends data to four client processors.
Streaming Data to Multiple Clients Example 7-16.
Streaming Data Between Target and Host 7.8 Streaming Data Between Target and Host Using the Configuration Tool, you can create host channel objects (HST objects), which allow an application to stream data between the target and files on the host. In DSP/BIOS Analysis Tools, you bind these channels to host files and start them. DSP/BIOS includes a host I/O module (HST) that makes it easy to transfer data between the host computer and target program.
Device Driver Template 7.9 Device Driver Template Since device drivers interact directly with hardware, the low-level details of device drivers can vary considerably. However, all device drivers must present the same interface to SIO. In the following sections, an example driver template called Dxx is presented. The template contains (mainly) C code for higher-level operations and pseudocode for lower-level operations.
Device Driver Template Example 7-17. Required Statements in dxx.h Header File /* * ======== dxx.h ======== */ #include extern DEV_Fxns Dxx_FXNS; /* * ======== Dxx_Params ======== */ typedef struct { `device parameters go here` } Dxx_Params; ❏ Device parameters, such as Dxx_Params, are specified as properties of the device object in the Configuration Tool. The required table of device functions is contained in dxx.c. This table is used by the SIO module to call specific device driver functions.
Streaming DEV Structures 7.10 Streaming DEV Structures The DEV_Fxns structure contains pointers to internal driver functions corresponding to generic I/O operations as shown in Example 7-19. Example 7-19.
Streaming DEV Structures Device driver functions take a DEV_Handle as their first or only parameter, followed by any additional parameters. The DEV_Handle is a pointer to a DEV_Obj, which is created and initialized by SIO_create and passed to Dxx_open for additional initialization. Among other things, a DEV_Obj contains pointers to the buffer queues that SIO and the device use to exchange buffers. All driver functions take a DEV_Handle as their first parameter. Example 7-21.
Streaming DEV Structures ❏ mode specifies whether the device is an input (DEV_INPUT) or output (DEV_OUTPUT) device. ❏ devid is the device ID. ❏ params is a generic pointer to any device-specific parameters. Some devices have additional parameters which are found here. ❏ object is a pointer to the device object. Most devices create an object that is referenced in successive device operations. ❏ fxns is a DEV_Fxns structure containing the driver’s functions.
Device Driver Initialization 7.11 Device Driver Initialization The driver function table Dxx_FXNS is initialized in dxx.c, as shown in section 7.10, Streaming DEV Structures, page 7-30. Additional initialization is performed by Dxx_init. The Dxx module is initialized when other application-level modules are initialized. Dxx_init typically calls hardware initialization routines and initializes static driver structures as shown in Example 7-22. Example 7-22.
Opening Devices 7.12 Opening Devices Dxx_open opens a Dxx device and returns its status seen in Example 7-23: Example 7-23. Opening a Device with Dxx_open status = Dxx_open(device, name); SIO_create calls Dxx_open to open a Dxx device as seen in Example 7-24. Example 7-24.
Opening Devices The device parameter points to an object of type DEV_Obj whose fields have been initialized by SIO_create. name is the string remaining after the device name has been matched by SIO_create using DEV_match. Recall that SIO_create takes the parameters and is called as shown in Example 7-26. Example 7-26.
Opening Devices Example 7-28.
Opening Devices The configurable device parameters are used to set the operating parameters of the hardware. There are no DSP/BIOS constraints on which parameters should be set in Dxx_init rather than in Dxx_open. The object semaphore objptr→sync is typically used to signal a task that is pending on the completion of an I/O operation. For example, a task can call SIO_put, which can block by pending on objptr→sync. When the required output is accomplished, SEM_post is called with objpt→sync.
Real-Time I/O 7.13 Real-Time I/O In DSP/BIOS there are two models that can be used for real-time I/O—the DEV_STANDARD streaming model and the DEV_ISSUERECLAIM streaming model. Each of these models is described in this section. 7.13.1 DEV_STANDARD Streaming Model In the DEV_STANDARD streaming model, SIO_get is used to get a nonempty buffer from an input stream. To accomplish this, SIO_get first places an empty frame on the device->todevice queue.
Real-Time I/O Note that objptr->sync is a counting semaphore and that tasks do not always block here. The value of objptr->sync represents the number of available frames on the fromdevice queue. 7.13.2 DEV_ISSUERECLAIM Streaming Model In the DEV_ISSUERECLAIM streaming model, SIO_issue is used to send buffers to a stream. To accomplish this, SIO_issue first places the frame on the device->todevice queue. It then calls Dxx_issue which starts the I/O and returns.
Real-Time I/O Figure 7-29 is a template for Dxx_issue for a typical terminating device. Example 7-29. Template for Dxx_issue for a Typical Terminating Device /* * ======== Dxx_issue ======== */ Int Dxx_issue(DEV_Handle device) { Dxx_Handle objptr = (Dxx_Handle) device->object; if ( `device is not operating in correct mode` ) { `start the device for correct mode` } return (SYS_OK); } A call to Dxx_issue starts the device for the appropriate mode, either DEV_INPUT or DEV_OUTPUT.
Closing Devices 7.14 Closing Devices A device is closed by calling SIO_delete, which in turn calls Dxx_idle and Dxx_close. Dxx_close closes the device after Dxx_idle returns the device to its initial state, which is the state of the device immediately after it was opened. This is shown in Example 7-31. Example 7-31.
Closing Devices Example 7.31. Closing a Device (continued) /* * Don't simply SEM_reset the count here. There is a * possibility that the HWI had just completed working on a * buffer just before we checked, and we don't want to mess * up the semaphore count.
Device Control 7.15 Device Control Dxx_ctrl is called by SIO_ctrl to perform a control operation on a device. A typical use of Dxx_ctrl is to change the contents of a device control register or the sampling rate for an A/D or D/A device. Dxx_ctrl is called as follows: status = Dxx_ctrl(DEV_Handle device, Uns cmd, Arg arg); ❏ cmd is a device-specific command. ❏ arg provides an optional command argument.
Device Ready The device’s ready semaphore handle is set to the semaphore handle passed in by SIO_select. To better understand Dxx_ready, consider the following details of SIO_select. SIO_select can be summarized in pseudocode as shown in Example 7-33. Example 7-33.
Device Ready SIO_select makes two calls to Dxx_ready for each Dxx device. The first call is used to register sem with the device, and the second call (with sem = NULL) is used to un-register sem. Each Dxx_ready function holds on to sem in its device-specific object (for example, objptr->ready = sem). When an I/O operation completes (that is, a buffer has been filled or emptied), and objptr->ready is not NULL, SEM_post is called to post objptr->ready.
Types of Devices 7.17 Types of Devices There are two main types of devices: terminating devices and stackable devices. Each exports the same device functions, but they implement them slightly differently. A terminating device is any device that is a data source or sink. A stackable device is any device that does not source or sink data, but uses the DEV functions to send (or receive) data to or from another device. Refer to Figure 7-12 to see how the stacking and terminating devices fit into a stream.
Types of Devices Figure 7-13. Buffer Flow in a Terminating Device Current Device todevice queue fromdevice queue To/From Physical Device Figure 7-14 shows the buffer flow of an in-place stacking driver. All data processing is done in a single buffer. This is a relatively simple device, but it is not as general-purpose as the copying stacking driver. Figure 7-14.
Types of Devices Figure 7-15 shows the buffer flow of a copying stacking driver. Notice that the buffers that come down from the task side of the stream never actually move to the device side of the stream. The two buffer pools remain independent. This is important, since in a copying stacking device, the task-side buffers can be a different size than the device-side buffers.
Index *.cmd 2-13 *.obj 2-13 .bss section 2-9, 2-10 .c files 2-12 .cdb files 2-13 .cmd files 2-13 .h files 1-10, 2-13 .h54 file 1-10 .o29 files 2-13 .o50 files 2-13 .o54 files 2-13 .pinit table 2-21 BIOS_init 2-20, 2-21 BIOS_start 2-21 BIOSREGS memory segment Bool 1-12 boot.
Index real time vs. data-driven 4-74 Code Composer Studio debugging capabilities of 1-8 code size 2-4 compiling 2-16 components 1-4 configuration files 2-13 creating 2-3 custom templates 2-3 See Also custom template files Configuration Tool 1-3, 1-6, 2-3 constant 1-13 constants trace 3-17 trace enabling 3-17 conventions 1-10 count 3-11, 3-24 counting semaphores.
Index E EDATA memory segment 1-13, 1-14 EDATA1 memory segment 1-13, 1-14 environment registers 4-22 EPROG memory segment 1-13, 1-14 EPROG1 memory segment 1-13, 1-14 error handling by Dxx_open 7-36 program errors 5-13 SPOX system services 5-13 Event Log Manager 3-7, 3-8 events 3-20 examples controlling streams 7-23, 7-24, 7-25, 7-26, 7-29, 730, 7-31, 7-33, 7-34, 7-35, 7-36, 7-40, 7-41, 7-42, 7-43, 7-44 Dxx_idle 7-41, 7-42, 7-43, 7-44 Dxx_issue and terminating device 7-40 Dxx_ready 7-43 memory management 5-7
Index parameters 4-20 writing 4-11 HWI accumulations enable 3-24 HWI dispatcher 4-19 HWI interrupt triggering 4-11 HWI interrupts.
Index log 3-8 circular 3-9 fixed 3-9 LOG module explicit instrumentation 3-8 implicit instrumentation 3-19 overview 3-8 LOG_printf 2-18 LOG_system object 4-81 logs objects 3-19 performance 3-4 sequence numbers 4-79 low-resolution times 4-68 M MADU 5-10 mailbox and SWI objects 4-31 length 4-66 memory segment number 3-33 message size 3-33 messages 3-33 name 3-33 priority 4-66 scheduling 4-66 wait time 4-66 mailboxes 3-32 creating. See MBX_create deleting.
Index opening, devices 7-34 operations HWI objects 3-28 names 1-11 optimization instrumentation 3-4 overview 1-4 Q queue QUE module 5-14 Quinn-Curtis 3-38 R P performance I/O 6-15 instrumentation 3-4 real-time statistics 3-13 performance monitoring 1-8 period 3-13 Periodic Function Manager 4-74 periodic functions 4-3 suggested use 4-4 PIP_startup 2-22 poll rate 3-4 polling disabled 3-12 portability 1-3, 1-12 PRD functions 4-74 PRD module implicit instrumentation 4-76 PRD_F_swi 1-11 PRD_F_tick function 1-1
Index SEM_delete 4-55 SEM_pend 4-55 SEM_post 4-56 semaphore count 3-34 name 3-34 semaphores 3-34, 4-55 creating. See SEM_create deleting. See SEM_delete signal. See SEM_post synchronization, and device drivers 7-37 waiting on.
Index data buffer output 7-7 data buffer output. See also SIO_put definition of 6-2 deleting.
Index TRC module 3-4 control of implicit instrumentation 3-16 explicit instrumentation 3-16 TRC_disable 3-18 constants 3-17 TRC_enable 3-18 constants 3-17 TRUE 1-13 TSK_create 4-41 TSK_delete 4-41 TSK_exit 4-46 when automatically called 4-46 TSK_startup 2-22 type casting 4-59, 4-73 V U W underscore 2-6 Uninitialized Variables Memory 2-10 USER traces 3-17 user traces 3-4 user-defined logs 3-8 USERREGS memory segment 1-13, 1-14 words data memory 3-4 of code 1-5 wrapper function 2-25 value current 3-14 d