<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div></div><div>We can menuconfig to change malloc to use spiram, but that is not really practical. Too inflexible. We really need a simple way to say allocate this in spiram if possible.</div><div><br></div><div>In a few months, it will be easier (as the IDF better supports explicit declarations for internal memory stuff).</div><div><br></div><div>The std allocator method may be a cleaner approach than a derived base class. I will look into it.</div><div><br></div><div>Regards, Mark</div><div><br>On 13 Jan 2018, at 2:30 AM, Michael Balzer <<a href="mailto:dexter@expeedo.de">dexter@expeedo.de</a>> wrote:<br><br></div><blockquote type="cite"><div>
  
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  
  
    Mark,<br>
    <br>
    a base class can also provide an malloc() override.<br>
    <br>
    Additionally, all standard containers can be instantiated with a
    custom Allocator. Default is std::allocator.<br>
    <br>
    <a class="moz-txt-link-freetext" href="http://en.cppreference.com/w/cpp/concept/Allocator">http://en.cppreference.com/w/cpp/concept/Allocator</a><br>
    <br>
    So with an SPIAllocator we can put the container management overhead
    into SPI RAM as well very easily. But that may affect performance
    badly on central lists & maps under load, we should be careful
    with that option.<br>
    <br>
    Regards,<br>
    Michael<br>
    <br>
    <br>
    <div class="moz-cite-prefix">Am 12.01.2018 um 03:09 schrieb Mark
      Webb-Johnson:<br>
    </div>
    <blockquote type="cite" cite="mid:CC7E6515-25EB-4E65-B2F7-D26CC6E9BBA5@webb-johnson.net">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <div class=""><br class="">
      </div>
      <div class="">Before:</div>
      <div class=""><br class="">
      </div>
      <blockquote style="margin: 0 0 0 40px; border: none; padding:
        0px;" class="">
        <div class="">
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">OVMS > module
                memory</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">============================</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">Free 8-bit
                4291676/4507468, 32-bit 1608/16760, blocks dumped = 0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=no task        
                total=  38116      0      0      0 change= +38116     +0
                    +0     +0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=esp_timer      
                total=  49628      0    644      0 change= +49628     +0
                  +644     +0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=main          
                 total=   9868      0      0  26924 change=  +9868    
                +0     +0 +26924</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=ipc0          
                 total=  11096      0      0      0 change= +11096    
                +0     +0     +0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=Housekeeping  
                 total=  44032      0      0     12 change= +44032    
                +0     +0    +12</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=ipc1          
                 total=     12      0      0      0 change=    +12    
                +0     +0     +0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=Tmr Svc        
                total=     16      0      0      0 change=    +16     +0
                    +0     +0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=tiT            
                total=      0      0      0    128 change=     +0     +0
                    +0   +128</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=AsyncConsole  
                 total=     20      0  14404  12000 change=    +20    
                +0 +14404 +12000</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">============================</span></font></div>
        </div>
      </blockquote>
      <div class=""><br class="">
      </div>
      <div class="">The change:</div>
      <div class=""><br class="">
      </div>
      <blockquote style="margin: 0 0 0 40px; border: none; padding:
        0px;" class="">
        <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">class OvmsCommand</span></font></div>
        <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">  {</span></font></div>
        <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">  public:</span></font></div>
        <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">    void* operator
              new(size_t sz) { return heap_caps_malloc(sz,
              MALLOC_CAP_SPIRAM); }</span></font></div>
        <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">    void operator delete
               (void* ptr) { return free(ptr); }</span></font></div>
      </blockquote>
      <div class=""><br class="">
      </div>
      <div class="">After:</div>
      <div class=""><br class="">
      </div>
      <blockquote style="margin: 0 0 0 40px; border: none; padding:
        0px;" class="">
        <div class="">
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">OVMS > module
                memory</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">============================</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">Free 8-bit
                4291676/4507468, 32-bit 1608/16760, blocks dumped = 0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=no task        
                total=  38116      0      0      0 change= +38116     +0
                    +0     +0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=esp_timer      
                total=  28708      0    644  20916 change= +28708     +0
                  +644 +20916</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=main          
                 total=   9868      0      0  26924 change=  +9868    
                +0     +0 +26924</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=ipc0          
                 total=  11096      0      0      0 change= +11096    
                +0     +0     +0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=Housekeeping  
                 total=  37984      0      0   6060 change= +37984    
                +0     +0  +6060</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=ipc1          
                 total=     12      0      0      0 change=    +12    
                +0     +0     +0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=Tmr Svc        
                total=     16      0      0      0 change=    +16     +0
                    +0     +0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=tiT            
                total=      0      0      0    128 change=     +0     +0
                    +0   +128</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">task=AsyncConsole  
                 total=  12020      0  14404      0 change= +12020    
                +0 +14404     +0</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">============================</span></font></div>
        </div>
      </blockquote>
      <div class=""><br class="">
      </div>
      <div class="">So, simply moving OvmsCommand objects to SPI RAM
        saves us about 26KB of internal RAM.</div>
      <div class=""><br class="">
      </div>
      <div class="">Our goal would be to move as much of our
        infrequently accessed stuff as possible to SPI RAM. This would
        free up as much internal ram as possible for things like stacks,
        DMA, etc.</div>
      <div class=""><br class="">
      </div>
      <div class="">Here are the restrictions on SPI RAM that Espressif
        point out:</div>
      <div class=""><br class="">
      </div>
      <blockquote style="margin: 0 0 0 40px; border: none; padding:
        0px;" class="">
        <div class="">
          <dl class="docutils" style="box-sizing: border-box; margin:
            0px 0px 24px; padding: 0px; list-style: none none; color:
            rgb(64, 64, 64); font-family: Lato, proxima-nova,
            "Helvetica Neue", Arial, sans-serif; font-size:
            16px;">
            <dt style="box-sizing: border-box; font-weight: bold;" class="">The use of external RAM has a few restrictions:</dt>
            <dd style="box-sizing: border-box; margin: 0px 0px 12px
              24px;" class="">
              <ul class="first last simple" style="box-sizing:
                border-box; margin: 0px 0px 24px; padding: 0px;
                list-style-position: initial; list-style-image: initial;
                line-height: 24px;">
                <li style="box-sizing: border-box; list-style: disc;
                  margin-left: 24px;" class="">When disabling flash
                  cache (for example, because the flash is being written
                  to), the external RAM also becomes inaccessible; any
                  reads from or writes to it will lead to an illegal
                  cache access exception. This is also the reason that
                  ESP-IDF will never allocate a tasks stack in external
                  RAM.</li>
                <li style="box-sizing: border-box; list-style: disc;
                  margin-left: 24px;" class="">External RAM cannot be
                  used as a place to store DMA transaction descriptors
                  or as a buffer for a DMA transfer to read from or
                  write into. Any buffers that will be used in
                  combination with DMA must be allocated using <code class="literal docutils" style="box-sizing:
                    border-box; font-family: Consolas, "Andale Mono
                    WT", "Andale Mono", "Lucida
                    Console", "Lucida Sans Typewriter",
                    "DejaVu Sans Mono", "Bitstream Vera
                    Sans Mono", "Liberation Mono",
                    "Nimbus Mono L", Monaco, "Courier
                    New", Courier, monospace; font-size: 12px;
                    white-space: nowrap; max-width: 100%;
                    background-color: rgb(255, 255, 255); border: 1px
                    solid rgb(225, 228, 229); padding: 2px 5px; color:
                    rgb(231, 76, 60); overflow-x: auto;
                    background-position: initial initial;
                    background-repeat: initial initial;"><span class="pre" style="box-sizing: border-box;">heap_caps_malloc(size,</span> <span class="pre" style="box-sizing: border-box;">MALLOC_CAP_DMA)</span></code> (and
                  can be freed using a standard <code class="literal
                    docutils" style="box-sizing: border-box;
                    font-family: Consolas, "Andale Mono WT",
                    "Andale Mono", "Lucida Console",
                    "Lucida Sans Typewriter", "DejaVu
                    Sans Mono", "Bitstream Vera Sans
                    Mono", "Liberation Mono",
                    "Nimbus Mono L", Monaco, "Courier
                    New", Courier, monospace; font-size: 12px;
                    white-space: nowrap; max-width: 100%;
                    background-color: rgb(255, 255, 255); border: 1px
                    solid rgb(225, 228, 229); padding: 2px 5px; color:
                    rgb(231, 76, 60); overflow-x: auto;
                    background-position: initial initial;
                    background-repeat: initial initial;"><span class="pre" style="box-sizing: border-box;">free()</span></code> call.)</li>
                <li style="box-sizing: border-box; list-style: disc;
                  margin-left: 24px;" class="">External RAM uses the
                  same cache region as the external flash. This means
                  that often accessed variables in external RAM can be
                  read and modified almost as quickly as in internal
                  ram. However, when accessing large chunks of data
                  (>32K), the cache can be insufficient and speeds
                  will fall back to the access speed of the external
                  RAM. Moreover, accessing large chunks of data can
                  ‘push out’ cached flash, possibly making execution of
                  code afterwards slower.</li>
                <li style="box-sizing: border-box; list-style: disc;
                  margin-left: 24px;" class="">External RAM cannot be
                  used as task stack memory; because of this,
                  xTaskCreate and similar functions will always allocate
                  internal memory for stack and task TCBs and
                  xTaskCreateStatic-type functions will check if the
                  buffers passed are internal. However, for tasks not
                  calling on code in ROM in any way, directly or
                  indirectly, the menuconfig option <a class="internal
                    reference" href="http://esp-idf.readthedocs.io/en/latest/api-reference/kconfig.html#config-spiram-allow-stack-external-memory" style="box-sizing: border-box; color: rgb(155, 89,
                    182); text-decoration: none; cursor: pointer;" moz-do-not-send="true">SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY</a> will
                  eliminate the check in xTaskCreateStatic, allowing
                  task stack in external RAM. Using this is not advised,
                  however.</li>
              </ul>
            </dd>
          </dl>
          <p style="box-sizing: border-box; line-height: 24px; margin:
            0px 0px 24px; font-size: 16px; color: rgb(64, 64, 64);
            font-family: Lato, proxima-nova, "Helvetica Neue",
            Arial, sans-serif;" class="">Because there are a fair few
            situations that have a specific need for internal memory,
            but it is also possible to use malloc() to exhaust internal
            memory, there is a pool reserved specifically for requests
            that cannot be resolved from external memory; allocating
            task stack, DMA buffers and memory that stays accessible
            when cache is disabled is drawn from this pool. The size of
            this pool is configurable in menuconfig.</p>
        </div>
      </blockquote>
      <div class="">
        <div class="">I’m not having much luck trying to globally
          override the new() and delete() memory allocators, so I’m now
          thinking of making a base class with new and delete operators,
          plus some other utility functions to make spi ram allocation
          easier. Then whenever we want to make one of our objects
          allocatable from spiram we simply derive from that base class.
          That class could pickup on the menuconfig hardware version
          (3.0 WROOM-32 vs 3.1 WROVER) and turn on/off SPIRAM
          appropriately.</div>
      </div>
      <div class=""><br class="">
      </div>
      <div class="">Here is how Espressif do it:</div>
      <div class=""><br class="">
      </div>
      <blockquote style="margin: 0 0 0 40px; border: none; padding:
        0px;" class="">
        <div class="">
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">IRAM_ATTR void
                *heap_caps_malloc_default( size_t size )</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">{</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">    if
                (malloc_alwaysinternal_limit==MALLOC_DISABLE_EXTERNAL_ALLOCS)
                {</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">        return
                heap_caps_malloc( size, MALLOC_CAP_DEFAULT |
                MALLOC_CAP_INTERNAL);</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">    } else {</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">        void *r;</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">        if (size <=
                malloc_alwaysinternal_limit) {</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">           
                r=heap_caps_malloc( size, MALLOC_CAP_DEFAULT |
                MALLOC_CAP_INTERNAL );</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">        } else {</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">           
                r=heap_caps_malloc( size, MALLOC_CAP_DEFAULT |
                MALLOC_CAP_SPIRAM );</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">        }</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">        if (r==NULL) {</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">            //try
                again while being less picky</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">           
                r=heap_caps_malloc( size, MALLOC_CAP_DEFAULT );</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">        }</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">        return r;</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">    }</span></font></div>
          <div class=""><font class="" face="Andale Mono"><span style="font-size: 14px;" class="">}</span></font></div>
        </div>
      </blockquote>
      <div class=""><br class="">
      </div>
      <div class="">We want to do the opposite - try to allocate from
        SPIRAM if it is available. There is a heap_caps_malloc_prefer
        that could do it for us.</div>
      <div class=""><br class="">
      </div>
      <div class="">Thoughts?</div>
      <div class=""><br class="">
      </div>
      <div class="">Regards, Mark.</div>
      <div class=""><br class="">
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">_______________________________________________
OvmsDev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:OvmsDev@lists.teslaclub.hk">OvmsDev@lists.teslaclub.hk</a>
<a class="moz-txt-link-freetext" href="http://lists.teslaclub.hk/mailman/listinfo/ovmsdev">http://lists.teslaclub.hk/mailman/listinfo/ovmsdev</a>
</pre>
    </blockquote>
    <br>
    <pre class="moz-signature" cols="160">-- 
Michael Balzer * Helkenberger Weg 9 * D-58256 Ennepetal
Fon 02333 / 833 5735 * Handy 0176 / 206 989 26
</pre>
  

</div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>OvmsDev mailing list</span><br><span><a href="mailto:OvmsDev@lists.teslaclub.hk">OvmsDev@lists.teslaclub.hk</a></span><br><span><a href="http://lists.teslaclub.hk/mailman/listinfo/ovmsdev">http://lists.teslaclub.hk/mailman/listinfo/ovmsdev</a></span><br></div></blockquote></body></html>