hardwareregister

Provide an abstract representation of hardware registers that allows defining registers and fields as a generic description without having to write boilerplate code.

Description of hardware registers.

A register has a name and an offset (which can be an address). It may also have an initial (reset) value.

A register is made up of one or more fields. A field starts at a (low) first bit and ends as a last (high) bit. The bit range is inclusive.

The bits in the field can be converted to several types:
  • boolean (one bit only)

  • enum

  • integer (unsigned)

A register value holds the value of a register. The Register describes a register and the fields it contains. The RegisterValue holds a register value and references a Register.

Example use

wdt_ctrla = Register('WDT.CTRLA', 0x0100,
                     RegisterDescription( 8, [
                         RegisterFieldInt('PERIOD', 0, 3),
                         RegisterFieldInt('WINDOW', 4, 7)])
                     )
wdt_status = Register('WDT.STATUS', 0x0101,
                      RegisterDescription(8, [
                          RegisterFieldBool('SYNCBUSY', 0),
                          RegisterFieldBool('LOCK', 7)]),
                      0)

@enum.unique
class VrefAC0RegSel(enum.IntEnum):

    V0_55 = 0x00
    V1_1  = 0x01
    V2_5  = 0x02
    V4_4  = 0x04
    res1  = 0x05
    res2  = 0x06
    AVDD  = 0x07

vref_ctrla = Register('VREF.CTRLA', 0x00A0,
                      RegisterDescription(8, [
                          RegisterFieldEnum('AC0REFSEL', 0, 2, VrefAC0RegSel)]),
                      0)

nvmctrl_addr = Register('NVMCTRL.ADDR', 0x1008,
                        RegisterDescription(16, [
                            RegisterFieldInt('ADDR', 0, 15, RegisterField.Endian.Big),]),
                        0)
nvmctrl_addr_value = RegisterValue(nvmctrl_addr, 0x1234)
nvmctrl_addr_value = RegisterValue(nvmctrl_addr, 0x1234)
print(f'nvmctrl_addr_value 0x{nvmctrl_addr_value.value:04x} is {nvmctrl_addr_value}')
nvmctrl_addr_value.value = 0x5678
print(f'nvmctrl_addr_value 0x{nvmctrl_addr_value.value:04x} is {nvmctrl_addr_value}')

Output:

nvmctrl_addr_value 0x1234 is ADDR:4660
nvmctrl_addr_value 0x5678 is ADDR:22136
class pymisclib.hardwareregister.Register(name: str, offset: int, description: RegisterDescription, initial: int = -1)

A register at an offset with a name and description.

__init__(name: str, offset: int, description: RegisterDescription, initial: int = -1)

Initialize self.

Parameters:
  • name (str) – Name of the register.

  • offset (int) – Offset of the register.

  • description (RegisterDescription) – Description of the register.

  • initial (int) – Initial value of the register after reset. Use -1 for unknown initial value.

property description: RegisterDescription

Description of the register.

property initial: int

Initial value of the register after reset. -1 is unknown.

property name: str

Return the register name.

property offset: int

Offset of the register in memory.

class pymisclib.hardwareregister.RegisterDescription(nr_bits: int, fields: list[RegisterField])

Describes the layout and fields of a register.

__init__(nr_bits: int, fields: list[RegisterField])

Initialize self.

Parameters:
  • nr_bits (int) – Number of bits in the register.

  • fields (list[RegisterField]) – Fields of the register.

Raises:
  • IndexError – An error was found in the fields.

  • KeyError – A field name was used multiple times.

check_field_consistency()

Check that the fields are consistently defined.

Raises:

IndexError – An error was found in the fields.

field(name: str) RegisterField

Return the field with the given name.

Parameters:

name (str) – Name of the field.

Raises:

KeyError – The given name is not a field.

fields_by_end_bit() Generator[RegisterField, None, None]

Yield all register fields in falling order of their end bit.

Returns:

A register field per call.

Return type:

RegisterField

fields_by_start_bit() Generator[RegisterField, None, None]

Yield all register fields in rising order of their start bit.

Returns:

A register field per call.

Return type:

RegisterField

mask_keep_field(field: RegisterField) int

Create a mask to remove all bits not belonging to the field.

