• Aucun résultat trouvé

Driver-Specific Insert Files

Dans le document apollo with (Page 59-64)

Insert Files

5.2 Driver-Specific Insert Files

Driver-specific insert files serve as links between the call side and the interrupt side of the driver and between the driver and the application. They fall into two categories:

• Public Insert Files: Declare data structures and driver routines that the application can use

• Private Insert Files: Declare the structures and routines to which the driver alone refers

This division between public and private is admittedly an artificial distinction, and you may wish to ignore it by creating only one driver-specific insert file, especially if your driver is simple and straightforward. However, creating two insert files does have the advantage of presenting to the user, who may not care to know the inner workings of the driver, only what is pertinent to interfacing the application with the driver. At any rate, we have fol-lowed the distinction here, and Subsections 5.2.1 and 5.2.2 describe private and public insert files separately.

Examples of public and private insert files appear in the bm_example in Appendix F, Sec-tions F.1 and F.2.

5-2 Insert Files

5.2.1 Private Insert File

corresponding register in controller memory. This procedure ensures against, for example, the driver writing to what it takes to be a write-only command register when in fact it is a read-only status register.

An example of a CSR page as declared in a private insert file follows:

typedef union mm_csr-page_t { struct {

As you examine the previous example, note the following points:

• The #attribute [device] directive in this example is designed for use in a device driver to protect against any undesired compiler optimization. Its function is ex-plained more fully in Appendix C, Section C.3.

• The record structure itself is of the union type so that, in this case, the CSR page can be accessed either as a whole or register by register; it could, however, have been constructed of fixed parts only, depending upon the requirements of the driver.

• Each structure member is of the char data type because each register consists of eight bits; that is, the space allocated to the char data type. (Use of the char data type, or arrays of chars, to specify structure members ensures that the compiler does not perform improper compressions.)

• The field" all" is declared as an array of bytes.,JJer.,JJage chars because that is the space allocated to any CSR page.

• Finally, pads are used where appropriate to maintain proper spacing between regis-ters. Note that pad_5 through pad_9 could also have been coded as an array:

char pads [9-5+iJ ;

• In this CSR page, the interrupt enable register (int_ enable), a write-only register, is offset at 09 hex from the base address. If we were to remove the pads from the CSR page record, int_enable would then be offset at 05 hex. Any attempt to write to this register would result in a bus time-out error since we would actually be trying to write to a read-only register, the interrupt status register (int_status), which is offset at 05 hex. If you are in any doubt about the positioning of fields within the CSR page, you should use the compiler's -map option so that you can check the field displacements within the CSR page definition.

• The record structure that defines the CSR page is referenced as a pointer; for this reason, a declaration such as the following also appears in the private insert file:

typedef union mm_csr-»age-»tr_t {

mm_csr-»age_t *c;

pbu_$csr_page-»tr_t p;

} mm_csr_page-»tr_t;

• The pointer in this example is declared as a union so that it can be used in two different contexts, either in the driver or in a GPIO routine.

For tips on setting up the CSR page, refer to Appendix C, Section C.l.

5-4 Insert Files

5.2.1. 2 Driver Control Block

Although the driver control block is optional, you may find it useful to include one in your driver as a storage area to be used for communications between the call and interrupt sides. It contains information that is shared by different driver routines and continuously updated, such as status flags, buffer address and length, and so on. The nature and layout of this information depend upon the requirements of the driver and the convenience of the programmer. In the following example, because the control block is referenced by the in-terrupt handler, it must be part of the inin-terrupt library.

typedef struct {

/* initialization command (see bm_$init!) */

/* read command */

/* write command */

/* main control block */

5.2.1.3 Internal Driver Routines

The only routines that must be referenced (using the EXTERN clause) in the private insert file are those functions and procedures that are shared by the call and interrupt sides, but not by the application. These routines must be allocated in the interrupt side. In

bm_example, there is only one such routine: bm_Ssio (the start 1/0 routine). However, you may wish to list all external routines (except those already referenced in the public insert file; see Subsection 5.2.2) for documentation purposes.

5.2.2 Public Insert File

The public insert file is a convenience for the user who wants to know only what is neces-sary to interface the driver with the application. It therefore typically contains device status codes that the user may want to access and any user-callable routines within the driver, such as status-checking routines and user-visible entry points. The three user-call-able routines listed in the bm_example_c public insert file, bm.h, are bm_Sread,

bm_Swait, and bm_Swrite.

---88---5-6 Insert Files

Chapter 6

Dans le document apollo with (Page 59-64)