Introducing Swift MMIO

Sure, but what does this have to do with the RawRepresentable example I posted above?

My fault, sorry. I was misled by this

1 Like

Happy New Year!

As someone without MMIO experience, the additional context was very helpful. Thanks!

Ahhh, I think this is the part I misunderstood in the original post. I didn’t realize that you can only access the properties inside .modify or after calling .read, and I didn’t realize that the @Register struct isn’t the struct that is being accessed!

I guess I should have seen it given that the property in the @RegisterBank struct in the original post is of type Register<CR1> rather than just CR1. That being said, it seems like something that would be easy to miss. In fact…

I think this should be let isr = Register<CEC_ISR>(unsafeAddress: 0x1000), no? :smile:

After clearing up this misunderstanding, I think the design overall makes a lot of sense. There a few details that I think could be changed to make it easier to understand and more familiar to Swift developers:

  1. Rename @Register to @RegisterDescriptor to make it clear that the struct is not the one you will read from or write to.
  2. Swap the projected type and the descriptor type in the property declaration. As mentioned before, it feels more natural to have the projected type be the property type. Also, moving the descriptor type to the macro with a parameter name like generatedDescriptorType helps the user understand that they can change the generated type name to anything they want. (At first, I thought the name had to be a ā€œto uppercaseā€ transformation of the property name.)
  3. Add RawRepresentable conformance to the generated Read and Write structs instead of defining a storage property. As @ole pointed out, the initializer can be non-optional and still satisfy the protocol requirement.
  4. Perhaps consider eliminating the generated Raw struct and moving the members into the generated Read and Write structs as $-prefixed members. This would avoid having similarly-named raw and rawValue properties in the Read and Write structs.
  5. If possible, use an associated type to provide the bit width rather than specifying it in the @RegisterDescriptor macro. The associated type could be constrained to FixedWidthInteger & UnsignedInteger.

After applying these changes to the example in the original post, the code looks a lot clearer to me:

import MMIO

/// An example 32-bit wide register, encompassing three individual bit fields:
/// - "en" (Enable)
/// - "clken" (Clock Enable)
/// - "rst" (Reset)
@RegisterDescriptor
struct CR1 {
  typealias RawValue = UInt32

  @ReadWrite(bits: 0..<1, generatedDescriptorType: EN.self)
  var en: Bool
  @ReadWrite(bits: 1..<2, generatedDescriptorType: CLKEN.self)
  var clken: Bool
  @ReadWrite(bits: 2..<3, generatedDescriptorType: RST.self)
  var rst: Bool
}

@RegisterBank
struct Control {
  @RegisterBank(offset: 0x0)
  var cr1: Register<CR1>
  @RegisterBank(offset: 0x4)
  var cr2: Register<CR2>
}

var control = Control(unsafeAddress: 0x1000)

// Get a reference to the cr1 register in the control bank.
var cr1 = control.cr1

// Perform a read-modify-write of the cr1 register.
cr1.modify { cr1 in
  // Mutate `en` as a Bool.
  cr1.en = true

  // Mutate `clken` as a raw integer.
  cr1.$clken = 0

  // Mutate `rst` using C-style manual bit operations.
  cr1.rawValue |= (1 & CR1.RST.bitMask) << CR1.RST.bitOffset
}
2 Likes

These are great ideas, but there may be some more design discussion needed to make them happen; do you mind opening an issue on the swift-mmio repo and continuing the discussion there?

Done!

  1. Rename `@Register` to `@RegisterDescriptor` Ā· Issue #69 Ā· apple/swift-mmio Ā· GitHub
  2. Existing issue: Register field definitions are confusing due to vacuous types Ā· Issue #33 Ā· apple/swift-mmio Ā· GitHub
  3. Add `RawRepresentable` conformance to the generated `Read` and `Write` structs Ā· Issue #70 Ā· apple/swift-mmio Ā· GitHub
  4. Merge properties of `Raw` struct into `Read`/`Write` structs Ā· Issue #71 Ā· apple/swift-mmio Ā· GitHub
  5. Use an associated type to provide the bit width of a register Ā· Issue #72 Ā· apple/swift-mmio Ā· GitHub
1 Like

Great work!

Here's some feedback from using Swift MMIO.

1 Like