DSP BIOS FAQ

From Texas Instruments Wiki
Jump to: navigation, search

This topic discusses several common questions when using TI's DSP/BIOS.

Contents

Q: Do Real-time Mode GEL Functions work together with DSP/BIOS RTA tools?

RTA tools work with Real-time mode enabled, but care must be taken to avoid loss of synchronization with the debug tools. Once the application is loaded to the target (either in RAM or in Flash) the Real-time mode can be manually enabled without penalty to the RTA tools. To manually enable it go to menu Debug -> Real-time mode or Rude Real-time mode.

Soft halts (shift-F5) or Full halts (menu GEL -> Realtime Emulation Control -> Full halt or Full halt with restart) do not cause loss of sync in the RTA tools.

However, care must be taken if the commands GEL -> Realtime Emulation Control -> Run realtime with restart or Run realtime with Reset are issued. It is imperative to halt the target and disable Real-time mode manually before issuing these commands.

If the two GEL scripts are issued without halting the target, CCS spawns an error message box that asks to perform a Rude Retry. At this point RTA tools lose sync with the target and do not update information in real-time, even with a soft halt (shift F5).

This last situation, however, can be recovered if you perform either a Full halt with restart or a Full halt followed by a Run realtime with restart.

As a reminder, do not perform a Run realtime with Reset when using any RAM-based applications, since a Reset usually erases the contents of RAM memory. This is useful for Flash-based projects only.

Q: Does LOG_printf() really loads the strings to the target? If so, what is the memory section used?

In initial BIOS versions all the LOG_printf() strings were loaded to the target in .const section. As this takes valuable target memory space, newer BIOS releases store not only the LOG_printf() but all static strings used by RTA tools in the section .printf, but they are not loaded to the target. This section is defined as a COPY section (see section 7.11 of TMS320C6000 Assembly Language Tools User Guide (SPRU186)). Note: this section .printf is not used for C rts printf(). This code goes into .text section and the data goes to .cio.

The DSP/BIOS RTA tools use the COFF file to retrieve the string and perform the display. The string does not therefore need to be loaded onto the target. The LOG_printf(), simply passes a pointer to the string, which can then be read directly from the coff file. This helps to make execution of LOG_printf() deterministic and not dependent on the string length.

Due to a bug found in BIOS 4.x releases, BIOS 5.x was modified to group the .printf section to the bottom of the .const section. The .printf section is still a COPY section, but this grouping is used to guarantee that the values in the .printf section are different than the values in the .const section. A bug reported previously shows that it was possible for .printf and .const to have overlapping addresses. This would confuse RTA since it would grab and print the wrong strings.

Therefore the placement of these sections is always grouped by the BIOS graphical configuration tool in the option Constant Sections (.const, .printf) in MEM Memory Section Manager -> tab Compiler. The auto-generated linker command file (.cmd) then creates:

 GROUP {
  .const: {} 
  .printf (COPY): {} 
 } > IRAM

For older BIOS releases, the workaround is to add the grouping command above to your custom linker .cmd file.

Q: What are the steps needed to process a maskable interrupt in C6000?

Please see Setting up interrupts in DSP BIOS for a detailed description. From the hardware perspective the following steps should be taken care for a maskable interrupt to be processed:

  1. The peripheral must be configured properly to generate an interrupt.
  2. The interrupt source must be mapped to one of the 12 maskable CPU interrupts through the INTMUX registers (MUXL/MUXH on devices prior to 64x+).
  3. The corresponding interrupt enable (IE) bit in the IER should be set to one.
  4. The non-maskable interrupt enable bit (NMIE) bit in the interrupt enable register (IER) should be set to one. Note: once NMIE is set to one it cannot be cleared except by an NMI or reset.
  5. The global interrupt enable bit (GIE) bit in the control status register (CSR) should be set to one.


When the interrupt occurs, the corresponding bit in the IFR will be set to one. The interrupt will be serviced if there are no higher priority interrupt flag (IF) bits set in the IFR. The CPU automatically clears the corresponding IFR flag as the interrupt is taken.

