feat(rmt): support calling rmt_receive in ISR callback

pull/13022/head
morris 2023-11-02 11:39:29 +08:00
rodzic d260d43168
commit bfeae3857c
15 zmienionych plików z 101 dodań i 36 usunięć

Wyświetl plik

@ -352,6 +352,15 @@ menu "Driver Configurations"
Ensure the RMT interrupt is IRAM-Safe by allowing the interrupt handler to be
executable when the cache is disabled (e.g. SPI Flash write).
config RMT_RECV_FUNC_IN_IRAM
bool "Place RMT receive function into IRAM"
default n
select GDMA_CTRL_FUNC_IN_IRAM if SOC_RMT_SUPPORT_DMA # RMT needs to start the GDMA in the receive function
help
Place RMT receive function into IRAM,
so that the receive function can be IRAM-safe and able to be called when the flash cache is disabled.
Enabling this option can improve driver performance as well.
config RMT_SUPPRESS_DEPRECATE_WARN
bool "Suppress legacy driver deprecated warning"
default n

Wyświetl plik

@ -21,3 +21,7 @@ entries:
if MCPWM_CTRL_FUNC_IN_IRAM = y:
mcpwm_cmpr: mcpwm_comparator_set_compare_value (noflash)
mcpwm_timer: mcpwm_timer_set_period (noflash)
if RMT_RECV_FUNC_IN_IRAM = y:
rmt_rx: rmt_receive (noflash)
if SOC_RMT_SUPPORT_DMA = y:
rmt_rx: rmt_rx_mount_dma_buffer (noflash)

Wyświetl plik

