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.
Service Function or Data | Virtual Vector Number | Description |
---|---|---|
Virtual Vector Table Version | 0 | Version 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 Table | 1 | Interrupt service routine table, hal_interrupt_handlers, address. |
Exception Table | 2 | Exception vector service routine table, hal_vsr_table, address. |
Debug Vector | 3 | UNUSED |
Kill Vector | 4 | Function to execute when a kill instruction is received from the debugger. This typically calls the platform-specific reset function. |
Console I/O Procedures Table | 5 | Communication 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 Table | 6 | Communication interface procedures table used for debugging I/O. This is described in further detail in the Communication Channels section of this chapter. |
Flush Data Cache | 7 | Flush processor data cache for a specified region. Uses the HAL macros HAL_DCACHE_FLUSH and HAL_DCACHE_INVALIDATE. |
Flush Instruction Cache | 8 | Flush processor instruction cache for a specified region. Uses the HAL macros HAL_ICACHE_FLUSH and HAL_ICACHE_INVALIDATE. |
CPU Data | 9 | UNUSED |
Board Data | 10 | UNUSED |
System Information | 11 | UNUSED |
Set Debug Communication Channel | 12 | Sets the current debug communication channel. |
Set Console Communication Channel | 13 | Sets the current console communication channel. |
Set Serial Baud Rate | 14 | UNUSED |
Debug System Call | 15 | Communication 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. |
Reset | 16 | Performs a software reset. |
Console Interrupt Flag | 17 | This flag is set when a debugger interrupt is detected during the processing of console I/O. |
Microsecond Delay | 18 | Delay by the specified number of microseconds. |
Debug Data | 19 | UNUSED |
Flash ROM Configuration | 20 | Allows 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 Breakpoint | 35 | Installs a breakpoint at a specified address, which is used by asynchronous breakpoint support for GDB. |
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.
Option Name | Inherit Console Settings From ROM Monitor |
CDL Name | CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE |
Description | Allows the RAM application to inherit the console setup by the ROM monitor using the configured channel and text encoding style. |
Option Name | Debug Channel Is Configurable |
CDL Name | CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE |
Description | Allows the HAL startup code to make use of the debug channel configuration. |
Option Name | Console Channel Is Configurable |
CDL Name | CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE |
Description | Allows the HAL startup code to make use of the console channel configuration. |
Option Name | Initialize Whole Virtual Vector Table |
CDL Name | CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE |
Description | Causes the entire VVT to be initialized a default service function, nop_service. This is performed in hal_if_init. |
Option Name | Claim Virtual Vector Table Entries By Default |
CDL Name | CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DEFAULT |
Description | Allows 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 Name | Claim Reset Virtual Vectors |
CDL Name | CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET |
Description | Allows the image to provide the Reset and Kill Vector services. |
Option Name | Claim DELAY_US Virtual Vector |
CDL Name | CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US |
Description | Allows the image to provide the Microsecond Delay service. |
Option Name | Claim Cache Virtual Vectors |
CDL Name | CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_CACHE |
Description | Allows the image to provide the Instruction and Data Cache Flush services. |
Option Name | Claim Data Virtual Vectors |
CDL Name | CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DATA |
Description | Allows the image to provide the Data services, which are currently unused in the VVT. |
Option Name | Claim COMMS Virtual Vectors |
CDL Name | CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS |
Description | Allows the image to provide the Debug and Console Communication Channels. |
Option Name | Do Diagnostic IO Via Virtual Vector Table |
CDL Name | CYGSEM_HAL_VIRTUAL_VECTOR_DIAG |
Description | Allows 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. |
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.
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.
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.
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.
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:
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 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.
18.119.104.238