Can i use high frequency in event callback in ESP32 with MCPWM?

40 views Asked by At

unfortunately after a week of trying to solve or try to understand the problem in question, I'm here to ask for your help to find a solution to my case. (I'm coding in Espressif-ide)

I am using the ESP-WROOM-32 to generate a dulty cycle control signal to use a WS1228B RGB led. However, it works with a super low PWM period of 1.2us, which means that my PWM is at a very high frequency. Furthermore, to be able to generate a signal that it considers as a high logic level, I need to leave the PWM at a high logic level for 0.9us and 0.3us at a low one. The opposite so that the IC inside the RGB LED understands that I am sending 0.

As we have 3 primary colors there, red, green and blue, I need to send 24 PWM pulses with a fixed period of 1.2us, in addition to controlling their dulty cycle.

So I created a comparator in MCPWM along with a counter and generator to generate the PWM when the counter reaches the comparator value. So far so good.

The problem is when I try to update the value of dultycicle to send the 24 bits, because I tried inside a while(true) and I have no control over the update time, that is, as the period is 1.2us, there is no way for me to keep checking the time because the "esp_timer_get_time()" function only brings me at least 1us.

So I tried to create a callback event whenever the counter reaches the comparison value, then within this function I update the dulty cycle to represent the next bit.

The issue is that after doing this, I realized that the code hangs on "TEST_ESP_OK(mcpwm_timer_enable(timer));" When am I going to enable enable. It only works if I lower the PWM period to at least 4us, which is far from 1.2us.

I've even tried configuring his wdt (watchdog), as that's what was causing the problem. The code is right below. The question I have is: Will it be possible to do something so that I can work with an event callback below 4us, that is, with 1.2us, as I know that there are libraries in Arduino that use ESP32 and generate this type of signal?

The code is below along with a printout of the error it is currently giving.

#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <inttypes.h>
#include "main.h"
#include <rtc_wdt.h>

/*Fonte do codigo:
 *
 * https://github.com/espressif/esp-idf/commit/54813cc19bcf6246753807de1ae7ac7dc0b96fc5
 *
 * */
static bool IRAM_ATTR test_compare_on_reach(mcpwm_cmpr_handle_t cmpr, const mcpwm_compare_event_data_t *ev_data, void *user_data)
{

    rtc_wdt_feed();
    return false;
}

static void IRAM_ATTR test_delay_post_cache_disable(void *args)
{
    esp_rom_delay_us(1000);
}

// Gerenciado das tasks:
TaskHandle_t myTaskHandle = NULL;

// Inicio da criacao das task:

// Task de gerenciamento do RGB
void RGB_task(void *arg) {

    while(1) {
        rtc_wdt_feed();
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}


mcpwm_comparator_event_callbacks_t cbs = {
        .on_reach = test_compare_on_reach,
    };

mcpwm_timer_handle_t timer;
    mcpwm_oper_handle_t oper;
    mcpwm_cmpr_handle_t comparator;
    mcpwm_gen_handle_t gen;

    mcpwm_timer_config_t timer_config = {
        .group_id = 0,
        .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
//      .resolution_hz = 1 * 1000 * 1000,
//      .period_ticks = 50,
        .resolution_hz = 10000000,
        .period_ticks = 20,
        .count_mode = MCPWM_TIMER_COUNT_MODE_DOWN,
    };

    mcpwm_operator_config_t operator_config = {
        .group_id = 0,
    };

    mcpwm_comparator_config_t comparator_config = {
//      .flags.update_cmp_on_tep = true,
        .flags.update_cmp_on_tez = true,
    };

    mcpwm_generator_config_t gen_config = {
            .gen_gpio_num = 27,
        };

void app_main(void)
{
    // Reconfigurando o timeout do Watchdog
    rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us);
    rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_SYSTEM);
    rtc_wdt_set_time(RTC_WDT_STAGE0, 10000);