@ -72,6 +72,8 @@ esp_err_t rmt_new_rx_channel(const rmt_rx_channel_config_t *config, rmt_channel_
*
* @note This function is non-blocking, it initiates a new receive job and then returns.
* User should check the received data from the `on_recv_done` callback that registered by `rmt_rx_register_event_callbacks()`.
* @note This function can also be called in ISR context.
* @note If you want this function to work even when the flash cache is disabled, please enable the `CONFIG_RMT_RECV_FUNC_IN_IRAM` option.
*
* @param[in] rx_channel RMT RX channel that created by `rmt_new_rx_channel()`
* @param[in] buffer The buffer to store the received RMT symbols

Wyświetl plik

@ -27,7 +27,7 @@
extern "C" {
#endif
#if CONFIG_RMT_ISR_IRAM_SAFE
#if CONFIG_RMT_ISR_IRAM_SAFE || CONFIG_RMT_RECV_FUNC_IN_IRAM
#define RMT_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define RMT_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT

Wyświetl plik

@ -342,16 +342,16 @@ esp_err_t rmt_rx_register_event_callbacks(rmt_channel_handle_t channel, const rm
esp_err_t rmt_receive(rmt_channel_handle_t channel, void *buffer, size_t buffer_size, const rmt_receive_config_t *config)
{
ESP_RETURN_ON_FALSE(channel && buffer && buffer_size && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(channel->direction == RMT_CHANNEL_DIRECTION_RX, ESP_ERR_INVALID_ARG, TAG, "invalid channel direction");
ESP_RETURN_ON_FALSE_ISR(channel && buffer && buffer_size && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE_ISR(channel->direction == RMT_CHANNEL_DIRECTION_RX, ESP_ERR_INVALID_ARG, TAG, "invalid channel direction");
rmt_rx_channel_t *rx_chan = __containerof(channel, rmt_rx_channel_t, base);
if (channel->dma_chan) {
ESP_RETURN_ON_FALSE(esp_ptr_internal(buffer), ESP_ERR_INVALID_ARG, TAG, "buffer must locate in internal RAM for DMA use");
ESP_RETURN_ON_FALSE_ISR(esp_ptr_internal(buffer), ESP_ERR_INVALID_ARG, TAG, "buffer must locate in internal RAM for DMA use");
}
if (channel->dma_chan) {
ESP_RETURN_ON_FALSE(buffer_size <= rx_chan->num_dma_nodes * RMT_DMA_DESC_BUF_MAX_SIZE,
ESP_ERR_INVALID_ARG, TAG, "buffer size exceeds DMA capacity");
ESP_RETURN_ON_FALSE_ISR(buffer_size <= rx_chan->num_dma_nodes * RMT_DMA_DESC_BUF_MAX_SIZE,
ESP_ERR_INVALID_ARG, TAG, "buffer size exceeds DMA capacity");
}
rmt_group_t *group = channel->group;
rmt_hal_context_t *hal = &group->hal;
@ -359,13 +359,13 @@ esp_err_t rmt_receive(rmt_channel_handle_t channel, void *buffer, size_t buffer_
uint32_t filter_reg_value = ((uint64_t)group->resolution_hz * config->signal_range_min_ns) / 1000000000UL;
uint32_t idle_reg_value = ((uint64_t)channel->resolution_hz * config->signal_range_max_ns) / 1000000000UL;
ESP_RETURN_ON_FALSE(filter_reg_value <= RMT_LL_MAX_FILTER_VALUE, ESP_ERR_INVALID_ARG, TAG, "signal_range_min_ns too big");
ESP_RETURN_ON_FALSE(idle_reg_value <= RMT_LL_MAX_IDLE_VALUE, ESP_ERR_INVALID_ARG, TAG, "signal_range_max_ns too big");
ESP_RETURN_ON_FALSE_ISR(filter_reg_value <= RMT_LL_MAX_FILTER_VALUE, ESP_ERR_INVALID_ARG, TAG, "signal_range_min_ns too big");
ESP_RETURN_ON_FALSE_ISR(idle_reg_value <= RMT_LL_MAX_IDLE_VALUE, ESP_ERR_INVALID_ARG, TAG, "signal_range_max_ns too big");
// check if we're in a proper state to start the receiver
rmt_fsm_t expected_fsm = RMT_FSM_ENABLE;
ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&channel->fsm, &expected_fsm, RMT_FSM_RUN_WAIT),
ESP_ERR_INVALID_STATE, TAG, "channel not in enable state");
ESP_RETURN_ON_FALSE_ISR(atomic_compare_exchange_strong(&channel->fsm, &expected_fsm, RMT_FSM_RUN_WAIT),
ESP_ERR_INVALID_STATE, TAG, "channel not in enable state");
// fill in the transaction descriptor
rmt_rx_trans_desc_t *t = &rx_chan->trans_desc;
@ -383,7 +383,7 @@ esp_err_t rmt_receive(rmt_channel_handle_t channel, void *buffer, size_t buffer_
}
rx_chan->mem_off = 0;
portENTER_CRITICAL(&channel->spinlock);
portENTER_CRITICAL_SAFE(&channel->spinlock);
// reset memory writer offset
rmt_ll_rx_reset_pointer(hal->regs, channel_id);
rmt_ll_rx_set_mem_owner(hal->regs, channel_id, RMT_LL_MEM_OWNER_HW);
@ -393,7 +393,7 @@ esp_err_t rmt_receive(rmt_channel_handle_t channel, void *buffer, size_t buffer_
rmt_ll_rx_set_idle_thres(hal->regs, channel_id, idle_reg_value);
// turn on RMT RX machine
rmt_ll_rx_enable(hal->regs, channel_id, true);
portEXIT_CRITICAL(&channel->spinlock);
portEXIT_CRITICAL_SAFE(&channel->spinlock);
// saying we're in running state, this state will last until the receiving is done
// i.e., we will switch back to the enable state in the receive done interrupt handler
@ -577,6 +577,9 @@ static bool IRAM_ATTR rmt_isr_handle_rx_done(rmt_rx_channel_t *rx_chan)
}
trans_desc->copy_dest_off += copy_size;
trans_desc->received_symbol_num += copy_size / sizeof(rmt_symbol_word_t);
// switch back to the enable state, then user can call `rmt_receive` to start a new receive
atomic_store(&channel->fsm, RMT_FSM_ENABLE);
// notify the user with receive RMT symbols
if (rx_chan->on_recv_done) {
rmt_rx_done_event_data_t edata = {
@ -587,8 +590,6 @@ static bool IRAM_ATTR rmt_isr_handle_rx_done(rmt_rx_channel_t *rx_chan)
need_yield = true;
}
}
// switch back to the enable state, then user can call `rmt_receive` to start a new receive
atomic_store(&channel->fsm, RMT_FSM_ENABLE);
return need_yield;
}
@ -683,6 +684,9 @@ static bool IRAM_ATTR rmt_dma_rx_eof_cb(gdma_channel_handle_t dma_chan, gdma_eve
rmt_ll_rx_enable(hal->regs, channel_id, false);
portEXIT_CRITICAL_ISR(&channel->spinlock);
// switch back to the enable state, then user can call `rmt_receive` to start a new receive
atomic_store(&channel->fsm, RMT_FSM_ENABLE);
if (rx_chan->on_recv_done) {
rmt_rx_done_event_data_t edata = {
.received_symbols = trans_desc->buffer,
@ -692,8 +696,7 @@ static bool IRAM_ATTR rmt_dma_rx_eof_cb(gdma_channel_handle_t dma_chan, gdma_eve
need_yield = true;
}
}
// switch back to the enable state, then user can call `rmt_receive` to start a new receive
atomic_store(&channel->fsm, RMT_FSM_ENABLE);
return need_yield;
}
#endif // SOC_RMT_SUPPORT_DMA

Wyświetl plik

@ -90,22 +90,27 @@ TEST_CASE("rmt_tx_iram_safe_with_dma", "[rmt]")
}
#endif
#define TEST_RMT_SYMBOLS 2
static void IRAM_ATTR test_simulate_input_post_cache_disable(void *args)
{
int gpio_num = (int)args;
// simulate input signal, should only be recognized as one RMT symbol
gpio_set_level(gpio_num, 0);
esp_rom_delay_us(50);
gpio_set_level(gpio_num, 1);
esp_rom_delay_us(50);
gpio_set_level(gpio_num, 0);
esp_rom_delay_us(20000);
// simulate input signal, should only be recognized as two RMT symbols
for (int i = 0; i < TEST_RMT_SYMBOLS; i++) {
gpio_set_level(gpio_num, 0);
esp_rom_delay_us(50);
gpio_set_level(gpio_num, 1);
esp_rom_delay_us(50);
gpio_set_level(gpio_num, 0);
esp_rom_delay_us(20000);
}
}
typedef struct {
TaskHandle_t task_to_notify;
size_t received_symbol_num;
rmt_receive_config_t rx_config;
rmt_symbol_word_t remote_codes[128];
} test_nec_rx_user_data_t;
IRAM_ATTR
@ -113,8 +118,15 @@ static bool test_rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx
{
BaseType_t high_task_wakeup = pdFALSE;
test_nec_rx_user_data_t *test_user_data = (test_nec_rx_user_data_t *)user_data;
test_user_data->received_symbol_num = edata->num_symbols;
vTaskNotifyGiveFromISR(test_user_data->task_to_notify, &high_task_wakeup);
test_user_data->received_symbol_num += edata->num_symbols;
// should receive one RMT symbol at a time
if (edata->num_symbols == 1) {
if (test_user_data->received_symbol_num == TEST_RMT_SYMBOLS) {
vTaskNotifyGiveFromISR(test_user_data->task_to_notify, &high_task_wakeup);
} else {
rmt_receive(channel, test_user_data->remote_codes, sizeof(test_user_data->remote_codes), &test_user_data->rx_config);
}
}
return high_task_wakeup == pdTRUE;
}
@ -141,27 +153,25 @@ static void test_rmt_rx_iram_safe(size_t mem_block_symbols, bool with_dma, rmt_c
};
test_nec_rx_user_data_t test_user_data = {
.task_to_notify = xTaskGetCurrentTaskHandle(),
.received_symbol_num = 0,
.rx_config = {
.signal_range_min_ns = 1250,
.signal_range_max_ns = 12000000,
},
};
TEST_ESP_OK(rmt_rx_register_event_callbacks(rx_channel, &cbs, &test_user_data));
printf("enable rx channel\r\n");
TEST_ESP_OK(rmt_enable(rx_channel));
rmt_symbol_word_t remote_codes[128];
rmt_receive_config_t receive_config = {
.signal_range_min_ns = 1250,
.signal_range_max_ns = 12000000,
};
// ready to receive
TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, sizeof(remote_codes), &receive_config));
TEST_ESP_OK(rmt_receive(rx_channel, test_user_data.remote_codes, sizeof(test_user_data.remote_codes), &test_user_data.rx_config));
// disable the flash cache, and simulate input signal by GPIO
unity_utils_run_cache_disable_stub(test_simulate_input_post_cache_disable, 0);
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000)));
TEST_ASSERT_EQUAL(1, test_user_data.received_symbol_num);
TEST_ASSERT_EQUAL(TEST_RMT_SYMBOLS, test_user_data.received_symbol_num);
printf("disable rx channels\r\n");
TEST_ESP_OK(rmt_disable(rx_channel));

