4.1. Virtual Vectors

eCos defines a group of pointers to service functions and data called virtual vectors. The principal role of the virtual vectors is to allow services provided by a ROM startup configuration, such as a ROM monitor, to be accessed by a RAM startup configuration, the application being debugged.

For example, during typical application development, the target hardware boots up using a ROM monitor, such as RedBoot. The application being debugged is built using a RAM startup type. Then, the host running a debugger, such as GDB, uses a communication channel to download the application software and exchange debug information with RedBoot. It is also useful for the application to use this same communication channel for diagnostic messages, such as diag_printf. The application's diagnostic code needs to be aware of the communication channel to use in order to output information. Therefore, either RedBoot needs to pass the communication channel information to the application during startup, or a level of indirection can be used. The level of indirection is a virtual vector, which offers a more general solution. Using this type of configuration also eliminates the need for debug code from the user application because the ROM monitor provides this functionality. Additional information about the RedBoot ROM monitor can be found in Chapter 9, The RedBoot ROM Monitor.

During typical development, the application does not need to be aware of the virtual vectors; diagnostic output is seamlessly routed to the appropriate communication channel.

Using virtual vectors also makes it possible to debug user applications from an arbitrary channel. For example, if an application only contains a device driver for a serial port for its own communications, a ROM monitor can use an Ethernet port, with proper networking support, for debug communications. The user application does not need to contain an Ethernet device driver or networking stack because this is all handled by the ROM monitor. Since this Ethernet port debugging functionality can be eliminated from the user application, the result is a smaller image that only contains code used in the production release.

One issue with sharing resources between a ROM monitor and a user application is that the two are linked separately; therefore, each is unaware of the location of objects in the other's address space. Virtual vectors are used to overcome this problem by providing a common structure with a defined layout that is known by the ROM monitor and user application.

Virtual vectors are contained within the Virtual Vector Table (VVT). The VVT is then placed at a static memory location in the target address space, of which both the RAM application and ROM monitor are aware. The VVT, defined as hal_virtual_vector_table in the file hal_if.h under the common HAL subdirectory, is an array of 64 vectors. The actual location of the VVT is dependent on the HAL architecture and setup in the linker script file. Linker script files are located under the arch subdirectory and have a .ld extension. The memory, 256 bytes, for the VVT is allocated whether or not the VVT is used.

The method for using the VVT varies depending on the functionality needed by the RAM application. Functions in the VVT can be implemented in the ROM monitor, the RAM application, disabled by installing pointers to dummy routines at certain locations, or control can be taken over at run time by reinitializing certain pointers in the VVT.

In general, a loose policy for governing the VVT is that the ROM monitor or the standalone application initializes all vectors in the table. The RAM application can then reinitialize any services it needs to provide. The default configuration is that the ROM monitor provides the console and debugging I/O services, and the RAM application initializes all other services.

NOTE

Some platforms do not use virtual vectors. However, it is recommended that all new ports implement virtual vector functionality.


Table 4.1 lists the available virtual vectors contained in the VVT. The virtual vector numbers, which are defined in the file hal_if.h under the common HAL subdirectory, correspond to the location of the vector in the VVT. Service functions that are unused are set to the nop_service function, which returns 0, defined in the common HAL. Data services that are unused are set to 0.

