SPI vs RMT conflict

vgonet
Posts: 20
Joined: Thu Dec 13, 2018 10:01 am

SPI vs RMT conflict

Postby vgonet » Fri Nov 29, 2019 9:55 am

Hello,

In my project, I use the RMT module to receive RC5 command. I also use the SPI bus (HSPI in master mode, transmit only) to control a LED display. Everything is working.

Now I want to add a second SPI bus to communicate with another uController. So I use the VSPI (in master mode). I've initialized the new SPI and sent data on the bus. The data are sent correctly on the bus but I have an error with the RMT module and the module is unable to decode the RC5 frames.

E (15122) rmt: rmt_driver_uninstall(674): No RMT driver for this channel
E (16222) rmt: rmt_driver_uninstall(674): No RMT driver for this channel
E (17322) rmt: rmt_driver_uninstall(674): No RMT driver for this channel
E (18422) rmt: rmt_driver_uninstall(674): No RMT driver for this channel
E (19522) rmt: rmt_driver_uninstall(674): No RMT driver for this channel

Is there a shared memory between SPI and RMT modules or something like that ? How can I fix that issue ?

Best regards
Vincent

ESP_Sprite
Posts: 9769
Joined: Thu Nov 26, 2015 4:08 am

Re: SPI vs RMT conflict

Postby ESP_Sprite » Sat Nov 30, 2019 3:03 am

No, the devices are completely independent; there is no hardware reason for the one to affect the other.

vgonet
Posts: 20
Joined: Thu Dec 13, 2018 10:01 am

RMT vs Timer conflict

Postby vgonet » Tue Dec 10, 2019 9:09 am

Hello

My project uses many driver like I2C, SPI, WIFI, RMT, Timer, ...

When I install the RMT driver, the timer interrupt is never reached. If I disable the RMT initialization, the timer interrupt is reached.

I don't understand the link between the RMT and the timers.

Code: Select all

void RC5_Init(void)
{
  rmt_rx.channel                       = RMT_RX_CHANNEL;
  rmt_rx.gpio_num                      = IR_RECEIVER_PIN;
  rmt_rx.clk_div                       = RMT_CLK_DIV;
  rmt_rx.mem_block_num                 = 1;
  rmt_rx.rmt_mode                      = RMT_MODE_RX;
  rmt_rx.rx_config.filter_en           = true;
  rmt_rx.rx_config.filter_ticks_thresh = 255;
  rmt_rx.rx_config.idle_threshold      = RMT_ITEM32_TIMEOUT_us / 10 * (RMT_TICK_10_US);

  rmt_config(&rmt_rx);

  TaskIsStarted = false;

  ESP_ERROR_CHECK(rmt_driver_install(rmt_rx.channel, 1000, 0));

  ESP_LOGI(Tag, "IR receiver is initialized");
}

Code: Select all

void Mode_Init(void)
{
  uint8_t buffer[SEQUENCE_BUFFER_SIZE];

  SequenceFifo = Fifo8bits_Create(buffer, SEQUENCE_BUFFER_SIZE);

  RecordSequenceIsFinished = false;
  MovementIsInProgress = false;
  RotationIsInProgress = false;

  TimerHw_Init(1, 0, true, MOVEMENT_DURATION_us, ISR_EndOfMovement);
}

Code: Select all

void TimerHw_Init(int16_t timerGroup, int timerIndex, bool autoReload, double interval, TimerCallback callback)
{
  // Select and initialize basic parameters of the timer
  timer_config_t config;

  config.divider     = TIMER_DIVIDER;
  config.counter_dir = TIMER_COUNT_UP;
  config.counter_en  = TIMER_PAUSE;
  config.alarm_en    = TIMER_ALARM_EN;
  config.intr_type   = TIMER_INTR_LEVEL;
  config.auto_reload = autoReload;

  if ((timerGroup < TIMER_GROUP_MAX) && (timerIndex < TIMER_MAX))
  {
    timer_init(timerGroup, timerIndex, &config);

    // Timer's counter will initially start from value below
    // Also, if auto_reload is set, this value will be automatically reload on alarm
    timer_set_counter_value(timerGroup, timerIndex, 0x00000000ULL);

    // Configure the alarm value and the interrupt on alarm
    timer_set_alarm_value(timerGroup, timerIndex, interval);
    timer_enable_intr(timerGroup, timerIndex);


    timer_isr_register(timerGroup, timerIndex, callback,
                       (void*) timerIndex, ESP_INTR_FLAG_IRAM, NULL);

    ESP_LOGI(Tag, "Group %d Timer %d is initialized", timerGroup, timerIndex);
  }
  else
  {
    ESP_LOGE(Tag, "Invalid parameters, Group = %d, Index = %d", timerGroup, timerIndex);
  }
}

Code: Select all

static void IRAM_ATTR ISR_EndOfMovement(void* para)
{
  // Retrieve the interrupt status and the counter value
  // from the timer that reported the interrupt
  uint32_t intr_status = TIMERG1.int_st_timers.val;
  TIMERG1.hw_timer[0].update = 1;

  // Clear the interrupt and update the alarm time for the timer with without reload
  if (intr_status & BIT(0))
  {
    TIMERG1.int_clr_timers.t0 = 1;
  }

  // After the alarm has been triggered, we need enable it again, so it is triggered the next time
  TIMERG1.hw_timer[0].config.alarm_en = TIMER_ALARM_EN;
}
Best regards,
Vincent

Who is online

Users browsing this forum: Majestic-12 [Bot], Nespressif and 68 guests