Skip to content

Commit 8d5e093

Browse files
authored
Rmt dma only when necessary
* enable dma in rmt only when necessary * Document limitations of PulseIn
1 parent 473557c commit 8d5e093

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

ports/espressif/common-hal/pulseio/PulseIn.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,20 @@ static bool _done_callback(rmt_channel_handle_t rx_chan,
7474

7575
void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu_pin_obj_t *pin,
7676
uint16_t maxlen, bool idle_state) {
77+
78+
// Only use dma when necessary, since dma-rmt might not be available.
79+
// If dma is not available, this will raise an error below.
80+
bool use_dma = maxlen > 128;
81+
7782
self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t));
7883
if (self->buffer == NULL) {
7984
m_malloc_fail(maxlen * sizeof(uint16_t));
8085
}
8186
// We add one to the maxlen version to ensure that two symbols at lease are
8287
// captured because we may skip the first portion of a symbol.
83-
self->raw_symbols_size = MIN(64, maxlen / 2 + 1) * sizeof(rmt_symbol_word_t);
84-
self->raw_symbols = (rmt_symbol_word_t *)m_malloc_without_collect(self->raw_symbols_size);
88+
self->raw_symbols_size = (maxlen / 2 + 1) * sizeof(rmt_symbol_word_t);
89+
// RMT DMA mode cannot access PSRAM -> ensure raw_symbols is in internal ram
90+
self->raw_symbols = (rmt_symbol_word_t *)port_malloc(self->raw_symbols_size, use_dma);
8591
if (self->raw_symbols == NULL) {
8692
m_free(self->buffer);
8793
m_malloc_fail(self->raw_symbols_size);
@@ -109,17 +115,30 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu
109115
.clk_src = RMT_CLK_SRC_DEFAULT,
110116
// 2 us resolution so we can capture 65ms pulses. The RMT period is only 15 bits.
111117
.resolution_hz = 1000000 / 2,
112-
.mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL,
118+
.mem_block_symbols = use_dma ? self->raw_symbols_size : SOC_RMT_MEM_WORDS_PER_CHANNEL,
119+
.flags.with_dma = use_dma
113120
};
114-
// If we fail here, the buffers allocated above will be garbage collected.
115-
CHECK_ESP_RESULT(rmt_new_rx_channel(&config, &self->channel));
121+
// If we fail here, the self->buffer will be garbage collected.
122+
esp_err_t result = rmt_new_rx_channel(&config, &self->channel);
123+
if (result != ESP_OK) {
124+
port_free(self->raw_symbols);
125+
if (result == ESP_ERR_NOT_SUPPORTED) {
126+
mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_maxlen);
127+
} else {
128+
raise_esp_error(result);
129+
}
130+
}
116131

117132
rmt_rx_event_callbacks_t rx_callback = {
118133
.on_recv_done = _done_callback
119134
};
120135
rmt_rx_register_event_callbacks(self->channel, &rx_callback, self);
121136
rmt_enable(self->channel);
122-
rmt_receive(self->channel, self->raw_symbols, self->raw_symbols_size, &rx_config);
137+
result = rmt_receive(self->channel, self->raw_symbols, self->raw_symbols_size, &rx_config);
138+
if (result != ESP_OK) {
139+
port_free(self->raw_symbols);
140+
raise_esp_error(result);
141+
}
123142
}
124143

125144
bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t *self) {

shared-bindings/pulseio/PulseIn.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
//| :param bool idle_state: Idle state of the pin. At start and after `resume`
3434
//| the first recorded pulse will the opposite state from idle.
3535
//|
36+
//| **Limitations**: The `maxlen` parameter is limited depending on the specific board.
37+
//| On most ESP32 variants the limit is 128. On ESP32-S3 and ESP32-P4 the first `PulseIn` instance
38+
//| can use `maxlen` up to available RAM; all subsequent instances are limited to 128.
39+
//|
3640
//| Read a short series of pulses::
3741
//|
3842
//| import pulseio

0 commit comments

Comments
 (0)