Skip Headers
Oracle® Java ME Embedded Device Access API Guide
Release 3.3
E35134-02
  Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
 
Next
Next
 

9 Memory-Mapped Input/Output

This chapter describes the interfaces and classes for embedded memory-mapped input and output (MMIO).

Memory mapped I/O is typically used for controlling hardware peripherals by reading from and writing to registers or memory blocks mapped to the hardware's system memory. The MMIO API allows for low-level control over the peripheral.

In order to access a specific memory block that a device has been mapped to, an application should first open and obtain an MMIODevice instance for the memory-mapped I/O device, using its numerical ID, name, type (interface) or properties. This is an example of using the ID.

 MMIODevice device = (MMIODevice) PeripheralManager.open(7);
 

This is an example of using its name and interface.

 MMIODevice device = (MMIODevice) PeripheralManager.open("RTC", MMIODevice.class, null);
 

Once the peripheral is opened, the application can retrieve registers using methods of the MMIODevice interface such as the MMIODevice.getByteRegister(String) method.

 RawByte seconds = (RawByte) device.getByteRegister("Seconds");
 

When done, the application should call the Peripheral.close() method to release MMIO device.

 device.close();
 

The following code give examples of using the MMIO API to communicate Real Time Clock device.

import com.oracle.deviceaccess.PeripheralException;
import com.oracle.deviceaccess.PeripheralManager;
import com.oracle.deviceaccess.PeripheralNotAvailableException;
import com.oracle.deviceaccess.mmio.MMIODevice;
import com.oracle.deviceaccess.mmio.MMIOEvent;
import com.oracle.deviceaccess.mmio.MMIOEventListener;
import com.oracle.deviceaccess.mmio.RawBlock;
import com.oracle.deviceaccess.mmio.RawByte;
import java.io.IOException;
 
public class MMIOExample {
 
    static final int INTERRUPT = 0;
    MMIODevice rtc = null;
 
    public MMIOExample() {

        try {
            rtc = (MMIODevice) PeripheralManager.open("RTC",
                   MMIODevice.class, (String[]) null);
            //The RTC device has 14 bytes of clock/control registers and 50 bytes
            // of general purpose RAM (see data sheet of the HITACHI HD146818 RTC)
            RawByte seconds = rtc.getByteRegister("Seconds");
            RawByte secAlarm = rtc.getByteRegister("SecAlarm");
            RawByte minutes = rtc.getByteRegister("Minutes");
            RawByte minAlarm = rtc.getByteRegister("MinAlarm");
            RawByte hours = rtc.getByteRegister("Hours");
            RawByte hrAlarm = rtc.getByteRegister("HrAlarm");
 
            RawByte registerA = rtc.getByteRegister("RegisterA");
            RawByte registerB = rtc.getByteRegister("RegisterB");
            RawByte registerC = rtc.getByteRegister("RegisterC");
            RawByte registerD = rtc.getByteRegister("RegisterD");
            RawBlock userRAM = rtc.getBlock("UserRam");
 
        } catch (PeripheralException pe) {
        } catch (IOException ioe) {
        } finally {
            if (rtc != null) {
                try {
                    rtc.close();
                } catch (IOException ex) {
                }
            }
        }
    }


    // Sets the daily alarm for after some delay
 
    public void setAlarm(byte delaySeconds, byte delayMinutes, byte delayHours)
        throws IOException, PeripheralException
   {
        MMIODevice rtc = (MMIODevice) PeripheralManager.open("RTC",
            MMIODevice.class, (String[]) null);
        RawByte seconds = rtc.getByteRegister("Seconds");
        RawByte secAlarm = rtc.getByteRegister("SecAlarm");
        RawByte minutes = rtc.getByteRegister("Minutes");
        RawByte minAlarm = rtc.getByteRegister("MinAlarm");
        RawByte hours = rtc.getByteRegister("Hours");
        RawByte hrAlarm = rtc.getByteRegister("HrAlarm");
        RawByte registerB = rtc.getByteRegister("RegisterB");
 
        // 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 = (MMIODevice) event.getPeripheral();
                    RawByte registerC = rtc.getByteRegister("RegisterC");
                    // Check the Alarm Interrupt Flag (AF)
                    if ((registerC.get() & 0X20) != 0) {
                        // Notify application of alarm
                    }
                } catch (IOException ex) {
                } catch (PeripheralNotAvailableException ex) {
                }
            }
        });
        // 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 = (byte) event.getCapturedRegisterValue();
          // Check the Alarm Interrupt Flag (AF)
          if ((v & 0X20) != 0) {
               // Notify application of alarm
          }
     }
 });

MMIO devices are opened by invoking one of the com.oracle.deviceaccess.PeripheralManager.open() methods. The com.oracle.deviceaccess.mmio permission allows access to be granted to MMIO devices as a whole. This permission must be requested in the JAD file under MIDlet-Permissions or MIDlet-Permissions-Opt, and the application must be digitally signed by a trusted authority to gain access to the APIs. Alternatively, the permission may be allowed for all applications in the untrusted domain of the security policy file (policy.txt).

