Jelajahi Sumber

psram: add configuration macros to move workaround libc functions to flash

Workaround libc can be moved to flash thanks to KConfig macros.
However, the following functions: `itoa`, `memcmp`, `memcpy`, `memset`, `strcat`, `strcmp`, and `strlen` are always kept it in IRAM.
Omar Chebib 4 tahun lalu
induk
melakukan
da731a7eeb

+ 121 - 0
components/esp32/Kconfig

@@ -169,8 +169,129 @@ menu "ESP32-specific"
             config SPIRAM_WORKAROUND_NEED_VOLATILE_SPINLOCK
                 bool
                 default "y" if SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST
+        endmenu
+
+        menu "SPIRAM workaround libraries placement"
+            visible if SPIRAM_CACHE_WORKAROUND
+
+            config SPIRAM_CACHE_LIBJMP_IN_IRAM
+                bool "Put libc's jump related functions in IRAM"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: longjmp and setjmp.
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
+
+            config SPIRAM_CACHE_LIBMATH_IN_IRAM
+                bool "Put libc's math related functions in IRAM"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: abs, div, labs, ldiv, quorem, fpclassify,
+                    and nan.
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
+
+            config SPIRAM_CACHE_LIBNUMPARSER_IN_IRAM
+                bool "Put libc's number parsing related functions in IRAM"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: utoa, itoa, atoi, atol, strtol, and strtoul.
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
+
+            config SPIRAM_CACHE_LIBIO_IN_IRAM
+                bool "Put libc's I/O related functions in IRAM"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: wcrtomb, fvwrite, wbuf, wsetup, fputwc, wctomb_r,
+                    ungetc, makebuf, fflush, refill, and sccl.
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
+
+            config SPIRAM_CACHE_LIBTIME_IN_IRAM
+                bool "Put libc's time related functions in IRAM"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: asctime, asctime_r, ctime, ctime_r, lcltime, lcltime_r,
+                    gmtime, gmtime_r, strftime, mktime, tzset_r, tzset, time, gettzinfo, systimes, month_lengths,
+                    timelocal, tzvars, tzlock, tzcalc_limits, and strptime.
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
+
+            config SPIRAM_CACHE_LIBCHAR_IN_IRAM
+                bool "Put libc's characters related functions in IRAM"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: ctype_, toupper, tolower, toascii, strupr, bzero,
+                    isalnum, isalpha, isascii, isblank, iscntrl, isdigit, isgraph, islower, isprint, ispunct,
+                    isspace, and isupper.
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
+
+            config SPIRAM_CACHE_LIBMEM_IN_IRAM
+                bool "Put libc's memory related functions in IRAM"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: memccpy, memchr memmove, and memrchr.
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
+
+            config SPIRAM_CACHE_LIBSTR_IN_IRAM
+                bool "Put libc's string related functions in IRAM"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: strcasecmp, strcasestr, strchr, strcoll,
+                    strcpy, strcspn, strdup, strdup_r, strlcat, strlcpy, strlen, strlwr, strncasecmp,
+                    strncat, strncmp, strncpy, strndup, strndup_r, strrchr, strsep, strspn, strstr,
+                    strtok_r, and strupr.
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
+
+            config SPIRAM_CACHE_LIBRAND_IN_IRAM
+                bool "Put libc's random related functions in IRAM"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: srand, rand, and rand_r.
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
 
+            config SPIRAM_CACHE_LIBENV_IN_IRAM
+                bool "Put libc's environment related functions in IRAM"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: environ, envlock, and getenv_r.
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
 
+            config SPIRAM_CACHE_LIBFILE_IN_IRAM
+                bool "Put libc's file related functions in IRAM"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: lock, isatty, fclose, open, close, creat, read,
+                    rshift, sbrk, stdio, syssbrk, sysclose, sysopen, creat, sysread, syswrite, impure, fwalk,
+                    and findfp.
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
+
+            config SPIRAM_CACHE_LIBMISC_IN_IRAM
+                bool "Put libc's miscellaneous functions in IRAM, see help"
+                depends on SPIRAM_CACHE_WORKAROUND
+                default "y"
+                help
+                    The functions affected by this option are: raise and system
+                    Putting these function in IRAM will allow them to be called when flash cache is disabled
+                    but it will also reduce the available size of free IRAM for the user application.
         endmenu
 
         config SPIRAM_BANKSWITCH_ENABLE

