Wavelet-Based Edge Detection (Image Processing) Part 3

HPI Interactive Multiscale Edge Detector Application with Visual Studio and the TI C6701 EVM

In 5.2 we developed an interactive combined host/target application, with an MFC GUI running on the host PC communicating with a DSP target running an edge detector and image segmentation back-end. Here, we build upon the multiscale edge detector from the previous section and develop an interactive application that communicates to the EVM over the PCI bus using TI’s host port interface (HPI)1516. HPI is similar to RTDX in that it enables communication between the host and a target, but it differs in that it removes the CCStudio IDE as a middle-man, thereby enabling direct connectivity between the host and the DSP’s memory space. HPI has numerous advantages over RTDX, including:

• It is faster than RTDX, although there is an enhanced "high-speed" RTDX (HS-RTDX1718) that provides better performance than the standard version of RTDX we used in next topic Nevertheless, TI reports benchmarks of 20-30 Mbytes/sec (depending on reading or writing) to SDRAM on a C6701 DSP19. Practically speaking, those benchmarks refer to a direct host to HPI connection, whereas with the EVM a PCI bridge is in the loop. As a result, one can expect throughput within the range of 10-12 MB/sec over a 33 MHz PCI bus, which is still superior to RTDX. HPI is the fastest means of transferring large blocks of data between the DSP target and a host PC.


• RTDX only works if the Code Composer Studio IDE is running on the host machine. Obviously in production-level systems the IDE is not going to be running and thus HPI can be used instead.

• The programming model for HPI versus RTDX is decidedly simpler, especially for C/C++ programmers. The host side of HPI is accessed through a relatively simple C API hosted within a few Windows DLLs and consequently the programmer need not concern themselves with all of the nuances of COM, which as we witnessed in 5.2.5.2 can get quite verbose and frankly abstruse in the C and C++ languages. This architecture has performance ramifications on the host side as well; since HPI allows direct access to the DSP’s memory, block memory copies are comparatively much simpler than with RTDX hosts, where one must remain cognizant of the COM underpinnings and marshal the SAFEARRAY data into C/C++ arrays. • HPI does appear to work more reliably than RTDX, at least on the development platform used in this topic. As we shall see, we do not need to tailor the host/target communication protocol due to issues relating to the reliability of communication channel. Recall that with RTDX, while we were able to send 256×256 8-bit images in one block to the target from the host over RTDX, the reverse operation failed. There is one significant HPI problem that impacts Window 2000/XP host, emanating from the EVM Windows device driver.

Since the API is not provided as a COM object, certain alternative programming languages such as Visual Basic 6 are precluded when using HPI on the host. More importantly however, HPI is not available for all development platforms, in particular certain DSKs. For example, on the standard C6416 DSK, the HPI port is unpopulated and the USB emulation does not support HPI – thus the HPI applications in this topic will not run on those development platforms.

Figure 6-14 is a screen-shot of the host application. To use this application:

1. Load in the COFF binary executable (you can point the host application to the . out file by clicking on the "Browse" button). Recall that with the RTDX applications in next topic, we either relied on Link for Code Composer Studio MATLAB functions to start the CCStudio IDE or we assumed that the CCStudio IDE was up and the user had already manually started the target via Debug|Run.

2. Initialize the target, and perform the host/target handshake by clicking on the "Init" button.

3. Load an input image using the File|Load menu selection.

4. Select the number of wavelet decompositions and click on the "Process" button. The image is sent to the DSP, processed, and then sent back to the host and displayed.

The EVM board can be temperamental at times, thus you will sometimes need to reset the EVM prior to starting the host application, particularly after having run the CCStudio IDE (this can be done by running the evm6xrst.bat batch file in the TI bin directory). This demo program follows a tried-and-true template used by many HPI-DSP applications – a similar example can be found in [20]. Broadly speaking, what typically occurs is that the host sends a message to the DSP by writing to a memory address on the DSP (remember, with HPI the host has direct access to the DSP’s memory), thereby signifying that data is ready for processing. The host sends the data to the target, and the DSP processes this data. To send a completion message from the DSP to the host, the DSP interrupts the host, which then reads the data from the DSP. The exact protocol used for this application is shown in Figure 6-15; in contrast to the equivalent diagram for an RTDX application (see Figure 5-9), note that we send large blocks of data in a full-duplex fashion using single HPI messages.

C6701 EVM TARGET

The C6701 EVM target program uses PCI functions from the EVM DSP Support Software, defined in the header pci . h, to implement its end of the HPI protocol depicted in Figure 6-13.

Interactive HPI multiscale edge detector demo application.

Figure 6-14. Interactive HPI multiscale edge detector demo application.

Data flow protocol between host and target communicating over HPI for the wavelet-based edge detection application.

Figure 6-15. Data flow protocol between host and target communicating over HPI for the wavelet-based edge detection application.

The target code may be found in the Chap6\wave__edge\C6701EVM_HPI directory, and Listing 6-9 is the contents of wave edge. c that handles HPI communication with the host. Only main has changed, and the core image processing from Listing 6-7 remains intact.

Listing 6-9: HPI communication infrastructure in wave edge . c.

Listing 6-9: HPI communication infrastructure in wave edge . c.

 

 

 

 

Listing 6-9: HPI communication infrastructure in wave edge . c.

 

 

 

 

Listing 6-9: HPI communication infrastructure in wave edge . c.