Q: Whenever I open (double-click) one of the newer BIOS configuration files (.tcf), it always opens up a message box asking for an input. What is this?

If the box you see is similar to the one on the right:

Dconfig.importPath box.JPG

Then you need to direct BIOS to search specific include paths that contain seed files to be imported by the .tcf file you are opening.

The newer BIOS TCF configuration files make a better job in re-using default configurations stored in seed files, and these are usually located in some specific places in your system. For the examples supplied with BIOS, typically the example .tcf files use seed files located in the parent directory and the examples\common directory. For example, if you open the file <bigtime.tcf> under the folder examples\bigtime\dsk6713, you must include the paths ..\ and ..\..\..\common where the files <bigtime.tci> and <dsk6713_common.tci> are located. This way it will search its own directory (default), the parent directory and the examples\common directory.

  • Note: if you are opening an example project from Code Composer Studio it probably contains these directories already configured in Build Options -> DspBiosBuilder tab. These (and several other) settings are passed to the <Tconf.exe> (the DSP/BIOS textual configuration tool) in a file with extension .TCO that is located together with its corresponding .TCF. This file is automatically generated by CCS when the corresponding project is open.

Q: Can I modify or create LOG and STS objects in my code (dynamically)? What about the other BIOS modules?

It is not possible to modify or create any STS or LOG modules dynamically. This is due to the fact that the built-in debug tools must be highly deterministic and optimized to minimize the overhead on the application.

Depending on the module, BIOS allows dynamic configuration of an object defined statically. However there are several categories of objects:

  • Certain BIOS modules can be created dynamically using the 'create' and 'alloc' APIs like TSK_create(), MSGQ_alloc() and so on. You can also modify certain properties of these statically created objects using the APIs. The modules that allow dynamic and static creation and configuration are: TSK, SWI, SEM, SIO, BUF, QUE, LCK, MBX, MEM, RTDX, MSGQs, PIPs, DEV and GIO.
  • Other modules must be created statically using the configuration (either CDB or TCF, depending on the BIOS release) and can be either dynamically or statically modified: that is the case of HOOK and HST.
  • However, certain structures can only be created and configured statically: LOG and STS objects, IDL functions, HST and CLK.
  • Additional modules are configuration-only (no actual objects are created): ATM, BCACHE, C28, C55, ECM, EXC, HWI, MPC, PWRM, SYS and TRC.

Q: Which BIOS releases were shipped with CCS throughout the years?

  • CCS2.2 with all updates: BIOS 4.8
  • CCS3.1: BIOS 4.9 but can be safely updated up to BIOS 5.20.05
  • CCS3.2: BIOS 5.21 but can be safely updated up to BIOS 5.31.09
  • CCS3.3: BIOS 5.31.02 but can be safely updated up to BIOS 5.31.09 and BIOS 5.32.x and 5.33.x releases

Note: For information about which codegen tools (CGT) can be used on which version of DSP/BIOS, please refer to the <release_notes.html> file located at the DSP/BIOS installation directory.

Q: I can't find the DSP/BIOS Manual in the CCS help!

Starting with BIOS 5.x releases, the help files are not located in the default CCS location C:\CCStudio_v3.3\docs\hlp but instead inside the DSP/BIOS tree %BIOS_INSTALL_DIR%\packages\ti\bios\help\doc. Whenever the DSP/BIOS release is changed using Component Manager, an OCX control BiosHelpCmdObject.ocx is registered in the Windows registry file and sets the pointers to the current version help directory.

For reasons not yet entirely clear (May/08), sometimes running different CCS releases in the same machine can cause a disruption in the registry keys that point to the correct locations of the help files. For example, if you are using C64x family you can check this by navigating to the key below in the Windows Registry Editor:

HKEY_LOCAL_MACHINE\SOFTWARE\GODSP\CodeComposer\TMS320C64XX\Plugins\Command Tools\DSP/BIOS Help\1.40

