feat(rmt): introduce RMT_ENCODER_FUNC_ATTR for encoder functions

Closes https://github.com/espressif/esp-idf/issues/15832
This commit is contained in:
morris
2025-04-23 15:37:54 +08:00
parent 182b33efb2
commit ae5f8e550c
19 changed files with 88 additions and 33 deletions

View File

@@ -1,12 +1,16 @@
menu "ESP-Driver:RMT Configurations" menu "ESP-Driver:RMT Configurations"
depends on SOC_RMT_SUPPORTED depends on SOC_RMT_SUPPORTED
config RMT_ENCODER_FUNC_IN_IRAM
bool "Place RMT encoder function in IRAM"
default y
help
Place RMT encoder function into IRAM for better performance and fewer cache misses.
config RMT_TX_ISR_HANDLER_IN_IRAM config RMT_TX_ISR_HANDLER_IN_IRAM
bool "Place RMT TX ISR handler in IRAM to reduce latency" bool "Place RMT TX ISR handler in IRAM to reduce latency"
default y default y
select RMT_OBJ_CACHE_SAFE select RMT_OBJ_CACHE_SAFE
select GDMA_CTRL_FUNC_IN_IRAM if SOC_RMT_SUPPORT_DMA
select BITSCRAMBLER_CTRL_FUNC_IN_IRAM if SOC_BITSCRAMBLER_SUPPORTED && SOC_RMT_SUPPORT_DMA
help help
Place RMT TX ISR handler in IRAM to reduce latency caused by cache miss. Place RMT TX ISR handler in IRAM to reduce latency caused by cache miss.
@@ -21,14 +25,13 @@ menu "ESP-Driver:RMT Configurations"
bool "Place RMT receive function in IRAM" bool "Place RMT receive function in IRAM"
default n default n
select RMT_OBJ_CACHE_SAFE select RMT_OBJ_CACHE_SAFE
select GDMA_CTRL_FUNC_IN_IRAM if SOC_RMT_SUPPORT_DMA
help help
Place RMT receive function into IRAM for better performance and fewer cache misses. Place RMT receive function into IRAM for better performance and fewer cache misses.
config RMT_TX_ISR_CACHE_SAFE config RMT_TX_ISR_CACHE_SAFE
bool "Allow RMT TX ISR to execute when cache is disabled" bool "Allow RMT TX ISR to execute when cache is disabled" if !SPI_FLASH_AUTO_SUSPEND
select RMT_TX_ISR_HANDLER_IN_IRAM select RMT_TX_ISR_HANDLER_IN_IRAM
select GDMA_ISR_HANDLER_IN_IRAM if SOC_RMT_SUPPORT_DMA select RMT_ENCODER_FUNC_IN_IRAM
default n default n
help help
Enable this option to allow the RMT TX Interrupt Service Routine (ISR) Enable this option to allow the RMT TX Interrupt Service Routine (ISR)
@@ -36,9 +39,8 @@ menu "ESP-Driver:RMT Configurations"
might be turned off, but the RMT TX functionality is still required to operate correctly. might be turned off, but the RMT TX functionality is still required to operate correctly.
config RMT_RX_ISR_CACHE_SAFE config RMT_RX_ISR_CACHE_SAFE
bool "Allow RMT RX ISR to execute when cache is disabled" bool "Allow RMT RX ISR to execute when cache is disabled" if !SPI_FLASH_AUTO_SUSPEND
select RMT_RX_ISR_HANDLER_IN_IRAM select RMT_RX_ISR_HANDLER_IN_IRAM
select GDMA_ISR_HANDLER_IN_IRAM if SOC_RMT_SUPPORT_DMA
default n default n
help help
Enable this option to allow the RMT RX Interrupt Service Routine (ISR) Enable this option to allow the RMT RX Interrupt Service Routine (ISR)
@@ -63,7 +65,7 @@ menu "ESP-Driver:RMT Configurations"
Please enable this option by caution, as it will increase the binary size. Please enable this option by caution, as it will increase the binary size.
config RMT_ISR_IRAM_SAFE config RMT_ISR_IRAM_SAFE
bool "RMT ISR IRAM-Safe (Deprecated)" bool "RMT ISR IRAM-Safe (Deprecated)" if !SPI_FLASH_AUTO_SUSPEND
select RMT_TX_ISR_CACHE_SAFE select RMT_TX_ISR_CACHE_SAFE
select RMT_RX_ISR_CACHE_SAFE select RMT_RX_ISR_CACHE_SAFE
default n default n