+ 146 - 122
components/newlib/esp32-spiram-rom-functions-c.lf

@@ -16,132 +16,156 @@ archive:
     libc.a
 entries:
   if SPIRAM_CACHE_WORKAROUND = y:
-    lib_a-utoa (noflash)
-    lib_a-longjmp (noflash)
-    lib_a-setjmp (noflash)
-    lib_a-abs (noflash)
-    lib_a-div (noflash)
-    lib_a-labs (noflash)
-    lib_a-ldiv (noflash)
-    lib_a-quorem (noflash)
-    lib_a-utoa (noflash)
+    # The following libs are either used in a lot of places or in critical
+    # code. (such as panic or abort)
+    # Thus, they shall always be placed in IRAM.
     lib_a-itoa (noflash)
-    lib_a-atoi (noflash)
-    lib_a-atol (noflash)
-    lib_a-strtol (noflash)
-    lib_a-strtoul (noflash)
-    lib_a-wcrtomb (noflash)
-    lib_a-fvwrite (noflash)
-    lib_a-wbuf (noflash)
-    lib_a-wsetup (noflash)
-    lib_a-fputwc (noflash)
-    lib_a-wctomb_r (noflash)
-    lib_a-ungetc (noflash)
-    lib_a-makebuf (noflash)
-    lib_a-fflush (noflash)
-    lib_a-refill (noflash)
-    lib_a-s_fpclassify (noflash)
-    lib_a-asctime (noflash)
-    lib_a-ctime (noflash)
-    lib_a-ctime_r (noflash)
-    lib_a-lcltime (noflash)
-    lib_a-lcltime_r (noflash)
-    lib_a-gmtime (noflash)
-    lib_a-gmtime_r (noflash)
-    lib_a-strftime (noflash)
-    lib_a-mktime (noflash)
-    lib_a-syswrite (noflash)
-    lib_a-tzset_r (noflash)
-    lib_a-tzset (noflash)
-    lib_a-toupper (noflash)
-    lib_a-tolower (noflash)
-    lib_a-toascii (noflash)
-    lib_a-systimes (noflash)
-    lib_a-time (noflash)
-    lib_a-gettzinfo (noflash)
-    lib_a-strupr (noflash)
-    lib_a-asctime_r (noflash)
-    lib_a-bzero (noflash)
-    lib_a-close (noflash)
-    lib_a-creat (noflash)
-    lib_a-environ (noflash)
-    lib_a-fclose (noflash)
-    lib_a-isalnum (noflash)
-    lib_a-isalpha (noflash)
-    lib_a-isascii (noflash)
-    lib_a-isblank (noflash)
-    lib_a-iscntrl (noflash)
-    lib_a-isdigit (noflash)
-    lib_a-isgraph (noflash)
-    lib_a-islower (noflash)
-    lib_a-isprint (noflash)
-    lib_a-ispunct (noflash)
-    lib_a-isspace (noflash)
-    lib_a-isupper (noflash)
-    lib_a-memccpy (noflash)
-    lib_a-memchr (noflash)
     lib_a-memcmp (noflash)
     lib_a-memcpy (noflash)
-    lib_a-memmove (noflash)
-    lib_a-memrchr (noflash)
     lib_a-memset (noflash)
-    lib_a-open (noflash)
-    lib_a-rand (noflash)
-    lib_a-rand_r (noflash)
-    lib_a-read (noflash)
-    lib_a-rshift (noflash)
-    lib_a-sbrk (noflash)
-    lib_a-srand (noflash)
-    lib_a-strcasecmp (noflash)
-    lib_a-strcasestr (noflash)
     lib_a-strcat (noflash)
-    lib_a-strchr (noflash)
     lib_a-strcmp (noflash)
-    lib_a-strcoll (noflash)
-    lib_a-strcpy (noflash)
-    lib_a-strcspn (noflash)
-    lib_a-strdup (noflash)
-    lib_a-strlcat (noflash)
-    lib_a-strlcpy (noflash)
     lib_a-strlen (noflash)