//  RGB_Init();     // Inicializacao do RGB

    printf("install timer, operator and comparator\r\n");

    TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timer));
    TEST_ESP_OK(mcpwm_new_operator(&operator_config, &oper));
    TEST_ESP_OK(mcpwm_new_comparator(oper, &comparator_config, &comparator));

    printf("connect MCPWM timer and operators\r\n");
    TEST_ESP_OK(mcpwm_operator_connect_timer(oper, timer));
    TEST_ESP_OK(mcpwm_comparator_set_compare_value(comparator, 10));

    printf("install MCPWM generator\r\n");


    TEST_ESP_OK(mcpwm_new_generator(oper, &gen_config, &gen));


    printf("set generator actions on timer and compare events\r\n");

    TEST_ESP_OK(mcpwm_generator_set_actions_on_timer_event(gen,
                MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH),
                MCPWM_GEN_TIMER_EVENT_ACTION_END()));
    TEST_ESP_OK(mcpwm_generator_set_actions_on_compare_event(gen,
                MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_DOWN, comparator, MCPWM_GEN_ACTION_LOW),
                MCPWM_GEN_COMPARE_EVENT_ACTION_END()));

    printf("register compare event callback\r\n");

    rtc_wdt_feed();

    printf("Guru");
    TEST_ESP_OK(mcpwm_timer_enable(timer));
    printf("start mcpwm");

    TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP));

    TEST_ESP_OK(mcpwm_comparator_register_event_callbacks(comparator, &cbs, NULL));

    printf("disable flash cache and check the compare events are still in working\r\n");
    for (int i = 0; i < 50; i++) {
        unity_utils_run_cache_disable_stub(test_delay_post_cache_disable, NULL);
     }

    printf("uninstall timer, operator and comparator\r\n");
        TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_STOP_EMPTY));
        TEST_ESP_OK(mcpwm_timer_disable(timer));
        TEST_ESP_OK(mcpwm_del_generator(gen));
        TEST_ESP_OK(mcpwm_del_comparator(comparator));
        TEST_ESP_OK(mcpwm_del_operator(oper));
        TEST_ESP_OK(mcpwm_del_timer(timer));

//  ESP_ERROR_CHECK(mcpwm_timer_start_stop(NULL, MCPWM_TIMER_START_NO_STOP));

    uint8_t timeStampRed = 0;
    uint8_t timeStampGreen = 200;
    uint8_t timeStampBlue = 0;
    uint8_t colorSelect = 0;

    // Muda o status do buffer que contem o codigo dos leds em cada cor
//  RGB_changeStatus(1, timeStampRed, timeStampGreen, timeStampBlue);

    // Criando a task para gerenciar o rgb:
    xTaskCreate(RGB_task, "RGB_Task", 4096, NULL, 10, &myTaskHandle);   // Criando a task do RGB


}

The terminal:

I (288) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM I (294) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM I (301) heap_init: At 4008C3A0 len 00013C60 (79 KiB): IRAM I (308) spi_flash: detected chip: generic I (311) spi_flash: flash io: dio W (315) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (329) app_start: Starting scheduler on CPU0 I (334) app_start: Starting scheduler on CPU1 I (334) main_task: Started on CPU0 I (344) main_task: Calling app_main() install timer, operator and comparator connect MCPWM timer and operators install MCPWM generator I (354) gpio: GPIO[27]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 set generator actions on timer and compare events register compare event callback Guru Meditation Error: Core 0 panic'ed (Interrupt wdt timeout on CPU0).

Core 0 register dump: PC : 0x40083268 PS : 0x00060034 A0 : 0x80082284 A1 : 0x3ffb0d40 0x40083268: mcpwm_comparator_default_isr at C:/Espressif/frameworks/esp-idf-v5.1.2/components/driver/mcpwm/mcpwm_cmpr.c:220

A2 : 0x3ffb5c6c A3 : 0x00060021 A4 : 0x00000000 A5 : 0x00060023 A6 : 0xb33fffff A7 : 0xb33fffff A8 : 0x80083263 A9 : 0x3ffb0d20 A10 : 0x00000000 A11 : 0x3ffb0d40 A12 : 0x00000000 A13 : 0x00008000 A14 : 0xb33fffff A15 : 0xb33fffff SAR : 0x00000011 EXCCAUSE: 0x00000005 EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000 0x4000c46c: memset in ROM