The keys HelpContentFile, HelpFile and HelpIndexFile should contain valid directories to the help files. A disrupt pointer usually contains something similar to C:\CCStudio_v3.3\cc\bin\cc_a.\doc\c6xbios.cnt.

The workaround is to re-register the OCX control. Close CCS and go to the directory %BIOS_INSTALL_DIR%\packages\ti\bios\help\bin that contains the OCX control BiosHelpCmdObject.ocx. Open a DOS window and issue the following command:

regsvr32 BiosHelpCmdObject.ocx

By reopening CCS Help you should see the DSP/BIOS Manuals there.

Q: In BIOS releases 5.31 and older I see in the <log.h> a LOG_printf4() function. Does it mean I can use four parameters for LOG_printf()?

No. For these releases LOG_print4() is an unsupported API and should not be used in any circumstances. Use LOG_printf() instead.

Q: Why does my printf() not work?

You can still use printf with BIOS, though you should consult these Tips for using printf.

Also, see this topic below for additional constraints.

Q: When I configure a TSK name it as task0, it will create a symbol task0$stack point to the task stack, but what is the symbol task0$stkptr denotes?

task0$stkptr is the initial stack pointer for a statically generated task0. It marks the top of the initial TSK stack frame. The initial TSK stack frame is the stack frame, generated by TSK creation code, that allows a TSK to be switched in for the first time. task0$stack is the base address of task0's stack.

Q: When I simultaneous use DSP/BIOS 5.x APIs and target content that uses RTSC tools, I am getting type names clashes as I include std.h. How do I fix this?

DSP/BIOS 5.x and RTSC both include a file named <std.h>. When both header files are needed in a C source file, use the following the ordering of #include:

#include <xdc/std.h> /* include new standard base types from the xdc package */
#include <std.h> /* include DSP/BIOS 5.x std.h */

It's arguable whether the #include <std.h> of the bios header should be #include <ti/bios/include/std.h> instead.

Q: Converting CDB files to TCF Files

Please read the topic Migrating from BIOS 4.9 to BIOS 5.x.

Q: Is it possible to change the default directories for the BIOS generated files?

For example how to store a xyz.tcf file in one directory and the resulting xxx.s62 code into another directory?

To specify a different output directory for BIOS generated files, follow these steps mentioned below, :

  • Specify <output directory>/<program> in the "Override default BIOS generated filenames and location" field (under CCS->Project Options->Build options->DspBiosBuilder tab,Advanced category).For example, they could use Debug/myapp, or Release/myapp. This option places the BIOS generated files in a folder that matches the <output directory>. The option translates to -Dconfig.programName=<output directory>/<program> on the tconf command line.
  • In the Compiler tab of the Project Build Options dialog, add a -i"<output directory>" compiler option. For example, -i "$(Proj_dir)\Debug" or -i"$(Proj_dir)\Release". This allows the compiler to find the generated <program>cfg.h header file in the configuration-specific directory specified for tconf.
  • Remove any <program>cfg.cmd file from the project. In the Linker tab of the Build Options dialog, add a -l"<output directory>/<program>cfg.cmd" option. For example, use -l"Debug/appcfg.cmd" for app.tcf and the Debug configuration. This allows the linker to find the generated <program>cfg.cmd linker command file.

Q: Is it possible to get the start, end and the size of a memory section when using BIOS?

Yes it is possible. You can make use of the START(), END(), and SIZE() operators. These operators allow you to define symbols to represent the load-time start, address and size inside the link command file.

You can edit the .cmd (for CMD files generated by Config tool) file and add start()/end() directives. However since its auto-generated we do not advise this. Alternatively you can define separate memory segments for each of the BIOS sections. Note also that BIOS creates symbols which automatically attain the beginning, end, and length for most sections e.g

.sts: {
 STS_A_TABBEG = .;
 _STS_A_TABBEG = .;
 *(.sts)
 STS_A_TABEND = .;
 _STS_A_TABEND = .;
 STS_A_TABLEN = (. - _STS_A_TABBEG) / 16;
 _STS_A_TABLEN = (. - _STS_A_TABBEG) / 16;
} > IRAM