Note that version 3.3 of the Oracle Java ME Embedded platform has discarded all functions from version 3.2 that employed the long datatype.

The MMIODevice Interface

The MMIODevice class provides methods to retrieve memory-mapped registers and memory blocks of a peripheral device. Each memory-mapped I/O device is identified by a numerical ID and by a name. An MMIODevice instance can be acquired by a call to MMIOManager.getDevice(int) or MMIOManager.getDevice(java.lang.String).With memory-mapped I/O, peripheral devices can be controlled by directly reading or writing to memory areas representing the registers or memory blocks of the peripheral device. Each register or memory block is represented by a RawMemory instance. All the mapped registers, including memory blocks, of an MMIO device can be retrieved by a call to the appropriate get...Registers() method. The RawMemory instance associated to a register has a fixed, determined index in the array returned by those methods. Each register or memory block is also usually assigned a name that can be used for name-based lookup.An application can register an MMIOEventListener instance to monitor native events of the designated type fired by the peripheral device. To register a MMIOEventListener instance, the application must call the setMMIOEventListener(int, MMIOEventListener) method. The registered listener can later on be removed by calling the same method with a null parameter. Asynchronous notification might not be supported by all memory-mapped devices. An attempt to set a listener on a memory-mapped device that does not supports it throws an InvalidOperationException.

The MMIODevice interface consists of the following methods:

The MMIOEventListener Interface

The MMIOEventListener interface defines methods for getting notified of events fired by peripherals mapped to memory. A MMIOEventListener can be registered using the MMIODevice.setMMIOEventListener(int, MMIOEventListener) method.

The interface consists of only one method, void eventDispatched(MMIOEvent event). This method is invoked when an event is fired by a memory-mapped peripheral.

The RawMemory Interface

The RawMemory interface provides generic methods for the different types of raw memory area to which a peripheral device's registers may be mapped.

The interface consists of only one method, java.lang.String getName(). This method returns the name assigned to this RawMemory instance.

The RawBlock Interface

The RawBlock interface provides methods to access a continuous range of physical memory (raw memory). A RawBlock instance can be obtained from a MMIODevice instance. The index values map to physical memory addresses and are measured in bytes. The index values are relative to the base address of the raw memory area. The index value 0 corresponds to the base address of raw memory area. The byte ordering of the underlying raw memory area can be retrieved using the MMIODevice.getByteOrdering() method.

The RawBlock interface consists of the following methods:

The RawByte Interface

The RawByte interface provides methods for setting and getting the value of a register or memory area holding a byte value. A RawByte instance can be obtained from a MMIODevice instance.

The RawInt Interface

The RawInt interface provides methods for setting and getting the value of a register or memory area holding an int value. A RawInt instance can be obtained from a MMIODevice instance.

The RawShort Interface

The RawShort interface provides methods for setting and getting the value of a register or memory area holding a short value. A RawShort instance can be obtained from a MMIODevice instance.

The MMIOEvent Class

The MMIOEvent class encapsulates events fired by peripherals mapped to memory. The MMIOEvent class consists of the following constructors and methods.

The MMIODeviceConfig Class

The MMIODeviceConfig class encapsulates the hardware addressing information, and static and dynamic configuration parameters of an MMIO device.Some hardware addressing parameter, and static and dynamic configuration parameters may be set to PeripheralConfig.DEFAULT. Whether such default settings are supported is platform- as well as peripheral driver-dependent.An instance of MMIODeviceConfig can be passed to the PeripheralManager.open(PeripheralConfig) or PeripheralManager.open(Class, PeripheralConfig) method to open the designated MMIO device with the specified configuration. A PeripheralConfigInvalidException is thrown when attempting to open a peripheral device with an invalid or unsupported configuration.

The MMIODeviceConfig class itself contains three nested classes.

The MMIODeviceConfig class also contains three constants.

Finally, the MMIODeviceConfig class consists of one constructor and four accessors.

The MMIODeviceConfig.RawMemoryConfig Class

The abstract MMIODeviceConfig.RawMemoryConfig class encapsulates the configuration parameters of a generic raw memory area. The abstract class consists of two methods.

The MMIODeviceConfig.RawBlockConfig Class

The MMIODeviceConfig.RawBlockConfig class extends the abstract MMIODeviceConfig.RawMemoryConfig class and encapsulates the configuration parameters of a memory block. The class consists of one constructor and one accessor.

The MMIODeviceConfig.RawRegisterConfig Class

The MMIODeviceConfig.RawRegisterConfig class extends the abstract MMIODeviceConfig.RawMemoryConfig class and encapsulates the configuration parameters of a register. The class consists of one constructor and one accessor.

The MMIOEvent Class

The MMIOEvent class encapsulates events fired by peripherals mapped to memory..The class consists of four constructors and three methods.

AccessOutOfBoundsException

AccessOutOfBoundsException is an exception that is thrown by an instance of RawBlock if the offset used is out of valid boundary of the specified memory block.