-    lib_a-strlwr (noflash)
-    lib_a-strncasecmp (noflash)
-    lib_a-strncat (noflash)
-    lib_a-strncmp (noflash)
-    lib_a-strncpy (noflash)
-    lib_a-strndup (noflash)
-    lib_a-strnlen (noflash)
-    lib_a-strrchr (noflash)
-    lib_a-strsep (noflash)
-    lib_a-strspn (noflash)
-    lib_a-strstr (noflash)
-    lib_a-strtok_r (noflash)
-    lib_a-strupr (noflash)
-    lib_a-stdio (noflash)
-    lib_a-syssbrk (noflash)
-    lib_a-sysclose (noflash)
-    lib_a-sysopen (noflash)
-    creat (noflash)
-    lib_a-sysread (noflash)
-    lib_a-syswrite (noflash)
-    lib_a-impure (noflash)
-    lib_a-tzvars (noflash)
-    lib_a-sf_nan (noflash)
-    lib_a-tzcalc_limits (noflash)
-    lib_a-month_lengths (noflash)
-    lib_a-timelocal (noflash)
-    lib_a-findfp (noflash)
-    lock (noflash)
-    lib_a-getenv_r (noflash)
-    isatty (noflash)
-    lib_a-fwalk (noflash)
-    lib_a-getenv_r (noflash)
-    lib_a-tzlock (noflash)
-    lib_a-ctype_ (noflash)
-    lib_a-sccl (noflash)
-    lib_a-strptime (noflash)
-    lib_a-envlock (noflash)
-    lib_a-raise (noflash)
-    lib_a-strdup_r (noflash)
-    lib_a-system (noflash)
-    lib_a-strndup_r (noflash)
+
+    if SPIRAM_CACHE_LIBJMP_IN_IRAM = y:
+        lib_a-longjmp (noflash)
+        lib_a-setjmp (noflash)
+
+    if SPIRAM_CACHE_LIBMATH_IN_IRAM = y:
+        lib_a-abs (noflash)
+        lib_a-div (noflash)
+        lib_a-labs (noflash)
+        lib_a-ldiv (noflash)
+        lib_a-quorem (noflash)
+        lib_a-s_fpclassify (noflash)
+        lib_a-sf_nan (noflash)
+
+    if SPIRAM_CACHE_LIBNUMPARSER_IN_IRAM = y:
+        lib_a-utoa (noflash)
+        lib_a-atoi (noflash)
+        lib_a-atol (noflash)
+        lib_a-strtol (noflash)
+        lib_a-strtoul (noflash)
+
+    if SPIRAM_CACHE_LIBIO_IN_IRAM = y:
+        lib_a-wcrtomb (noflash)
+        lib_a-fvwrite (noflash)
+        lib_a-wbuf (noflash)
+        lib_a-wsetup (noflash)
+        lib_a-fputwc (noflash)
+        lib_a-wctomb_r (noflash)
+        lib_a-ungetc (noflash)
+        lib_a-makebuf (noflash)
+        lib_a-fflush (noflash)
+        lib_a-refill (noflash)
+        lib_a-sccl (noflash)
+
+    if SPIRAM_CACHE_LIBTIME_IN_IRAM = y:
+        lib_a-asctime (noflash)
+        lib_a-asctime_r (noflash)
+        lib_a-ctime (noflash)
+        lib_a-ctime_r (noflash)
+        lib_a-lcltime (noflash)
+        lib_a-lcltime_r (noflash)
+        lib_a-gmtime (noflash)
+        lib_a-gmtime_r (noflash)
+        lib_a-strftime (noflash)
+        lib_a-mktime (noflash)
+        lib_a-tzset_r (noflash)
+        lib_a-tzset (noflash)
+        lib_a-time (noflash)
+        lib_a-gettzinfo (noflash)
+        lib_a-systimes (noflash)
+        lib_a-month_lengths (noflash)
+        lib_a-timelocal (noflash)
+        lib_a-tzvars (noflash)
+        lib_a-tzlock (noflash)
+        lib_a-tzcalc_limits (noflash)
+        lib_a-strptime (noflash)
+
+    if SPIRAM_CACHE_LIBCHAR_IN_IRAM = y:
+        lib_a-ctype_ (noflash)
+        lib_a-toupper (noflash)
+        lib_a-tolower (noflash)
+        lib_a-toascii (noflash)
+        lib_a-strupr (noflash)
+        lib_a-bzero (noflash)
+        lib_a-isalnum (noflash)
+        lib_a-isalpha (noflash)
+        lib_a-isascii (noflash)
+        lib_a-isblank (noflash)
+        lib_a-iscntrl (noflash)
+        lib_a-isdigit (noflash)
+        lib_a-isgraph (noflash)
+        lib_a-islower (noflash)
+        lib_a-isprint (noflash)
+        lib_a-ispunct (noflash)
+        lib_a-isspace (noflash)
+        lib_a-isupper (noflash)
+
+    if SPIRAM_CACHE_LIBMEM_IN_IRAM = y:
+        lib_a-memccpy (noflash)
+        lib_a-memchr (noflash)
+        lib_a-memmove (noflash)
+        lib_a-memrchr (noflash)
+
+    if SPIRAM_CACHE_LIBSTR_IN_IRAM = y:
+        lib_a-strcasecmp (noflash)
+        lib_a-strcasestr (noflash)
+        lib_a-strchr (noflash)
+        lib_a-strcoll (noflash)
+        lib_a-strcpy (noflash)
+        lib_a-strcspn (noflash)
+        lib_a-strdup (noflash)
+        lib_a-strdup_r (noflash)
+        lib_a-strlcat (noflash)
+        lib_a-strlcpy (noflash)
+        lib_a-strlwr (noflash)
+        lib_a-strncasecmp (noflash)
+        lib_a-strncat (noflash)
+        lib_a-strncmp (noflash)
+        lib_a-strncpy (noflash)
+        lib_a-strndup (noflash)
+        lib_a-strndup_r (noflash)
+        lib_a-strnlen (noflash)
+        lib_a-strrchr (noflash)
+        lib_a-strsep (noflash)
+        lib_a-strspn (noflash)
+        lib_a-strstr (noflash)
+        lib_a-strtok_r (noflash)
+        lib_a-strupr (noflash)
+
+    if SPIRAM_CACHE_LIBRAND_IN_IRAM = y:
+        lib_a-srand (noflash)
+        lib_a-rand (noflash)
+        lib_a-rand_r (noflash)
+
+    if SPIRAM_CACHE_LIBENV_IN_IRAM = y:
+        lib_a-environ (noflash)
+        lib_a-envlock (noflash)
+        lib_a-getenv_r (noflash)
+
+    if SPIRAM_CACHE_LIBFILE_IN_IRAM = y:
+        lock (noflash)
+        isatty (noflash)
+        lib_a-fclose (noflash)
+        lib_a-open (noflash)
+        lib_a-close (noflash)
+        lib_a-creat (noflash)
+        lib_a-read (noflash)
+        lib_a-rshift (noflash)
+        lib_a-sbrk (noflash)
+        lib_a-stdio (noflash)
+        lib_a-syssbrk (noflash)
+        lib_a-sysclose (noflash)
+        lib_a-sysopen (noflash)
+        creat (noflash)
+        lib_a-sysread (noflash)
+        lib_a-syswrite (noflash)
+        lib_a-impure (noflash)
+        lib_a-fwalk (noflash)
+        lib_a-findfp (noflash)
+
+    if SPIRAM_CACHE_LIBMISC_IN_IRAM = y:
+        lib_a-raise (noflash)
+        lib_a-system (noflash)

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

