From fd3712965125452a167d01d31f7b030343f2ffa7 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Thu, 30 Jun 2022 15:43:45 +0800 Subject: [PATCH] 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 --- components/driver/Kconfig | 1 + components/driver/deprecated/rmt_legacy.c | 7 ++++ components/driver/i2c.c | 8 ++++ components/esp_ringbuf/Kconfig | 24 +++++++++++ components/esp_ringbuf/linker.lf | 43 ++++++++++++-------- components/esp_ringbuf/test/test_ringbuf.c | 7 +++- docs/en/api-guides/performance/ram-usage.rst | 2 + docs/en/migration-guides/freertos.rst | 5 +++ tools/unit-test-app/configs/freertos_flash | 1 + 9 files changed, 79 insertions(+), 19 deletions(-) create mode 100644 components/esp_ringbuf/Kconfig diff --git a/components/driver/Kconfig b/components/driver/Kconfig index 9a1ee7e6d0..1259bb75d3 100644 --- a/components/driver/Kconfig +++ b/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 diff --git a/components/driver/deprecated/rmt_legacy.c b/components/driver/deprecated/rmt_legacy.c index 64c052a7bb..53a8e6c79e 100644 --- a/components/driver/deprecated/rmt_legacy.c +++ b/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 diff --git a/components/driver/i2c.c b/components/driver/i2c.c index 0fb9513d88..9c3ed57ab8 100644 --- a/components/driver/i2c.c +++ b/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); diff --git a/components/esp_ringbuf/Kconfig b/components/esp_ringbuf/Kconfig new file mode 100644 index 0000000000..db646218c1 --- /dev/null +++ b/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 diff --git a/components/esp_ringbuf/linker.lf b/components/esp_ringbuf/linker.lf index 0f69153343..fb7a09986d 100644 --- a/components/esp_ringbuf/linker.lf +++ b/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) diff --git a/components/esp_ringbuf/test/test_ringbuf.c b/components/esp_ringbuf/test/test_ringbuf.c index 4222ab2895..cd98cfbad7 100644 --- a/components/esp_ringbuf/test/test_ringbuf.c +++ b/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); diff --git a/docs/en/api-guides/performance/ram-usage.rst b/docs/en/api-guides/performance/ram-usage.rst index 8eca4560b5..a2cdd93e12 100644 --- a/docs/en/api-guides/performance/ram-usage.rst +++ b/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). diff --git a/docs/en/migration-guides/freertos.rst b/docs/en/migration-guides/freertos.rst index 76829e9ff2..61d5d9b090 100644 --- a/docs/en/migration-guides/freertos.rst +++ b/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`. diff --git a/tools/unit-test-app/configs/freertos_flash b/tools/unit-test-app/configs/freertos_flash index 828901dda2..3f20ec3c5e 100644 --- a/tools/unit-test-app/configs/freertos_flash +++ b/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