GP_timer not working properly

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

GP_timer not working properly

Postby Baldhead » Sat Oct 19, 2024 1:45 am

Hi,

I am trying to do the gp_timer to work, at first how one-shot with a pulse of 100 us.

Inside a rise edge i/o interrupt(pin 38), i set an a i/o(pin 40) and load the gp-timer with 100 us.
Inside a gp-timer interrup, i reset the pin 40 i/o.

The interrupts are working but the pulse width is not 100 us(It appears that the timer is not setting the value of 100 us correctly).
The current pulse width is only 5,8 us.
Maybe this time of 5,8 us is just the time to exit the rising edge interrup and already enter the timer interruption, which, for some reason, already has the timer interruption flag set.

And the timer_handle is returning 0(zero) during the first cycles of the interrupts, after a few cycles the handle returns the correct value within the interrupt. During gp_timer initialization the handle is created correctly. I printed the handle value at initialization and within interrupt using ESP_EARLY_LOGI to confirm this.

Program:

Code: Select all

gptimer_handle_t timer_handle;

// rise edge isr
static IRAM_ATTR void sync_isr(void *args)
{
    gpio_set_level( (gpio_num_t)40, 1 );

    // ESP_EARLY_LOGI(TC_TAG, LOG_USER("interrupt: &timer_handle = %p\n"), &timer_handle);    
    // ESP_EARLY_LOGI(TC_TAG, LOG_USER("interrupt: timer_handle = %p\n"), timer_handle);

    gptimer_set_raw_count(timer_handle, (uint64_t)100);  // load timer value com 100us          
    gptimer_start(timer_handle);  // Start GPTimer (internal counter starts counting).           
    return;
}

// gp_timer isr
static IRAM_ATTR bool timer_on_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
    gpio_set_level( (gpio_num_t)40, 0 );
    gptimer_stop(timer_handle);  // Stop GPTimer (internal counter stops counting).       
    return false;    
}

// gp_timer init
static esp_err_t my_gptime_init()
{
    esp_err_t ret;
    
    ESP_LOGI(TC_TAG, "Installing gptimer");

    gptimer_config_t timer_config;
    timer_config.clk_src = GPTIMER_CLK_SRC_DEFAULT;
    timer_config.direction = GPTIMER_COUNT_UP;
    timer_config.resolution_hz = 1 * 1000 * 1000;  // 1MHz, 1tick = 1us 
    
    ret = gptimer_new_timer(&timer_config, &timer_handle);
    if(ret!=ESP_OK) { return ret; }


    ESP_LOGI(TC_TAG, LOG_USER("init: &timer_handle = %p\n"), &timer_handle);    
    ESP_LOGI(TC_TAG, LOG_USER("init: timer_handle = %p\n"), timer_handle);
    

    ESP_LOGI(TC_TAG, "Installing gptimer alarm");
    
    gptimer_alarm_config_t gptimer_alarm;
    gptimer_alarm.alarm_count = (uint64_t)100;
    gptimer_alarm.flags.auto_reload_on_alarm = false;
    
    ret = gptimer_set_alarm_action(timer_handle, &gptimer_alarm);
    if(ret!=ESP_OK) { return ret; }


    ESP_LOGI(TC_TAG, "Register callback for alarm");

    gptimer_event_callbacks_t cbs =
    {
        .on_alarm = timer_on_alarm_cb,  // register user callback
    };
    ret = gptimer_register_event_callbacks(timer_handle, &cbs, NULL);
    if(ret!=ESP_OK) { return ret; }

    ret = gptimer_enable(timer_handle);
    if(ret!=ESP_OK) { return ret; }

    return ESP_OK;
}

Debug:

