Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP32 RMT TX repeating first few items on loop (IDFGH-2579) #4664

Closed
nickzoic opened this issue Jan 24, 2020 · 8 comments
Closed

ESP32 RMT TX repeating first few items on loop (IDFGH-2579) #4664

nickzoic opened this issue Jan 24, 2020 · 8 comments

Comments

@nickzoic
Copy link

Environment

  • Development Kit: ESP32-DevKitC
  • Kit version: v2 (rev1 silicon, also tested on old rev0 silicon)
  • Module or chip used: ESP32-WROOM-32
  • IDF version (run git describe --tags to find it):
    // v4.0-beta1 310beae
    // also tested with v3.3 6ccb4cf
  • Build System: Make
  • Compiler version:
    // xtensa-esp32-elf-gcc (crosstool-NG crosstool-ng-1.22.0-61-gab8375a) 5.2.0
  • Operating System: Linux
  • Using an IDE?: No
  • Power Supply: USB

Problem Description

When used in repeating mode, the RMT transmission "stutters", repeating the first few items where those items start within the first few microseconds.

This was originally discovered by @jonathanhogg as part of MicroPython/ESP32 but has been replicated in C code (attached below)

See extensive investigation at mattytrentini/micropython#11

Expected Behavior

Pulses should be sent as specified.

Actual Behavior

First few microseconds of pulses repeat at start of transmission.
The time window of the repeating sequence depends on CPU clock speed.

Steps to reproduce

  1. Compile code below.
  2. Attach DSO to GPIO12

Code to reproduce this issue

This file replaces the main.c in the esp-idf-template project:

https://gist.github.com/nickzoic/f552a4933e147481f9bafd63b4c245be

Debug Logs

image

(there should only be one wide pulse followed by 8 narrow pulses in each group)

Other items if possible

Attached: sdkconfig, main/main.c and build/app-template.elf in a zip file:

rmt-issue.zip

@github-actions github-actions bot changed the title ESP32 RMT TX repeating first few items on loop ESP32 RMT TX repeating first few items on loop (IDFGH-2579) Jan 24, 2020
@Alvin1Zhang
Copy link
Collaborator

Thanks for reporting and sorry for the slow turnaround. Sorry that we are now during the holiday of Chinese Lunar New Year. Will update to you when we are back, thanks.

@nickzoic
Copy link
Author

No problem! Happy New Year!

@koobest
Copy link
Contributor

koobest commented Feb 16, 2020

Hi, @nickzoic
On ESP32, when the tx_conti_mode register is set, it will start the transmitter (same as tx_start register), and then works in cyclic sending mode and cannot be changed or stopped. When you set the config.tx_config.loop_en parameter to true(tx_conti_mode register will be set if loop en is true), the transmitter will start working after the initialization process is done. When you call rmt_write_items function to write data to the transmitter's memory, the hardware is reading this memory and sending the read data, so the phenomenon you described appears.

Can you test the following code:

rmt_item32_t items[] = {
    {{{ 50, 0, 50, 0 }}},
    {{{ 2, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 1, 1, 1, 0 }}},
    {{{ 0, 0, 0, 0 }}},
};

void app_main(void *ignore)
{
    rmt_config_t config;
    config.rmt_mode = RMT_MODE_TX;
    config.channel = RMT_CHANNEL_0;
    config.gpio_num = 12;
    config.mem_block_num = 1;
    config.tx_config.carrier_en = 0;
    // config.tx_config.loop_en = 1;
    config.tx_config.loop_en = false;
    config.tx_config.idle_output_en = 1;
    config.tx_config.idle_level = 0;
    config.clk_div = 10;

    ESP_LOGI(TAG, "rmt_config");
    ESP_ERROR_CHECK(rmt_config(&config));
    ESP_LOGI(TAG, "rmt_driver_install");
    ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));
    int number_of_items = sizeof(items) / sizeof(rmt_item32_t);
    ESP_LOGI(TAG, "rmt_write_items");
    // ESP_ERROR_CHECK(rmt_write_items(RMT_CHANNEL_0, items, number_of_items, false));
    rmt_fill_tx_items(RMT_CHANNEL_0, (const rmt_item32_t *)items, number_of_items, 0);
    rmt_set_tx_intr_en(RMT_CHANNEL_0, false);
    rmt_set_tx_loop_mode(RMT_CHANNEL_0, true);
    while (1) {
        ESP_LOGI(TAG, "Waitink");
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    vTaskDelete(NULL);
}

thanks !!

@jonathanhogg
Copy link

I'm afraid that I didn't really understand your explanation, but I did notice that you disable the transmission-complete interrupt before turning on looping. I've just tried the same thing and the problem has gone away.

I feel a bit stupid now as I was convinced that the behaviour looked like an interrupt triggering twice and then got distracted by discovering that the looping is hardware based. It didn't occur to me that the problem might be the hardware automatically looping and then the interrupt messing with the hardware afterwards!

@jonathanhogg
Copy link

To be clear, I mean that the problem does not reside in the choice of rmt_write_items() or rmt_fill_tx_items(), but just in the default interrupt handler. It is a sufficient fix to the code to just add the call to rmt_set_tx_intr_en().

It would be good to update the ESP-IDF Programming Guide to make it clear that looping doesn't work properly if the default interrupt handler is in place for TX-complete.

Thanks for your help @koobest!

@nickzoic
Copy link
Author

That's great! I'll test it out, but it sounds like this will provide a solution to our original Micropython bug!

@Alvin1Zhang
Copy link
Collaborator

Thanks for reporting, the issue has been fixed on our latest master, please help try and see whether the issue still happens, feel free to reopen if it still exists. Thanks. @nickzoic

shubhamkulkarni97 pushed a commit to shubhamkulkarni97/esp-idf that referenced this issue May 28, 2020
…y refactoring.

    After RMT driver refactor, two breaking change are introduced:

    1. Users needs to call `rmt_driver_install` before `rmt_config`.

    2. Do not support memory block count > 1,

    fix this two issues

    closes espressif#4664

    closes espressif#4959
@phatpaul
Copy link
Contributor

I'm running into this issue on IDF 3.3 branch. Can this be backported?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants