Parcourir la source

vfs: fix build & ci errors

Jiacheng Guo il y a 5 ans
Parent
commit
bbb0e7a573

+ 1 - 1
.gitlab/ci/target-test.yml

@@ -410,7 +410,7 @@ UT_001:
 
 UT_002:
   extends: .unit_test_esp32_template
-  parallel: 13
+  parallel: 15
   tags:
     - ESP32_IDF
     - UT_T1_1

+ 1 - 1
components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c

@@ -151,7 +151,7 @@ static spp_slot_t *spp_malloc_slot(void)
                 break;
             }
             if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) {
-                if (esp_vfs_register_fd(spp_local_param.spp_vfs_id, -1, /*permanent=*/true, &(*slot)->fd) != ESP_OK) {
+                if (esp_vfs_register_fd(spp_local_param.spp_vfs_id, &(*slot)->fd) != ESP_OK) {
                     BTC_TRACE_ERROR("%s unable to register fd!", __func__);
                     err_no = 3;
                     break;

+ 1 - 1
components/vfs/README.rst

@@ -242,7 +242,7 @@ Event fds
 ``eventfd()`` call is a powerful tool to notify a ``select()`` based loop of custom events. The ``eventfd()`` implementation in ESP-IDF is generally the same as described in ``man(2) eventfd`` except for:
 
 - ``esp_vfs_eventfd_register()`` has to be called before calling ``eventfd()``
-- Option ``EFD_CLOEXEC``, ``EFD_NONBLOCK`` and ``EFD_SEMAPHORE`` is not supported in flags.
+- Options ``EFD_CLOEXEC``, ``EFD_NONBLOCK`` and ``EFD_SEMAPHORE`` are not supported in flags.
 - Option ``EFD_SUPPORT_ISR`` has been added in flags. This flag is required to read and the write the eventfd in an interrupt handler.
 
 Note that creating an eventfd with ``EFD_SUPPORT_ISR`` will cause interrupts to be temporarily disabled when reading, writing the file and during the beginning and the ending of the ``select()`` when this file is set.

+ 15 - 2
components/vfs/include/esp_vfs.h

@@ -339,15 +339,28 @@ esp_err_t esp_vfs_unregister_with_id(esp_vfs_id_t vfs_id);
  * by esp_vfs_register_with_id.
  *
  * @param vfs_id VFS identificator returned by esp_vfs_register_with_id.
+ * @param fd The registered file descriptor will be written to this address.
+ *
+ * @return  ESP_OK if the registration is successful,
+ *          ESP_ERR_NO_MEM if too many file descriptors are registered,
+ *          ESP_ERR_INVALID_ARG if the arguments are incorrect.
+ */
+esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd);
+
+/**
+ * Special function for registering another file descriptor with given local_fd
+ * for a VFS registered by esp_vfs_register_with_id.
+ *
+ * @param vfs_id VFS identificator returned by esp_vfs_register_with_id.
  * @param local_fd The fd in the local vfs. Passing -1 will set the local fd as the (*fd) value.
- * @param permanenent Whether the fd should be treated as permannet (not removed after close())
+ * @param permanent Whether the fd should be treated as permannet (not removed after close())
  * @param fd The registered file descriptor will be written to this address.
  *
  * @return  ESP_OK if the registration is successful,
  *          ESP_ERR_NO_MEM if too many file descriptors are registered,
  *          ESP_ERR_INVALID_ARG if the arguments are incorrect.
  */
-esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int local_fd, bool permanent, int *fd);
+esp_err_t esp_vfs_register_fd_with_local_fd(esp_vfs_id_t vfs_id, int local_fd, bool permanent, int *fd);
 
 /**
  * Special function for unregistering a file descriptor belonging to a VFS

+ 5 - 2
components/vfs/include/esp_vfs_eventfd.h

@@ -1,4 +1,4 @@
-// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+// Copyright 2021 Espressif Systems (Shanghai) CO LTD
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -25,8 +25,11 @@
 extern "C" {
 #endif
 
+/**
+ * @brief Eventfd vfs initialization settings
+ */
 typedef struct {
-    size_t max_fds;
+    size_t max_fds;     /*!< The maxinum number of eventfds supported */
 } esp_vfs_eventfd_config_t;
 
 #define ESP_VFS_EVENTD_CONFIG_DEFAULT() (esp_vfs_eventfd_config_t) { \

+ 2 - 3
components/vfs/test/test_vfs_eventfd.c

@@ -217,7 +217,7 @@ TEST_CASE("eventfd signal from task", "[vfs][eventfd]")
     TEST_ESP_OK(esp_vfs_eventfd_unregister());
 }
 