Table 4.1. Virtual Vector Table Service Functions and Data
Service Function or DataVirtual Vector NumberDescription
Virtual Vector Table Version0Version of the table. This value contains the total number of virtual vectors in the upper 16 bits, and the definition number of the last supported virtual vectors in the lower 16 bits. For this VVT, the total number of virtual vectors is 64d (0x40), and the definition number of the last virtual vector, Flash ROM Configuration, is 20d (0x14). The version is therefore 0x4014.
Interrupt Table1Interrupt service routine table, hal_interrupt_handlers, address.
Exception Table2Exception vector service routine table, hal_vsr_table, address.
Debug Vector3UNUSED
Kill Vector4Function to execute when a kill instruction is received from the debugger. This typically calls the platform-specific reset function.
Console I/O Procedures Table5Communication interface procedures table used for console I/O. This is described in further detail in the Communication Channels section of this chapter.
Debug I/O Procedures Table6Communication interface procedures table used for debugging I/O. This is described in further detail in the Communication Channels section of this chapter.
Flush Data Cache7Flush processor data cache for a specified region. Uses the HAL macros HAL_DCACHE_FLUSH and HAL_DCACHE_INVALIDATE.
Flush Instruction Cache8Flush processor instruction cache for a specified region. Uses the HAL macros HAL_ICACHE_FLUSH and HAL_ICACHE_INVALIDATE.
CPU Data9UNUSED
Board Data10UNUSED
System Information11UNUSED
Set Debug Communication Channel12Sets the current debug communication channel.
Set Console Communication Channel13Sets the current console communication channel.
Set Serial Baud Rate14UNUSED
Debug System Call15Communication vector between ROM monitor and RAM application. The ROM monitor uses this function, which is provided by the RAM application, to retrieve debug data about the application, such as thread information.
Reset16Performs a software reset.
Console Interrupt Flag17This flag is set when a debugger interrupt is detected during the processing of console I/O.
Microsecond Delay18Delay by the specified number of microseconds.
Debug Data19UNUSED
Flash ROM Configuration20Allows an application to access the Flash ROM configuration data in the ROM monitor. The information contained in the configuration is monitor specific, but can include the Ethernet Media Access Control (MAC) address, for example.
Install Breakpoint35Installs a breakpoint at a specified address, which is used by asynchronous breakpoint support for GDB.

4.1.1. Virtual Vector Configuration

The virtual vector configuration options affect the initialization of the VVT. The default configuration options for the VVT, which can be overridden, are that the ROM monitor provides the debugging and diagnostic I/O services, and RAM applications rely on these services. In the case of a standalone production system, all services are provided by the application.

The virtual vector configuration options are located under the ROM Monitor Support (CYGPKG_HAL_ROM_MONITOR) configuration option within the HAL Common Configuration Components. The main virtual vector configuration option is Enable Use of Virtual Vector Calling Interface (CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT), which is enabled by default and can only be disabled by hand-editing configuration files. Item List 4.1 lists the virtual vector configuration suboptions.

The two configuration options, Behave as a ROM Monitor (CYGSEM_HAL_ROM_MONITOR) and Work With a ROM Monitor (CYGSEM_HAL_USE_ROM_MONITOR), determine the type of image being built. These options are also found under the ROM Monitor Support (CYGPKG_HAL_ROM_MONITOR) configuration option within the HAL Common Configuration Components. The two ROM monitor options dictate where the virtual vector configuration suboption settings take effect. For RAM application debugging, typically Work With a ROM Monitor is enabled. If a ROM monitor or released application is being built, Behave as a ROM Monitor is selected.

Item list 4.1. Virtual Vector Configuration Suboptions
Option NameInherit Console Settings From ROM Monitor
CDL NameCYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE
DescriptionAllows the RAM application to inherit the console setup by the ROM monitor using the configured channel and text encoding style.
Option NameDebug Channel Is Configurable
CDL NameCYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE
DescriptionAllows the HAL startup code to make use of the debug channel configuration.
Option NameConsole Channel Is Configurable
CDL NameCYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE
DescriptionAllows the HAL startup code to make use of the console channel configuration.
Option NameInitialize Whole Virtual Vector Table
CDL NameCYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE
DescriptionCauses the entire VVT to be initialized a default service function, nop_service. This is performed in hal_if_init.
Option NameClaim Virtual Vector Table Entries By Default
CDL NameCYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DEFAULT
DescriptionAllows the image to provide all services in the VVT, except Debug and Console Communication services, which will be provided by the ROM monitor. This option enables or disables the claiming of the individual virtual vector configuration options.
Option NameClaim Reset Virtual Vectors
CDL NameCYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET
DescriptionAllows the image to provide the Reset and Kill Vector services.
Option NameClaim DELAY_US Virtual Vector
CDL NameCYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US
DescriptionAllows the image to provide the Microsecond Delay service.
Option NameClaim Cache Virtual Vectors
CDL NameCYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_CACHE
DescriptionAllows the image to provide the Instruction and Data Cache Flush services.
Option NameClaim Data Virtual Vectors
CDL NameCYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DATA
DescriptionAllows the image to provide the Data services, which are currently unused in the VVT.
Option NameClaim COMMS Virtual Vectors
CDL NameCYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS
DescriptionAllows the image to provide the Debug and Console Communication Channels.
Option NameDo Diagnostic IO Via Virtual Vector Table
CDL NameCYGSEM_HAL_VIRTUAL_VECTOR_DIAG
DescriptionAllows all HAL-level I/O to be performed using the configuration settings in the VVT. This option is always enabled on platforms that contain virtual vector support.

