Sure, but what does this have to do with the RawRepresentable
example I posted above?
My fault, sorry. I was misled by this
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?
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:
- Rename
@Register
to@RegisterDescriptor
to make it clear that the struct is not the one you will read from or write to. - 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.) - Add
RawRepresentable
conformance to the generatedRead
andWrite
structs instead of defining astorage
property. As @ole pointed out, the initializer can be non-optional and still satisfy the protocol requirement. - Perhaps consider eliminating the generated
Raw
struct and moving the members into the generatedRead
andWrite
structs as$
-prefixed members. This would avoid having similarly-namedraw
andrawValue
properties in theRead
andWrite
structs. - 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 toFixedWidthInteger & 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
}
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!
- Rename `@Register` to `@RegisterDescriptor` Ā· Issue #69 Ā· apple/swift-mmio Ā· GitHub
- Existing issue: Register field definitions are confusing due to vacuous types Ā· Issue #33 Ā· apple/swift-mmio Ā· GitHub
- Add `RawRepresentable` conformance to the generated `Read` and `Write` structs Ā· Issue #70 Ā· apple/swift-mmio Ā· GitHub
- Merge properties of `Raw` struct into `Read`/`Write` structs Ā· Issue #71 Ā· apple/swift-mmio Ā· GitHub
- Use an associated type to provide the bit width of a register Ā· Issue #72 Ā· apple/swift-mmio Ā· GitHub
Great work!
Here's some feedback from using Swift MMIO.