The <iohw.h> header is intended to be delivered from the compiler tool vendor for the specific CPU / platform type.
An implementation may use any intrinsic functionality provided by the compiler / tool vendor.
For the same reason is will also often be the compiler / tool vendor which have the last word about how
ioreg_designators for the I/O registers is defined with the specific tool / platform.
This may sound complicated but in practice it is usually rather straightforward for most cases.
Consider these simple examples for a processor with memory mapped I/O and one single address bus range.
Implementation example 1
The example illustrates the principles for how to create a minimum <iohw.h> implementation. The implementation provides no machine code overhead.
You simply get I/O driver source code portability at no extra cost.
This method can be used with many existing embedded C (C++) compilers on the market today.
The I/O register (or ioreg_designator) definition.
#define DISP_DATA ((volatile unsigned char *) 0x0001234)
This definition fulfil the three basic requirements for a valid ioreg_designator definition:
- Provide a symbolic name for the I/O register
- Define the (logical) I/O register size in number of bits
- Define the physical address of the I/O register in the target platform
The iohw function implementation method are here based on macro functions which map to a
pointer based syntax for I/O register access used by the given compiler (only functions for I/O write access are shown here)
#define iowr( ioreg_desc, dat ) (((ioreg_desc)[0]) = (dat))
#define iowrbuf( ioreg_desc, index, dat ) (((ioreg_desc)[(index)]) = (dat))
Implementation example 2
When used with IOTester® tool the I/O driver source codes are the same but access is done via the "intrinsic" iot_xx(..) access functions provided with the IOTester tool.
The I/O register (or ioreg_designator) definition looks nearly the same:
#define DISP_DATA (IOT_REG8 | 0x0001234)
Again the definition fulfil the three basic requirements for a valid ioreg_designator definition:
- Provide a symbolic name for the I/O register
- Define the (logical) I/O register size in number of bits
- Define the physical address of the I/O register in the target platform
When used with IOTester the iohw functions just map directly to the corresponding IOTester functions
for direct access of target I/O registers from an "embedded" application running on the PC:
#define iowr( ioreg_desc, dat ) iot_wr( (ioreg_desc), (dat))
#define iowrbuf( ioreg_desc, index, dat ) iot_wrbuf( (ioreg_desc), (index), (dat))
A full <iohw.h> implementation is included with IOTester.
This header may be used both for PC mode and target mode compilation in cases where the embedded
target C compiler does not yet provides an <iohw.h> implementation.
Links to:
IOTester tool description
Example 1: Start using IOTester I/O port pins - "Single chip mode"
Example 2: Enabling the External bus
Example 3: Using Internal Devices and External bus.
Example 4: Using Target Interrupt.
Example 5: Writing portable I/O driver source code with <iohw.h>
Example 6: <iohw.h> implementation methods and definition of I/O registers
Example 7: Swapping source code between PC and target platforms