Code: Select all

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x18 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
Octal Flash Mode Enabled
For OPI Flash, Use Default Flash Boot Mode
mode:SLOW_RD, clock div:1
load:0x3fce2810,len:0x1868
load:0x403c8700,len:0x4
load:0x403c8704,len:0xe58
load:0x403cb700,len:0x30f0
entry 0x403c89bc
I (34) boot: ESP-IDF HEAD-HASH-NOTFOUND 2nd stage bootloader
I (34) boot: compile time Oct 18 2024 21:22:31
I (34) boot: Multicore bootloader
I (38) boot: chip revision: v0.1
I (42) boot.esp32s3: Boot SPI Speed : 80MHz
I (47) boot.esp32s3: SPI Mode       : SLOW READ
I (52) boot.esp32s3: SPI Flash Size : 32MB
I (57) boot: Enabling RNG early entropy source...
I (62) boot: Partition Table:
I (66) boot: ## Label            Usage          Type ST Offset   Length
I (73) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (80) boot:  1 otadata          OTA data         01 00 0000f000 00002000
I (88) boot:  2 ota_0            OTA app          00 10 00020000 00200000
I (95) boot:  3 ota_1            OTA app          00 11 00220000 00200000
I (103) boot: End of partition table
I (107) esp_image: segment 0: paddr=00020020 vaddr=3c020020 size=0b230h ( 45616) map
I (126) esp_image: segment 1: paddr=0002b258 vaddr=3fc97c00 size=02f68h ( 12136) load
I (130) esp_image: segment 2: paddr=0002e1c8 vaddr=40378000 size=01e50h (  7760) load
I (135) esp_image: segment 3: paddr=00030020 vaddr=42000020 size=1873ch (100156) map
I (164) esp_image: segment 4: paddr=00048764 vaddr=40379e50 size=0dd78h ( 56696) load
I (186) boot: Loaded app from partition at offset 0x20000
I (186) boot: Disabling RNG early entropy source...
I (204) MSPI Timing: Flash timing tuning index: 1
I (205) octal_psram: vendor id    : 0x0d (AP)
I (205) octal_psram: dev id       : 0x02 (generation 3)
I (209) octal_psram: density      : 0x03 (64 Mbit)
I (215) octal_psram: good-die     : 0x01 (Pass)
I (220) octal_psram: Latency      : 0x01 (Fixed)
I (225) octal_psram: VCC          : 0x00 (1.8V)
I (231) octal_psram: SRF          : 0x01 (Fast Refresh)
I (237) octal_psram: BurstType    : 0x01 (Hybrid Wrap)
I (242) octal_psram: BurstLen     : 0x01 (32 Byte)
I (248) octal_psram: Readlatency  : 0x02 (10 cycles@Fixed)
I (254) octal_psram: DriveStrength: 0x00 (1/1)
I (266) MSPI Timing: PSRAM timing tuning index: 2
I (266) esp_psram: Found 8MB PSRAM device
I (269) esp_psram: Speed: 120MHz
I (273) cpu_start: Multicore app
I (482) esp_psram: SPI SRAM memory test OK
I (491) cpu_start: Pro cpu start user code
I (491) cpu_start: cpu freq: 240000000 Hz
I (491) app_init: Application information:
I (494) app_init: Project name:     wss_server
I (499) app_init: App version:      1.1.2
I (504) app_init: Compile time:     Oct 18 2024 21:22:01
I (510) app_init: ELF file SHA256:  12ebe489f80f0ec1...
I (516) app_init: ESP-IDF:          HEAD-HASH-NOTFOUND
I (522) efuse_init: Min chip rev:     v0.0
I (526) efuse_init: Max chip rev:     v0.99
I (531) efuse_init: Chip rev:         v0.1
I (536) heap_init: Initializing. RAM available for dynamic allocation:
I (543) heap_init: At 3FC9B5E8 len 0004E128 (312 KiB): RAM
I (549) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM
I (556) heap_init: At 600FE100 len 00001EE8 (7 KiB): RTCRAM
I (562) esp_psram: Adding pool of 8192K of PSRAM memory to heap allocator
I (570) spi_flash: detected chip: mxic (opi)
I (574) spi_flash: flash io: opi_dtr
I (579) sleep: Configure to isolate all GPIO pins in sleep state
I (585) sleep: Enable automatic switching of GPIO sleep configuration
I (593) main_task: Started on CPU0
I (597) main_task: Calling app_main()
I (601) gpio: GPIO[38]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 1| Intr:1 
I (611) TC: InstaE (614) gptimer: gptimer_set_raw_count(237): invalid argument
E (614) gptimer: gptimer_start(388): invalid argument
lling gptime
D (629) gptimE (630) gptimer: gptimer_set_raw_count(237): invalid argument
E (630) gptimer: gptimer_start(388): invalid argument
er: new group (0) @0x3fc9ffc0
D (645) gptimer: E (647) gptimer: gptimer_set_raw_count(237): invalid argument
E (647) gptimer: gptimer_start(388): invalid argument
new gptimer (0,0) at 0x3fc9ff04, resolution=1000000E (663) gptimer: gptimer_set_raw_count(237): invalid argument
E (663) gptimer: gptimer_start(388): invalid argument
Hz
I (676) TC: init: &trE (680) gptimer: gptimer_start(399): timer is not enabled yet
iac_2.timer_handle = 0E (688) gptimer: gptimer_start(399): timer is not enabled yet
x3fc97ef8


 (697) gptimer: gptimer_start(399): timer is not enabled yet
