-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Refining Zephyr's Device Driver Model #6293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi @tbursztyka , Thanks for structuring this topic and giving some directions. dts based pinmux generation#5021: Pinmux configuration code generated from Device tree These 2 works are concurrent and don't cover exact same scope but both provide a way to generate c code for pinmux board definition. Driver init function generationAvailable in the following branch: Learnings so farAll these works have flaws, and should be refined. Main learnings as of now from the feedbacks: |
I noticed indeed that we are many chasing similar rabbits, so it would be nice to centralize efforts. A bit like what is being done for the APIs in #5697 extract_dts_include would require some love indeed, even renaming it would be wise as it's going to be used for more various things. it's quite messy as it is. (kconfiglib.py for instance is super easy to manipulate, it's well commented etc... ) About the #5799, I'll take a look (the pr is big), but importing yet another external tool (chaos_pp), not sure it's wise. Moreover your dts_struct_pinctrl branch is playing with yaml/dts nicely to do what chaos_pp has been kind of used for in #5799 it seems, but your solution is generic and fits better in S4. About your branch, it seems to me that it would be the right approach. There are technical details that may change. For instance: is it better to generate a header that is then included in the driver, or generate one .c file instantiating all devices (knowing that the same routine would generate the future header listing all devices as extern as described in O3). Also, maybe using some template for generic part (DEVICE_* macro usage) could make the code a bit clearer. We need to find a way to manage specific irq settings as well. Some devices need more than 1 (spi_dw on arc for instance), or need to request to unmasq these and so on. Finding a way to solve this in a generic way could be a little bit challenging. But first things first: we need to finalize porting all arch/soc/boards/devs to dts. Maybe it would be useful to list what's missing (not sure there is an issue listing what needed to be done on that front at least). There are even devices drivers I made that miss such support so... :) |
By moving more ports to DeviceTree, it should be possible to revisit IRQ_CONNECT() as well. The current best known method to "connect" an IRQ line to an ISR is quite awkward, and it would be good if we could do as much as possible during compilation time, without requiring a "call" to IRQ_CONNECT() to be inside a function. This is technically possible already, given that most ports are using the gen_isr_table script. |
@lpereira first, very good issue (descriptions). For me, contributing a bare-metal BLE controller into Zephyr and slowly porting to re-use Zephyr OS features, every change gets me to profile the controller with respect to CPU usage (current consumption). Most BLE end-user usecases are race-to-idle, which means CPU wakeup is always by IRQ then followed up by (seldom) thread mode execution, and of course, in all such wakeup there is the use of Driver API. Observation from the current driver API is (without care to use const), each API call adds added latency passing device structure in RAM, indirect memory access needing many instruction cycles in an MCU. Please consider these API call overhead in this issue addressing refinement of Driver Model (if not considered already). Reference: |
Some (biased) remarks from the author of #5799 regarding DTS extraction and driver data/code generationI see #5799 (green) and #5021 (yellow) as two of several options a driver implementer may choose from. She may also decide to write her own script to transfer DTS info to the driver. All this should be controlled by the CMakefile of the driver inplementation. The Zephyr device driver infrastructure should be open to several solutions to enable the driver implementor to select the one that best fits to the needs. The device driver infrastructure should provide capabilities such as
No specific solution should be mandated. The yellow solution for example seems to be less complex and fully sufficent for an e.g. adc driver. It will most probably not work for a pinctrl driver. It may be too inflexible in case not only data but also template functions have to be instantiated for a device (e.g. to call IRQ_CONNECT). |
@b0661 I have to disagree on "No specific solution should be mandated." The least freedom you'll give in this domain will lead to a bunch of completely different ways of doing things. And who will maintain what then? The idea of having one solution fits all, is that everybody will "speak the same language". Anybody should be able to go and fix easily any driver, board, device integration, review PRs, etc... I have a preference on the yellow approach mostly because it does all in python in a tool zephyr owns fully (no need of any external tool) and which removes details of device instantiation in driver code. @lpereira Sure, I'll revisit/rewrite the issue and add that one. I need also to add the one dealing with avoiding linking unused device: currently, even if a device is not used by any part of the code, fact that it gets its driver and its instance brought up will make it part of the final image. [edit]: issue updated. Btw: is there an issue tracking what's being done moving towards DTS (S1)? Could not find any. |
No specific solution should be mandated means: even if there is a preferred solution other solutions should be at least supported by the technical capabilities (e.g. hooks, data formats, ...). The capabilities shall be available to allow new solutions to emerge. That does not mean that there is a bunch of different solutions used. The solution(s) to be used should be decided by the review process and not dictated by technical shortcomings.
I agree. The point to discuss is the features of the "language".
In this sense CHAOS is not a tool but a set of macros comparable to python scripts. The respective tool is also fully owned by Zephyr - it is the C preprocessor. I think the CHAOS thing is somehow overrated. A big deal of data preparation is done in extract_dts_includes.py. generated_dts_board.h acts as a 'database' with a strange data format - C defines. The CHAOS C preprocessor macro library perfectly fits to this data format. There is a work split between extract_dts_includes.py and some C preprocessor macros.
As described above this is a matter of work split between the python tool and the C preprocessor. If everything is done by the python tool there is no flexibility and freedom to do something different if it is needed. At that point you start providing templates, configuration data, ... to the python tool or change it. In the end you come up with some "language" to specify the driver type to be generated by the tool. On the other side if you hand over less eleborated data but provide eleborated "language" contructs for the C preprocessor you create the driver configuration "language" on the C preprocessor side. Doing that you do not have to foresee future needs of the driver implementers. You just provide means to empower them to do what is necessary.
This can be achieved independent from the used tooling or work split. Device instantiation is already handled by macros and may be handled by C code generated by python too.
So my suggestion is: use the C preprocessor and some sophisticated macros to get that flexibility. I already created template like interrupt configuration for the STM32 SPI driver in #5799. Thx. |
I am closing that one, since issue #22941 is meant to be a more exhaustive replacement. |
For more information on Zephyr's Device Driver Mode, refer to http://docs.zephyrproject.org/devices/drivers/drivers.html
Current situation
There are good reasons for all of it, mostly. When ramping up Zephyr, there was not dts yet, Kconfig was the only way.
All of it works just fine. But as we see more architectures, more SoCs, boards and thus more devices being ported: it starts to clutter the system a bit and can be somewhat confusing to new comers. Moreover when things could be simpler and better optimized.
This is a known problem, on-going work is already fixing some of it. Let's list issues/ideas on how to improve the Device Drivel Model.
Tooling
Refactor/rewrite extract_dts_includes.py
Issue: Cleaning up a bit dts scripts #6504 But there is still more to do
Drop dtc C based compiler for the python version (PR Python replacement for DTC [DNM/WIP] #5615), this would help for the below changes probably (and maintaining current dtc for windows gives extra work)
Simplifications (S)
Move all boards (arch/soc/devices) to dts. Issue: All boards for all arch's should use DTS #4960
Remove Kconfig device specific settings and use dts only
Only generic support would survive (CONFIG_GPIO, CONFIG_IEEE802154, etc...) ?
DEVICE_* macro call for each device should be externalized from device source code:
The idea would be to generate these automatically from dts.
Optimizations (O)
Reversing the actual device and config interdependency to gain a bit of space:
SYS_INIT would then take less space than currently (ok just 12 bytes less)
Remove the 'name' attribute in struct device_init (aka device_config):
This will need many steps, but mostly requires S1 to be done in order to avoid messing up with Kconfig. I already tried quickly to hack around dts, and Kconfig, since not all boards are dts ready and it is very ugly. It was just a quick PoC. (see https://github.com/tbursztyka/zephyr/tree/dev_name_const).
Zephyr will gain some ROM space from it: no device name, and direct bindings (which also will improve boot time a tiny bit)
Remove drv_name in DEVICE_* macro, keep only dev_name (which is the semantically right name, there is no such thing à as "driver name" anywhere at runtime).
Make all devices constant:
Easy now that getting the bindings are made at built time. (const in DEVICE_ macro, extern const struct device ... in the generated file etc...)
DTS can generate such unique name via node name, thus 'label' could be removed altogether. No need for any name maintenance then in dtsi/yaml files.
Revise how IRQ are connected: this would reduce runtime necessary calls for it and save some ROM space, while simplifying maintenance as well (connection could be generated automatically via the dts workflow)
Do not built/link built device drivers, and there relevant device instances, if none of these are used anywhere. I.e. even if gpio port C is requested to be built, but proven to be let alone then: do not embed it in the final image. Again saving ROM space relevantly.
Issues ordering
Let's discuss and update this issue accordingly
The text was updated successfully, but these errors were encountered: