struct metal_init_params metal_param = METAL_INIT_DEFAULTS;
metal_init(&metal_param);
- Initialize libmetal environment with call to
metal_init(). - Add devices:
- This step is only needed for Baremetal or FreeRTOS as there is no standard such as device tree used in Baremetal to describe devices.
- Statically define the libmetal device and register it to the appropriate bus.
- The following code snippet shows how to statically define the Triple Timer Counter device for Baremetal or FreeRTOS.
- When initializing the
metal_devicestruct provide the following: a name string, a bus for the device, the number of regions, table of each region in the device, a node to keep track of the device for the appropriate bus, the number of IRQs per device and an IRQ ID if necessary.
const metal_phys_addr ipi_phy_addr = 0xff310000;
static struct metal_device static_dev = {
.name = "ff310000.ipi",
.bus = NULL, // will be set later in metal_device_open()
.num_regions = 1, // number of I/O regions
.regions = {
{
.virt = (void *)0xff310000, // virtual address
.physmap = &ipi_phy_addr, // pointer to base physical address of the I/O region
.size = 0x1000, // size of the region
.page_shift = (-1UL), // page shift; in baremetal/FreeRTOS, memory is flat, no pages
.page_mask = (-1UL), // page mask
.mem_flags = DEVICE_NONSHARED | PRIV_RW_USER_RW, // memory attributes
.ops = { NULL }, // no user-specific I/O region operations
}
},
.node = { NULL }, // will be set by libmetal later
.irq_num = 1, // number of interrupts of this device
.irq_info = (void *)65 // interrupt information; here it's the IRQ vector ID
};
// Register the device
metal_register_generic_device(&static_dev);
For libmetal in Linux userspace, devices need to be placed in the device tree. Here is an example:
amba {
ipi_amp: ipi@ff340000 {
compatible = "ipi_uio"; /* used just as a label as libmetal will bind this device as UIO device */
reg = <00x 0xff340000 0x0 0x1000>;
interrupt-parent = <&gic>;
interrupts = <0 29 4>;
};
};
Open Devices.
Next, open the device to access the memory mapped device I/O regions and retrieve interrupts if applicable.
struct metal_device *dev;
… // instantiate device here
metal_device_open(BUS_NAME, DEVICE_NAME, &dev);