[0;32mI (697) TC E (705) gptimer: gptimer_start(399): timer is not enabled yet
: init: E (713) gptimer: gptimer_start(399): timer is not enabled yet
timer_handle = 0x3E (722) gptimer: gptimer_start(399): timer is not enabled yet
fc9ff04

 (730) gptimer: gptimer_start(399): timer is not enabled yet
;32mI (730) TC E (738) gptimer: gptimer_start(399): timer is not enabled yet
: Installing gptimeE (747) gptimer: gptimer_start(399): timer is not enabled yet
r alarm E (755) gptimer: gptimer_start(399): timer is not enabled yet

I (7E (763) gptimer: gptimer_start(399): timer is not enabled yet
62) TC: Reg E (772) gptimer: gptimer_start(399): timer is not enabled yet
ister callback for ala E (780) gptimer: gptimer_start(399): timer is not enabled yet
rm
 (788) gptimer: gptimer_start(399): timer is not enabled yet
[0m
I (795) MAIN_TAG: tc_init() OK !!!
E (5611) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (5611) task_wdt:  - IDLE1 (CPU 1)
E (5611) task_wdt: Tasks currently running:
E (5611) task_wdt: CPU 0: IDLE0
E (5611) task_wdt: CPU 1: main
E (5611) task_wdt: Print CPU 1 backtrace


Backtrace: 0x4037C57A:0x3FC992F0 0x4037B641:0x3FC99310 0x42007031:0x3FC9E090 0x420174DB:0x3FC9E0B0
--- 0x4037c57a: esp_crosscore_isr at C:/esp-idf/components/esp_system/crosscore_int.c:73
0x4037b641: _xt_lowint1 at C:/esp-idf/components/xtensa/xtensa_vectors.S:1240
0x42007031: app_main at C:/esp32-Proj/WSS_SERVER_AND_UI_INTEGRATION_S3_06-08-2023/main/src/main.c:74 (discriminator 1)
0x420174db: main_task at C:/esp-idf/components/freertos/app_startup.c:208

Notes:
esp32-s3
esp-idf v5.3.1

Thank's.

MicroController
Posts: 1724
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: GP_timer not working properly

Postby MicroController » Sat Oct 19, 2024 7:23 am

You're setting the alarm to go off when the timer reaches 100, then you set the timer to 100, start it, and it fires immediately.
Instead of

Code: Select all

gptimer_set_raw_count(timer_handle, (uint64_t)100);  // load timer value com 100us
use

Code: Select all

gptimer_set_raw_count(timer_handle, 0);
And try making the handle volatile:

Code: Select all

volatile gptimer_handle_t timer_handle;
(Or alternatively force the compiler to write the handle to RAM 'early' with something like

Code: Select all

ret = gptimer_new_timer(&timer_config, &timer_handle);
__asm__ ("":: "m" (timer_handle)); // Make the compiler believe that this (empty) piece of assembly code needs to read the value currently held in timer_handle from memory.
)

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: GP_timer not working properly

Postby Baldhead » Mon Oct 21, 2024 6:43 pm

MicroController wrote:
Sat Oct 19, 2024 7:23 am
You're setting the alarm to go off when the timer reaches 100, then you set the timer to 100, start it, and it fires immediately.
Instead of

Code: Select all

gptimer_set_raw_count(timer_handle, (uint64_t)100);  // load timer value com 100us
use

Code: Select all

gptimer_set_raw_count(timer_handle, 0);
And try making the handle volatile:

Code: Select all

volatile gptimer_handle_t timer_handle;
(Or alternatively force the compiler to write the handle to RAM 'early' with something like

Code: Select all

ret = gptimer_new_timer(&timer_config, &timer_handle);
__asm__ ("":: "m" (timer_handle)); // Make the compiler believe that this (empty) piece of assembly code needs to read the value currently held in timer_handle from memory.
)
Hi @MicroController,

"You're setting the alarm to go off when the timer reaches 100, then you set the timer to 100, start it, and it fires immediately."
My bad.
Working with 0, but sometimes the pulse width is much greater than 100 us; 200us, 1ms, 5ms or more.
Is there any way to increase the priority of the rising edge interrupt ?
I put priority 3 because it can only be greater than that if the isr is written in assembly.
gpio_install_isr_service(ESP_INTR_FLAG_EDGE|ESP_INTR_FLAG_IRAM|ESP_INTR_FLAG_LEVEL3);

Is there any way to increase the priority of the gp_timer too ?

"And try making the handle volatile:
volatile gptimer_handle_t timer_handle;"
Didn't solve the problem.

Code: Select all

warning: passing argument 2 of 'gptimer_new_timer' discards 'volatile' qualifier from pointer target type [-Wdiscarded-qualifiers]
  372 |     ret = gptimer_new_timer(&timer_config, &timer_handle);
      |                                            ^~~~~~~~~~~~~~~~~~~~~
C:/esp-idf/components/esp_driver_gptimer/include/driver/gptimer.h:51:79: note: expected 'struct gptimer_t **' but argument is of type 'struct gptimer_t * volatile*'
   51 | esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *ret_timer);
      |                                                             ~~~~~~~~~~~~~~~~~~^~~~~~~~~
Removing the volatile from the timer_handle and adding just this line of asm code also didn't solve the problem.
"__asm__ ("":: "m" (timer_handle));"


Thank's.

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: GP_timer not working properly

Postby Baldhead » Mon Oct 21, 2024 9:01 pm

Hi @MicroController,

When i removed while(1){} infinite loop in the main function, the watchdog is not triggered anymore and the pulse width is ok now, ie: 100us.

But the timer_handle problem still persists.

Code: Select all

DE (617) gptimer: gptimer_set_raw_count(237): invalid argument
E (617) gptimer: gptimer_start(388): invalid argument
 (617) gptimer: new group (0) @0x3fc9ffc0
D (63E (634) gptimer: gptimer_set_raw_count(237): invalid argument
E (634) gptimer: gptimer_start(388): invalid argument
3) gptimer: new gptimer (0,0) at 0x3fc9ff04, resolutE (650) gptimer: gptimer_set_raw_count(237): invalid argument
E (650) gptimer: gptimer_start(388): invalid argument
ion=1000000Hz
 (667) gptimer: gptimer_start(399): timer is not enabled yet
(675) gptimer: gptimer_start(399): timer is not enabled yet
_handle = 0x3fc97eec
E (684) gptimer: gptimer_start(399): timer is not enabled yet

I (69E (692) gptimer: gptimer_start(399): timer is not enabled yet
 (700) gptimer: gptimer_start(399): timer is not enabled yet
(709) gptimer: gptimer_start(399): timer is not enabled yet
andle = 0x3fc9ff04
 (717) gptimer: gptimer_start(399): timer is not enabled yet
0m
(724)E (725) gptimer: gptimer_start(399): timer is not enabled yet
E (734) gptimer: gptimer_start(399): timer is not enabled yet
E (742) gptimer: gptimer_start(399): timer is not enabled yet
E (750) gptimer: gptimer_start(399): timer is not enabled yet
E (759) gptimer: gptimer_start(399): timer is not enabled yet
E (767) gptimer: gptimer_start(399): timer is not enabled yet
E (775) gptimer: gptimer_start(399): timer is not enabled yet

MicroController
Posts: 1724
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: GP_timer not working properly

Postby MicroController » Tue Oct 22, 2024 8:15 am

Baldhead wrote:
Mon Oct 21, 2024 9:01 pm
But the timer_handle problem still persists.
Of course you have to set up and enable the timer before enabling the GPIO interrupt handler.

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: GP_timer not working properly

Postby Baldhead » Tue Oct 22, 2024 2:09 pm

MicroController wrote:
Tue Oct 22, 2024 8:15 am
Baldhead wrote:
Mon Oct 21, 2024 9:01 pm
But the timer_handle problem still persists.
Of course you have to set up and enable the timer before enabling the GPIO interrupt handler.
Hi @MicroController,

But i did this.
See my first post.

This only happens during the first interruptions, more or less close to the first second, then the error stops and everything works ok. The problem only happens at startup.

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: GP_timer not working properly

Postby Baldhead » Tue Oct 22, 2024 2:16 pm

MicroController wrote:
Tue Oct 22, 2024 8:15 am
Baldhead wrote:
Mon Oct 21, 2024 9:01 pm
But the timer_handle problem still persists.
Of course you have to set up and enable the timer before enabling the GPIO interrupt handler.
Hi @MicroController,

Now I understand, I think I'm initializing the timer after the gpio. I'll check in the afternoon when I'm on the desktop computer.

Thank's.

MicroController
Posts: 1724
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: GP_timer not working properly

Postby MicroController » Tue Oct 22, 2024 5:43 pm

Btw, forget about my advice above to defeat the compiler's optimizer; it doesn't apply in this case because the handle will already have been written to RAM through the pointer &timer_handle, which is not as 'optimizable' as timer_handle = some_func();

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: GP_timer not working properly

Postby Baldhead » Tue Oct 22, 2024 6:02 pm

MicroController wrote:
Tue Oct 22, 2024 5:43 pm
Btw, forget about my advice above to defeat the compiler's optimizer; it doesn't apply in this case because the handle will already have been written to RAM through the pointer &timer_handle, which is not as 'optimizable' as timer_handle = some_func();
Hi @MicroController,

I first initialized the gp_timer and then the rising edge interrupt and it worked.

So there was a problem because i hadn't initialized some struct members like the "timer_config.intr_priority", because in the documentation(https://docs.espressif.com/projects/esp ... r_handle_t) dont show this.
Error only at in run time: "E (607) gptimer: gptimer_new_timer(155): invalid interrupt priority:12"

So after init the struct member timer_config.intr_priority, worked.

before:

Code: Select all

    gptimer_config_t timer_config;
    timer_config.clk_src = GPTIMER_CLK_SRC_DEFAULT;
    timer_config.direction = GPTIMER_COUNT_UP;
    timer_config.resolution_hz = 1 * 1000 * 1000;  // 1MHz, 1tick = 1us     
after:

Code: Select all

    gptimer_config_t timer_config;
    timer_config.clk_src = GPTIMER_CLK_SRC_DEFAULT;
    timer_config.direction = GPTIMER_COUNT_UP;
    timer_config.resolution_hz = 1 * 1000 * 1000;  // 1MHz, 1tick = 1us 
    timer_config.intr_priority = 3;
    timer_config.flags.intr_shared = 0;
    timer_config.flags.backup_before_sleep = 0; 
Thank's.

MicroController
Posts: 1724
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: GP_timer not working properly

Postby MicroController » Tue Oct 22, 2024 9:10 pm

Glad you got it working.
Baldhead wrote:
Tue Oct 22, 2024 6:02 pm
So there was a problem because i hadn't initialized some struct members like the "timer_config.intr_priority",
To mitigate these kinds of issues, it's common practice in C to 'clear' any uninitialized (local) variables of structure types via memset( &myStructVar, 0, sizeof(myStructVar) ) before use.
This also (mostly) prevents your existing code from suddenly producing "unspecified behavior" when there are new elements added to the structure type in the future (i.e. in a new IDF version).

Who is online

Users browsing this forum: Baidu [Spider], Bryght-Richard, Lobelois and 102 guests