In a user defined CMD file, one can use the linker directives START(), SIZE() and END(). These directives get the starting address, end address and Size of the section respectively and store them in the variables mentioned inside the directives. This is better than using symbols in a linker command file, since there are a few corner cases which spru186 outlines.

For a detailed description you can refer to TMS320C6000 Assembly Language Tools User Guide - SPRU186.

Q: When does SIO_create() function call fail?

The SIO_create() would fail if not enough heap is allocated. In this case, the call to MEM_alloc() would fail resulting in the SIO_create() failure.

There are some constraints for calling SIO_create(). A couple of them are listed below:

  • Do not call SIO_create() on a stream that was created with the DSP/BIOS Configuration Tool.
  • Do not call SIO_create() from a SWI or HWI.

Q: Does DSP/BIOS support the similar function as Windows of WaitForSingleObject(event, timeoutvalue)?

The WaitForSingleObject(event, timeoutvalue) is a Windows call that waits either for event to occur or timeoutvalue to happen (see this reference). In this sense it is similar to the DSP/BIOS API SEM_pend(SEM_Obj, timeout).

Please note that WaitForSingleObject(event,timeout value) APIs are not supported anymore. We recommend using Chip Support Library (CSL) for your application. You can get the CSL from this link. It is also available with CCS.

Q: The CPU Load Graph is a DSP/BIOS plug-in and can be used only on DSP/BIOS projects using the configuration tool(.tcf file)

The CPU Load Graph is updated only when the CPU falls into the Idle Loop. CPU Load Graph cannot be used with simulators .When you select CPU load graph for any simulator configuration, you will see the message "CPU N/A on Sim" at the right bottom of the window indicating that CPU load graph is not available on simulators. The CPU load graph will work with target boards.

The CPU is in the idle loop only when the following are not occurring:

  • Hardware interrupts are being serviced
  • Software interrupts and periodic functions are being run
  • Task functions are being run
  • User functions are being executed from the idle Loop
  • HST channels are transferring data to the host
  • Real-time analysis data is uploaded to the DSP/BIOS Analysis Tools

Therefore if your application is not allowing the CPU to go into Idle loop because of a number of the above events, the load graph might not be getting updated.

Additional details can be found at chapter 3 of DSP/BIOS User's Guide (SPRU423).

Q: Is it true that the TSK manager needs to be enabled in order to get the runtime update of the Message log window?

Task manager does not need to be enabled to get runtime update of message log window. Communication between host and target takes place in the context of an idle loop.

Idle loop can be entered in two ways:

In the first way, when the task manager is enabled the Task scheduler runs TSK_idle() which calls IDL_Loop(). In the second way, the Task Manager is disabled and thus the calls to BIOS_start() returns and call to IDL_Loop() follows. By calling IDL_Loop() boot routine falls in idle loop forever.

Please note that in both the cases it is necessary to return from the main.

In the first case on returning from main, TSK _idle (lowest priority, 0 among Tasks) gets executed. All IDL_Loop runs in the context of this task.

BIOS startup sequence is given below:

c_int00 -> auto_init() ->BIOS_init()->main()- >BIOS_start()->IDL_loop()

In the second case the sequence of events is same: (TSK_Manager disabled)

c_int00 -> auto_init() ->BIOS_init()->main()- >BIOS_start()->IDL_loop()

Therefore it is necessary to return from main() to get into the idle loop irrespective of whether TSK Manager is enabled or not.

Additional details can be found at chapter 3 of DSP/BIOS User's Guide (SPRU423F).

Q: Useful Tips on Stack Overflow

There are two basic types of stacks in a DSP/BIOS application: the system stack and task stack. Each task has its own private stack; software and hardware interrupts do not. The system stack (sometimes called the application stack) is the common stack used by all interrupts.

The KNL and TSK displayed in the Kernel/Object View show the peak usage of the system stack and task stack. For both types of stacks, the Peak Used value is highlighted in red and yellow if a stack overflow is detected when the target halts. You can programmatically check for task stack overflows using the TSK_checkstacks function.

