All right, gotta answer my own question.
I've bought a hardware timer (DS3231), set up SQW at 1024 Hz connected to pin 22 and the code boils down to:
Code: Select all
/* ESP HTTP Client Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "protocol_examples_common.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "esp_websocket_client.h"
#include "esp_event.h"
#define NO_DATA_TIMEOUT_SEC 5
#define IRQ_GPIO 18
static const char *TAG = "WEBSOCKET";
int64_t last_tick = 0;
int64_t timer_dt_min = INT64_MAX;
int64_t timer_dt_max = 0;
esp_websocket_client_handle_t client;
void IRAM_ATTR handler() {
int64_t tick = esp_timer_get_time();
if (last_tick != 0) {
int64_t dt = tick - last_tick;
if (dt < timer_dt_min) timer_dt_min = dt;
if (dt > timer_dt_max) timer_dt_max = dt;
}
last_tick = tick;
}
void attachIRQ(gpio_num_t irq_gpio, void* irq_handler) {
gpio_config_t irq_io_conf = {
.pin_bit_mask = 1ULL << irq_gpio, // IRQ pin
.mode = GPIO_MODE_INPUT, // input mode
.pull_up_en = GPIO_PULLUP_ENABLE, // enable pull-up
.pull_down_en = GPIO_PULLDOWN_DISABLE, // disable pull-down
.intr_type = GPIO_INTR_NEGEDGE // falling edge interrupt
};
ESP_ERROR_CHECK(gpio_config(&irq_io_conf));
// install the GPIO ISR service
ESP_ERROR_CHECK(gpio_install_isr_service(0));
// hook an ISR handler for the specific GPIO pin
ESP_ERROR_CHECK(gpio_isr_handler_add(irq_gpio, irq_handler, NULL));
}
static void websocket_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
switch (event_id) {
case WEBSOCKET_EVENT_CONNECTED:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_CONNECTED");
break;
case WEBSOCKET_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_DISCONNECTED");
break;
case WEBSOCKET_EVENT_DATA:
break;
case WEBSOCKET_EVENT_ERROR:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_ERROR");
break;
}
}
void task_send() {
char data[512];
while (1) {
if (esp_websocket_client_is_connected(client)) {
esp_websocket_client_send_bin(client, data, sizeof(data), pdMS_TO_TICKS(10));
printf("dt_min = %lld us, dt_max = %lld us\n", timer_dt_min,
timer_dt_max);
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
static void websocket_app_start(void)
{
esp_websocket_client_config_t websocket_cfg = {};
websocket_cfg.uri = "ws://echo.websocket.events";
ESP_LOGI(TAG, "Connecting to %s...", websocket_cfg.uri);
client = esp_websocket_client_init(&websocket_cfg);
esp_websocket_register_events(client, WEBSOCKET_EVENT_ANY, websocket_event_handler, (void *)client);
esp_websocket_client_start(client);
attachIRQ(IRQ_GPIO, handler);
xTaskCreatePinnedToCore(task_send, "task_send", 4096, NULL, 0, NULL, PRO_CPU_NUM);
}
void app_main(void)
{
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("WEBSOCKET_CLIENT", ESP_LOG_DEBUG);
esp_log_level_set("TRANSPORT_WS", ESP_LOG_DEBUG);
esp_log_level_set("TRANS_TCP", ESP_LOG_DEBUG);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
websocket_app_start();
}
The console output:
- When WiFi is disabled (commented out):
- When WiFi is enabled but no websocket is running:
- When WiFi is enabled and a websocket is running:
Code: Select all
I (10112) WEBSOCKET: WEBSOCKET_EVENT_CONNECTED
dt_min = 406 us, dt_max = 1547 us
...
E (10972) TRANSPORT_WS: Error transport_poll_write
E (10972) WEBSOCKET_CLIENT: Network error: esp_transport_write() returned 0, errno=0
E (10972) TRANSPORT_BASE: poll_read select error 0, errno = Success, fd = 54
E (10982) WEBSOCKET_CLIENT: Network error: esp_transport_poll_read() returned -1, errno=119
I (10992) WEBSOCKET_CLIENT: Reconnect after 10000 ms
I (10992) WEBSOCKET_CLIENT: Reconnect after 10000 ms
I (11002) WEBSOCKET: WEBSOCKET_EVENT_DISCONNECTED
I (11002) WEBSOCKET: WEBSOCKET_EVENT_DISCONNECTED
dt_min = 381 us, dt_max = 1572 us
I (21372) WEBSOCKET: WEBSOCKET_EVENT_CONNECTED
dt_min = 381 us, dt_max = 1572 us
...
E (319582) TRANSPORT_WS: Error transport_poll_write
E (319582) WEBSOCKET_CLIENT: Network error: esp_transport_write() returned 0, errno=0
E (319582) TRANSPORT_BASE: poll_read select error 0, errno = Success, fd = 54
E (319592) WEBSOCKET_CLIENT: Network error: esp_transport_poll_read() returned -1, errno=119
I (319602) WEBSOCKET_CLIENT: Reconnect after 10000 ms
I (319602) WEBSOCKET: WEBSOCKET_EVENT_DISCONNECTED
I (319612) WEBSOCKET_CLIENT: Reconnect after 10000 ms
I (319612) WEBSOCKET: WEBSOCKET_EVENT_DISCONNECTED
dt_min = 226 us, dt_max = 1728 us
The reason why I saw 8000+ us delays in the previous post is that, as @ESP_Sprite described, the line "ulTaskNotifyTake(pdTRUE, portMAX_DELAY);" is executed after the lock has been released in the timer callback much further in time due to WiFi things scheduled right before my task.
Hope I got it right. And I don't see any solution how to bring the gap of 8000+ us down. Also, WiFi severely influences the delay on its own.