4.1.2. Virtual Vector Table Initialization

The common HAL defines macros, in the file hal_if.h, to execute and set the services within the VVT, hal_virtual_vector_table. There are two macros defined for each virtual vector, a call macro—which executes the service in the VVT, and a set macro—which sets the service in the VVT. Code Listing 4.1 shows the call and set macros for the Reset virtual vector. The call macro has the form CYG_ACC_CALL_IF_XXX, as we see on lines 1 and 2, and set macro has the form CYG_ACC_CALL_IF_XXX_SET, shown on lines 4 and 5, where XXX is the defined name of the virtual vector that gives its location in the VVT. The number of parameters passed into the call macro varies depending on the virtual vector service function. The set macro always has a single value passed in, the address of the service function or the data value to set in the VVT.

Code Listing 4.1. Common HAL VVT call and set macros for Reset virtual vector.
1  #define CYGACC_CALL_IF_RESET(_p_, _n_) 
2  (hal_virtual_vector_table[CYGNUM_CALL_IF_RESET])((_p_), (_n_))
3
4  #define CYGACC_CALL_IF_RESET_SET(_x_) 
5  hal_virtual_vector_table[CYGNUM_CALL_IF_RESET]=(CYG_ADDRWORD)(_x_)

All HAL initialization sequences, whether running from a ROM monitor, a ROM application, or RAM application, call the function hal_if_init, located in the file hal_if.c under the common HAL subdirectory. Within this function, the initialization sequence for the VVT is determined by the virtual vector configuration suboptions selected and the type of image, ROM monitor/application or RAM application, the eCos library is built for use with.

NOTE

It is not possible to step through the hal_if_init function if the RAM application is configured to initialize the whole VVT or reconfigure the communication channels. This scenario would create a problem with the RAM application HAL reinitializing services in the VVT while the ROM monitor is trying to use the services already configured in the VVT for debugging I/O. One way to debug this scenario is to leave the VVT that the ROM monitor is using alone and use a RAM application version of the VVT, at another address, for debugging the RAM application code.


In a typical eCos debug environment, two separate images exist, a ROM monitor and a RAM application. Using these two images and the default virtual vector configuration suboptions, the steps involved in the initialization of the VVT are:

1.
ROM monitor is booted, causing the HAL built into the ROM monitor image to initialize the VVT with its own default service vectors according to the virtual vector configuration suboption settings.

2.
The RAM application is loaded into memory via the debug channel in the ROM monitor.

3.
Next, the ROM monitor is given a command to execute the RAM application. This turns control over to the RAM application; however, the VVT still contains function and data services provided by the ROM monitor.

4.
Finally, the RAM application HAL executes, reinitializing the VVT according to the virtual vector configuration suboption settings. Any services that the RAM application provides are set into the VVT.

Figure 4.1 shows the initialization sequence and default VVT after the common HAL has performed its setup. The functions in the VVT, shown in Figure 4.1, are implemented in the common HAL.

Figure 4.1. Virtual vector table initialization sequence.


We can see in Figure 4.1 that the HAL common function hal_if_init initializes the VVT with its default service functions and data. The platform-specific configuration of the VVT is accomplished in the function cyg_hal_plf_comms_init, found in the file hal_diag.c. The accesses to the VVT are shown with dashed lines in the figure. The platform-specific function initializes the communications channels because the platform code is aware of the number of communications channels supported on the target hardware. During this initialization sequence, the console communication interface tables are allocated and configured with the appropriate HAL platform-specific procedures for accessing the configured console port.