@@ -136,6 +136,27 @@ The following options will reduce IRAM usage of some ESP-IDF features:
     - Disabling :ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM` prevents spi_master interrupts from being serviced while writing to flash, and may otherwise reduce spi_master performance, but will save some IRAM.
     - Setting :ref:`CONFIG_HAL_DEFAULT_ASSERTION_LEVEL` to disable assertion for HAL component will save some IRAM especially for HAL code who calls `HAL_ASSERT` a lot and resides in IRAM.
 
+.. only:: esp32
+
+   When compiling for ESP32 revisions older than ECO3 (:ref:`CONFIG_ESP32_REV_MIN`), PSRAM cache bug workaround (:ref:`CONFIG_SPIRAM_CACHE_WORKAROUND`) option is enabled, and the C library functions normally located in ROM are recompiled with the workaround and placed into IRAM instead. For most applications, it is safe to move many of the C library functions into Flash, reclaiming some IRAM. Corresponding options include:
+
+   .. list::
+
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBJMP_IN_IRAM`: affects the functions ``longjmp`` and ``setjump``.
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBMATH_IN_IRAM`: affects the functions ``abs``, ``div``, ``labs``, ``ldiv``, ``quorem``, ``fpclassify`` and ``nan``.
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBNUMPARSER_IN_IRAM`: affects the functions ``utoa``, ``itoa``, ``atoi``, ``atol``, ``strtol``, and ``strtoul``.
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBIO_IN_IRAM`: affects the functions ``wcrtomb``, ``fvwrite``, ``wbuf``, ``wsetup``, ``fputwc``, ``wctomb_r``, ``ungetc``, ``makebuf``, ``fflush``, ``refill``, and ``sccl``.
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBTIME_IN_IRAM`: affects the functions ``asctime``, ``asctime_r``, ``ctime``, ``ctime_r``, ``lcltime``, ``lcltime_r``, ``gmtime``, ``gmtime_r``, ``strftime``, ``mktime``, ``tzset_r``, ``tzset``, ``time``, ``gettzinfo``, ``systimes``, ``month_lengths``, ``timelocal``, ``tzvars``, ``tzlock``, ``tzcalc_limits``, and ``strptime``.
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBCHAR_IN_IRAM`: affects the functions ``ctype_``, ``toupper``, ``tolower``, ``toascii``, ``strupr``, ``bzero``, ``isalnum``, ``isalpha``, ``isascii``, ``isblank``, ``iscntrl``, ``isdigit``, ``isgraph``, ``islower``, ``isprint``, ``ispunct``, ``isspace``, and ``isupper``.
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBMEM_IN_IRAM`: affects the functions ``memccpy``, ``memchr``, ``memmove``, and ``memrchr``.
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBSTR_IN_IRAM`: affects the functions ``strcasecmp``, ``strcasestr``, ``strchr``, ``strcoll``, ``strcpy``, ``strcspn``, ``strdup``, ``strdup_r``, ``strlcat``, ``strlcpy``, ``strlen``, ``strlwr``, ``strncasecmp``, ``strncat``, ``strncmp``, ``strncpy``, ``strndup``, ``strndup_r``, ``strrchr``, ``strsep``, ``strspn``, ``strstr``, ``strtok_r, and ``strupr``.
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBRAND_IN_IRAM`: affects the functions ``srand``, ``rand``, and ``rand_r``.
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBENV_IN_IRAM`: affects the functions ``environ``, ``envlock``, and ``getenv_r``.
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBFILE_IN_IRAM`: affects the functions lock``, ``isatty``, ``fclose``, ``open``, ``close``, ``creat``, ``read``, ``rshift``, ``sbrk``, ``stdio``, ``syssbrk``, ``sysclose``, ``sysopen``, ``creat``, ``sysread``, ``syswrite``, ``impure``, ``fwalk``, and ``findfp``.
+       - :ref:`CONFIG_SPIRAM_CACHE_LIBMISC_IN_IRAM`: affects the functions ``raise`` and ``system``.
+
+   The exact amount of IRAM saved will depend on how much C library code is actually used by the application. In addition to these, the following options may be used to move more of the C library code into Flash, however note that this may result in reduced performance. Also take care to not use corresponding C library functions from interrupts which may be called while cache is disabled (allocated with :c:macro:`ESP_INTR_FLAG_IRAM` flag), refer to :ref:`iram-safe-interrupt-handlers` for more details. For these reasons, the functions ``itoa``, ``memcmp``, ``memcpy``, ``memset``, ``strcat``, ``strcmp``, and ``strlen`` are always put in IRAM.
+
 .. note::
 
     Moving frequently-called functions from IRAM to flash may increase their execution time.