Page 1 of 1

ledc_isr_register() does not work for me [solved]

Posted: Fri Feb 01, 2019 8:29 pm
by joba-1
Hi all,

I have written a small example to use LEDC to fade in a led.
Worked great.

Then I wanted to extend this: Enable interrupt on fade end to start a fade out, then again an interrupt to fade in again.
This did not work. I tried a lot of things (ISR with IRAM_ATTR or without, use separate Task to handle the ledc stuff, pin this task to CPU 0 or 1, increase task stack size and enable debug logging and used ledc_channel_config_t.intr_type = LEDC_INTR_FADE_END or not.

For now I am out of options. Can you help me with this?

Complete code is here: https://github.com/joba-1/Breathe-LEDC

This is the main.c code used:

Code: Select all

#include <stdio.h>          // printf()
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"  // for xTask* stuff
#include "freertos/queue.h" // for xQueue* stuff
#include "driver/ledc.h"    // for ledc led fading (nothing to do with ulp)


static xQueueHandle evt_queue = NULL;
static bool fade_inverted = false;


// ISR routine for changing fade direction of LEDC demo
static void IRAM_ATTR toggle_fade_isr( void *dummy ) {
  xQueueSendFromISR(evt_queue, &fade_inverted, NULL);
  fade_inverted = !fade_inverted;
}


// Handle LEDC in task (got wdt if logs enabled if not: didnt help)
void handle_ledc( void *arg ) {
  // setup timer and channel similar to ledc_example_main.c
  ledc_timer_config_t ledc_timer = {
    .duty_resolution = LEDC_TIMER_13_BIT,    // resolution of pwm duty
    .freq_hz         = 5000,                 // frequency of pwm signal
    .speed_mode      = LEDC_HIGH_SPEED_MODE, // timer mode
    .timer_num       = LEDC_TIMER_0          // timer index
  };

  // set configuration of timer0 for high speed channels
  ledc_timer_config(&ledc_timer);

  // Prepare individual configuration for a channel of the LED Controller 
  ledc_channel_config_t ledc_channel = {
    .channel    = LEDC_CHANNEL_0,
    .duty       = 0,
    .gpio_num   = 27,
    .speed_mode = LEDC_HIGH_SPEED_MODE,
    .hpoint     = 0,
    .timer_sel  = LEDC_TIMER_0
    .intr_type  = LEDC_INTR_FADE_END // not in ledc_example_main.c, but I guess is required
  };
  ESP_ERROR_CHECK( ledc_channel_config(&ledc_channel) );

  // Initialize fade service.
  ESP_ERROR_CHECK( ledc_fade_func_install(0) );

  // Set ISR routine to change fade direction -> aborts with ESP_ERR_NOT_FOUND!? 
  // Read the sources: only parameter flags can induce this error message:
  // ledc_isr_register(.., flags, ...) tried all permutations with ESP_INTR_FLAG_IRAM and ESP_INTR_FLAG_SHARED
  // -> esp_intr_alloc(source=ETS_LEDC_INTR_SOURCE, flags, ...)
  // -> esp_intr_alloc_intrstatus(source=ETS_LEDC_INTR_SOURCE, flags, ...) = ESP_ERR_NOT_FOUND
  // -> get_available_int(flags, cpu=xPortGetCoreID(), force=-1, source=ETS_LEDC_INTR_SOURCE) = -1

  ESP_ERROR_CHECK( ledc_isr_register(toggle_fade_isr, &ledc_channel, 0, NULL) );

  // Start fading
  evt_queue = xQueueCreate(1, sizeof(uint32_t)); // never more than one event
  xQueueSend(evt_queue, &fade_inverted, 0);
  printf("Started LEDC\n");

  bool inverted;
  for(;;) {
    if( xQueueReceive(evt_queue, &inverted, portMAX_DELAY)) {
      printf("Fade %s\n", inverted ? "out" : "in");
      ESP_ERROR_CHECK( ledc_set_fade_with_time(ledc_channel.speed_mode, ledc_channel.channel, inverted ? 0 : 4000, 3000) );
      ESP_ERROR_CHECK( ledc_fade_start(ledc_channel.speed_mode, ledc_channel.channel, LEDC_FADE_NO_WAIT) );
    }
  }
}


void app_main()
{
  printf("Hello Breathe LEDC!\n");
  // Test pinning to core 0 because no irq on core 1 (does not help...):
  xTaskCreatePinnedToCore(handle_ledc, "ledc_task", 4*configMINIMAL_STACK_SIZE, NULL, 4, NULL, 0);
}
This is what the log says when I try to register:
Hello Breathe LEDC!
D (2443) ledc: LEDC_PWM CHANNEL 0|GPIO 27|Duty 0000|Time 0
V (2453) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): checking args
V (2453) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): Args okay. Resulting flags 0x40E
D (2453) intr_alloc: get_available_int: try to find existing. Cpu: 0, Source: 43
D (2453) intr_alloc: get_free_int: start looking. Current cpu: 0
D (2453) intr_alloc: Int 0 reserved 1 level 1 LEVEL hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 1 reserved 1 level 1 LEVEL hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 2 reserved 0 level 1 LEVEL hasIsr 1
D (2453) intr_alloc: ....Unusable: already in (non-shared) use.
D (2453) intr_alloc: Int 3 reserved 0 level 1 LEVEL hasIsr 1
D (2453) intr_alloc: ....Unusable: already in (non-shared) use.
D (2453) intr_alloc: Int 4 reserved 1 level 1 LEVEL hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 5 reserved 1 level 1 LEVEL hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 6 reserved 1 level 1 EDGE hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 7 reserved 0 level 1 EDGE hasIsr 0
D (2453) intr_alloc: ....Unusable: special-purpose int
D (2453) intr_alloc: Int 8 reserved 1 level 1 LEVEL hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 9 reserved 0 level 1 LEVEL hasIsr 1
D (2453) intr_alloc: ....Unusable: already in (non-shared) use.
D (2453) intr_alloc: Int 10 reserved 0 level 1 EDGE hasIsr 0
D (2453) intr_alloc: ....Unusable: incompatible trigger type
D (2453) intr_alloc: Int 11 reserved 0 level 3 EDGE hasIsr 0
D (2453) intr_alloc: ....Unusable: special-purpose int
D (2453) intr_alloc: Int 12 reserved 0 level 1 LEVEL hasIsr 1
D (2453) intr_alloc: ....Unusable: already in (non-shared) use.
D (2453) intr_alloc: Int 13 reserved 0 level 1 LEVEL hasIsr 0
D (2453) intr_alloc: Int 14 reserved 1 level 7 LEVEL hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 15 reserved 0 level 3 EDGE hasIsr 0
D (2453) intr_alloc: ....Unusable: special-purpose int
D (2453) intr_alloc: Int 16 reserved 0 level 5 EDGE hasIsr 0
D (2453) intr_alloc: ....Unusable: special-purpose int
D (2453) intr_alloc: Int 17 reserved 0 level 1 LEVEL hasIsr 0
D (2453) intr_alloc: ...worse than int 13
D (2453) intr_alloc: Int 18 reserved 0 level 1 LEVEL hasIsr 0
D (2453) intr_alloc: ...worse than int 13
D (2453) intr_alloc: Int 19 reserved 0 level 2 LEVEL hasIsr 0
D (2453) intr_alloc: ...worse than int 13
D (2453) intr_alloc: Int 20 reserved 0 level 2 LEVEL hasIsr 0
D (2453) intr_alloc: ...worse than int 13
D (2453) intr_alloc: Int 21 reserved 0 level 2 LEVEL hasIsr 0
D (2453) intr_alloc: ...worse than int 13
D (2453) intr_alloc: Int 22 reserved 1 level 3 EDGE hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 23 reserved 0 level 3 LEVEL hasIsr 0
D (2453) intr_alloc: ...worse than int 13
D (2453) intr_alloc: Int 24 reserved 1 level 4 LEVEL hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 25 reserved 1 level 4 LEVEL hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 26 reserved 1 level 5 LEVEL hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 27 reserved 1 level 3 LEVEL hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 28 reserved 0 level 4 EDGE hasIsr 0
D (2453) intr_alloc: ....Unusable: incompatible level
D (2453) intr_alloc: Int 29 reserved 0 level 3 EDGE hasIsr 0
D (2453) intr_alloc: ....Unusable: special-purpose int
D (2453) intr_alloc: Int 30 reserved 1 level 4 EDGE hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: Int 31 reserved 1 level 5 LEVEL hasIsr 0
D (2453) intr_alloc: ....Unusable: reserved
D (2453) intr_alloc: get_available_int: using int 13
D (2453) intr_alloc: Connected src 43 to int 13 (cpu 0)
V (2813) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): checking args
V (2813) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): Args okay. Resulting flags 0xE
D (2813) intr_alloc: get_available_int: try to find existing. Cpu: 0, Source: 43
D (2813) intr_alloc: get_avalible_int: existing vd found. intno: 13
D (2813) intr_alloc: ....Unusable: already in (non-shared) use.
D (2813) intr_alloc: get_avalible_int: existing vd invalid.
ESP_ERROR_CHECK failed: esp_err_t 0x105 (ESP_ERR_NOT_FOUND) at 0x400d25b3
0x400d25b3: handle_ledc at /tmp/blink-17736/Breathe-LEDC/main/main.c:60 (discriminator 1)

file: "/tmp/blink-17736/Breathe-LEDC/main/main.c" line 60
func: handle_ledc
expression: ledc_isr_register(toggle_fade_isr, &ledc_channel, 0, NULL)

Backtrace: 0x40087170:0x3ffb7040 0x4008761c:0x3ffb7060 0x400d25b3:0x3ffb7080
0x40087170: invoke_abort at /home/joachim/.platformio/packages/framework-espidf/components/esp32/panic.c:649

0x4008761c: _esp_error_check_failed at /home/joachim/.platformio/packages/framework-espidf/components/esp32/panic.c:665

0x400d25b3: handle_ledc at /tmp/blink-17736/Breathe-LEDC/main/main.c:60 (discriminator 1)


Rebooting...

Re: ledc_isr_register() does not work for me [solved]

Posted: Sat Feb 02, 2019 11:37 am
by joba-1
Found the solution at the end of this post:

https://www.esp32.com/viewtopic.php?f=1 ... dbebaadd21

(need to share interrupt with myself in ledc_isr_register() AND ledc_fade_func_install()