ESP32S3 RMT "no free tx channels" opening third channel

horace99
Posts: 8
Joined: Mon Oct 14, 2024 10:38 am

ESP32S3 RMT "no free tx channels" opening third channel

Postby horace99 » Mon Oct 14, 2024 10:52 am

using ESP32-S3-DevKitC-1 using ESP-IDE on Windows 10
attempting to generate 1KHz three phase pulses using RMT
ESP32S3 technical reference manual section 37.2 states
• Four TX channels
• Four RX channels
running the following code which attempts to open three Tx channels
  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <unistd.h>
  4. // ESP32S3 RMT 1KHz three phase square wave  sync test
  5.  
  6.  
  7. #include "driver/rmt_tx.h"
  8.  
  9. void app_main(void)
  10. {
  11.  
  12.  printf("ESP32S3 RMT !KHz three phase sync test\n");
  13.   //delay(2000);
  14.   // setup Tx channels
  15.   rmt_channel_handle_t tx_channels[3] = { NULL };
  16.   gpio_num_t tx_gpio_number[3] = { GPIO_NUM_16, GPIO_NUM_17, GPIO_NUM_18 };  // pin numbers
  17.   for (int i = 0; i < 3; i++) {
  18.     printf("setting up channel %d\n", i);
  19.     rmt_tx_channel_config_t tx_chan_config = {
  20.       .gpio_num = tx_gpio_number[i],
  21.       .clk_src = RMT_CLK_SRC_DEFAULT,
  22.       .resolution_hz = 1 * 1000 * 1000,  // 1MHz clock
  23.       .mem_block_symbols = 64,
  24.       .trans_queue_depth = 1,
  25.     };
  26.     ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &tx_channels[i]));
  27.   }
  28.   rmt_transmit_config_t transmitConfig = {
  29.     .loop_count = -1
  30.   };
  31.   rmt_encoder_handle_t copyEncoder =NULL;
  32.   rmt_copy_encoder_config_t copyEncoderConfig = {};
  33.   assert(rmt_new_copy_encoder(&copyEncoderConfig, &copyEncoder) == ESP_OK && "Failed to Create Copy Encoder");
  34.   ESP_ERROR_CHECK(rmt_enable(tx_channels[2]));
  35.   ESP_ERROR_CHECK(rmt_enable(tx_channels[1]));
  36.   ESP_ERROR_CHECK(rmt_enable(tx_channels[0]));
  37.  
  38.   // setup sync manage for the three pulses
  39.   rmt_sync_manager_handle_t synchro = NULL;
  40.   rmt_sync_manager_config_t synchro_config = {
  41.     .tx_channel_array = tx_channels,
  42.     .array_size = sizeof(tx_channels) / sizeof(tx_channels[0]),
  43.   };
  44.   ESP_ERROR_CHECK(rmt_new_sync_manager(&synchro_config, &synchro));
  45.  
  46.   printf("Starting Transmitters\n");
  47.   // setup pulse patterns - clock is 1MHz
  48.   // two 200KHz pulses 40% duty cycle
  49.   const rmt_symbol_word_t pulsePattern1[] = {
  50.     { .duration0 = 500, .level0 = 1, .duration1 = 500, .level1 = 0 },
  51.   };
  52.   const rmt_symbol_word_t pulsePattern2[] = {
  53.     { .duration0 = 333, .level0 = 0, .duration1 = 500, .level1 = 1 },
  54.     { .duration0 = 100, .level0 = 0, .duration1 = 67, .level1 = 0 },
  55.   };
  56.     const rmt_symbol_word_t pulsePattern3[] = {
  57.     { .duration0 = 167, .level0 = 0, .duration1 = 500, .level1 = 1 },
  58.     { .duration0 = 100, .level0 = 0, .duration1 = 233, .level1 = 0 },
  59.   };
  60.  
  61.   assert(rmt_transmit(tx_channels[0], copyEncoder, &pulsePattern1, sizeof(pulsePattern1), &transmitConfig) == ESP_OK && "Failed to begin transmitting");
  62.   assert(rmt_transmit(tx_channels[1], copyEncoder, &pulsePattern2, sizeof(pulsePattern2), &transmitConfig) == ESP_OK && "Failed to begin transmitting");
  63.   assert(rmt_transmit(tx_channels[2], copyEncoder, &pulsePattern3, sizeof(pulsePattern3), &transmitConfig) == ESP_OK && "Failed to begin transmitting");
  64.   printf("Transmitters Running\n");
  65. }
