Page 1 of 2

Is there a way to reset an RMT channel if the buffer has been filled?

Posted: Tue Mar 27, 2018 2:39 pm
by jcsbanks
rmt_rx_start(rmt_rx.channel, 1); to restart if receiving ended because there was a timeout. In my case with a continuous pulse train this is an error.

rmt_memory_rw_rst(rmt_rx.channel); to reset the buffer position after reading items. In my case I do this in a FreeRTOS task after reading the buffer.

What can be done to reset if the receive buffer has been filled? Neither of the two above work so the ESP32 has to be reset. It is an error condition, but I want to be able to handle it. It should never arise unless a much higher frequency than I need to read is input, I simply need to recover from it.

I am not using the ring buffer as it didn't work with longer idle thresholds than 11ms. I barely need 1 or 2 items, certainly not 64 or more, unless there is an error in which case I do not want the data, so I do not want to use the ring buffer.

Re: Is there a way to reset an RMT channel if the buffer has been filled?

Posted: Tue Mar 27, 2018 4:05 pm
by jcsbanks
rmt_config(&rmt_rx);
rmt_rx_start(rmt_rx.channel, 1);

Also does not restart it. I might have to try silly things like configuring it as a transmitter, or stopping and starting the driver, then trying again.

Re: Is there a way to reset an RMT channel if the buffer has been filled?

Posted: Tue Mar 27, 2018 5:18 pm
by jcsbanks
rmt_rx_stop(rmt_rx.channel);
rmt_config(&rmt_rx);
rmt_driver_install(rmt_rx.channel, 1000, 0);
rmt_driver_uninstall(rmt_rx.channel);
rmt_rx_start(rmt_rx.channel, 1);

This or variations of it do not work.

Re: Is there a way to reset an RMT channel if the buffer has been filled?

Posted: Tue Mar 27, 2018 5:39 pm
by jcsbanks
Unable to transmit on channel 0 after receive has filled the buffer.

Re: Is there a way to reset an RMT channel if the buffer has been filled?

Posted: Tue Mar 27, 2018 7:12 pm
by jcsbanks
esp_restart() doesn't even recover it. Only a reset by button.

rmt_memory_rw_rst either alone or inside rmt_rx_start(rmt_rx.channel, 1); changes the error code.

Re: Is there a way to reset an RMT channel if the buffer has been filled?

Posted: Tue Mar 27, 2018 8:11 pm
by jcsbanks
periph_module_reset(PERIPH_RMT_MODULE);
rmt_config(&rmt_rx);
rmt_rx_start(rmt_rx.channel, 1);

Finally! This allows recovery from buffer full.

Somewhat brutal to restart the whole RMT module though as would affect other channels.

Re: Is there a way to reset an RMT channel if the buffer has been filled?

Posted: Tue Mar 27, 2018 8:36 pm
by WiFive
jcsbanks wrote:esp_restart() doesn't even recover it. Only a reset by button.

rmt_memory_rw_rst either alone or inside rmt_rx_start(rmt_rx.channel, 1); changes the error code.
Changes from what to what?

Re: Is there a way to reset an RMT channel if the buffer has been filled?

Posted: Tue Mar 27, 2018 8:42 pm
by WiFive
jcsbanks wrote: It should never arise unless a much higher frequency than I need to read is input
Can't you set threshold filter to prevent that?

Re: Is there a way to reset an RMT channel if the buffer has been filled?

Posted: Wed Mar 28, 2018 8:56 am
by jcsbanks
Filter threshold is max 255 ticks of 80MHz already. "RMT_RX_FILTER_THRES_CHn In receive mode, channel n ignores input pulse when the pulse width is smaller than this value in APB clock periods."

Error codes are undocumented in the status register but the high byte is 03 and the low byte is the count during normal operation on channel 0 it seems. High byte changes to 0x13 when buffer is full, then 0x14 if it overfull, then 04 if you rmt_memory_rw_rst.

Re: Is there a way to reset an RMT channel if the buffer has been filled?

Posted: Wed Mar 03, 2021 4:41 am
by jhnlmn
I found that changing conf0.idle_thres will make RMT on my ESP32-D0WD-V3 leave Wait state and resume RX.

uint32_t status = RMT.status_ch[RMT_CHANNEL_0];
int state = (status >> RMT_STATE_CH0_S) & RMT_STATE_CH0_V;
if(state == 4) { //4 is "Wait" state
ESP_LOGI(TAG, "rmt status %x", RMT.status_ch[RMT_CHANNEL_0]);
rmt_ll_enable_rx(&RMT, RMT_CHANNEL_0, false);
rmt_ll_reset_rx_pointer(&RMT, RMT_CHANNEL_0);
int idle_thres = RMT.conf_ch[RMT_CHANNEL_0].conf0.idle_thres;
RMT.conf_ch[RMT_CHANNEL_0].conf0.idle_thres = 0;
RMT.conf_ch[RMT_CHANNEL_0].conf0.idle_thres = idle_thres;
rmt_ll_enable_rx(&RMT, RMT_CHANNEL_0, true);
ESP_LOGI(TAG, "rmt status %x", RMT.status_ch[RMT_CHANNEL_0]);
}
This prints
I (68103) PWM: rmt status 14000040
I (68113) PWM: rmt status 1