ZigEmbeddedGroup / regz

Generate zig code from ATDF or SVD files for microcontrollers.
MIT License
82 stars 29 forks source link

Merge sequential fields with common prefix and same size to arrays #73

Closed ekoeppen closed 1 year ago

ekoeppen commented 1 year ago

Symbolic fields names in registers make it more complicated to create generic abstractions which work with numerical indices. As an example, the ODR register in the STM32 GPIO peripheral is composed of 16 bits, and setting a pin requires passing in a struct to the write function. I've been experimenting with creating that struct at comptime, but it doesn't seem very elegant.

One way to simplify this would be what svd2ada does when generating fields, which is to generate an array of fields if subsequent fields have the same size and share a common prefix, see here for an example of the resulting code.

ekoeppen commented 1 year ago

To clarify the common prefix a bit more, it would probably also make sense to check if it is followed by a digit, especially the MSP430 SVD files seem to use a lot of common prefixes.

ekoeppen commented 1 year ago

After further experiments it unfortunately seems that it is not possible to have arrays in extern structs where the element sizes are not multiple of 8, not sure if the array approach would work at all.

mattnite commented 1 year ago

Could you explain some of the use cases you're wanting to see? I can imagine some, but I'm sure I'm missing context. I'll share some of my thoughts:

I understand that the struct pattern is less elegant in some scenarios, but it has two qualities:

It does make something like iterating GPIO bitfields more difficult, it can be done with comptime and a wrapping function, but there's also something like StaticBitSet that you can cast to to get an array-like interface.

it is not possible to have arrays in extern structs where the element sizes are not multiple of 8

it is also not possible to have arrays of bitfields in a packed struct. Not sure if there are any special cases

generate an array of fields if subsequent fields have the same size and share a common prefix

I've explored incorporating convention parsing before and the problem with it is when you automate it completely, it doesn't scale:

Instead I plan to automate importing the different xml registers schemas, and then have tools for refactoring the register structure that provide suggestions that the user explicitly opts in to (as well as manual edits ofc), so an interactive, semi-automatic process. With suggestions for type deduplication, repeated fields, etc, we could improve the generated code, user experience of bringing up a chip, and share these benefits with other communities.

ekoeppen commented 1 year ago

Thanks for the reply! I'm currently working on yet another iteration of an embedded driver library, this time using Zig (after C++ and Ada), it's very much work in progress, but seems very well suited to do in Zig because of the metaprogramming capabilities: https://gitlab.com/40hz/zig/ezdl

While working on the Ada version, I realized that it would make sense to create MCU specific wrappers based on collections of peripherals which are shared between the different MCUs, e.g. on STM32. As an example, using comptime in Zig, this is a GPIO layer which works with duck typing: https://gitlab.com/40hz/zig/ezdl/-/blob/main/src/stm32/peripherals/gpio_v2.zig

Creating support for a new MCU is then quite easily done by adding a new wrapper: https://gitlab.com/40hz/zig/ezdl/-/blob/main/src/stm32/mcus/stm32f072x.zig

The array approach allows for things like GPIOs to use simple integers on the high level API.

I do like the approach to add a refactoring step though, I think that would help with more tricky cases like MSP430, where the definitions are not really usable out of the box (e.g. encoding the peripheral name in the field name).

ekoeppen commented 1 year ago

Let me close this issue, as it's not going to work, looking forward to the postprocessing approach!

mattnite commented 1 year ago

That's an awesome project! Chime in anytime because I want to make device support and writing drivers enjoyable.

Doing a bit more thinking, instead of using the bitset in the standard library, there's precedence for an embedded version (we need a volatile pointer), it'll be part of the mmio namespace in microzig, and we can have something like a BitArray for single bit fields, and FieldArray for multi-bit, repeated fields. Then all you'd have to do to get them is define it in the schema properly. Looking forward to putting that together :)

ikskuh commented 1 year ago

A note here:

packed struct { bool, bool, bool, bool, bool, bool, bool, bool }

is a thing and is an 8 bit "array" of integers, that you can index with comptime known indices

ekoeppen commented 1 year ago

That's an awesome project! Chime in anytime because I want to make device support and writing drivers enjoyable.

Thanks :) ezdl is in this half experimenting, half doing some real stuff phase, so far I've been able to take it much further than with C++ or Ada. I'll definitely check how to contribute to Microzig, it has some nice traction and better out of the box experience.