RMT idle threshold accuracy
Posted: Fri Mar 12, 2021 10:26 am
Hi,
I want to use the RMT peripheral to detect that nothing change on a bus. I configured RMT so, that it should trigger an interrupt, if the input pin doesnt change for 1,75 ms. Im using that peripheral in combination with UART receive timeout. The RMT receiver is always enabled and I'm enabling the RXEND interrupt first on the UART receive timeout interrupt (triggers after 0,75 ms). There I'm also clearing the RMT buffer to prevent overflow.
The most time it is working fine, and the interrupt of RMT is triggered correctly. But like 1 out of 20-50 times it will trigger the interrupt too late. Partially it takes more than 5ms to trigger the interrupt. Im measured that pin with an oscilloscope and have not detected any peak in between.
Any known hardware issues? Or I'm missing something?
Only relevant code below:
I want to use the RMT peripheral to detect that nothing change on a bus. I configured RMT so, that it should trigger an interrupt, if the input pin doesnt change for 1,75 ms. Im using that peripheral in combination with UART receive timeout. The RMT receiver is always enabled and I'm enabling the RXEND interrupt first on the UART receive timeout interrupt (triggers after 0,75 ms). There I'm also clearing the RMT buffer to prevent overflow.
The most time it is working fine, and the interrupt of RMT is triggered correctly. But like 1 out of 20-50 times it will trigger the interrupt too late. Partially it takes more than 5ms to trigger the interrupt. Im measured that pin with an oscilloscope and have not detected any peak in between.
Any known hardware issues? Or I'm missing something?
Only relevant code below:
Code: Select all
void init_rmt()
{
int rmt_channel = 0;
DPORT_REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_RMT_CLK_EN);
DPORT_REG_CLR_BIT(DPORT_PERIP_RST_EN_REG, DPORT_RMT_RST);
RMT.apb_conf.fifo_mask = 1;
RMT.conf_ch[rmt_channel].conf1.ref_cnt_rst = 1;
RMT.conf_ch[rmt_channel].conf1.ref_cnt_rst = 0;
RMT.conf_ch[rmt_channel].conf1.ref_always_on = 1;
RMT.conf_ch[rmt_channel].conf1.rx_filter_en = 0;
RMT.conf_ch[rmt_channel].conf1.rx_filter_thres = 0;
RMT.conf_ch[rmt_channel].conf0.carrier_en = 0;
RMT.conf_ch[rmt_channel].conf0.carrier_out_lv = 0;
RMT.conf_ch[rmt_channel].conf0.clk_en = 0;
RMT.conf_ch[rmt_channel].conf0.div_cnt = 4
RMT.conf_ch[rmt_channel].conf0.idle_thres = 35000; // 1,75ms
RMT.conf_ch[rmt_channel].conf0.mem_pd = 0;
RMT.conf_ch[rmt_channel].conf0.mem_size = 1;
RMT.conf_ch[rmt_channel].conf1.apb_mem_rst = 1;
RMT.conf_ch[rmt_channel].conf1.apb_mem_rst = 0;
RMT.conf_ch[rmt_channel].conf1.idle_out_en = 0;
RMT.conf_ch[rmt_channel].conf1.idle_out_lv = 0;
RMT.conf_ch[rmt_channel].conf1.mem_rd_rst = 1;
RMT.conf_ch[rmt_channel].conf1.mem_rd_rst = 0;
RMT.conf_ch[rmt_channel].conf1.mem_wr_rst = 1;
RMT.conf_ch[rmt_channel].conf1.mem_wr_rst = 0;
RMT.conf_ch[rmt_channel].conf1.tx_conti_mode = 0;
RMT.conf_ch[rmt_channel].conf1.tx_start = 0;
RMT.conf_ch[rmt_channel].conf1.mem_owner = 1;
RMT.conf_ch[rmt_channel].conf1.rx_en = 1;
}
void uart_receive_isr(void *arg)
{
int rmt_channel = 0;
RMT.conf_ch[rmt_channel].conf1.mem_wr_rst = 1; // Reset receiver address
RMT.conf_ch[rmt_channel].conf1.mem_wr_rst = 0;
RMT.conf_ch[rmt_channel].conf1.mem_owner = 1;
RMT.int_clr.val = (1 << (RMT_CH0_RX_END_INT_ENA_S + (rmt_channel * 3))); // Clear interrupt
RMT.int_ena.val |= (1 << (RMT_CH0_RX_END_INT_ENA_S + (rmt_channel * 3))); // Enable interrupt for rx end (bus rest)
}
void rmt_isr()
{
// Triggered sometimes too late
int rmt_channel = 0;
RMT.int_ena.val &= ~(1 << (RMT_CH0_RX_END_INT_ENA_S + (rmt_channel * 3)));
RMT.int_clr.val = (1 << (RMT_CH0_RX_END_INT_ENA_S + (rmt_channel * 3)));
/// ...
}