4.1.2.1. Communication Channels

Since the HAL controls the low-level I/O functions for diagnostic and debug communication, it is important to understand the scheme that eCos uses to allow access to the different I/O ports. All HAL I/O happens via the communication channels, also called COMMS channels. There are two types of COMMS channels within the HAL, console and debug. Each channel type can be individually configured to use any physical port, such as serial or Ethernet, on the target hardware.

Console channels are used for diagnostic I/O during the debugging process; for example, routing diag_printf function output for event logging, traces, or assertion messages. Normal I/O communication should use proper device drivers as described in the I/O Control System section of Chapter 7. Debug channels are used for communication between the host debugger, such as GDB, and the ROM monitor.

The number of communication channels varies among the different platforms. The configuration option Number of Communication Channels on the Board (CYGNUM_HAL_VIRTUAL_ VECTOR_COMM_CHANNELS), under the HAL architecture-specific components, defines how many channels are present for a particular platform.

There is a Communication Interface Table (CIT) associated with each COMMS channel in the system. The CIT, defined as hal_virtual_comm_table_t in the common HAL, is an array that contains pointers to procedures or data relevant to the specific COMMS channel. A CIT is allocated, in the file hal_if.c, for each COMMS channel supported by the platform using the Number of Communication Channels on the Board configuration option, plus an additional CIT for the possible use of mangler procedures. The use of mangler procedures is described later in this section. Table 4.2 lists the supported COMMS CIT procedures. The procedures in the CIT allow access to various COMMS channel functionality.

Table 4.2. Console and Debug Communication Interface Table Procedures
ProcedureTable IndexDescription
Channel Data0Pointer to the communication controller base address. All procedures in the table use this base address as their first argument.
Write1Send a buffer to a device.
Read2Get a buffer from a device.
Put Character3Write a character to a device.
Get Character4Read a character from a device.
Control5Device settings control. The second argument to this procedure is one of the following functions:

Set Baud— Changes the baud rate.

Get Baud— Returns the current baud rate.

Install Debug ISR— Not used.

Remove Debug ISR— Not used.

IRQ Disable— Disable debugging receive interrupts.

IRQ Enable— Enable debugging receive interrupts.

Get Debug ISR Vector— Return the ISR vector for debugging receive interrupts.

Set Timeout— Set the Get Character timeout.

Debug ISR6ISR used to handle receive interrupts from the device.
Get Character With Timeout7Read a character from the device with a timeout.

The console COMMS channel within a RAM application can be configured to use the ROM monitor debug channel or an independent channel. The virtual vector configuration suboption that determines the console COMMS channel used is Inherit Console Settings From ROM Monitor (CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE). This option is enabled by default when using a ROM monitor. If an independent channel is configured by the RAM application, the configuration option Route Diagnostic Output To Debug Channel (CYGDBG_HAL_DIAG_TO_DEBUG_CHAN) is available. This configuration option is located under the HAL common configuration components.

NOTE

Two scenarios will cause an Ethernet debug connection to be dropped when the application is executed. First, if the console is not inherited by the application using the configuration option Inherit Console Settings From ROM Monitor (CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE). Second, if the debug COMMS channel is reinitialized by the application using the configuration option Claim COMMS Virtual Vectors (CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS).


To allow diagnostic messages to use the debug COMMS channel, it is necessary to wrap the message with the protocol so that it can be properly displayed by GDB. This wrapping of the message with the protocol is called mangling. If the text is not properly mangled, the debugger might reject the message. The HAL provides functions to encapsulate messages according to the selected mangler.

Debuggers, such as GDB, typically use some type of protocol to encode the commands exchanged between the target hardware and the host debugger machine. An explanation of the GDB protocol can be found online at:

http://sources.redhat.com/gdb/onlinedocs/gdb_toc.html

The configuration option Mangler Used on Diag Output (CYGSEM_HAL_DIAG_MANGLER), under the HAL common configuration components, allows the selection of a mangler. The possible values for this option are GDB—in which case, the GDB protocol is applied to text messages—or None, which outputs raw text messages. The mangler procedures are contained in a communication interface table supporting the same functionality shown in Table 4.2.