View File

@@ -7,7 +7,9 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include "sdkconfig.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_attr.h"
#include "hal/rmt_types.h" #include "hal/rmt_types.h"
#include "driver/rmt_types.h" #include "driver/rmt_types.h"
@@ -69,6 +71,12 @@ struct rmt_encoder_t {
esp_err_t (*del)(rmt_encoder_t *encoder); esp_err_t (*del)(rmt_encoder_t *encoder);
}; };
#if CONFIG_RMT_ENCODER_FUNC_IN_IRAM
#define RMT_ENCODER_FUNC_ATTR IRAM_ATTR
#else
#define RMT_ENCODER_FUNC_ATTR
#endif
/** /**
* @brief Callback for simple callback encoder * @brief Callback for simple callback encoder
* *

View File

@@ -8,13 +8,6 @@ entries:
rmt_tx: rmt_tx_do_transaction (noflash) rmt_tx: rmt_tx_do_transaction (noflash)
rmt_tx: rmt_encode_check_result (noflash) rmt_tx: rmt_encode_check_result (noflash)
rmt_tx: rmt_tx_mark_eof (noflash) rmt_tx: rmt_tx_mark_eof (noflash)
rmt_encoder: rmt_encoder_reset (noflash)
rmt_encoder_bytes: rmt_encode_bytes (noflash)
rmt_encoder_bytes: rmt_bytes_encoder_reset (noflash)
rmt_encoder_copy: rmt_encode_copy (noflash)
rmt_encoder_copy: rmt_copy_encoder_reset (noflash)
rmt_encoder_simple: rmt_encode_simple (noflash)
rmt_encoder_simple: rmt_simple_encoder_reset (noflash)
if SOC_RMT_SUPPORT_TX_LOOP_COUNT = y: if SOC_RMT_SUPPORT_TX_LOOP_COUNT = y:
rmt_tx: rmt_isr_handle_tx_loop_end (noflash) rmt_tx: rmt_isr_handle_tx_loop_end (noflash)
@@ -22,9 +15,8 @@ entries:
if SOC_RMT_SUPPORT_DMA = y: if SOC_RMT_SUPPORT_DMA = y:
rmt_tx: rmt_dma_tx_eof_cb (noflash) rmt_tx: rmt_dma_tx_eof_cb (noflash)
if SOC_BITSCRAMBLER_SUPPORTED = y: if RMT_ENCODER_FUNC_IN_IRAM = y:
rmt_encoder_bs: rmt_encode_bs (noflash) rmt_encoder: rmt_encoder_reset (noflash)
rmt_encoder_bs: rmt_bs_encoder_reset (noflash)
if RMT_RX_ISR_HANDLER_IN_IRAM = y: if RMT_RX_ISR_HANDLER_IN_IRAM = y:
rmt_rx: rmt_rx_default_isr (noflash) rmt_rx: rmt_rx_default_isr (noflash)

View File

@@ -14,6 +14,7 @@ typedef struct rmt_bs_encoder_t {
bitscrambler_handle_t bs; // BitScrambler handle bitscrambler_handle_t bs; // BitScrambler handle
} rmt_bs_encoder_t; } rmt_bs_encoder_t;
RMT_ENCODER_FUNC_ATTR
static esp_err_t rmt_bs_encoder_reset(rmt_encoder_t *encoder) static esp_err_t rmt_bs_encoder_reset(rmt_encoder_t *encoder)
{ {
rmt_bs_encoder_t *bs_encoder = __containerof(encoder, rmt_bs_encoder_t, base); rmt_bs_encoder_t *bs_encoder = __containerof(encoder, rmt_bs_encoder_t, base);
@@ -23,14 +24,7 @@ static esp_err_t rmt_bs_encoder_reset(rmt_encoder_t *encoder)
return ESP_OK; return ESP_OK;
} }
static esp_err_t rmt_del_bs_encoder(rmt_encoder_t *encoder) RMT_ENCODER_FUNC_ATTR
{
rmt_bs_encoder_t *bs_encoder = __containerof(encoder, rmt_bs_encoder_t, base);
bitscrambler_free(bs_encoder->bs);
free(bs_encoder);
return ESP_OK;
}
static size_t rmt_encode_bs(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *input_raw, static size_t rmt_encode_bs(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *input_raw,
size_t data_size, rmt_encode_state_t *ret_state) size_t data_size, rmt_encode_state_t *ret_state)
{ {
@@ -109,11 +103,24 @@ static size_t rmt_encode_bs(rmt_encoder_t *encoder, rmt_channel_handle_t channel
return copy_len; return copy_len;
} }
static esp_err_t rmt_del_bs_encoder(rmt_encoder_t *encoder)
{
rmt_bs_encoder_t *bs_encoder = __containerof(encoder, rmt_bs_encoder_t, base);
bitscrambler_free(bs_encoder->bs);
free(bs_encoder);
return ESP_OK;
}
esp_err_t rmt_new_bitscrambler_encoder(const rmt_bs_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder) esp_err_t rmt_new_bitscrambler_encoder(const rmt_bs_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder)
{ {
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
rmt_bs_encoder_t *encoder = NULL; rmt_bs_encoder_t *encoder = NULL;
ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); ESP_RETURN_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
// bitscrambler function is used under RMT TX ISR context
// if the cache is disabled, all functions called by ISR must be in IRAM
#if CONFIG_RMT_TX_ISR_CACHE_SAFE && !CONFIG_BITSCRAMBLER_CTRL_FUNC_IN_IRAM
ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_STATE, TAG, "CONFIG_BITSCRAMBLER_CTRL_FUNC_IN_IRAM must be enabled");
#endif
encoder = rmt_alloc_encoder_mem(sizeof(rmt_bs_encoder_t)); encoder = rmt_alloc_encoder_mem(sizeof(rmt_bs_encoder_t));
ESP_GOTO_ON_FALSE(encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for bitscrambler encoder"); ESP_GOTO_ON_FALSE(encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for bitscrambler encoder");

View File

@@ -18,6 +18,7 @@ typedef struct rmt_bytes_encoder_t {
} flags; } flags;
} rmt_bytes_encoder_t; } rmt_bytes_encoder_t;
RMT_ENCODER_FUNC_ATTR
static esp_err_t rmt_bytes_encoder_reset(rmt_encoder_t *encoder) static esp_err_t rmt_bytes_encoder_reset(rmt_encoder_t *encoder)
{ {
rmt_bytes_encoder_t *bytes_encoder = __containerof(encoder, rmt_bytes_encoder_t, base); rmt_bytes_encoder_t *bytes_encoder = __containerof(encoder, rmt_bytes_encoder_t, base);
@@ -27,6 +28,7 @@ static esp_err_t rmt_bytes_encoder_reset(rmt_encoder_t *encoder)
return ESP_OK; return ESP_OK;
} }
RMT_ENCODER_FUNC_ATTR
static size_t rmt_encode_bytes(rmt_encoder_t *encoder, rmt_channel_handle_t channel, static size_t rmt_encode_bytes(rmt_encoder_t *encoder, rmt_channel_handle_t channel,
const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
{ {

View File

@@ -12,6 +12,7 @@ typedef struct rmt_copy_encoder_t {
size_t last_symbol_index; // index of symbol position in the primary stream size_t last_symbol_index; // index of symbol position in the primary stream
} rmt_copy_encoder_t; } rmt_copy_encoder_t;
RMT_ENCODER_FUNC_ATTR
static esp_err_t rmt_copy_encoder_reset(rmt_encoder_t *encoder) static esp_err_t rmt_copy_encoder_reset(rmt_encoder_t *encoder)
{ {
rmt_copy_encoder_t *copy_encoder = __containerof(encoder, rmt_copy_encoder_t, base); rmt_copy_encoder_t *copy_encoder = __containerof(encoder, rmt_copy_encoder_t, base);
@@ -19,6 +20,7 @@ static esp_err_t rmt_copy_encoder_reset(rmt_encoder_t *encoder)
return ESP_OK; return ESP_OK;
} }
RMT_ENCODER_FUNC_ATTR
static size_t rmt_encode_copy(rmt_encoder_t *encoder, rmt_channel_handle_t channel, static size_t rmt_encode_copy(rmt_encoder_t *encoder, rmt_channel_handle_t channel,
const void *input_symbols, size_t data_size, rmt_encode_state_t *ret_state) const void *input_symbols, size_t data_size, rmt_encode_state_t *ret_state)
{ {

View File

@@ -19,6 +19,7 @@ typedef struct rmt_simple_encoder_t {
bool callback_done; //true if we can't call the callback for more data anymore. bool callback_done; //true if we can't call the callback for more data anymore.
} rmt_simple_encoder_t; } rmt_simple_encoder_t;
RMT_ENCODER_FUNC_ATTR
static esp_err_t rmt_simple_encoder_reset(rmt_encoder_t *encoder) static esp_err_t rmt_simple_encoder_reset(rmt_encoder_t *encoder)
{ {
rmt_simple_encoder_t *simple_encoder = __containerof(encoder, rmt_simple_encoder_t, base); rmt_simple_encoder_t *simple_encoder = __containerof(encoder, rmt_simple_encoder_t, base);
@@ -29,6 +30,7 @@ static esp_err_t rmt_simple_encoder_reset(rmt_encoder_t *encoder)
return ESP_OK; return ESP_OK;
} }
RMT_ENCODER_FUNC_ATTR
static size_t rmt_encode_simple(rmt_encoder_t *encoder, rmt_channel_handle_t channel, static size_t rmt_encode_simple(rmt_encoder_t *encoder, rmt_channel_handle_t channel,
const void *data, size_t data_size, rmt_encode_state_t *ret_state) const void *data, size_t data_size, rmt_encode_state_t *ret_state)
{ {

View File

@@ -180,7 +180,13 @@ esp_err_t rmt_new_rx_channel(const rmt_rx_channel_config_t *config, rmt_channel_
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(config->gpio_num), ESP_ERR_INVALID_ARG, TAG, "invalid GPIO number %d", config->gpio_num); ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(config->gpio_num), ESP_ERR_INVALID_ARG, TAG, "invalid GPIO number %d", config->gpio_num);
ESP_RETURN_ON_FALSE((config->mem_block_symbols & 0x01) == 0 && config->mem_block_symbols >= SOC_RMT_MEM_WORDS_PER_CHANNEL, ESP_RETURN_ON_FALSE((config->mem_block_symbols & 0x01) == 0 && config->mem_block_symbols >= SOC_RMT_MEM_WORDS_PER_CHANNEL,
ESP_ERR_INVALID_ARG, TAG, "mem_block_symbols must be even and at least %d", SOC_RMT_MEM_WORDS_PER_CHANNEL); ESP_ERR_INVALID_ARG, TAG, "mem_block_symbols must be even and at least %d", SOC_RMT_MEM_WORDS_PER_CHANNEL);
#if !SOC_RMT_SUPPORT_DMA #if SOC_RMT_SUPPORT_DMA
if (config->flags.with_dma) {
#if CONFIG_RMT_RX_ISR_CACHE_SAFE && (!CONFIG_GDMA_ISR_HANDLER_IN_IRAM || !CONFIG_GDMA_CTRL_FUNC_IN_IRAM)
ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_STATE, TAG, "CONFIG_GDMA_ISR_HANDLER_IN_IRAM and CONFIG_GDMA_CTRL_FUNC_IN_IRAM must be enabled");
#endif
}
#else
ESP_RETURN_ON_FALSE(config->flags.with_dma == 0, ESP_ERR_NOT_SUPPORTED, TAG, "DMA not supported"); ESP_RETURN_ON_FALSE(config->flags.with_dma == 0, ESP_ERR_NOT_SUPPORTED, TAG, "DMA not supported");
#endif // SOC_RMT_SUPPORT_DMA #endif // SOC_RMT_SUPPORT_DMA

View File

@@ -243,7 +243,13 @@ esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(config->gpio_num), ESP_ERR_INVALID_ARG, TAG, "invalid GPIO number %d", config->gpio_num); ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(config->gpio_num), ESP_ERR_INVALID_ARG, TAG, "invalid GPIO number %d", config->gpio_num);
ESP_RETURN_ON_FALSE((config->mem_block_symbols & 0x01) == 0 && config->mem_block_symbols >= SOC_RMT_MEM_WORDS_PER_CHANNEL, ESP_RETURN_ON_FALSE((config->mem_block_symbols & 0x01) == 0 && config->mem_block_symbols >= SOC_RMT_MEM_WORDS_PER_CHANNEL,
ESP_ERR_INVALID_ARG, TAG, "mem_block_symbols must be even and at least %d", SOC_RMT_MEM_WORDS_PER_CHANNEL); ESP_ERR_INVALID_ARG, TAG, "mem_block_symbols must be even and at least %d", SOC_RMT_MEM_WORDS_PER_CHANNEL);
#if !SOC_RMT_SUPPORT_DMA #if SOC_RMT_SUPPORT_DMA
if (config->flags.with_dma) {
#if CONFIG_RMT_TX_ISR_CACHE_SAFE && (!CONFIG_GDMA_ISR_HANDLER_IN_IRAM || !CONFIG_GDMA_CTRL_FUNC_IN_IRAM)
ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_STATE, TAG, "CONFIG_GDMA_ISR_HANDLER_IN_IRAM and CONFIG_GDMA_CTRL_FUNC_IN_IRAM must be enabled");
#endif
}
#else
ESP_RETURN_ON_FALSE(config->flags.with_dma == 0, ESP_ERR_NOT_SUPPORTED, TAG, "DMA not supported"); ESP_RETURN_ON_FALSE(config->flags.with_dma == 0, ESP_ERR_NOT_SUPPORTED, TAG, "DMA not supported");
#endif #endif

View File

@@ -97,6 +97,13 @@ TEST_CASE("rmt TX with bitscrambler", "[rmt]")
}, 5, &transmit_config)); }, 5, &transmit_config));
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000))); TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000)));
TEST_ESP_OK(rmt_receive(rx_channel, symbols, sizeof(symbols), &receive_config));
printf("transmit again!\r\n");
TEST_ESP_OK(rmt_transmit(tx_channel, bs_encoder, (uint8_t[]) {
0x12, 0x34, 0x56, 0x78, 0x9a, // dummy test values, will be further processed by bitscrambler program
}, 5, &transmit_config));
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000)));
printf("disable tx+rx channel\r\n"); printf("disable tx+rx channel\r\n");
TEST_ESP_OK(rmt_disable(tx_channel)); TEST_ESP_OK(rmt_disable(tx_channel));
TEST_ESP_OK(rmt_disable(rx_channel)); TEST_ESP_OK(rmt_disable(rx_channel));

View File

@@ -20,7 +20,8 @@ typedef struct {
rmt_symbol_word_t reset_code; rmt_symbol_word_t reset_code;
} rmt_led_strip_encoder_t; } rmt_led_strip_encoder_t;
IRAM_ATTR static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) RMT_ENCODER_FUNC_ATTR
static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
{ {
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
rmt_encode_state_t session_state = RMT_ENCODING_RESET; rmt_encode_state_t session_state = RMT_ENCODING_RESET;
@@ -62,7 +63,8 @@ static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder)
return ESP_OK; return ESP_OK;
} }
IRAM_ATTR static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder) RMT_ENCODER_FUNC_ATTR
static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder)
{ {
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
rmt_encoder_reset(led_encoder->bytes_encoder); rmt_encoder_reset(led_encoder->bytes_encoder);
@@ -113,7 +115,8 @@ typedef struct {
int state; int state;
} rmt_nec_protocol_encoder_t; } rmt_nec_protocol_encoder_t;
IRAM_ATTR static size_t rmt_encode_nec_protocol(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) RMT_ENCODER_FUNC_ATTR
static size_t rmt_encode_nec_protocol(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
{ {
rmt_nec_protocol_encoder_t *nec_encoder = __containerof(encoder, rmt_nec_protocol_encoder_t, base); rmt_nec_protocol_encoder_t *nec_encoder = __containerof(encoder, rmt_nec_protocol_encoder_t, base);
rmt_encode_state_t session_state = RMT_ENCODING_RESET; rmt_encode_state_t session_state = RMT_ENCODING_RESET;
@@ -177,7 +180,8 @@ static esp_err_t rmt_del_nec_protocol_encoder(rmt_encoder_t *encoder)
return ESP_OK; return ESP_OK;
} }
IRAM_ATTR static esp_err_t rmt_nec_protocol_encoder_reset(rmt_encoder_t *encoder) RMT_ENCODER_FUNC_ATTR
static esp_err_t rmt_nec_protocol_encoder_reset(rmt_encoder_t *encoder)
{ {
rmt_nec_protocol_encoder_t *nec_encoder = __containerof(encoder, rmt_nec_protocol_encoder_t, base); rmt_nec_protocol_encoder_t *nec_encoder = __containerof(encoder, rmt_nec_protocol_encoder_t, base);
rmt_encoder_reset(nec_encoder->copy_encoder); rmt_encoder_reset(nec_encoder->copy_encoder);

View File

@@ -3,6 +3,9 @@ CONFIG_RMT_TX_ISR_CACHE_SAFE=y
CONFIG_RMT_RX_ISR_CACHE_SAFE=y CONFIG_RMT_RX_ISR_CACHE_SAFE=y
CONFIG_RMT_RECV_FUNC_IN_IRAM=y CONFIG_RMT_RECV_FUNC_IN_IRAM=y
CONFIG_GPIO_CTRL_FUNC_IN_IRAM=y CONFIG_GPIO_CTRL_FUNC_IN_IRAM=y
CONFIG_BITSCRAMBLER_CTRL_FUNC_IN_IRAM=y
CONFIG_GDMA_ISR_HANDLER_IN_IRAM=y
CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y
CONFIG_COMPILER_OPTIMIZATION_NONE=y CONFIG_COMPILER_OPTIMIZATION_NONE=y
# place non-ISR FreeRTOS functions in Flash # place non-ISR FreeRTOS functions in Flash
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y

View File

@@ -589,6 +589,8 @@ There is a Kconfig option :ref:`CONFIG_RMT_TX_ISR_CACHE_SAFE` and :ref:`CONFIG_R
This Kconfig option allows the interrupt handler to run while the cache is disabled but comes at the cost of increased IRAM consumption. This Kconfig option allows the interrupt handler to run while the cache is disabled but comes at the cost of increased IRAM consumption.
Please note, when :ref:`CONFIG_RMT_TX_ISR_CACHE_SAFE` is enabled, you must also place the encoder functions (mainly the :cpp:member:`rmt_encoder_t::encode` and :cpp:member:`rmt_encoder_t::reset`) into IRAM. You can use :c:macro:`RMT_ENCODER_FUNC_ATTR` to decorate your encoder functions.
Another Kconfig option :ref:`CONFIG_RMT_RECV_FUNC_IN_IRAM` can place :cpp:func:`rmt_receive` into the IRAM as well. So that the receive function can be used even when the flash cache is disabled. Another Kconfig option :ref:`CONFIG_RMT_RECV_FUNC_IN_IRAM` can place :cpp:func:`rmt_receive` into the IRAM as well. So that the receive function can be used even when the flash cache is disabled.
.. _rmt-thread-safety: .. _rmt-thread-safety:

View File

@@ -589,6 +589,8 @@ Cache 安全
启用该选项可以保证 cache 禁用时的中断运行,但会相应增加 IRAM 占用。 启用该选项可以保证 cache 禁用时的中断运行,但会相应增加 IRAM 占用。
请注意,当 :ref:`CONFIG_RMT_TX_ISR_CACHE_SAFE` 使能后,你必须将编码器函数 (主要是 :cpp:member:`rmt_encoder_t::encode`:cpp:member:`rmt_encoder_t::reset`) 放进 IRAM 中。建议你使用 :c:macro:`RMT_ENCODER_FUNC_ATTR` 来装饰你的编码器函数。
另外一个 Kconfig 选项 :ref:`CONFIG_RMT_RECV_FUNC_IN_IRAM` 可以将 :cpp:func:`rmt_receive` 函数放进内部的 IRAM 中,从而当 flash cache 被关闭的时候,这个函数也能够被使用。 另外一个 Kconfig 选项 :ref:`CONFIG_RMT_RECV_FUNC_IN_IRAM` 可以将 :cpp:func:`rmt_receive` 函数放进内部的 IRAM 中,从而当 flash cache 被关闭的时候,这个函数也能够被使用。
.. _rmt-thread-safety: .. _rmt-thread-safety:

View File

@@ -45,6 +45,7 @@ static void make_dshot_frame(dshot_esc_frame_t *frame, uint16_t throttle, bool t
frame->val = ((val & 0xFF) << 8) | ((val & 0xFF00) >> 8); frame->val = ((val & 0xFF) << 8) | ((val & 0xFF00) >> 8);
} }
RMT_ENCODER_FUNC_ATTR
static size_t rmt_encode_dshot_esc(rmt_encoder_t *encoder, rmt_channel_handle_t channel, static size_t rmt_encode_dshot_esc(rmt_encoder_t *encoder, rmt_channel_handle_t channel,
const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
{ {
@@ -97,6 +98,7 @@ static esp_err_t rmt_del_dshot_encoder(rmt_encoder_t *encoder)
return ESP_OK; return ESP_OK;
} }
RMT_ENCODER_FUNC_ATTR
static esp_err_t rmt_dshot_encoder_reset(rmt_encoder_t *encoder) static esp_err_t rmt_dshot_encoder_reset(rmt_encoder_t *encoder)
{ {
rmt_dshot_esc_encoder_t *dshot_encoder = __containerof(encoder, rmt_dshot_esc_encoder_t, base); rmt_dshot_esc_encoder_t *dshot_encoder = __containerof(encoder, rmt_dshot_esc_encoder_t, base);

View File

@@ -18,6 +18,7 @@ typedef struct {
int state; int state;
} rmt_ir_nec_encoder_t; } rmt_ir_nec_encoder_t;
RMT_ENCODER_FUNC_ATTR
static size_t rmt_encode_ir_nec(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) static size_t rmt_encode_ir_nec(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
{ {
rmt_ir_nec_encoder_t *nec_encoder = __containerof(encoder, rmt_ir_nec_encoder_t, base); rmt_ir_nec_encoder_t *nec_encoder = __containerof(encoder, rmt_ir_nec_encoder_t, base);
@@ -85,6 +86,7 @@ static esp_err_t rmt_del_ir_nec_encoder(rmt_encoder_t *encoder)
return ESP_OK; return ESP_OK;
} }
RMT_ENCODER_FUNC_ATTR
static esp_err_t rmt_ir_nec_encoder_reset(rmt_encoder_t *encoder) static esp_err_t rmt_ir_nec_encoder_reset(rmt_encoder_t *encoder)
{ {
rmt_ir_nec_encoder_t *nec_encoder = __containerof(encoder, rmt_ir_nec_encoder_t, base); rmt_ir_nec_encoder_t *nec_encoder = __containerof(encoder, rmt_ir_nec_encoder_t, base);

View File

@@ -17,6 +17,7 @@ typedef struct {
rmt_symbol_word_t reset_code; rmt_symbol_word_t reset_code;
} rmt_led_strip_encoder_t; } rmt_led_strip_encoder_t;
RMT_ENCODER_FUNC_ATTR
static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
{ {
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
@@ -62,6 +63,7 @@ static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder)
return ESP_OK; return ESP_OK;
} }
RMT_ENCODER_FUNC_ATTR
static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder) static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder)
{ {
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);

View File

@@ -15,6 +15,7 @@ typedef struct {
uint32_t resolution; uint32_t resolution;
} rmt_musical_score_encoder_t; } rmt_musical_score_encoder_t;
RMT_ENCODER_FUNC_ATTR
static size_t rmt_encode_musical_score(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) static size_t rmt_encode_musical_score(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
{ {
rmt_musical_score_encoder_t *score_encoder = __containerof(encoder, rmt_musical_score_encoder_t, base); rmt_musical_score_encoder_t *score_encoder = __containerof(encoder, rmt_musical_score_encoder_t, base);
@@ -41,6 +42,7 @@ static esp_err_t rmt_del_musical_score_encoder(rmt_encoder_t *encoder)
return ESP_OK; return ESP_OK;
} }
RMT_ENCODER_FUNC_ATTR
static esp_err_t rmt_musical_score_encoder_reset(rmt_encoder_t *encoder) static esp_err_t rmt_musical_score_encoder_reset(rmt_encoder_t *encoder)
{ {
rmt_musical_score_encoder_t *score_encoder = __containerof(encoder, rmt_musical_score_encoder_t, base); rmt_musical_score_encoder_t *score_encoder = __containerof(encoder, rmt_musical_score_encoder_t, base);

View File

@@ -27,6 +27,7 @@ typedef struct {
rmt_symbol_word_t curve_table[]; rmt_symbol_word_t curve_table[];
} rmt_stepper_curve_encoder_t; } rmt_stepper_curve_encoder_t;
RMT_ENCODER_FUNC_ATTR
static size_t rmt_encode_stepper_motor_curve(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) static size_t rmt_encode_stepper_motor_curve(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
{ {
rmt_stepper_curve_encoder_t *motor_encoder = __containerof(encoder, rmt_stepper_curve_encoder_t, base); rmt_stepper_curve_encoder_t *motor_encoder = __containerof(encoder, rmt_stepper_curve_encoder_t, base);
@@ -53,6 +54,7 @@ static esp_err_t rmt_del_stepper_motor_curve_encoder(rmt_encoder_t *encoder)
return ESP_OK; return ESP_OK;
} }
RMT_ENCODER_FUNC_ATTR
static esp_err_t rmt_reset_stepper_motor_curve_encoder(rmt_encoder_t *encoder) static esp_err_t rmt_reset_stepper_motor_curve_encoder(rmt_encoder_t *encoder)
{ {
rmt_stepper_curve_encoder_t *motor_encoder = __containerof(encoder, rmt_stepper_curve_encoder_t, base); rmt_stepper_curve_encoder_t *motor_encoder = __containerof(encoder, rmt_stepper_curve_encoder_t, base);