-static void IRAM_ATTR eventfd_select_test_isr(void *arg)
+static void eventfd_select_test_isr(void *arg)
 {
     int fd = *((int *)arg);
     uint64_t val = 1;
@@ -248,7 +248,7 @@ TEST_CASE("eventfd signal from ISR", "[vfs][eventfd]")
     TEST_ESP_OK(timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TIMER_BASE_CLK / 16));
     TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0));
     TEST_ESP_OK(timer_isr_register(TIMER_GROUP_0, TIMER_0, eventfd_select_test_isr,
-                                   &fd, ESP_INTR_FLAG_IRAM, NULL));
+                                   &fd, ESP_INTR_FLAG_LOWMED, NULL));
     TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0));
 
     struct timeval wait_time;
@@ -300,7 +300,6 @@ TEST_CASE("eventfd select closed fd", "[vfs][eventfd]")
     TEST_ASSERT_EQUAL(1, ret);
     TEST_ASSERT(FD_ISSET(fd, &error_fds));
 
-    TEST_ASSERT_EQUAL(0, close(fd));
     TEST_ESP_OK(esp_vfs_eventfd_unregister());
 }
 

+ 10 - 4
components/vfs/vfs.c

@@ -209,10 +209,16 @@ esp_err_t esp_vfs_unregister(const char* base_path)
     return ESP_ERR_INVALID_STATE;
 }
 
-esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int local_fd, bool permanent, int *fd)
+esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd)
+{
+    return esp_vfs_register_fd_with_local_fd(vfs_id, -1, true, fd);
+}
+
+esp_err_t esp_vfs_register_fd_with_local_fd(esp_vfs_id_t vfs_id, int local_fd, bool permanent, int *fd)
 {
     if (vfs_id < 0 || vfs_id >= s_vfs_count || fd == NULL) {
-        ESP_LOGD(TAG, "Invalid arguments for esp_vfs_register_fd(%d, 0x%x)", vfs_id, (int) fd);
+        ESP_LOGD(TAG, "Invalid arguments for esp_vfs_register_fd_with_local_fd(%d, %d, %d, 0x%p)",
+                 vfs_id, local_fd, permanent, fd);
         return ESP_ERR_INVALID_ARG;
     }
 
@@ -234,7 +240,8 @@ esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int local_fd, bool permanent,
     }
     _lock_release(&s_fd_table_lock);
 
-    ESP_LOGD(TAG, "esp_vfs_register_fd(%d, 0x%x) finished with %s", vfs_id, (int) fd, esp_err_to_name(ret));
+    ESP_LOGD(TAG, "esp_vfs_register_fd_with_local_fd(%d, %d, %d, 0x%p) finished with %s",
+             vfs_id, local_fd, permanent, fd, esp_err_to_name(ret));
 
     return ret;
 }
