Ver código fonte

esp_ringbuf: placement in flash is no longer controlled by CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH

esp-ringbuf funtion placement is now controlled by its own configs:
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH and CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH

Closes https://github.com/espressif/esp-idf/issues/9198
Marius Vikhammer 3 anos atrás
pai
commit
fd37129651

+ 1 - 0
components/driver/Kconfig

@@ -157,6 +157,7 @@ menu "Driver Configurations"
 
         config UART_ISR_IN_IRAM
             bool "Place UART ISR function into IRAM"
+            depends on !RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH
             default n
             help
                 If this option is not selected, UART interrupt will be disabled for a long time and

+ 7 - 0
components/driver/deprecated/rmt_legacy.c

@@ -1000,6 +1000,13 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr
         return ESP_ERR_INVALID_STATE;
     }
 
+#if CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH
+            if (intr_alloc_flags & ESP_INTR_FLAG_IRAM ) {
+                ESP_LOGE(TAG, "ringbuf ISR functions in flash, but used in IRAM interrupt");
+                return ESP_ERR_INVALID_ARG;
+            }
+#endif
+
 #if !CONFIG_SPIRAM_USE_MALLOC
     p_rmt_obj[channel] = calloc(1, sizeof(rmt_obj_t));
 #else

+ 8 - 0
components/driver/i2c.c

