| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- /* eventfd 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 <sys/select.h>
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "esp_err.h"
- #include "esp_log.h"
- #include "esp_vfs.h"
- #include "esp_vfs_dev.h"
- #include "esp_vfs_eventfd.h"
- #include "esp_timer.h"
- #include "driver/gptimer.h"
- #define TIMER_RESOLUTION 1000000 // 1MHz, 1 tick = 1us
- #define TIMER_INTERVAL_US 2500000 // 2.5s
- #define PROGRESS_INTERVAL_MS 3500
- #define TIMER_SIGNAL 1
- #define PROGRESS_SIGNAL 2
- /* Print the signals value a bit before 5 seconds, else, `select` would run again
- * and the following print may happen 2 seconds (timeout value) later. */
- #define PRINT_INTERVAL_MSEC 4990
- static const char *TAG = "eventfd_example";
- static int s_timer_fd;
- static int s_progress_fd;
- static TaskHandle_t s_worker_handle;
- static gptimer_handle_t s_gptimer;
- static bool eventfd_timer_isr_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
- {
- uint64_t signal = TIMER_SIGNAL;
- ssize_t val = write(s_timer_fd, &signal, sizeof(signal));
- assert(val == sizeof(signal));
- return true;
- }
- static void eventfd_timer_init(void)
- {
- gptimer_config_t timer_config = {
- .clk_src = GPTIMER_CLK_SRC_DEFAULT,
- .direction = GPTIMER_COUNT_UP,
- .resolution_hz = TIMER_RESOLUTION,
- };
- ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &s_gptimer));
- gptimer_alarm_config_t alarm_config = {
- .reload_count = 0,
- .alarm_count = TIMER_INTERVAL_US,
- .flags.auto_reload_on_alarm = true,
- };
- gptimer_event_callbacks_t cbs = {
- .on_alarm = eventfd_timer_isr_callback,
- };
- ESP_ERROR_CHECK(gptimer_register_event_callbacks(s_gptimer, &cbs, NULL));
- ESP_ERROR_CHECK(gptimer_set_alarm_action(s_gptimer, &alarm_config));
- ESP_ERROR_CHECK(gptimer_enable(s_gptimer));
- ESP_ERROR_CHECK(gptimer_start(s_gptimer));
- }
- static void worker_task(void *arg)
- {
- /* Wait for the collector to be ready. */
- ulTaskNotifyTake(true, portMAX_DELAY);
- while (true) {
- vTaskDelay(pdMS_TO_TICKS(PROGRESS_INTERVAL_MS));
- uint64_t signal = PROGRESS_SIGNAL;
- ssize_t val = write(s_progress_fd, &signal, sizeof(signal));
- assert(val == sizeof(signal));
- }
- vTaskDelete(NULL);
- }
- static void collector_task(void *arg)
- {
- esp_vfs_eventfd_config_t config = ESP_VFS_EVENTD_CONFIG_DEFAULT();
- ESP_ERROR_CHECK(esp_vfs_eventfd_register(&config));
- s_timer_fd = eventfd(0, EFD_SUPPORT_ISR);
- s_progress_fd = eventfd(0, 0);
- assert(s_timer_fd > 0);
- assert(s_progress_fd > 0);
- int maxFd = s_progress_fd > s_timer_fd ? s_progress_fd : s_timer_fd;
- int select_timeout_count = 0;
- int timer_trigger_count = 0;
- int progress_trigger_count = 0;
- /* Notify the worker we are ready to catch the signals */
- assert( xTaskNotifyGive(s_worker_handle) == pdPASS );
- uint64_t start = esp_timer_get_time();
- uint64_t previous = start;
- while (1) {
- struct timeval timeout;
- uint64_t signal;
- timeout.tv_sec = 2;
- timeout.tv_usec = 0;
- fd_set readfds;
- FD_ZERO(&readfds);
- FD_SET(s_timer_fd, &readfds);
- FD_SET(s_progress_fd, &readfds);
- int num_triggered = select(maxFd + 1, &readfds, NULL, NULL, &timeout);
- assert(num_triggered >= 0);
- ESP_LOGI(TAG, "Elapsed since test start: %lld ms", (esp_timer_get_time() - start) / 1000);
- if (FD_ISSET(s_progress_fd, &readfds)) {
- ssize_t ret = read(s_progress_fd, &signal, sizeof(signal));
- assert(ret == sizeof(signal));
- assert(signal == PROGRESS_SIGNAL);
- progress_trigger_count++;
- ESP_LOGI(TAG, "Progress fd event triggered");
- }
- if (FD_ISSET(s_timer_fd, &readfds)) {
- ssize_t ret = read(s_timer_fd, &signal, sizeof(signal));
- assert(ret == sizeof(signal));
- assert(signal == TIMER_SIGNAL);
- timer_trigger_count++;
- ESP_LOGI(TAG, "TimerEvent fd event triggered");
- }
- if (num_triggered == 0) {
- select_timeout_count++;
- ESP_LOGI(TAG, "Select timeout");
- }
- /* Print information about received events every PRINT_INTERVAL_MSEC milliseconds. */
- const uint64_t current = esp_timer_get_time();
- const uint64_t elapsed = current - previous;
- if (elapsed >= PRINT_INTERVAL_MSEC * 1000) {
- ESP_LOGI(TAG, "=================================");
- ESP_LOGI(TAG, "Select timeouted for %d times", select_timeout_count);
- ESP_LOGI(TAG, "Timer triggerred for %d times", timer_trigger_count);
- ESP_LOGI(TAG, "Progress triggerred for %d times", progress_trigger_count);
- ESP_LOGI(TAG, "=================================");
- previous = current;
- }
- }
- gptimer_stop(s_gptimer);
- gptimer_disable(s_gptimer);
- gptimer_del_timer(s_gptimer);
- close(s_timer_fd);
- close(s_progress_fd);
- esp_vfs_eventfd_unregister();
- vTaskDelete(NULL);
- }
- void app_main(void)
- {
- eventfd_timer_init();
- /* Save the handle for this task as we will need to notify it */
- xTaskCreate(worker_task, "worker_task", 4 * 1024, NULL, 5, &s_worker_handle);
- xTaskCreate(collector_task, "collector_task", 4 * 1024, NULL, 5, NULL);
- }
|