@@ -906,7 +913,6 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds
         }
 
         if (is_socket_fd) {
-            assert(false);
             if (!socket_select) {
                 // no socket_select found yet so take a look
                 if (esp_vfs_safe_fd_isset(fd, readfds) ||

+ 28 - 10
components/vfs/vfs_eventfd.c

@@ -34,14 +34,30 @@
 #define FD_INVALID -1
 #define FD_PENDING_SELECT -2
 
+/*
+ * About the event_select_args_t linked list
+ *
+ * Each event_select_args_t structure records a pending select from a select call
+ * on a file descriptor.
+ *
+ * For each select() call, we form a linked list in end_select_args containing
+ * all the pending selects in this select call.
+ *
+ * For each file descriptor, we form a double linked list in event_context_t::select_args.
+ * This list contains all the pending selects on this file descriptor from
+ * different select() calls.
+ *
+ */
 typedef struct event_select_args_t {
     int                         fd;
     fd_set                      *read_fds;
     fd_set                      *error_fds;
     esp_vfs_select_sem_t        signal_sem;
+    // linked list node in event_context_t::select_args
     struct event_select_args_t  *prev_in_fd;
     struct event_select_args_t  *next_in_fd;
-    struct event_select_args_t  *next_in_args; // a linked list for all pending select args for one select call
+    // linked list node in end_select_arg
+    struct event_select_args_t  *next_in_args;
 } event_select_args_t;
 
 typedef struct {
@@ -49,9 +65,11 @@ typedef struct {
     bool                    support_isr;
     volatile bool           is_set;
     volatile uint64_t       value;
-    event_select_args_t     *select_args;   // a double-linked list for all pending select args with this fd
+    // a double-linked list for all pending select args with this fd
+    event_select_args_t     *select_args;
     _lock_t                 lock;
-    spinlock_t              data_spin_lock; // only for event fds that support ISR.
+    // only for event fds that support ISR.
+    spinlock_t              data_spin_lock;
 } event_context_t;
 
 esp_vfs_id_t s_eventfd_vfs_id = -1;
@@ -79,6 +97,7 @@ static void trigger_select_for_event_isr(event_context_t *event, BaseType_t *tas
     }
 }
 
+#ifdef CONFIG_VFS_SUPPORT_SELECT
 static esp_err_t event_start_select(int                  nfds,
                                     fd_set              *readfds,
                                     fd_set              *writefds,
@@ -100,7 +119,8 @@ static esp_err_t event_start_select(int                  nfds,
                 portENTER_CRITICAL(&s_events[i].data_spin_lock);
             }
 
-            event_select_args_t *event_select_args = (event_select_args_t *)malloc(sizeof(event_select_args_t));
+            event_select_args_t *event_select_args =
+                (event_select_args_t *)malloc(sizeof(event_select_args_t));
             event_select_args->fd = i;
             event_select_args->signal_sem = signal_sem;
 
@@ -200,6 +220,7 @@ static esp_err_t event_end_select(void *end_select_args)
 
     return ESP_OK;
 }
+#endif // CONFIG_VFS_SUPPORT_SELECT
 
 static ssize_t signal_event_fd_from_isr(int fd, const void *data, size_t size)
 {
@@ -353,15 +374,12 @@ esp_err_t esp_vfs_eventfd_register(const esp_vfs_eventfd_config_t *config)
     esp_vfs_t vfs = {
         .flags        = ESP_VFS_FLAG_DEFAULT,
         .write        = &event_write,
-        .open         = NULL,
-        .fstat        = NULL,
         .close        = &event_close,
         .read         = &event_read,
-        .fcntl        = NULL,
-        .fsync        = NULL,
-        .access       = NULL,
+#ifdef CONFIG_VFS_SUPPORT_SELECT
         .start_select = &event_start_select,
         .end_select   = &event_end_select,
+#endif
     };
     return esp_vfs_register_with_id(&vfs, NULL, &s_eventfd_vfs_id);
 }
@@ -401,7 +419,7 @@ int eventfd(unsigned int initval, int flags)
         _lock_acquire_recursive(&s_events[i].lock);
         if (s_events[i].fd == FD_INVALID) {
 
-            error = esp_vfs_register_fd(s_eventfd_vfs_id, i, /*permanent=*/false, &global_fd);
+            error = esp_vfs_register_fd_with_local_fd(s_eventfd_vfs_id, i, /*permanent=*/false, &global_fd);
             if (error != ESP_OK) {
                 _lock_release_recursive(&s_events[i].lock);
                 break;

+ 1 - 1
examples/system/eventfd/Makefile

@@ -3,6 +3,6 @@
 # project subdirectory.
 #
 
-PROJECT_NAME := select
+PROJECT_NAME := eventfd
 
 include $(IDF_PATH)/make/project.mk

+ 66 - 1
examples/system/eventfd/README.md

@@ -6,4 +6,69 @@ The example demonstrates the use of `eventfd()` to collect events from other tas
 2. The timer interrupt handler writes to the second `eventfd`.
 3. The second task collects the event from two fds with a `select()` loop.
 
-See the README.md file in the upper level 'examples' directory for more information about examples.
+## How to use example
+
+### Hardware Required
+
+This example should be able to run on any commonly available ESP32, ESP32S2, ESP32S3 or ESP32C3 development board.
+
+### Configure the project
+
+```
+idf.py menuconfig
+```
+
+The default config will work.
+
+### Build and Flash
+
+Build the project and flash it to the board, then run monitor tool to view serial output:
+
+```
+idf.py -p PORT flash monitor
+```
+
+(Replace PORT with the name of the serial port to use.)
+
+(To exit the serial monitor, type ``Ctrl-]``.)
+
+See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
+
+## Example Output
+
+The following log output should appear when the example runs (note that the bootloader log has been omitted).
+
+```
+I (4310) eventfd_example: Time: 1.99s
+I (4310) eventfd_example: Select timeout
+I (4310) eventfd_example: =================================
+I (4310) eventfd_example: Select timeouted for 1 times
+I (4320) eventfd_example: Timer triggerred for 0 times
+I (4320) eventfd_example: Progress triggerred for 0 times
+I (4330) eventfd_example: =================================
+I (4810) eventfd_example: Time: 2.50s
+I (4810) eventfd_example: TimerEvent fd event triggered
+I (5810) eventfd_example: Time: 3.49s
+I (5810) eventfd_example: Progress fd event triggered
+I (7310) eventfd_example: Time: 5.00s
+I (7310) eventfd_example: TimerEvent fd event triggered
+I (9310) eventfd_example: Time: 6.99s
+I (9310) eventfd_example: Select timeout
+I (9310) eventfd_example: Time: 6.99s
+I (9310) eventfd_example: Progress fd event triggered
+I (9810) eventfd_example: Time: 7.50s
+I (9810) eventfd_example: TimerEvent fd event triggered
+I (11810) eventfd_example: Time: 9.49s
+I (11810) eventfd_example: Select timeout
+I (12310) eventfd_example: Time: 10.00s
+I (12310) eventfd_example: TimerEvent fd event triggered
+I (12810) eventfd_example: Time: 10.49s
+I (12810) eventfd_example: Progress fd event triggered
+I (14810) eventfd_example: Time: 12.49s
+I (14810) eventfd_example: Select timeout
+I (14810) eventfd_example: =================================
+I (14810) eventfd_example: Select timeouted for 4 times
+I (14820) eventfd_example: Timer triggerred for 4 times
+I (14820) eventfd_example: Progress triggerred for 3 times
+I (14830) eventfd_example: =================================
+```

+ 29 - 0
examples/system/eventfd/example_test.py

@@ -0,0 +1,29 @@
+from __future__ import unicode_literals
+
+import os
+
+import ttfw_idf
+from tiny_test_fw import Env, Utility
+
+
+@ttfw_idf.idf_example_test(env_tag='Example_GENERIC')
+def test_examples_eventfd(env, extra_data):
+    # type: (Env, None) -> None
+
+    dut = env.get_dut('eventfd', 'examples/system/eventfd')
+    dut.start_app()
+
+    dut.expect('cpu_start: Starting scheduler', timeout=30)
+
+    exp_list = [
+        'eventfd_example: Select timeouted for 4 times',
+        'eventfd_example: Timer triggerred for 4 times',
+        'eventfd_example: Progress triggerred for 3 times',
+    ]
+
+    Utility.console_log('Expecting:{}{}'.format(os.linesep, os.linesep.join(exp_list)))
+    dut.expect_all(*exp_list, timeout=60)
+
+
+if __name__ == '__main__':
+    test_examples_eventfd()

+ 1 - 0
examples/system/eventfd/main/CMakeLists.txt

@@ -1,2 +1,3 @@
 idf_component_register(SRCS "eventfd_example.c"
+                       LDFRAGMENTS linker.lf
                        INCLUDE_DIRS ".")

+ 2 - 0
examples/system/eventfd/main/component.mk

@@ -2,3 +2,5 @@
 # "main" pseudo-component makefile.
 #
 # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
+
+COMPONENT_ADD_LDFRAGMENTS += linker.lf

+ 1 - 1
examples/system/eventfd/main/eventfd_example.c

@@ -34,7 +34,7 @@ static const char *TAG = "eventfd_example";
 int s_timer_fd;
 int s_progress_fd;
 
-static void IRAM_ATTR eventfd_timer_group0_isr(void *para)
+static void eventfd_timer_group0_isr(void *para)
 {
     timer_spinlock_take(TIMER_GROUP_0);
     int timer_idx = (int) para;

+ 4 - 0
examples/system/eventfd/main/linker.lf

@@ -0,0 +1,4 @@
+[mapping:main]
+archive: libmain.a
+entries:
+    eventfd_example:eventfd_timer_group0_isr (noflash)