Skip to content

Conversation

@joelguittet
Copy link
Contributor

@joelguittet joelguittet commented Dec 22, 2025

Add initial version of the Espressif RMT driver.

A sample application is created to demonstrate the usage. This application comes from ESP-IDF: https://github.com/espressif/esp-idf/tree/v5.1.6/examples/peripherals/rmt/led_strip

Building of the driver is supported for ESP32 only. RMT peripheral is added to ESP32S2 and ESP32S3 device trees (disabled) but I have errors building for such targets.

For ESP32S2 the error is: undefined reference to __atomic_compare_exchange_4
For ESP32S3 the gdma functions are not available, the driver must be updated to use standard Zephyr DMA APIs.

This pull-request depends on an update of hal_espressif: zephyrproject-rtos/hal_espressif#510

Fixes: #72546

The Espressif RMT driver is created from the ESP-IDF version.

Signed-off-by: Joel Guittet <[email protected]>
* - ESP_ERR_NO_MEM: Create RMT bytes encoder failed because out of memory
* - ESP_FAIL: Create RMT bytes encoder failed because of other error
*/
esp_err_t rmt_new_bytes_encoder(const rmt_bytes_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're writing a zephyr driver, please return zephyr error codes :)
Also use @retval for documenting the discrete error values

# Copyright (c) 2025 Joel Guittet ([email protected])
# SPDX-License-Identifier: Apache-2.0

description: ESP32 RMT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a title, spell out the acronym according to the guidelines, and consider adding an actual description :) (bonus point for including an example of a dts snippet as well)