Stack overflows are detected when there is a change to the value stored at the last location on the stack. Problems may occur and not be detected by the Kernel/Object View or TSK_checkstacks if a stack is corrupted by another thread or if the stack overflows but does not change the value in the last address of the stack due to memory allocation alignment.

The Kernel Object Viewer in DSP/BIOS will give you how much stack is used and you can monitor it when the DSP is halted. To display the Kernel Object View, click the icon or choose the DSP/BIOS->Kernel/Object View menu item in Code Composer Studio. What you can do is to look at your map file and see how much memory is unused and this unused memory can be allocated to stack. The stack overflow should be caught during debugging. Try to avoid large local variables because of the resulting stack requirements. The Kernel/Object View tool should flag this overflow.

The application note titled Programming and Debugging Tips for DSP/BIOS (SPRA640) contains useful information about detecting stack overflow and corruption.

Also see: -

For more information on Kernel/Object View, you can refer to CCS contextual help.

Q: How is it possible to stop a TSK created dynamically from execution?

When the TSK_create API is called from the application, make sure that the priority of the task is set to a negative value in the TSK_Attrs structure. This will make sure that the newly created task will not run.

At a later stage when the task needs to be run, raise the priority of the task to a value greater than 0 by using the TSK_setpri API call. By doing so, one can control the execution of a newly created task. The task in execution can be temporarily suspended and made to context switch by setting a negative priority. At a later stage, by reverting the priority from a different thread, one can continue the execution of the stalled task.

Q: Reducing the System LOG Buffer:

The LOG module is used by the DSP/BIOS system to log system execution information. The default configuration sets the LOG buffer size to 64 (words) of the LOG_system object. User LOG instances also default to 64 words (or 16 LOG records). Though LOG_system can't be removed, the size of the LOG buffer can be modified. The following script line was added to reduce to LOG buffer size to zero (0).

    bios.LOG_system.bufLen = 0; // Set system LOG buffer to zero (0)

NOTE: Reducing the LOG_system buffer size provides only data savings. There is no code savings.

The application report SPRA772 contains information on the size impact of using DSP/BIOS modules in your application, as well as a number of hints and guidelines to help you optimize your application's use of memory. It highlights different aspects of the DSP/BIOS library that are under your control and that impact the overall memory usage of the DSP/BIOS kernel.

Q: How can I allocate all my code and data sections to external memory with DSP/BIOS 5?

The platform file included at the beginning of the .tcf file offers a default memory map and section allocation scheme for each supported platform. In example, if your tcf file begins with:

utils.loadPlatform("ti.platforms.evmDM6467");

you get all the defaults for the DM6467 EVM.

In the platform configuration file some sections are allocated in internal memory and some others in external memory. If you want to allocate all the sections in external memory, you can simply edit the tcf file in text mode and add the following lines, just after loading the platform file:

/* Move all the code and data sections to the DDR2 memory region */
var MEMSECTION = bios.DDR2; 
bios.setMemCodeSections(prog, MEMSECTION);
bios.setMemDataNoHeapSections(prog, MEMSECTION);

Q: Which BIOS memory sections do you recommend to place in internal memory?

This is a subjective question since it depends on how much internal memory you have. If you have 2Mb of L2SRAM like the C6455 then it may be easiest to just place everything on-chip via (if your memory name is IRAM or something other than L2SRAM then just find/replace): -

bios.setMemCodeSections(prog, L2SRAM);
bios.setMemDataNoHeapSections(prog, L2SRAM);
bios.setMemDataHeapSections(prog, L2SRAM);

If however you have limited on-chip RAM some of the typical sections that users place on-chip are: -

  • TSK stacks - often its critical to have key task stack variables in internal memory for speed.

-> on a per-TSK static basis...

myTsk.stackMemSeg = prog.get("L2SRAM");

-> for dynamically created TSKs you can set a TSK module property to assign the default memory segment to contain task stacks created at run-time with the TSK_create function...