Code Listing 4.2. Motorola PowerPC MBX860 platform communication interface table initialization for console I/O.
 1  void cyg_hal_plf_serial_init(
 2          void)
 3  {
 4     hal_virtual_comm_table_t *comm;
 5
 6     // Get the current console communication interface
 7     // table so we can restore it later.
 8     int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(
 9                CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
10
11     // Make sure we only go through this code once.
12     static int init = 0;
13     if ( init )
14        return;
15
16     init++;
17
18     // Configure the serial port registers
19     // in the processor.
20     cyg_hal_plf_serial_init_channel( );
21
22     //
23     // Setup the communication
24     // interface table routines for
25     // console I/O for channel 0.
26     //
27
28     // Set the communication
29     // interface table in the VVT to
30     // console 0.
31     CYGACC_CALL_IF_SET_CONSOLE_COMM( 0 );
32
33     // Get a pointer to the channel 0
34     comm = CYGACC_CALL_IF_CONSOLE_PROCS( );
35
36     // Set the base address of the channel 0 controller.
37     CYGACC_COMM_IF_CH_DATA_SET( *comm, eppc_base() );
38
39     // Set the write function.
40     CYGACC_COMM_IF_WRITE_SET(
41        *comm,
42        cyg_hal_plf_serial_write);
43
44     // Set the read function.
45     CYGACC_COMM_IF_READ_SET(
46        *comm,
47        cyg_hal_plf_serial_read);
48
49     // Set the put character function.
50     CYGACC_COMM_IF_PUTC_SET(
51        *comm,
52        cyg_hal_plf_serial_putc);
53
54     // Set the get character function.
55     CYGACC_COMM_IF_GETC_SET(
56        *comm,
57        cyg_hal_plf_serial_getc);
58
59     // Set the serial port control function.
60     CYGACC_COMM_IF_CONTROL_SET(
61        *comm,
62        cyg_hal_plf_serial_control);
63
64     // Set the ISR for debugging receive interrupts.
65     CYGACC_COMM_IF_DBG_ISR_SET(
66        *comm,
67        cyg_hal_plf_serial_isr);
68
69     // Set the get character with timeout function.
70     CYGACC_COMM_IF_GETC_TIMEOUT_SET(
71        *comm,
72        cyg_hal_plf_serial_getc_timeout);
73
74     // Restore the original
75     // console communication interface
76     // table.
77     CYGACC_CALL_IF_SET_CONSOLE_COMM( cur );
78  }

Code Listing 4.2 shows the initialization of the console communication interface table for the Motorola PowerPC MBX860 board. The MBX860 board contains a single serial port, designated as channel 0 in the listing. The routine cyg_hal_plf_serial_init, shown on line 1, is called from the function cyg_hal_plf_comms_init in the platform HAL. The routine cyg_hal_plf_comms_init is called from hal_if_init, as shown in Figure 4.1.

The first step is to store the current CIT setup in the VVT, as we see on line 8. Next, cyg_hal_plf_serial_init_channel, as shown on line 20, is called to configure the appropriate registers in the processor to enable communication via the physical serial port. This function can be called multiple times on other platforms that need to configure more than one serial port.

Next, the call CYGACC_CALL_IF_SET_CONSOLE_COMM, on line 31, is made to set the console channel to 0. This puts the CIT allocated for console channel 0 into the VVT, which a pointer to the table is then retrieved by the CYGACC_CALL_IF_CONSOLE_PROCS call on line 34. The next eight calls, starting on line 37 and ending on line 72, use the macros CYGACC_COMM_IF_XXX_SET, where XXX designates the CIT procedure. These macros set the functions for channel 0 in the CIT. Finally, CYGACC_CALL_IF_SET_CONSOLE_COMM, on line 77, is called to restore the CIT in the virtual vector table to its original setting.

The use of the CIT procedures for diagnostic I/O is enabled by the configuration option Do Diagnostic I/O Via Virtual Vector Table (CYGSEM_HAL_VIRTUAL_VECTOR_DIAG). This allows the console used for diagnostic I/O to be changed during run time.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.104.238