From a940064748fcf9da26592516258fe65d2e52aa9a 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/i2c.c | 8 ++++ components/driver/rmt.c | 7 ++++ 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 + tools/unit-test-app/configs/freertos_flash | 3 +- 8 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 components/esp_ringbuf/Kconfig diff --git a/components/driver/Kconfig b/components/driver/Kconfig index 68c421a698..4169d734f4 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -149,6 +149,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/i2c.c b/components/driver/i2c.c index d7bf4b95fb..027a059b01 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -270,6 +270,14 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_ #endif 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/driver/rmt.c b/components/driver/rmt.c index 46f29960bb..9083deb299 100644 --- a/components/driver/rmt.c +++ b/components/driver/rmt.c @@ -1029,6 +1029,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/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 f84bcd8855..35d4ba3f07 100644 --- a/components/esp_ringbuf/test/test_ringbuf.c +++ b/components/esp_ringbuf/test/test_ringbuf.c @@ -1030,11 +1030,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 75e8d7e716..5b4e08a793 100644 --- a/docs/en/api-guides/performance/ram-usage.rst +++ b/docs/en/api-guides/performance/ram-usage.rst @@ -130,6 +130,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. - 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/tools/unit-test-app/configs/freertos_flash b/tools/unit-test-app/configs/freertos_flash index ddbca23830..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_TASK_FUNCTIONS_INTO_FLASH=y +CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y +CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y