Wyświetl plik

@ -1,5 +1,6 @@
CONFIG_COMPILER_DUMP_RTL_FILES=y
CONFIG_RMT_ISR_IRAM_SAFE=y
CONFIG_RMT_RECV_FUNC_IN_IRAM=y
CONFIG_GPIO_CTRL_FUNC_IN_IRAM=y
CONFIG_COMPILER_OPTIMIZATION_NONE=y
# place non-ISR FreeRTOS functions in Flash

Wyświetl plik

@ -368,6 +368,7 @@ static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, ui
* @param channel RMT RX channel number
* @param thres Time length threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, idle_thres, thres);
@ -393,6 +394,7 @@ static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, rmt
* @param channel RMT RX chanenl number
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.rx_filter_en = enable;
@ -405,6 +407,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo
* @param channel RMT RX channel number
* @param thres Filter threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf1, rx_filter_thres, thres);

Wyświetl plik

@ -438,6 +438,7 @@ static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t chan
* @param dev Peripheral instance address
* @param channel RMT RX channel number
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->rx_conf[channel].conf1.mem_wr_rst = 1;
@ -480,6 +481,7 @@ static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, ui
* @param channel RMT RX channel number
* @param thres Time length threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->rx_conf[channel].conf0.idle_thres = thres;
@ -505,6 +507,7 @@ static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, rmt
* @param channel RMT RX chanenl number
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->rx_conf[channel].conf1.rx_filter_en = enable;
@ -517,6 +520,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo
* @param channel RMT RX channel number
* @param thres Filter threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_conf[channel].conf1, rx_filter_thres, thres);