This implementation is somewhat unique in that C scoping is used so that variables can be defined after the beginning of main, simulating the situation in C++ where variables can be defined anywhere within a function definition. The program uses 32-bit mailbox registers, located on the PCI controller, for communication between the target and the host PC. The mailbox is a useful abstraction for exchanging small amounts of data such as integers over the PCI bus and is covered quite thoroughly in [18] and sections 1.6.1-1.6.3 and 1.8.5-1.8.8 of [21]. Fortunately, much of the requisite "bit-banging" associated with dealing with these registers is encapsulated by the EVM DSP Support Software API functions within pci. h, and equivalent functionality is available through the HPI module in the Chip Support Library.

Much of the operation of the DSP, with regards to the HPI communication, should be evident from an understanding of Figure 6-13 and Listing 6-9. For further information, the reader is referred to the previously mentioned references as well as the useful comments in the pci. h header file. Finally, this particular implementation is good for only one go-around -the majority of main would need to be put in a loop for the program to operate in a fashion similar to the RTDX targets discussed in 5.1.2.2 and 5.2.5.1.

VISUAL STUDIO .NET 2003 HOST APPLICATION

The host application is found on the CD-ROM in the directory Chap6\wave_edge\Host. In stark contrast to an RTDX host, the host portion of HPI is accessed through a comparatively much simpler API defined in the evm6xdll. h header file (the host project includes this file in the precompiled header stdafx.h), and the primary functionality resides within three DLLs: evm6x.dll, evm6xdm.dll, and evm6xmsg.dll. In the RTDX host application of 5.2.5.2, we used the Visual C++ #import directive to bring the RTDX COM library into the Visual Studio project -here we explicitly link to the evm6x. lib static library. The majority of the code associated with this project is very similar to the previous Visual Studio applications presented in this topic. An MFC/GDI+ framework is used to read and display images, and the Intel IPP library is used for resizing the image to the dimensions the target is expecting.

Listing 6-10: Interface and implementation for C++ class that encapsulates the HPI host-side communication.

Listing 6-10: Interface and implementation for C++ class that encapsulates the HPI host-side communication.

 

 

 

 

 

Listing 6-10: Interface and implementation for C++ class that encapsulates the HPI host-side communication.

 

 

 

 

 

Listing 6-10: Interface and implementation for C++ class that encapsulates the HPI host-side communication.

 

 

 

 

 

 

Listing 6-10: Interface and implementation for C++ class that encapsulates the HPI host-side communication.

 

 

 

 

 

Listing 6-10: Interface and implementation for C++ class that encapsulates the HPI host-side communication.

 

 

 

Listing 6-10: Interface and implementation for C++ class that encapsulates the HPI host-side communication.

HPI are documented in section 2.3 of [19] and in various examples that accompany CCStudio. One point of difference between this code and the CCStudio HPI examples is that the examples were written and tested on Windows 95/98 and will not work without a modification in the way the Win32 HANDLE is created. HPI host applications use the Win32 API function WaitForSingleObj ect22 to pend on incoming HPI messages emanating from the target.Thus subsequent Win32 calls referencing this HANDLE return immediately with a failure code. The HPI host can be made to function, by replacing OpenEvent with CreateEvent, however not in the way TI designed it to work. The problem occurs within the readlmage method, where the hope is to use WaitForSingleObj ect in such a way that the host blocks until the target has completed the processing and then signals this completion by sending the host the amount of bytes to read (see Figure 6-13). If this truly worked, the host could theoretically be performing some other useful work while it waited for the target; it would rely on the operating system to raise a Win32 event when the target completed its processing, at which point the host application would then read the data. Thus, in the ideal case we might use the following function call, perhaps in another thread:

tmp17F-177_thumb[5][2]

HPI:: readlmage is the following:

tmp17F-178_thumb[5][2]

In effect, what we’ve done is turn this into a blocking call that effectively "sleeps" for 10,000 milliseconds. The underlying problem is due to the EVM driver and Windows 2000/XP; unfortunately the driver was never tested under Windows 2000/XP. One would surmise that the EVM driver (evm6x. sys) would call CreateEvent under the covers when the EVM is opened – and subsequently the user application would then call OpenEvent and everything should proceed smoothly from there. This is a serious problem, and unfortunately it appears that TI is in no hurry to fix the driver, which dates from 1998. Now that the C6701 EVM has been discontinued, it is something that developers will need to live with. There are similar third-party EVM-like development platforms – some of these include those products sold by Mango DSP (www.mangodsp.com), Signalogic (www.signalogic.com), and many others. Chances are their drivers are not afflicted with such issues, although in TI’s defense the EVM boards were released in 1998 prior to the advent of Windows 2000/XP. Theoretically, the Win32 HANDLE issue does not constitute a deal-breaker, because since the DSP is running in a deterministic real-time environment, it should be possible to measure exactly how much time it takes to perform the processing and code these delays into the host. While not an ideal solution, it is a feasible workaround.

Thankfully, aside from these shenanigans, the remainder of HPI. cpp is reasonably straightforward. The DSP sends the image dimensions and memory addresses for the input image buffer and the processed (edge) image buffer during the host/target handshake, and these are then used when calling evm6x_hpi_write in the sendlmage method and when calling evm6x_hpi_read in the readlmage method. Prior to shipping the input image down to the target, the image is resampled to the image dimensions specified by the DSP using Image8bpp: : resize (see Listing 5-14). The processed image buffer is read into an array, from which an Image8bpp object is instantiated and then displayed on the screen. Note that since the target takes care of making sure that all pixels in the segmented image are 0 or 255 (see segment_detail_image in Listing 6-7), no further postprocessing on the host is required prior to displaying the segmented image -it is simply rendered as a bitmap via GDI+.

Next post:

Previous post: