Device I/O API 1.1

Package jdk.dio.mmio

Interfaces and classes for performing memory-mapped I/O.

See: Description

Package jdk.dio.mmio Description

Interfaces and classes for performing memory-mapped I/O.

Memory mapped I/O is typically used for controlling hardware devices by reading from and writing to registers or memory blocks of the hardware mapped to the system memory. The MMIO APIs allows for low level control over the device.

In order to access a specific memory block a device has been mapped to, an application should first open and obtain an MMIODevice instance for the memory-mapped I/O device the application wants to control and access, using its numeric ID, name, type (interface) and/or properties:

Using its ID
 MMIODevice device = (MMIODevice) DeviceManager.open(7);
 
Using its name and interface
 MMIODevice device = DeviceManager.open("RTC", MMIODevice.class, null);
 
Once the device opened, the application can retrieve registers using methods of the MMIODevice interface such as the MMIODevice.getRegister method.
 device.getRegister("Seconds", Byte.class);
 
When done, the application should call the MMIODevice.close method to close the MMIO device.
 device.close();
 
The following sample codes give examples of using the MMIO API to communicate Real Time Clock device:
 static final int INTERRUPT = 0;
 
 try (MMIODevice rtc = DeviceManager.open("RTC", MMIODevice.class, null)) {
     //The RTC device has 14 bytes of clock and control registers and 50 bytes
     // of general purpose RAM (see the data sheet of the 146818 Real Time Clock such as HITACHI HD146818).
     RawRegister<Byte> seconds = rtc.getRegister("Seconds", Byte.class);
     RawRegister<Byte> secAlarm = rtc.getRegister("SecAlarm", Byte.class);
     RawRegister<Byte> minutes = rtc.getRegister("Minutes", Byte.class);
     RawRegister<Byte> minAlarm = rtc.getRegister("MinAlarm", Byte.class);
     RawRegister<Byte> hours = rtc.getRegister("Hours", Byte.class);
     RawRegister<Byte> hrAlarm = rtc.getRegister("HrAlarm", Byte.class);
     ... // More registers
     RawRegister<Byte> registerA = rtc.getRegister("RegisterA", Byte.class);
     RawRegister<Byte> registerB = rtc.getRegister("RegisterB", Byte.class);
     RawRegister<Byte> registerC = rtc.getRegister("RegisterC", Byte.class);
     RawRegister<Byte> registerD = rtc.getRegister("RegisterD", Byte.class);
     RawBlock userRAM = rtc.getBlock("UserRam");
     ...
 } catch (IOException ioe) {
     // handle exception
 }
 

The preceding example is using a try-with-resources statement; the MMI0Device.close method is automatically invoked by the platform at the end of the statement.

 // Sets the daily alarm for after some delay
 public void setAlarm(MMIODevice rtc, byte delaySeconds, byte delayMinutes, byte delayHours) throws IOException,
         DeviceException {
     Register<Byte> seconds = rtc.getByteRegister("Seconds", Byte.class);
     Register<Byte> secAlarm = rtc.getByteRegister("SecAlarm", Byte.class);
     Register<Byte> minutes = rtc.getByteRegister("Minutes", Byte.class);
     Register<Byte> minAlarm = rtc.getByteRegister("MinAlarm", Byte.class);
     Register<Byte> hours = rtc.getByteRegister("Hours", Byte.class);
     Register<Byte> hrAlarm = rtc.getByteRegister("HrAlarm", Byte.class);
     Register<Byte> registerB = rtc.getByteRegister("RegisterB", Byte.class);
     RawBlock userRAM = rtc.getBlock("UserRam", Byte.class);
 
     // Directly read from/write to the registers using RawByte instances.
     byte currentSeconds = seconds.get();
     byte currentMinutes = minutes.get();
     byte currentHours = hours.get();
     int i = (currentSeconds + delaySeconds) % 60;
     int j = (currentSeconds + delaySeconds) / 60;
     secAlarm.set((byte) i);
     i = (currentMinutes + delayMinutes + j) % 60;
     j = (currentMinutes + delayMinutes + j) / 60;
     minAlarm.set((byte) i);
     i = (currentHours + delayHours + j) % 24;
     hrAlarm.set((byte) i);
     rtc.setMMIOEventListener(INTERRUPT, new MMIOEventListener() {
 
         public void eventDispatched(MMIOEvent event) {
             try {
                 MMIODevice rtc = event.getDevice();
                 Register<Byte> registerC = rtc.getByteRegister("RegisterC", Byte.class);
                 // Check the Alarm Interrupt Flag (AF)
                 if ((registerC.get() & 0X20) != 0) {
                     // Notify application of alarm
                 }
             } catch (IOException ioe) {
                 // handle exception
             }
         }
     });
     // Set the Alarm Interrupt Enabled (AIE) flag
     registerB.set((byte) (registerB.get() | 0X20));
 }
 

Alternatively, in this example, the value of RegisterC could be automatically captured upon occurrence of an interrupt request from the Real Time Clock device as follows:

 rtc.setMMIOEventListener(INTERRUPT, "RegisterC", new MMIOEventListener() {
 
     public void eventDispatched(MMIOEvent event) {
         Byte v = event.getCapturedRegisterValue();
         // Check the Alarm Interrupt Flag (AF)
         if ((v.byteValue() & 0X20) != 0) {
             // Notify application of alarm
         }
     }
 });
 

Unless otherwise noted, permission and security checks that may cause a SecurityException to be thrown must be performed in priority to any other checks or operations once performed the checking of the input parameters from which the permission target names and action lists are retrieved and assembled.

Unless otherwise noted, passing a null argument to a constructor or method in any class or interface in this package will cause a NullPointerException to be thrown.

Since:
1.0
Device I/O API 1.1