This section contains common problems and pitfalls that we have encountered with previous ports. The TargetRTS is supported on approximately 71 platforms and has been verified on each of these platforms. In general, the problems and pitfalls encountered are due to RTOS and tool chain oddities and bugs. Other problems arise from lack of support for certain features required by the TargetRTS and thus require a custom workaround to satisfy the TargetRTS.
Compiler optimizations, in general, help speed up the application. Some optimizations can cause errors in the application. One such problem occurs when the compiler optimizes references to a memory location that is not modified by the application. It assumes that because the application does not modify the contents of the address, it is never modified. This can cause problems when a memory location is used to store a RTOS primitive, such as a semaphore. The operating system modifies the contents of the semaphore variable but the application does not. The compiler optimizes the references to the semaphore and consequently removes proper access to the semaphore.
Optimizations vary from compiler to compiler, so refer to the documentation for your specific tool chain. Review the optimizations that are available and be aware that some may cause errors in the application. Running a test suite such as the one described in section "Testing the TargetRTS" on page 95 is a good way to ensure the optimizations have not broken the TargetRTS.
When linking an application to a embedded target, there is usually some sort of linker configuration file that defines where in memory each section of the application will go. Many default linker configuration files are included without the user's knowledge and may cause strange linking errors as applications grow larger. Be sure to define your own linker configuration file appropriate for your target.
In ObjecTime the signals are defined globally. Many of these standard signal names may be duplicates of names used in RTOS libraries. This can cause duplicate reference errors at link time. One approach is to recompile the TargetRTS with these signal names redefined. This can be done by globally replacing <signal name> during compile time using the compile option "-D<signal_name>=rt<signal_name>".
The structure and content of include files can be a challenge when moving to a new tool chain. In the TargetRTS an attempt is made to isolate the nuances of include files for each RTOS into a few specific include files that can be used by all the target-specific code. In general, all RTOS-specific definitions should be combined into a file called RT<os_name>.h in the $(RTS_HOME)/src/target/<target_name> directory. This way all include files needed to access OS functions can be found in this one file. In the C++ TargetRTS, for TCP/IP specific include files, a file called RTtcp.h should be created in the $(RTS_HOME)/src/target/<target_name> directory. This file should contain all the necessary include files required for TCP/IP functions. For RTOSs that provide a POSIX interface to OS functions then a file called RTPosixDefines.h should be used to encapsulate all POSIX header files. Other, more specific, header files may be required to isolate unique interfaces for your RTOS. These may be added to the $(RTS_HOME)/src/target/<target_name> directory as needed, and are typically prefixed by "RT".
Even though POSIX is a standard, there are still some discrepancies in the implementation of the interface. Some implementations of the POSIX function calls return an error code, while others return -1 and store the result in global variable errno. Check your specific RTOS to see how error conditions are reported.
The TargetRTS provides no specific mechanism to prevent priority inversion. Some RTOSs, such as Tornado, support a priority inheritance mechanism for synchronization primitives such as mutexes and semaphores. The C++ TargetRTS for Tornado 1.0.1 enables this option for the RTMutex and RTSyncObject classes. If your RTOS supports this then enable this option when creating a mutex or semaphore.
Thread creation has caused problems in the past. One specific problem is the lack of free space on the heap to allocate the stack for the new thread. This causes a system crash with no error message or exception raised. Other potential pitfalls arise with thread priorities. Do not alter the relative priorities of the C++ TargetRTS threads (main thread, external layer thread, timer thread and debugger thread). Incorrect priorities may effect the functioning of the external layer, timers, debugger or even the ObjecTime application.
Most RTOSs provide a function to retrieve the current system time. Typically it may return clock ticks, milliseconds or even nanoseconds. In the C++ TargetRTS, a conversion from the RTOS time to RTTimespec is typically required in order to satisfy the requirements of the RTTimespec::getclock function. Some RTOSs may provide a macro or function to resolve the number of ticks per second and thus make conversion to RTTimespec straightforward. Others may require hard-coded conversion based on the known tick rate for the RTOS. If this rate is later changed then the conversion will fail. This results in incorrect behavior for all timers in the ObjecTime model.
In the C++ TargetRTS, when changing the system clock, note that if the time returned by the RTTimespec::getclock() function is affected by changes in the system clock, the function call that adjusts the time must be between the RTTimerSAP::adjustTimeBegin() and RTTimerSAP::adjustTimeEnd() functions. If, however, system clock changes do not affect the RTTimespec::getclock() function, do not use the RTTimerSAP::adjustTimeBegin and RTTimerSAP::adjustTimeEnd() functions. Timers will fail in this case and cause unwanted behavior in your ObjecTime application.
void AdjustTimeActor::setclock(constRTTimespec & new_time)
{
RTTimespec old_time;
RTTimespec delta;
timer.adjustTimeBegin();//stop ObjecTime timer service
sys_getclock(old_time);//an OS-specific function
sys_getclock(new_time);//an OS-specific function
delta = new_time;
delta -= old_timer;
timer.adjustTimeEnd(delta);//resume Objectime timer service
}
Many RTOSs do not use signals that are typical of UNIX operating systems. If your RTOS does not provide signals then be sure to override the C++ TargetRTS code in RTMain::installHandlers() and RTMain::installOneHandler().
The TargetRTS assumes that it defines the main() function for an application. Some RTOSs may provide there own main() function, which causes a duplicate reference error at link time. If this is the case for your RTOS, you have to modify the code in $(RTS_HOME)/src/target/<target_name>/MAIN/main.cc (/main.c for the C TargetRTS). Typically, you have to start a thread that contains the main() function for the ObjecTime application. The documentation for the RTOS will describe how to start your application in this manner.
Embedded targets do not usually have access to command line arguments, so RTOSs rarely provide a way to pass command line arguments to a running application. If your RTOS does not support command line arguments, use two globally defined variables default_argc and default_argv, defined in the generated code from the toolset, which contain command line arguments from the ObjecTime toolset. In the C and C++ TargetRTS, you can pass these variables to the RTMain::entryPoint() function from your modified main() function. See section "RTOS supplies main() function" on page 101. Default arguments can be specified in the toolset via the Update Browser's Configuration>Language Options>Targets menu.
In the C++ TargetRTS, the RTDiag::panic() function requires a way to terminate the application. This is generally achieved by exiting the application. If your RTOS does not support the exit() function, you have to override the code in $(RTS_HOME)/src/target/<target_name>/RTDiag/panic.cc to use the exit function specific to your RTOS.
Some implementations of the select() statement do not correctly use the value set in the width parameter. Consequently the function thinks the file descriptor sets are larger than they really are. This can cause memory corruption and, consequently, serious failures in the running application. To overcome this problem in the C++ TargetRTS, some targets (CLASSIX, OSE3, VRTX3) override the RTIOMonitor::min_size() function in $(RTS_HOME)/src/target/<target_name>/RTIOMonitor/min_size.cc. In these cases, the minimum size is assumed to be the maximum file descriptor set size.
A problem was found on some UNIX targets when trying to use the gethostbyname() function in a multi-threaded application. The call was replaced with a call to the gethostbyname_r() function, which is re-entrant and multi-thread safe. If this is the case for your target OS then replace the call RTTcpSocket::lookup() in $(RTS_HOME)/src/target/<target_name>/RTTcpSocket/lookup.cc in the C++ TargetRTS.