Răsfoiți Sursa

Cache zuluscsi.ini file contents to speed up booting.

This cuts about 1 second from boot time by only reading the ini
once on boot and after SD card hotplug.
Petteri Aimonen 2 ani în urmă
părinte
comite
56e55d7361
5 a modificat fișierele cu 171 adăugiri și 9 ștergeri
  1. 7 9
      lib/minIni/minGlue.h
  2. 147 0
      lib/minIni/minIni_cache.cpp
  3. 10 0
      lib/minIni/minIni_cache.h
  4. 6 0
      src/BlueSCSI.cpp
  5. 1 0
      src/BlueSCSI_disk.cpp

+ 7 - 9
lib/minIni/minGlue.h

@@ -1,15 +1,13 @@
-/*  Glue functions for the minIni library to SdFat library */
+/*  Glue functions for the minIni library to the cache functions in minIni_cache.cpp */
 
 #include <SdFat.h>
 
-extern SdFs SD;
-
 #define INI_READONLY 1
 #define INI_FILETYPE                    FsFile
-#define ini_openread(filename,file)     ((file)->open(SD.vol(), filename, O_RDONLY))
-#define ini_close(file)                 ((file)->close())
-#define ini_read(buffer,size,file)      ((file)->fgets((buffer),(size)) > 0)
-
 #define INI_FILEPOS                     fspos_t
-#define ini_tell(file,pos)              ((file)->fgetpos(pos))
-#define ini_seek(file,pos)              ((file)->fsetpos(pos))
+
+bool ini_openread(const char *filename, INI_FILETYPE *fp);
+bool ini_close(INI_FILETYPE *fp);
+bool ini_read(char *buffer, int size, INI_FILETYPE *fp);
+void ini_tell(INI_FILETYPE *fp, INI_FILEPOS *pos);
+void ini_seek(INI_FILETYPE *fp, INI_FILEPOS *pos);

+ 147 - 0
lib/minIni/minIni_cache.cpp

@@ -0,0 +1,147 @@
+// Custom .ini file access caching layer for minIni.
+// This reduces boot delay by only reading the ini file once
+// after boot or SD-card removal.
+
+#include <minGlue.h>
+#include <SdFat.h>
+
+// This can be overridden in platformio.ini
+// Set to 0 to disable the cache.
+#ifndef INI_CACHE_SIZE
+#define INI_CACHE_SIZE 4096
+#endif
+
+// Use the SdFs instance from main program
+extern SdFs SD;
+
+static struct {
+    bool valid;
+    INI_FILETYPE *fp;
+
+#if INI_CACHE_SIZE > 0
+    const char *filename;
+    uint32_t filelen;
+    INI_FILEPOS current_pos;
+    char cachedata[INI_CACHE_SIZE];
+#endif
+} g_ini_cache;
+
+// Invalidate any cached file contents
+void invalidate_ini_cache()
+{
+    g_ini_cache.valid = false;
+    g_ini_cache.fp = NULL;
+}
+
+// Read the config file into RAM
+void reload_ini_cache(const char *filename)
+{
+    g_ini_cache.valid = false;
+    g_ini_cache.fp = NULL;
+
+#if INI_CACHE_SIZE > 0
+    g_ini_cache.filename = filename;
+    FsFile config = SD.open(filename, O_RDONLY);
+    g_ini_cache.filelen = config.fileSize();
+    if (config.isOpen() && g_ini_cache.filelen <= INI_CACHE_SIZE)
+    {
+        if (config.read(g_ini_cache.cachedata, g_ini_cache.filelen) == g_ini_cache.filelen)
+        {
+            g_ini_cache.valid = true;
+        }
+    }
+    config.close();
+#endif
+}
+
+// Open .ini file either from cache or from SD card
+bool ini_openread(const char *filename, INI_FILETYPE *fp)
+{
+#if INI_CACHE_SIZE > 0
+    if (g_ini_cache.valid &&
+        (filename == g_ini_cache.filename || strcmp(filename, g_ini_cache.filename) == 0))
+    {
+        fp->close();
+        g_ini_cache.fp = fp;
+        g_ini_cache.current_pos.position = 0;
+        return true;
+    }
+#endif
+
+    return fp->open(SD.vol(), filename, O_RDONLY);
+}
+
+// Close previously opened file
+bool ini_close(INI_FILETYPE *fp)
+{
+#if INI_CACHE_SIZE > 0
+    if (g_ini_cache.fp == fp)
+    {
+        g_ini_cache.fp = NULL;
+        return true;
+    }
+    else
+#endif
+    {
+        return fp->close();
+    }
+}
+
+// Read a single line from cache or from SD card
+bool ini_read(char *buffer, int size, INI_FILETYPE *fp)
+{
+#if INI_CACHE_SIZE > 0
+    if (g_ini_cache.fp == fp)
+    {
+        // Read one line from cache
+        uint32_t srcpos = g_ini_cache.current_pos.position;
+        int dstpos = 0;
+        while (srcpos < g_ini_cache.filelen &&
+               dstpos < size - 1)
+        {
+            char b = g_ini_cache.cachedata[srcpos++];
+            buffer[dstpos++] = b;
+
+            if (b == '\n') break;
+        }
+        buffer[dstpos] = 0;
+        g_ini_cache.current_pos.position = srcpos;
+        return dstpos > 0;
+    }
+    else
+#endif
+    {
+        // Read from SD card
+        return fp->fgets(buffer, size) > 0;
+    }
+}
+
+// Get the position inside the file
+void ini_tell(INI_FILETYPE *fp, INI_FILEPOS *pos)
+{
+#if INI_CACHE_SIZE > 0
+    if (g_ini_cache.fp == fp)
+    {
+        *pos = g_ini_cache.current_pos;
+    }
+    else
+#endif
+    {
+        fp->fgetpos(pos);
+    }
+}
+
+// Go back to previously saved position
+void ini_seek(INI_FILETYPE *fp, INI_FILEPOS *pos)
+{
+#if INI_CACHE_SIZE > 0
+    if (g_ini_cache.fp == fp)
+    {
+        g_ini_cache.current_pos = *pos;
+    }
+    else
+#endif
+    {
+        fp->fsetpos(pos);
+    }
+}

+ 10 - 0
lib/minIni/minIni_cache.h

@@ -0,0 +1,10 @@
+// Custom .ini file access caching layer for minIni.
+// This reduces boot delay by only reading the ini file once
+// after boot or SD-card removal.
+
+#pragma once
+
+void invalidate_ini_cache();
+
+// Note: filename must be statically allocated, pointer is stored.
+void reload_ini_cache(const char *filename);

+ 6 - 0
src/BlueSCSI.cpp

@@ -47,6 +47,7 @@
 
 #include <SdFat.h>
 #include <minIni.h>
+#include <minIni_cache.h>
 #include <string.h>
 #include <strings.h>
 #include <ctype.h>
@@ -491,9 +492,14 @@ void readSCSIDeviceConfig()
 
 static bool mountSDCard()
 {
+  invalidate_ini_cache();
+
   // Check for the common case, FAT filesystem as first partition
   if (SD.begin(SD_CONFIG))
+  {
+    reload_ini_cache(CONFIGFILE);
     return true;
+  }
 
   // Do we have any kind of card?
   if (!SD.card() || SD.sdErrorCode() != 0)

+ 1 - 0
src/BlueSCSI_disk.cpp

@@ -80,6 +80,7 @@ bool scsiIsReadFinished(const uint8_t *data)
 #endif
 
 // SD card sector size is always 512 bytes
+extern SdFs SD;
 #define SD_SECTOR_SIZE 512
 
 /************************************************/