Wyświetl plik

@ -453,6 +453,7 @@ static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t chan
* @param dev Peripheral instance address
* @param channel RMT RX channel number
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->chmconf[channel].conf1.mem_wr_rst_chm = 1;
@ -495,6 +496,7 @@ static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, ui
* @param channel RMT RX channel number
* @param thres Time length threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->chmconf[channel].conf0.idle_thres_chm = thres;
@ -520,6 +522,7 @@ static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, rmt
* @param channel RMT RX chanenl number
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chmconf[channel].conf1.rx_filter_en_chm = enable;
@ -532,6 +535,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo
* @param channel RMT RX channel number
* @param thres Filter threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chmconf[channel].conf1, rx_filter_thres_chm, thres);

Wyświetl plik

@ -450,6 +450,7 @@ static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t chan
* @param dev Peripheral instance address
* @param channel RMT RX channel number
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->chmconf[channel].conf1.mem_wr_rst_chm = 1;
@ -492,6 +493,7 @@ static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, ui
* @param channel RMT RX channel number
* @param thres Time length threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->chmconf[channel].conf0.idle_thres_chm = thres;
@ -517,6 +519,7 @@ static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, rmt
* @param channel RMT RX chanenl number
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chmconf[channel].conf1.rx_filter_en_chm = enable;
@ -529,6 +532,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo
* @param channel RMT RX channel number
* @param thres Filter threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chmconf[channel].conf1, rx_filter_thres_chm, thres);

Wyświetl plik

@ -88,7 +88,7 @@ static inline void rmt_ll_enable_mem_access_nonfifo(rmt_dev_t *dev, bool enable)
* @param divider_numerator Numerator part of the divider
*/
static inline void rmt_ll_set_group_clock_src(rmt_dev_t *dev, uint32_t channel, rmt_clock_source_t src,
uint32_t divider_integral, uint32_t divider_denominator, uint32_t divider_numerator)
uint32_t divider_integral, uint32_t divider_denominator, uint32_t divider_numerator)
{
(void)divider_integral;
(void)divider_denominator;
@ -473,6 +473,7 @@ static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, ui
* @param channel RMT RX channel number
* @param thres Time length threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, idle_thres_chn, thres);
@ -498,6 +499,7 @@ static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, rmt
* @param channel RMT RX chanenl number
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.rx_filter_en_chn = enable;
@ -510,6 +512,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo
* @param channel RMT RX channel number
* @param thres Filter threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf1, rx_filter_thres_chn, thres);

Wyświetl plik