bios.TSK.STACKSEG = prog.get("L2SRAM");
  •  HWI/SWI system stack - if you have a lot of HWIs, SWIs then again you may want the global-stack variables in internal memory for speed: -
bios.MEM.STACKSEG = prog.get("L2SRAM");
  •  DSP/BIOS code - if you can afford to, then you could place the DSP/BIOS code in internal memory: -
bios.MEM.BIOSSEG = prog.get("L2SRAM");

These are probably the key configuration properties to play with.

Naturally if you are using the BIOS configuration tool (or tconf) to place standard compiler sections then you should also look at e.g.TEXTSEG, SWITCHSEG, BSSSEG, FARSEG, CONSTSEG etc. 

Q: Why should I use different BIOS HWI interrupt masks?

In BIOS the HWI dispatcher allows user to have 100% C-code ISR`s. User can set its Interrupt Mask to one of the following :-

self : can`t preepmpt/interrupt myself but can be interrupted by other ISRs. If my own interrupt does indeed retrigger whilst I`m processing it, the Interrupt Flag Register will see it and it`ll be processed as another interrupt after kernel is finished with the current one.

all : wholly atomic. While I`m in this HWI ISR dont allow other ISRs to interrupt me.

none : Wide open. Any interrupt including my own, can interrupt me.

bitmask : Prevent these X specific interrupts from interrupting my ISR. A `1` in a specific bit means `dont allow this particular ISR vector to interrupt me`.

BIOS HWIs default to `self`. If user is calling a function that truly needs a guarentee that interrupts are disabled throughout its duration then user should consider flipping the Interrupt Mask to `all`.

For example, in a hardware ISR user could perform PRD_tick() to notify a periodic function when data is available for processing (as opposed to using the on-device Clock). This function`s preconditions state `Interrupts need to be disabled before calling PRD_tick`. By flipping the Mask to `all` user can guarentee this precondition.

An alternative method which is slightly less brute force and has better granularity is to do this in ISR :-

Uns key = HWI_disable()
PRD_tick();
HWI_restore(key);

Q: How to handle priority inversion?

DSP/BIOS support several types of program threads with different priorities. Execution and preemption characteristics of a thread depend upon its type. A priority inversion occurs when a higher priority task must wait for the completion of a lower priority task over an indefinite period. There is a great section on how to handle priority inversion with DSP/BIOS in the following application note SPRAA25

Q: How to get RapidIO MQT software package?

The RapidIO® Message Queue Transport (MQT) allows applications to communicate to other TI DSP processors via serial RapidIO. This software is developed as a module which can be plugged in the MSGQ module of DSP/BIOS. The RapidIO MQT module uses the messaging logical layer of RapidIO to send MSGQ messages between processors. The MSGQ module manages the communication with the MQTs, off-loading that burden from the application .For the sake of completeness, this software does not manage direct I/O or congestion control on SRIO but does not limit the user application from using them. This software is available today, and if you have a valid license subscription of Code Composer Studio you might go to the update advisor and download the software.

The application note RapidIO MQT – SPRAAD3, which describes the software architecture and APIs that are available.

Q: Can runtime support (RTS) functions be called when using DSP/BIOS?

Many runtime support (RTS) functions use lock and unlock functions to prevent reentrancy. DSP/BIOS use the LCK_pend and LCK_post APIs to protect itself against reentrancy. However, DSP/BIOS SWI and HWI threads cannot call LCK_pend and LCK_post. As a result, RTS functions that call LCK_pend or LCK_post must only be used outside the context of SWI and HWI threads.

To determine whether a particular RTS function uses LCK_pend or LCK_post, refer to the source code for that function shipped with CCStudio. The following list shows the most common RTS functions that call LCK_pend and LCK_post in CCStudio.

  • fprintf, printf, vfprintf, sprintf, vprintf, vsprintf
  • minit, malloc, realloc, free, calloc, memalign, memmap
  • clock, strftime, rand, srand, getenv, exit, atexit
  • tabinit, add_device, remove_device, open, read, write, lseek, close, unlink, rename
  • HOSTopen, HOSTclose, HOSTread, HOSTwrite, HOSTlseek, HOSTunlink, HOSTrename, HOSTtime, HOSTclock.

