forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
[Drivers:] Add a DALI driver to Zephyr #1
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
Open
SvenHaedrich
wants to merge
3
commits into
main
Choose a base branch
from
add-dali-drivers
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,481
−0
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6f0d150 to
579f2e9
Compare
35e78a5 to
dff527d
Compare
bb8ec94 to
c9e8506
Compare
07c9a2c to
1447272
Compare
1447272 to
62d78f3
Compare
1983d32 to
da8c7a8
Compare
25bbe02 to
2a71ea5
Compare
4ad07f6 to
1e76677
Compare
db0d8d4 to
1a42478
Compare
SvenHaedrich
pushed a commit
that referenced
this pull request
Dec 5, 2025
Map all pins of RT685's Flexcomm #1 peripheral. Needed for opration of Flexcomm #1 in I2S mode or Flexcomm zephyrproject-rtos#3 in I2S mode with shared signals. Signed-off-by: Vit Stanicek <vit.stanicek@nxp.com>
SvenHaedrich
pushed a commit
that referenced
this pull request
Dec 5, 2025
Add SCK and WS signals to a shared signal set between Flexcomm #1 and Flexcomm zephyrproject-rtos#3 for the mimxrt685_evk/mimxrt685s/cm33. This enables the board to both transmit and receive audio, as the BCK and WS signals produced by the WM8904 codec are only connected to the Flexcomm #1 peripheral. Signed-off-by: Vit Stanicek <vit.stanicek@nxp.com>
3fd3a68 to
180773d
Compare
Defines the generic interface for the DALI driver. Signed-off-by: Sven Hädrich <sven.haedrich@sevenlab.de>
Provide a basic example how the DALI driver can be used. Signed-off-by: Sven Hädrich <sven.haedrich@sevenlab.de>
Implementation of a DALI driver for a cpu that provide a PWM interface for zephyr. The code is tested for a STM32F091 cpu and for the nRF52840 cpu. Signed-off-by: Sven Hädrich <sven.haedrich@sevenlab.de>
180773d to
7db4a82
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Add a DALI driver to Zephyr
DALI is the digital addressable lighting interface, a standard for professional lighting solutions. In its core the standard is based on Manchester encoded exchange of frames. Because specific behavior for the interface is required by the DALI-Alliance a dedicated driver is needed to pass the mandatory tests.
Driver Status
Here are two implementations for a DALI driver.
lpcxpresso11u68
This driver is very specific for this chip. There was no counter or pwm implementation available at the time of the implementation. So, the driver accesess these peripherals directly. This makes this implementation hardly transferable to other platforms. The reason to include this driver in this PR is the fact that it passes all the relevant DALI tests. Hence,m it can serve as a source of inspiration how to achieve full compatibility. You can select this implementation with
export BOARD=lpcxpresso11u68nucleo_f091rc
This is a more generic implementation of a DALI driver. Though, it requires a PWM peripheral that can capture edge events on gpio pins. This is true for a variety of STM32 controllers. Though, this driver is only tested for the f091.
export BOARD=nucleo_f091rcSample program
This code includes a sample application that sends DALI frames. These result in a blink action on LEDs (or device type 6 control gears, as we call it in the business) that are connected to the DALI bus. The device tree overlays are optimized for a DALI Click Adapter providing the physical interface to the DALI bus. Refer to the devicetree files to find details about the connection of Rx and Tx lines.
You can build the sample code:
west build --board $BOARD samples/drivers/daliLPC11U6x Dali Test Status
This low-level driver passes the following tests from the DALI-Alliance. (DiiA V2 2.6.0.0 - February 2024) This list will
not track tests that relate to the hardware of the DALI interface.
STM PWM Dali Test Status
This low-level driver passes the following tests from the DALI-Alliance. (DiiA V2 2.6.0.0 - February 2024) This list will
not track tests that relate to the hardware of the DALI interface.
Design Considerations for DALI Low Level Driver
API-Design
The API for the DALI bus needs to provide the following functionalities:
Further requirements
Frame Types
Currently, supported events and frame types are:
Receive
devis a pointer to a DALI devicerx_frameis a buffer for a DALI frame or an eventtimeouttimeout perioddali_receivewill return the next frame received from the DALI bus. The function has an input queue, to ensure that no frame or event is lost.return codes
*rx_frame*rx_frameis invalidSend
devis a pointer to a DALI devicetx_frameis a buffer holding a single DALI frame, the buffer is copied into data structures of the low-level driver and may be discarded after returnThis function supports async operation. Any frame is stored into an internal send slot and the
dali_sendreturns immediately.dali_sendmaintains two send slots. One slot is reserved for backward frames. The other slot is used for all kind of forward frames. In case of a forward frame in its slot that is pending for transmission, it is still possible to provide a backward frame. That backward frame will be transmitted before the pending forward frame, whenever possible. There is a strict timing limit from the DALI standard (see IEC 62386-101:2022 8.1.2 Table 17) for the timing of backward frames. When these restrictions can not be fulfilled, the backward frame may be dropped and an error code returned.return codes
Abort
devis a pointer to a DALI devicedali_abortwill abort all pending or ongoing forward frame transmissions. Transmission will be aborted, regardless of bit timings, at the shortest possible time. This can result in corrupt a frame.Reasoning
Firstly, I think an async send is the way to go. I can not think of a scenario where it is favorable to block execution until the frame is sent. Arguments for that:
Secondly, on using a send queue. I feel my stomach ache about that. But as good practitioners we need to grow above feelings. Here is some reasoning. To build a sound API for DALI we need to consider what we require from the higher stack levels.
There a basically two kind of DALI controls:
Control Gears
Let's start with the case 2 as it's much easier. All messages follow a simple sequence.
Actually, just a best effort to transmit the backward frame is required from the low-level-driver. The backward frame is send regardless of collisions, and I would say even a bus down condition does not matter as the transmission of the backward frame is bound to strict timing limits.
The higher levels of the DALI protocol ensure that there is only a single frame processed at a time. Hence, it is sufficient to have a single input slot for forward and backward frames.
Optionally, the low-level-driver can track whether the timing requirements for a backframe are meet. In case the backframe is overdue, the low-level-driver can decide to drop the backframe completely as it will be disregarded anyhow.
Control Devices
Now look at e.g. control devices with an application controller. Firstly, we have exactly the sequence pattern from above, where forward frames are received and require processing and an optional response from the DALI-stack. Parallel to that there might be an event that requires signalling (or it triggers sending of a forward frame typically something like a DAPC command).
The processing of a forward frame needs to have a higher priority than sending an event as it might require a backward frame that obeys the strict timing requirements. Actually, an event has to wait until the bus is idle for the time defined by the event´s inter frame timing priority.
sequenceDiagram DALI-Bus->>Low-Level-Driver: Forward Frame Event-Context-->>Low-Level-Driver: Event Frame Low-Level-Driver->>DALI-Stack: Forward Frame DALI-Stack-->>Low-Level-Driver: Backward Frame Low-Level-Driver-->>DALI-Bus: Backward Frame Low-Level-Driver-->>DALI-Bus: Event-FrameHow should this be expressed in code? The main loop of the DALI stack will be identical to the one for control gears.
Ideally events are generated in a different context and
dali_sendwill keep the event frame in a buffer and wait for the specified inter frame timing while back frames might sneak by.Collisions
The concepts of collision avoidance, detection, and recovery is found in IEC 62386-101:2022 9.2. These concepts apply for forward frames only. Collision of backward frames are neither detected, nor is it necessary or possible to re-send these. When the low-level driver detects a collision it will destroy the ongoing frame transmission by application of a break signal (see IEC 62386-101:2022 9.2.4 Table 25). After the recovery time the low-level-driver will automatically re-try to send the frame. It is the task of the application layer to control and tame the re-sending if necessary.
So, sending a forward frame from the application layer needs to look like this:
Transactions
The concept of transactions is found in IEC 62386-101:2022 9.3: The purpose of transactions is to ensure that a sequence of commands send by one control device cannot be interrupted by another control device.
Look, for instance, at the retrieval of a memory bank cell for a control gear. The required command sequence is something like:
There are two commands that prepare the query, and a query command that expects backward frames
from the addressed gears. The code to transmit these frames can look like this:
Obviously, there are a lot of code repetitions which can be saved when defining a function
Probably, this will be a blocking function. This should not hurt too much, as we most likely wait for a backframe anyhow.
We have to wait until the transmission of the preceding frame has finished before we call for the next frame to be send to the DALI bus. Otherwise, we can expect to see a
EBUSYerror code.