int channel_id = chan->channel_id;
uint32_t periph_src_clk_hz = 0;
bool clock_selection_conflict = false;
// check if we need to update the group clock source, group clock source is shared by all channels
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/* comments please

if ESPRESSIF_RMT

config ESPRESSIF_RMT_INIT_PRIORITY
int "Espressir RMT init priority"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Espressif

@fabiobaltieri
Copy link
Member

The support file should probably be in the esp hal, unless you want to rewrite them to comply with the upstream coding style, apis etc, then the upstream code should be a driver implementing the led_strip apis.

@joelguittet
Copy link
Contributor Author

@kartben thanks for the first comments. I basically agree with all of them and will update the code, but I should have explained a bit more: it's actually ported from esp-idf as is to permit Espressif and particularly @sylvioalves to provide the first feedbacks, we may consider as a draft PR probably for the moment. Support of RMT is also something asked several from community here so at least there is a first version people can cherry-pick.

@fabiobaltieri There will be an additional stuff for support of DMA and this need to use DMA APIs from Zephyr of course, so my guess is that it is probably better to have it in Zephyr. It's not a problem for me to update so that it follow Zephyr style. Basically the driver is based on esp-idf v5.1.6, which is already different from the latest esp-idf v6, so keeping in Zephyr is good I think (I have no interest to keep esp-idf style for the driver - and only the driver of course, hal is hal, driver is in zephyr !)
Also for the last part of your comment, maybe a I'm wrong and please in this case you can correct me, but just to clarify the sample: it's also retrieved from esp-idf and copied 95% as is. I'm not sure it's interesting to use led_strip APIs here for such purpose: the goal is just to show how to use RMT APIs. LED strip here is just an excuse. Later maybe some people will create a led strip driver for Espressif based on RMT driver, providing one more led strip driver in Zephyr :-)

@joelguittet joelguittet marked this pull request as draft December 23, 2025 09:59
@fabiobaltieri
Copy link
Member

fabiobaltieri commented Dec 23, 2025

Sure it's fair to have it in misc if you are willing to put to work down to fix it up, problem though is that if it gets updated in idf it'll be impossible to track the changes. Anyway, your call on that.

For the rest, yeah prob fair to have it in misc to be used without a specific behavior but then I don't think we should merge a sample that makes it do a functionality that we have a subsystem for if it does not use the subsystem apis. But at that point it should be pretty straightforward to implement a led_strip driver on top of it.

@wmrsouza
Copy link
Contributor

wmrsouza commented Dec 23, 2025

@joelguittet my 2 cents:

Comment on lines 4 to 7
menuconfig ESPRESSIF_RMT
bool "Espressif RMT driver"
help
Enable config options for Espressif RMT driver.
Copy link
Contributor

@wmrsouza wmrsouza Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My sugestion:

config RMT_ESP32
	bool "ESP32 RMT driver"
	default y
	depends on DT_HAS_ESPRESSIF_ESP32_RMT_ENABLED
	select DMA if DT_HAS_ESPRESSIF_ESP32_GDMA_ENABLED
	help
	  Enables the ESP32 Remote Control Transceiver driver.

Copy link
Contributor Author

@joelguittet joelguittet Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My comment on this proposition:

  • Renaming the name of the config: ok for me.
  • Why defaulting to y ? We may want to just not include it in general. => EDIT: with default y then we just need to activate rmt in the dts of course :-) I add this one.
  • select DMA should be added later when I will integrate DMA API for sure. However, this is only for ESP32S3 .so an additional condition should be added I guess.

@joelguittet
Copy link
Contributor Author

@fabiobaltieri I see there is a led_strip sample. I can imagine to not commit the sample I have done in this branch, and instead open another pull-request to add a rmt based led-strip driver. So that the current led_strip sample can be reused to demonstrate rmt usage. What do you think?

@wmrsouza your inputs are much appreciated! But I'm not sure to understand your 2 first bullet points. Today I have just followed the esp-idf APIs. RMT is specific to Espressif in any case so I don't see any interest to define a general driver API for that, isn't it ?
By the way, actually there is one thing that maybe do not follow the best practise (you will tell me @kartben please!): the APIs have no "struct device". It will not be used (at least for the moment), so I don't see any interest for this one. Tell me if I'm wrong.
You join the conversation with Fabio just above, a new pull-request for a led strip driver rmt based will be nice yes!

@joelguittet joelguittet force-pushed the feature/espressif-rmt-driver branch from 16c696f to b1249e5 Compare December 23, 2025 22:33
This commit is to be merged with the previous one before merging the PR.

Signed-off-by: Joel Guittet <[email protected]>
The RMT peripheral is added to the existing relevant devices.
A DTS bindings is created to support this peripheral.

Signed-off-by: Joel Guittet <[email protected]>
This commit is to be merged with the previous one before merging the PR.

Signed-off-by: Joel Guittet <[email protected]>
This sample application demonstrates usage of the Espressif RMT driver.

Signed-off-by: Joel Guittet <[email protected]>
This commit is to be merged with the previous one before merging the PR.

Signed-off-by: Joel Guittet <[email protected]>
@joelguittet joelguittet force-pushed the feature/espressif-rmt-driver branch from b1249e5 to de36e05 Compare December 23, 2025 23:38
@sonarqubecloud
Copy link

@wmrsouza
Copy link
Contributor

wmrsouza commented Dec 24, 2025

@joelguittet I think you should follow Zephyr's driver model:

  • driver api even if rmt is restricted to Espressif (config, read, write, ...)
  • struct device for each peripheral instance even if there is only one

in general way you should start with something like this:

#define ESP32_RMT_INIT(idx)                                                             \
                                                                                        \
    PINCTRL_DT_INST_DEFINE(idx);                                                        \
                                                                                        \
    static const DRAM_ATTR struct rmt_esp32_config rmt_esp32_cfg_##idx = {              \
        .hal =  { .dev = (rmt_dev_t *)DT_INST_REG_ADDR(idx),},                          \
        .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx),                                    \
        .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(idx, offset),       \
        .irq_source = DT_INST_IRQ_BY_IDX(idx, 0, irq),                                  \
        .irq_priority = DT_INST_IRQ_BY_IDX(idx, 0, priority),                           \
        .irq_flags = DT_INST_IRQ_BY_IDX(idx, 0, flags),                                 \
        ESP_RMT_DMA_INIT(idx),                                                          \
        .property_0 = DT_INST_PROP(idx, property_0),                                    \
        .property_1 = DT_INST_ENUM_IDX(idx, property_1),                                \
...                                                                                     \
        .property_n = DT_INST_ENUM_IDX(idx, property_n),                                \
};                                                                                      \
                                                                                        \
    static struct rmt_esp32_data rmt_esp32_data_##idx = {                               \
        .rx_config = {0},                                                               \
        .tx_config = {0},                                                               \
...                                                                                     \
        },                                                                              \
    };                                                                                  \
                                                                                        \
    DEVICE_DT_INST_DEFINE(idx, rmt_esp32_init, NULL, &rmt_esp32_data_##idx,             \
                          &rmt_esp32_cfg_##idx, POST_KERNEL,                            \
                          CONFIG_RMT_INIT_PRIORITY, &rmt_esp32_api);

DT_INST_FOREACH_STATUS_OKAY(ESP32_RMT_INIT);

@wmrsouza
Copy link
Contributor

wmrsouza commented Dec 24, 2025

@joelguittet
for instance, you can change hal_espressif revision to pull/510/head in the west.yml manifest so this PR will be take in account the hal_espressif PR while it is not merged

after hal_espressif PR is merged you change west.yml again to make hal_espressif revision point to the merged commit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ESP32/ESP32S3 RMT

6 participants