Another important thing to note regardless of whether or not BIOS is being used, is that the C I/O functions from the RTS library make use of the heap. If you have not defined a heap or have defined too small of a heap the C I/O functions will not operate correctly.

Q: What are the UTL functions?

The UTL functions are default routines provided by DSP/BIOS for certain system functions. There are four UTL functions: UTL_doAbort, UTL_doError, UTL_halt, UTL_doPutc. They are the defaults for the following System Settings Properties: abort, error, exit, and putc, respectively. They are only defaults, and may be substituted with your own routines on the System Settings Properties menu. Note that the routines specified in this menu will be executed when the BIOS APIs SYS_abort, SYS_error, SYS_exit, and SYS_putchar, respectively, are called. UTL_doAbort logs an error message and calls _halt, which in turn performs an infinite loop with all processor, interrupts disabled. UTL_doError logs an error message to the system log. UTL_halt performs an infinite loop with all processor interrupts disabled. UTL_doPutc writes a character to the trace buffer. If you desire greater functionality by the routines that handle these system functions, you should replace the default routine with your own on the System Settings Properties menu. For more information, refer the SPRU403 DSP/BIOS API Guide.

Q: Why users are not allowed to call MEM functions (MEM_alloc, MEM_stat etc) from an HWI or SWI?

Memory management functions (MEM_alloc(), MEM_stat(), MEM_free()) are blocking calls. This is because the functions require the caller to acquire a lock to the memory before proceeding. In case the MEM functions fail to get a lock to the memory, there is a context switch. A call to a SWI or HWI routine should be non-blocking in nature and hence TI recommends that customer should not call MEM functions inside a SWI or HWI. In case the user makes blocking calls (MEM calls) inside a SWI or HWI, the behavior is not guaranteed. Making any blocking calls from a HWI or SWI can affect the real time response of the system.

Q: How can I convert printf() statements to LOG_printf()?

The printf() function included in the run-time support library can severely impact real-time performance.

Problems with printf()

  • It runs often for 1000s of cycles in order to do the string formatting (e.g. displaying an integer as ascii text).
  • It causes CCS to do a "silent halt". That is, there is a breakpoint that gets hit during calls to printf. CCS responds by reading out the printed message and then starting the DSP running again.

These issues coupled together typically cause severe problems with real-time performance, but you can easily avoid these issues by using LOG_printf instead.

Advantages of LOG_printf()

  • Formatting is performed on the PC rather than the DSP, i.e. run-time overhead is 10s of cycles instead of 1000s.
  • The DSP is not halted to transfer the data. Instead DSP/BIOS utilizes RTDX to transfer the data.

Limitations of LOG_printf()

  • Only two variables can be passed as arguments, e.g. LOG_printf(&trace, "var1=%i, var2=%i", var1, var2);
  • Not all types are supported! Notably, the %f (float) is not supported. The supported types are:  %d, %u, %x, %o, %s, %r, %p. See the API Guide bundled with BIOS for more details (e.g. bios_5_xx_xx/docs).
Log_trace.jpg

To migrate from printf() to LOG_printf()

  • Add an object inside the LOG module of your DSP/BIOS configuration
    • In your BIOS tcf go to Instrumentation->LOG
    • Right-click on Event Log Manager and select "Insert LOG"
    • (Optional) You can give it any name you like, e.g. 'trace'.
    • (Optional) You can make the buffer size larger/smaller and place it in the memory section of your choice.
  • Add the DSP/BIOS-generated configuration header file (biosfilenamecfg.h) into any source files that will use the LOG_printf(). This header file includes log.h for you and externs your LOG object (e.g. trace).
  • Replace all printf("message\n"); with LOG_printf(&trace, "message\n");

This should help alleviate the pain of using the big and slow printf() calls.

Q: How do I start the DSP/BIOS scheduler?

Simply return from main, i.e do not have a while(1) loop in your main() function.

Q: Can I use C++ with BIOS?

Please see this topic.