0x4000c477: memset in ROM

Core 0 was running in ISR context: EPC1 : 0x400d22db EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x40083268 0x400d22db: uart_hal_write_txfifo at C:/Espressif/frameworks/esp-idf-v5.1.2/components/hal/uart_hal_iram.c:35

0x40083268: mcpwm_comparator_default_isr at C:/Espressif/frameworks/esp-idf-v5.1.2/components/driver/mcpwm/mcpwm_cmpr.c:220

Backtrace: 0x40083265:0x3ffb0d40 0x40082281:0x3ffb0d70 0x400829d9:0x3ffb0d90 0x400d7110:0x3ffb4d00 0x400d59f9:0x3ffb4d40 0x400e6fdc:0x3ffb4da0 0x40087fd1:0x3ffb4dd0 0x40083265: mcpwm_comparator_default_isr at C:/Espressif/frameworks/esp-idf-v5.1.2/components/driver/mcpwm/mcpwm_cmpr.c:218

0x40082281: shared_intr_isr at C:/Espressif/frameworks/esp-idf-v5.1.2/components/esp_hw_support/intr_alloc.c:436

0x400829d9: _xt_lowint1 at C:/Espressif/frameworks/esp-idf-v5.1.2/components/freertos/FreeRTOS-Kernel/portable/xtensa/xtensa_vectors.S:1240

0x400d7110: mcpwm_comparator_register_event_callbacks at C:/Espressif/frameworks/esp-idf-v5.1.2/components/driver/mcpwm/mcpwm_cmpr.c:186

0x400d59f9: app_main at C:/Users/leona/Documents/GitHub/ARMUPS_IO/RGB_test/main/main.c:129

0x400e6fdc: main_task at C:/Espressif/frameworks/esp-idf-v5.1.2/components/freertos/app_startup.c:208 (discriminator 13)

0x40087fd1: vPortTaskWrapper at C:/Espressif/frameworks/esp-idf-v5.1.2/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:162

Core 1 register dump: PC : 0x40084756 PS : 0x00060734 A0 : 0x800d2172 A1 : 0x3ffb5970 0x40084756: esp_cpu_wait_for_intr at C:/Espressif/frameworks/esp-idf-v5.1.2/components/esp_hw_support/cpu.c:121

A2 : 0x00000000 A3 : 0x00000000 A4 : 0x3ffaf840 A5 : 0x3ffaf820 A6 : 0x400844f8 A7 : 0x00000001 A8 : 0x800da5be A9 : 0x3ffb5930 0x400844f8: ipc_task at C:/Espressif/frameworks/esp-idf-v5.1.2/components/esp_system/esp_ipc.c:48

A10 : 0x00000000 A11 : 0x00000000 A12 : 0x3ffaf820 A13 : 0x3ffaf7f0 A14 : 0x00000001 A15 : 0x00000001 SAR : 0x00000000 EXCCAUSE: 0x00000005 EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000

Backtrace: 0x40084753:0x3ffb5970 0x400d216f:0x3ffb5990 0x40086a7e:0x3ffb59b0 0x40087fd1:0x3ffb59d0 0x40084753: xt_utils_wait_for_intr at C:/Espressif/frameworks/esp-idf-v5.1.2/components/xtensa/include/xt_utils.h:81 (inlined by) esp_cpu_wait_for_intr at C:/Espressif/frameworks/esp-idf-v5.1.2/components/esp_hw_support/cpu.c:111

0x400d216f: esp_vApplicationIdleHook at C:/Espressif/frameworks/esp-idf-v5.1.2/components/esp_system/freertos_hooks.c:59

0x40086a7e: prvIdleTask at C:/Espressif/frameworks/esp-idf-v5.1.2/components/freertos/FreeRTOS-Kernel/tasks.c:4327 (discriminator 1)

0x40087fd1: vPortTaskWrapper at C:/Espressif/frameworks/esp-idf-v5.1.2/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:162

Apparently it is crashing precisely at the moment the event call back is created and sometimes it crashes at the moment the timer is going to be enabled. I haven't tried disabling the watchdog yet.

0

There are 0 answers