gives result "no free tx channels" when attempting to open third channel
  1. ESP32S3 RMT !KHz three phase sync test
  2. setting up channel 0
  3. I (322) gpio: GPIO[16]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
  4. setting up channel 1
  5. I (332) gpio: GPIO[17]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
  6. setting up channel 2
  7. E (342) rmt: rmt_tx_register_to_group(152): no free tx channels
  8. E (352) rmt: rmt_new_tx_channel(288): register channel failed
the ESP32S3 technical reference states it has four Tx channels???

any idea on what the problem is?

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

Re: ESP32S3 RMT "no free tx channels" opening third channel

Postby ESP_Sprite » Tue Oct 15, 2024 6:28 am

Odd, as far as I can see that code should work. What ESP-IDF version is this?

horace99
Posts: 8
Joined: Mon Oct 14, 2024 10:38 am

Re: ESP32S3 RMT "no free tx channels" opening third channel

Postby horace99 » Tue Oct 15, 2024 9:18 am

version is esp-idf-v5.3.1

originally had this problem using the Arduino IDE - see https://forum.arduino.cc/t/esp32s3-rmt- ... el/1310503

thought it may just be an Arduino ESP32 problem so tried the ESP-IDF to check - same problem

using two RMT Tx channels works OK

nopnop2002
Posts: 107
Joined: Thu Oct 03, 2019 10:52 pm

Re: ESP32S3 RMT "no free tx channels" opening third channel

Postby nopnop2002 » Wed Oct 16, 2024 12:13 pm

This seems to be a bug in the ESP-IDF component when memory block symbol and SOC_RMT_MEM_WORDS_PER_CHANNEL do not match.

Code: Select all

$ grep -rn "#define SOC_RMT_MEM_WORDS_PER_CHANNEL" *
esp32/include/soc/soc_caps.h:278:#define SOC_RMT_MEM_WORDS_PER_CHANNEL   64 /*!< Each channel owns 64 words memory */
esp32c3/include/soc/soc_caps.h:243:#define SOC_RMT_MEM_WORDS_PER_CHANNEL         48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */
esp32c5/mp/include/soc/soc_caps.h:308:#define SOC_RMT_MEM_WORDS_PER_CHANNEL         48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */
esp32c5/beta3/include/soc/soc_caps.h:313:#define SOC_RMT_MEM_WORDS_PER_CHANNEL         48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */
esp32c6/include/soc/soc_caps.h:310:#define SOC_RMT_MEM_WORDS_PER_CHANNEL         48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */
esp32c61/include/soc/soc_caps.h:305:#define SOC_RMT_MEM_WORDS_PER_CHANNEL         48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */
esp32h2/include/soc/soc_caps.h:304:#define SOC_RMT_MEM_WORDS_PER_CHANNEL         48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */
esp32p4/include/soc/soc_caps.h:374:#define SOC_RMT_MEM_WORDS_PER_CHANNEL         48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */
esp32s2/include/soc/soc_caps.h:260:#define SOC_RMT_MEM_WORDS_PER_CHANNEL         64 /*!< Each channel owns 64 words memory (1 word = 4 Bytes) */
esp32s3/include/soc/soc_caps.h:269:#define SOC_RMT_MEM_WORDS_PER_CHANNEL         48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */


Basically, we need to fix a bug in ESP-IDF when memory block symbols and SOC_RMT_MEM_WORDS_PER_CHANNEL do not match.
But for ESP32S3 the following changes may work.

Code: Select all

    rmt_tx_channel_config_t tx_chan_config = {
      .gpio_num = tx_gpio_number[i],
      .clk_src = RMT_CLK_SRC_DEFAULT,
      .resolution_hz = 1 * 1000 * 1000,  // 1MHz clock
#if 0
      .mem_block_symbols = 64,
#endif
      .mem_block_symbols = 48,
      .trans_queue_depth = 1,
    };
There is a description like this below.
https://docs.espressif.com/projects/esp ... s/rmt.html

Code: Select all

Increase the rmt_tx_channel_config_t::mem_block_symbols, in steps of 48.
If SOC_RMT_MEM_WORDS_PER_CHANNEL is 48 and mem_block_symbols is 64, 2 blocks of memory are required, but there is a bug when using 2 blocks of memory.
When using 2 blocks of memory, up to 4 channels can be used according to the specifications.

I've reported a bug here.
https://github.com/espressif/esp-idf/issues/14736

horace99
Posts: 8
Joined: Mon Oct 14, 2024 10:38 am

Re: ESP32S3 RMT "no free tx channels" opening third channel

Postby horace99 » Wed Oct 16, 2024 4:36 pm