@@ -280,6 +280,14 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
 #endif
 #if SOC_I2C_SUPPORT_SLAVE
         if (mode == I2C_MODE_SLAVE) {
+
+#if CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH
+            if (intr_alloc_flags & ESP_INTR_FLAG_IRAM ) {
+                ESP_LOGE(I2C_TAG, "ringbuf ISR functions in flash, but used in IRAM interrupt");
+                goto err;
+            }
+#endif
+
             //we only use ringbuffer for slave mode.
             if (slv_rx_buf_len > 0) {
                 p_i2c->rx_ring_buf = xRingbufferCreate(slv_rx_buf_len, RINGBUF_TYPE_BYTEBUF);

+ 24 - 0
components/esp_ringbuf/Kconfig

@@ -0,0 +1,24 @@
+menu "ESP Ringbuf"
+
+
+    config RINGBUF_PLACE_FUNCTIONS_INTO_FLASH
+        bool "Place non-ISR ringbuf functions into flash"
+        default n
+        help
+            Place non-ISR ringbuf functions (like xRingbufferCreate/xRingbufferSend) into flash.
+            This frees up IRAM, but the functions can no longer be called when the cache is disabled.
+
+
+    config RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH
+        bool "Place ISR ringbuf functions into flash"
+        default n
+        help
+            Place non-ISR ringbuf functions (like xRingbufferSendFromISR/xRingbufferReceiveFromISR) into flash.
+            This frees up IRAM, but the functions can no longer be called when the cache is disabled
+            or from an IRAM interrupt context.
+
+            This option is not compatible with ESP-IDF drivers which is configured to run the ISR from an IRAM context,
+            e.g. CONFIG_UART_ISR_IN_IRAM.
+
+
+endmenu

+ 25 - 18
components/esp_ringbuf/linker.lf

@@ -2,32 +2,39 @@
 archive: libesp_ringbuf.a
 entries:
     * (noflash_text)
-    if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
+    if RINGBUF_PLACE_FUNCTIONS_INTO_FLASH = y:
         ringbuf: prvGetCurMaxSizeNoSplit (default)
         ringbuf: prvGetCurMaxSizeAllowSplit (default)
         ringbuf: prvGetCurMaxSizeByteBuf (default)
-        ringbuf: prvReturnItemByteBuf (default)
-        ringbuf: prvGetItemByteBuf (default)
-        ringbuf: prvCheckItemFitsByteBuffer (default)
-        ringbuf: prvReturnItemDefault (default)
-        ringbuf: prvGetItemDefault (default)
-        ringbuf: prvAcquireItemNoSplit (default)
-        ringbuf: prvSendItemDoneNoSplit (default)
-        ringbuf: prvCheckItemFitsDefault (default)
-        ringbuf: prvCopyItemByteBuf (default)
-        ringbuf: prvCopyItemAllowSplit (default)
-        ringbuf: prvCopyItemNoSplit (default)
         ringbuf: prvInitializeNewRingbuffer (default)
         ringbuf: prvReceiveGeneric (default)
+        ringbuf: vRingbufferDelete (default)
+        ringbuf: vRingbufferGetInfo (default)
+        ringbuf: vRingbufferReturnItem (default)
+        ringbuf: xRingbufferAddToQueueSetRead (default)
+        ringbuf: xRingbufferCanRead (default)
         ringbuf: xRingbufferCreate (default)
         ringbuf: xRingbufferCreateStatic (default)
-        ringbuf: xRingbufferSend (default)
         ringbuf: xRingbufferReceive (default)
         ringbuf: xRingbufferReceiveSplit (default)
         ringbuf: xRingbufferReceiveUpTo (default)
-        ringbuf: vRingbufferReturnItem (default)
-        ringbuf: vRingbufferDelete (default)
-        ringbuf: xRingbufferAddToQueueSetRead (default)
-        ringbuf: xRingbufferCanRead (default)
         ringbuf: xRingbufferRemoveFromQueueSetRead (default)
-        ringbuf: vRingbufferGetInfo (default)
+        ringbuf: xRingbufferSend (default)
+
+    if RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH = y:
+        ringbuf: prvReturnItemByteBuf (default)
+        ringbuf: prvReturnItemDefault (default)
+        ringbuf: prvGetItemByteBuf (default)
+        ringbuf: prvGetItemDefault (default)
+        ringbuf: prvCopyItemAllowSplit (default)
+        ringbuf: prvCopyItemByteBuf (default)
+        ringbuf: prvCopyItemNoSplit (default)
+        ringbuf: prvAcquireItemNoSplit (default)
+        ringbuf: prvCheckItemFitsByteBuffer (default)
+        ringbuf: prvCheckItemFitsDefault (default)
+        ringbuf: prvSendItemDoneNoSplit (default)
+        ringbuf: xRingbufferSendFromISR (default)
+        ringbuf: xRingbufferReceiveFromISR (default)
+        ringbuf: xRingbufferReceiveSplitFromISR (default)
+        ringbuf: xRingbufferReceiveUpToFromISR (default)
+        ringbuf: vRingbufferReturnItemFromISR (default)

+ 6 - 1
components/esp_ringbuf/test/test_ringbuf.c

@@ -1024,11 +1024,16 @@ TEST_CASE("Test static ring buffer SMP", "[esp_ringbuf]")
 static IRAM_ATTR __attribute__((noinline)) bool iram_ringbuf_test(void)
 {
     bool result = true;
-
+    uint8_t item[4];
+    size_t item_size;
     RingbufHandle_t handle = xRingbufferCreate(CONT_DATA_TEST_BUFF_LEN, RINGBUF_TYPE_NOSPLIT);
     result = result && (handle != NULL);
     spi_flash_guard_get()->start(); // Disables flash cache
+
     xRingbufferGetMaxItemSize(handle);
+    xRingbufferSendFromISR(handle, (void *)item, sizeof(item), NULL);
+    xRingbufferReceiveFromISR(handle, &item_size);
+
     spi_flash_guard_get()->end(); // Re-enables flash cache
     vRingbufferDelete(handle);
 

+ 2 - 0
docs/en/api-guides/performance/ram-usage.rst

@@ -131,6 +131,8 @@ The following options will reduce IRAM usage of some ESP-IDF features:
 
     - Enable :ref:`CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH`. Provided these functions are not (incorrectly) used from ISRs, this option is safe to enable in all configurations.
     - Enable :ref:`CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH`. Enabling this option will place snapshot-related functions, such as ``vTaskGetSnapshot`` or ``uxTaskGetSnapshotAll``, in flash.
+    - Enable :ref:`CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH`. Provided these functions are not (incorrectly) used from ISRs, this option is safe to enable in all configurations.
+    - Enable :ref:`CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH`. This option is not safe to use if the ISR ringbuf functions are used from an IRAM interrupt context, e.g. if :ref:`CONFIG_UART_ISR_IN_IRAM` is enabled. For the IDF drivers where this is the case you will get an error at run-time when installing the driver in question.
     :SOC_WIFI_SUPPORTED: - Disable Wi-Fi options :ref:`CONFIG_ESP32_WIFI_IRAM_OPT` and/or :ref:`CONFIG_ESP32_WIFI_RX_IRAM_OPT`. Disabling these options will free available IRAM at the cost of Wi-Fi performance.
     :esp32c3 or esp32s3: - :ref:`CONFIG_SPI_FLASH_ROM_IMPL` enabling this option will free some IRAM but will mean that esp_flash bugfixes and new flash chip support is not available.
     :esp32: - :ref:`CONFIG_SPI_FLASH_ROM_DRIVER_PATCH` disabling this option will free some IRAM but is only available in some flash configurations (see the configuration item help text).

+ 5 - 0
docs/en/migration-guides/freertos.rst

@@ -30,3 +30,8 @@ The file ``portmacro_deprecated.h`` which was added to maintain backward compati
 - ``vPortCPUAcquireMutex()`` is removed. Users should use the ``spinlock_acquire()`` function instead.
 - ``vPortCPUAcquireMutexTimeout()`` is removed. Users should use the ``spinlock_acquire()`` function instead.
 - ``vPortCPUReleaseMutex()`` is removed. Users should use the ``spinlock_release()`` function instead.
+
+
+Placing FreeRTOS Functions in Flash
+-----------------------------------
+Previously, the :ref:`CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH` would also place the functions from :component`esp_ringbuf` in flash. ESP-Ringbuf function placement are now controlled by its own configs: :ref:`CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH` and :ref:`CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH`.

+ 1 - 0
tools/unit-test-app/configs/freertos_flash

@@ -1,2 +1,3 @@
 TEST_COMPONENTS=freertos driver spi_flash esp_ringbuf
 CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
+CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y