Parameters:

field (RegisterField) – The field to mask.

Returns:

A mask leaving only the bits belonging to the field.

mask_remove_field(field: RegisterField) int

Create a mask to remove all bits belonging to the field.

Parameters:

field (RegisterField) – The field to mask.

Returns:

A mask removing all bits belonging to the field.

value_of_field(field: RegisterField, value: int) Any

Return the value of the field in the register.

class pymisclib.hardwareregister.RegisterField(name: str, first_bit: int = 0, last_bit: int = 31, conversion: Type = None, endian: Endian = Endian.Unknown)

Describe a field in a register.

class Endian(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Endianness of a register.

Big = 'BE'

Values are stored with the most significant byte at the lowest address and the least significant byte at the highest address.

Example ::

0x12345678 is stored as 0x12 0x34 0x56 0x78.

Litte = 'LE'

Values are stored with the least significant byte at the lowest address and the most significant byte at the highest address.

Example ::

0x12345678 is stored as 0x78 0x56 0x34 0x12.

Middle = 'ME'

Values are stored as big endian words where each word is stored as litte endian.

Example ::

0x12345678 is stored as 0x34 0x12 0x78 0x56.

Unknown = '??'

The endianness is unknown.

__init__(name: str, first_bit: int = 0, last_bit: int = 31, conversion: Type = None, endian: Endian = Endian.Unknown)

Initialize the instance.

Parameters:
  • name – The name of the field.

  • first_bit – The first bit of the register belonging to the field (inclusive).

  • last_bit – The last bit of the register belonging to the field (inclusive).

  • conversion (TypeVar) – The conversion class.

  • endian (Endian) – Endianness of the field. This is only relevant for fields spanning byte boundaries.

Raises:

IndexError – last_bit is smaller than first_bit.

convert(value: Any) Any

Convert the given value to the type of the field.

property conversion: Type

Return class used to convert the value.

property endian: Endian

Endianness of the field.

property first_bit: int

First bit of the register containing the field.

property last_bit: int

Last bit of the register containing the field.

property mask: int

A mask leaving only bits contained in the field.

property name: str

Name of the field.

property type: Type

Type of the field.

class pymisclib.hardwareregister.RegisterFieldBool(name: str, bit: int)

A field in a register that is a single bit.

__init__(name: str, bit: int)

Initialize the instance.

Parameters:
  • name (str) – Name of the field.

  • bit (int) – The bit in the register of the field.

class pymisclib.hardwareregister.RegisterFieldEnum(name: str, first_bit: int, last_bit: int, conversion: Type[IntEnum] | Type[IntFlag])
__init__(name: str, first_bit: int, last_bit: int, conversion: Type[IntEnum] | Type[IntFlag])

Initialize the instance.

Parameters:
  • name (str) – Name of the field.

  • first_bit (int) – First bit of the register containing the field (inclusive).

  • last_bit (int) – Last bit of the register containing the field (inclusive).

  • conversion (TypeVar) – The conversion class which must be an enum.

class pymisclib.hardwareregister.RegisterFieldInt(name: str, first_bit: int, last_bit: int, endian: Endian = Endian.Unknown)

A register field containing an integral value.

__init__(name: str, first_bit: int, last_bit: int, endian: Endian = Endian.Unknown)

Initialize the instance.

Parameters:
  • name (str) – Name of the field.

  • first_bit (int) – First bit of the register containing the field (inclusive).

  • last_bit (int) – Last bit of the register containing the field (inclusive).

  • endian (RegisterField.Endian) – Endianness of the field. This is only relevant for fields spanning byte boundaries.

property max_value: int

Maximum allowed value in the field (inclusive).

property min_value: int

Minimum allowed value in the field (inclusive).

class pymisclib.hardwareregister.RegisterValue(register: Register, value: int)
__init__(register: Register, value: int)
set(name: str, value: bool | int | IntEnum | IntFlag)

Set the value of the named field in the register.

Parameters:
  • name (str) – Name of the field.

  • value (bool|int|enum.IntEnum|enum.IntFlag) – Value of the field in the register.

Raises:

AttributeError – the field does not exist.

pymisclib.hardwareregister.example()

Module demonstration.