thanks, that fixed it!
updated code as suggested and in addition fixed timing of pulsePattern3
  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <unistd.h>
  4. // ESP32S3 RMT 1KHz three phase square wave  sync test
  5.  
  6.  
  7. #include "driver/rmt_tx.h"
  8.  
  9. void app_main(void)
  10. {
  11. //    while (true) {
  12.  //       printf("Hello from app_main!\n");
  13.  //       sleep(1);
  14.  //   }
  15.  printf("ESP32S3 RMT !KHz three phase sync test\n");
  16.   //delay(2000);
  17.   // setup Tx channels
  18.   rmt_channel_handle_t tx_channels[3] = { NULL };
  19.   gpio_num_t tx_gpio_number[3] = { GPIO_NUM_16, GPIO_NUM_17, GPIO_NUM_18 };  // pin numbers
  20.   for (int i = 0; i < 3; i++) {
  21.     printf("setting up channel %d\n", i);
  22.     rmt_tx_channel_config_t tx_chan_config = {
  23.       .gpio_num = tx_gpio_number[i],
  24.       .clk_src = RMT_CLK_SRC_DEFAULT,
  25.       .resolution_hz = 1 * 1000 * 1000,  // 1MHz clock
  26. #if 0
  27.       .mem_block_symbols = 64,
  28. #endif
  29.       .mem_block_symbols = 48,      .trans_queue_depth = 1,
  30.     };
  31.     ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &tx_channels[i]));
  32.   }
  33.   rmt_transmit_config_t transmitConfig = {
  34.     .loop_count = -1
  35.   };
  36.   rmt_encoder_handle_t copyEncoder =NULL;
  37.   rmt_copy_encoder_config_t copyEncoderConfig = {};
  38.   assert(rmt_new_copy_encoder(&copyEncoderConfig, &copyEncoder) == ESP_OK && "Failed to Create Copy Encoder");
  39.   ESP_ERROR_CHECK(rmt_enable(tx_channels[2]));
  40.   ESP_ERROR_CHECK(rmt_enable(tx_channels[1]));
  41.   ESP_ERROR_CHECK(rmt_enable(tx_channels[0]));
  42.  
  43.   // setup sync manage for the three pulses
  44.   rmt_sync_manager_handle_t synchro = NULL;
  45.   rmt_sync_manager_config_t synchro_config = {
  46.     .tx_channel_array = tx_channels,
  47.     .array_size = sizeof(tx_channels) / sizeof(tx_channels[0]),
  48.   };
  49.   ESP_ERROR_CHECK(rmt_new_sync_manager(&synchro_config, &synchro));
  50.  
  51.   printf("Starting Transmitters\n");
  52.   // setup pulse patterns - clock is 1MHz
  53.   // two 200KHz pulses 40% duty cycle
  54.   const rmt_symbol_word_t pulsePattern1[] = {
  55.     { .duration0 = 500, .level0 = 1, .duration1 = 500, .level1 = 0 },
  56.   };
  57.   const rmt_symbol_word_t pulsePattern2[] = {
  58.     { .duration0 = 333, .level0 = 0, .duration1 = 500, .level1 = 1 },
  59.     { .duration0 = 100, .level0 = 0, .duration1 = 67, .level1 = 0 },
  60.   };
  61.     const rmt_symbol_word_t pulsePattern3[] = {
  62.     { .duration0 = 133, .level0 = 1, .duration1 = 500, .level1 = 0 },
  63.     { .duration0 = 100, .level0 = 1, .duration1 = 267, .level1 = 1 },
  64.   };
  65.  
  66.   assert(rmt_transmit(tx_channels[0], copyEncoder, &pulsePattern1, sizeof(pulsePattern1), &transmitConfig) == ESP_OK && "Failed to begin transmitting");
  67.   assert(rmt_transmit(tx_channels[1], copyEncoder, &pulsePattern2, sizeof(pulsePattern2), &transmitConfig) == ESP_OK && "Failed to begin transmitting");
  68.   assert(rmt_transmit(tx_channels[2], copyEncoder, &pulsePattern3, sizeof(pulsePattern3), &transmitConfig) == ESP_OK && "Failed to begin transmitting");
  69.   printf("Transmitters Running\n");
  70. }
terminal reports
  1. ESP32S3 RMT !KHz three phase sync test
  2. setting up channel 0
  3. I (318) gpio: GPIO[16]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
  4. setting up channel 1
  5. I (328) gpio: GPIO[17]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
  6. setting up channel 2
  7. I (338) gpio: GPIO[18]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
  8. Starting Transmitters
  9. Transmitters Running
  10. I (348) main_task: Returned from app_main()

Who is online

Users browsing this forum: No registered users and 73 guests