qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC] peripheral/register/bitfield objects - new MCU model


From: Liviu Ionescu
Subject: [Qemu-devel] [RFC] peripheral/register/bitfield objects - new MCU model
Date: Wed, 8 Jul 2015 23:14:36 +0300

as anyone who did it knows, describing memory mapped peripherals is tedious. as 
far as I know, qemu support ends at defining memory regions and implementing 
the read/write callbacks for all accesses in this region.

while implementing several Cortex-M devices (currently STM32F103, F107, F407, 
F429 are functional for blinky projects), I experimented with some solutions to 
automate this.

the model that I stopped at uses a hierarchy of objects that goes down to 
register bitfield level (peripheral/register/bitfield).

the central object in this hierarchy is the peripheral register, which holds a 
value (up to 64-bits), and its content is automatically retrieved/updated by 
read/writes, based on accurate vendor bitmasks.

in addition, each register may have two user actions defined, a pre-read 
action, to load the register with an external value, and a post-write action, 
to forward the value to an external device, or to implement register 
interdependencies.

these actions are obviously user functions, registered as callbacks.

the other objects, the peripheral and bitfield, are more or less helpers.

the bitfield is a simple object, that stores a mask and a shift value, to 
retrieve a bitfield value; it is always a register child.

the peripheral is more or less a container of registers; it implements the 
logic to forward read/writes to the appropriate register.

registers and bitfields are defined with arrays of Info structures; special 
functions traverse these structures and create the objects.

an example of a read only 32-bit word register:

{
    .desc = "Port input data register (GPIOx_IDR)",
    .name = "idr",
    .offset_bytes = 0x08,
    .reset_value = 0x00000000,
    .reset_mask = 0xFFFF0000,
    .access_flags = PERIPHERAL_REGISTER_32BITS_WORD,
    .readable_bits = 0x0000FFFF,
    .rw_mode = REGISTER_RW_MODE_READ, 
},


an example of a register with bitfields defined:

{
    .desc = "RCC PLL configuration register (RCC_PLLCFGR)",
    .name = "pllcfgr",
    .offset_bytes = 0x04,
    .reset_value = 0x24003010,
    .bitfields = (RegisterBitfieldInfo[] ) {
        {
            .name = "pllm",
            .desc = "PLL division factor",
            .first_bit = 0,
            .width_bits = 6,
        },
        {
            .name = "plln",
            .desc =  "PLL multiplication factor",
            .first_bit = 6,
            .width_bits = 9, 
        },
        {
            .name = "pllp",
            .desc = "Main PLL (PLL) division factor",
            .first_bit = 16,
            .width_bits = 2, 
        },
        {
            .name = "pllsrc",
            .desc = "Main PLL (PLL) clock source",
            .first_bit = 22, 
        },
        {
            .name = "pllq",
            .desc = "Main PLL (PLL) division factor",
            .first_bit = 24,
            .width_bits = 4, 
        },                                                        
        { }, 
    }, 
},



accessing registers and reading bitfields is straightforward:

    peripheral_register_write_value(odr, new_value);

    ....

    pllm = register_bitfield_read_value(state->f4.fld.pllcfgr.pllm);



this model has several advantages:

- increased emulation accuracy; the functionality is fully and uniformly 
implemented for all objects, for example byte and unaligned accesses are 
implemented for all registers; read/write masks allow to affect only the 
desired bits; etc
- increased readability; the definitions are descriptive, not hidden inside code
- opens the door to automatically generate the MCU definitions

possible disadvantages:

- a small overhead, hopefully not impacting general performances


this model is currently implemented and functional in my branch, and it was 
used to implement the needed STM32 peripherals (RCC, GPIO, FLASH, PWR) for the 
STM32F1 and STM32F4 families, and will probably be part of the new GNU ARM 
Eclipse QEMU release, scheduled in 2-3 weeks.

however I would consider it still experimental, since I already have new ideas 
that I would like to experiment in future versions.


regards,

Liviu









reply via email to

[Prev in Thread] Current Thread [Next in Thread]