@ -463,6 +463,7 @@ static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t chan
* @param dev Peripheral instance address
* @param channel RMT RX channel number
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->chmconf[channel].conf1.mem_wr_rst_chm = 1;
@ -518,6 +519,7 @@ static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, ui
* @param channel RMT RX channel number
* @param thres Time length threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->chmconf[channel].conf0.idle_thres_chm = thres;
@ -543,6 +545,7 @@ static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, rmt
* @param channel RMT RX chanenl number
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chmconf[channel].conf1.rx_filter_en_chm = enable;
@ -555,6 +558,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo
* @param channel RMT RX channel number
* @param thres Filter threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chmconf[channel].conf1, rx_filter_thres_chm, thres);

Wyświetl plik

@ -550,7 +550,9 @@ There is a Kconfig option :ref:`CONFIG_RMT_ISR_IRAM_SAFE` that has the following
2. Place all functions used by the ISR into IRAM [2]_
3. Place the driver object into DRAM in case it is mapped to PSRAM by accident
This Kconfig option allows the interrupt 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.
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:
@ -560,6 +562,10 @@ Thread Safety
The factory function :cpp:func:`rmt_new_tx_channel`, :cpp:func:`rmt_new_rx_channel` and :cpp:func:`rmt_new_sync_manager` are guaranteed to be thread-safe by the driver, which means, user can call them from different RTOS tasks without protection by extra locks.
Other functions that take the :cpp:type:`rmt_channel_handle_t` and :cpp:type:`rmt_sync_manager_handle_t` as the first positional parameter, are not thread-safe. which means the user should avoid calling them from multiple tasks.
The following functions are allowed to use under ISR context as well.
- :cpp:func:`rmt_receive`
.. _rmt-kconfig-options:
Kconfig Options
@ -567,6 +573,7 @@ Kconfig Options
- :ref:`CONFIG_RMT_ISR_IRAM_SAFE` controls whether the default ISR handler can work when cache is disabled, see also :ref:`rmt-iram-safe` for more information.
- :ref:`CONFIG_RMT_ENABLE_DEBUG_LOG` is used to enable the debug log at the cost of increased firmware binary size.
- :ref:`CONFIG_RMT_RECV_FUNC_IN_IRAM` controls where to place the RMT receive function (IRAM or Flash), see :ref:`rmt-iram-safe` for more information.
Application Examples
--------------------

Wyświetl plik

@ -552,6 +552,8 @@ IRAM 安全
启用该选项可以保证 cache 禁用时的中断运行,但会相应增加 IRAM 占用。
另外一个 Kconfig 选项 :ref:`CONFIG_RMT_RECV_FUNC_IN_IRAM` 可以将 :cpp:func:`rmt_receive` 函数放进内部的 IRAM 中,从而当 flash cache 被关闭的时候,这个函数也能够被使用。
.. _rmt-thread-safety:
线程安全
@ -560,6 +562,10 @@ IRAM 安全
RMT 驱动程序会确保工厂函数 :cpp:func:`rmt_new_tx_channel`:cpp:func:`rmt_new_rx_channel`:cpp:func:`rmt_new_sync_manager` 的线程安全。使用时,可以直接从不同的 RTOS 任务中调用此类函数,无需额外锁保护。
其他以 :cpp:type:`rmt_channel_handle_t`:cpp:type:`rmt_sync_manager_handle_t` 作为第一个位置参数的函数均非线程安全,在没有设置互斥锁保护的任务中,应避免从多个任务中调用这类函数。
以下函数允许在 ISR 上下文中使用:
- :cpp:func:`rmt_receive`
.. _rmt-kconfig-options:
Kconfig 选项
@ -567,6 +573,7 @@ Kconfig 选项
- :ref:`CONFIG_RMT_ISR_IRAM_SAFE` 控制默认 ISR 处理程序能否在禁用 cache 的情况下工作。详情请参阅 :ref:`rmt-iram-safe`
- :ref:`CONFIG_RMT_ENABLE_DEBUG_LOG` 用于启用调试日志输出,启用此选项将增加固件的二进制文件大小。
- :ref:`CONFIG_RMT_RECV_FUNC_IN_IRAM` 用于控制 RMT 接收函数被链接到系统内存的哪个位置IRAM 还是 Flash。详情请参阅 :ref:`rmt-iram-safe`
应用示例
--------------------