<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    Ok, so as long as we don't do I/O (DMA presumed) from buffer inside
    a new'd object, we should be good.  The overall call-back
    architecture should favor the cache, so I'm not thinking there would
    be a lot of impact.<br>
    <br>
    Greg<br>
    <br>
    <br>
    <div class="moz-cite-prefix">Mark Webb-Johnson wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:96C535E2-87D2-4282-AE58-11EC22D4C63D@webb-johnson.net">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      Here is the Espressif document on it:
      <div class=""><br class="">
      </div>
      <blockquote style="margin: 0 0 0 40px; border: none; padding:
        0px;" class="">
        <div class=""><a
href="http://esp-idf.readthedocs.io/en/latest/api-guides/external-ram.html"
            class="" moz-do-not-send="true">http://esp-idf.readthedocs.io/en/latest/api-guides/external-ram.html</a></div>
        <div class=""><br class="">
        </div>
        <div class="">
          <h3 style="box-sizing: border-box; margin-top: 0px;
            font-family: "Roboto Slab", ff-tisa-web-pro,
            Georgia, Arial, sans-serif; font-size: 20px; color: rgb(64,
            64, 64); font-variant-ligatures: normal; orphans: 2; widows:
            2; background-color: rgb(252, 252, 252);" class="">Restrictions</h3>
          <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; font-variant-ligatures: normal; orphans: 2; widows: 2;
            background-color: rgb(252, 252, 252);">
            <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:
                    rgb(255, 255, 255); border: 1px solid rgb(225, 228,
                    229); padding: 2px 5px; color: rgb(231, 76, 60);
                    overflow-x: auto;"><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:
                    rgb(255, 255, 255); border: 1px solid rgb(225, 228,
                    229); padding: 2px 5px; color: rgb(231, 76, 60);
                    overflow-x: auto;"><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>
        </div>
      </blockquote>
      <div class="">
        <div><br class="">
        </div>
        <div>The way it works is that SPIRAM is accessed using SPI
          protocol at 40Mhz. The same speed and protocol as for flash
          memory for code. Then, a portion of internal ram is reserved
          as a cache (for both SPI ram and flash). Think of it as
          something like swap.</div>
        <div><br class="">
        </div>
        <div>Hard to guess as to performance impact, as it depends on
          cache hit rates. I would expect it to behave approximately the
          same as flash code access (same protocol, same bus speed).</div>
        <div><br class="">
        </div>
        <div>Regards, Mark.</div>
        <div><br class="">
          <blockquote type="cite" class="">
            <div class="">On 20 Feb 2018, at 10:36 AM, Greg D. <<a
                href="mailto:gregd2350@gmail.com" class=""
                moz-do-not-send="true">gregd2350@gmail.com</a>>
              wrote:</div>
            <br class="Apple-interchange-newline">
            <div class="">
              <meta http-equiv="Content-Type" content="text/html;
                charset=UTF-8" class="">
              <div text="#000000" bgcolor="#FFFFFF" class=""> Probably
                worth trying, at least.  That was kind of what I was
                thinking we would do. <br class="">
                <br class="">
                I think the only storage I access really frequently is
                already procedure-local, so should be on the stack.  Are
                there any restrictions on doing I/O to/from SPIRAM?  For
                example, I/O buffers aimed at a CAN bus?<br class="">
                <br class="">
                For the proverbial back-of-the-envelope purposes, what
                is the access speed for SPIRAM?  Also, what access
                granularity (i.e. is there a fundamental "block" that
                gets transacted, or is this a sizeof-level thing)?<br
                  class="">
                <br class="">
                Greg<br class="">
                <br class="">
                <br class="">
                <div class="moz-cite-prefix">Mark Webb-Johnson wrote:<br
                    class="">
                </div>
                <blockquote type="cite"
                  cite="mid:BFFE55DE-5E2E-450D-A16B-FB2BFCE3579C@webb-johnson.net"
                  class="">
                  <meta http-equiv="Content-Type" content="text/html;
                    charset=UTF-8" class="">
                  <div class=""><br class="">
                  </div>
                  Another interesting approach:
                  <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: 18px;" class="">main/ovms.cpp:</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class=""><br
                              class="">
                          </span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">
                            <div class="">void* operator new(std::size_t
                              sz)</div>
                            <div class="">  {</div>
                            <div class="">  return
                              ExternalRamMalloc(sz);</div>
                            <div class="">  }</div>
                          </span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class=""><br
                              class="">
                          </span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">OVMS >
                            module memory</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">Free 8-bit
                            197400/282424, 32-bit 424/27596, SPIRAM
                            4113632/4194252</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">--Task--  
                              Total DRAM D/IRAM   IRAM SPIRAM   +/- DRAM
                            D/IRAM   IRAM SPIRAM</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">esp_timer
                                    17068      0    644  35676    
                            +17068     +0   +644 +35676</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">main      
                                   12452      0      0   5352     +12452
                                +0     +0  +5352</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">Housekeeping
                                 28404      0      0  17292     +28404  
                              +0     +0 +17292</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">tiT      
                                        0      0      0    132        
                            +0     +0     +0   +132</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">AsyncConsole
                                     0      0  26404     20         +0  
                              +0 +26404    +20</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">no task  
                                     5348      0      0      0    
                             +5348     +0     +0     +0</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">ipc0      
                                   10848      0      0      0     +10848
                                +0     +0     +0</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">ipc1      
                                      12      0      0      0        +12
                                +0     +0     +0</span></font></div>
                      <div class=""><font class="" face="Andale Mono"><span
                            style="font-size: 18px;" class="">Tmr Svc  
                                     7328      0      0      0    
                             +7328     +0     +0     +0</span></font></div>
                    </div>
                    <div class=""><font class="" face="Andale Mono"><span
                          style="font-size: 18px;" class=""><br class="">
                        </span></font></div>
                    <div class=""><font class="" face="Andale Mono"><span
                          style="font-size: 18px;" class="">With WIFI
                          enabled and connected to an access point:</span></font></div>
                    <div class=""><font class="" face="Andale Mono"><span
                          style="font-size: 18px;" class=""><br class="">
                        </span></font></div>
                    <div class=""><font class="" face="Andale Mono"><span
                          style="font-size: 18px;" class="">
                          <div class="">OVMS > module memory</div>
                          <div class="">Free 8-bit 163600/282424, 32-bit
                            424/27596, SPIRAM 4110952/4194252</div>
                        </span></font></div>
                  </blockquote>
                  <div class="">
                    <div class=""><br class="">
                    </div>
                    <div class="">That is a global override for all C++
                      objects to be allocated from SPIRAM. I bet you
                      haven’t seen so much free internal RAM on an ESP32
                      before...</div>
                    <div class=""><br class="">
                    </div>
                    <div class="">There are also some C code malloc’s
                      that we could move over as well (the most obvious
                      being javascript duktape, of course, but also
                      mongoose).</div>
                    <div class=""><br class="">
                    </div>
                    <div class="">I’m wondering if there is any reason
                      not to simply do this global override for C++
                      code? Any stuff that won’t work in SPIRAM could
                      explicitly malloc what it needs.</div>
                    <div class=""><br class="">
                    </div>
                    <div class="">Regards, Mark.</div>
                    <div class=""><br class="">
                      <blockquote type="cite" class="">
                        <div class="">On 17 Feb 2018, at 9:41 PM, Mark
                          Webb-Johnson <<a
                            href="mailto:mark@webb-johnson.net" class=""
                            moz-do-not-send="true">mark@webb-johnson.net</a>>
                          wrote:</div>
                        <br class="Apple-interchange-newline">
                        <div class="">
                          <div class="">There is a significant
                            performance hit using SPI vs internal ram.
                            There are also restrictions (such as no
                            stacks, no dma targets, ISRs, etc). I’ve
                            tried just changing Malloc to use SPI ram
                            but the Espressif idf libraries don’t work.
                            Maybe in 3-6 months, but not today.<br
                              class="">
                            <br class="">
                            I still have to solve the problem of std::
                            objects (strings, etc). I think a new c++
                            memory allocator should work.<br class="">
                            <br class="">
                            Regards, Mark<br class="">
                            <br class="">
                            <blockquote type="cite" class="">On 17 Feb
                              2018, at 9:33 AM, Stephen Casner <<a
                                href="mailto:casner@acm.org" class=""
                                moz-do-not-send="true">casner@acm.org</a>>
                              wrote:<br class="">
                              <br class="">
                              Mark,<br class="">
                              <br class="">
                              This looks good to me (LGTM), but there
                              might be cases where we need<br class="">
                              to avoid adding the new
                              ExternalRamAllocated class as a base for a<br
                                class="">
                              building-block class and instead add it as
                              a base of a subset of the<br class="">
                              classes that derive from the
                              building-block class.<br class="">
                              <br class="">
                              If there isn't any significant performance
                              hit going to SPIRAM, then I<br class="">
                              expect most allocations other than stacks
                              and DMA buffers can go<br class="">
                              there.<br class="">
                              <br class="">
                                                      -- Steve<br
                                class="">
                              <br class="">
                              <blockquote type="cite" class="">On Fri,
                                16 Feb 2018, Mark Webb-Johnson wrote:<br
                                  class="">
                                <br class="">
                                <br class="">
                                I’ve committed (and pushed) an
                                experimental extension to allow C++
                                objects to be optionally moved to SPI
                                RAM.<br class="">
                                <br class="">
                                The code is in ovms.h, so should be
                                easily accessible to everything. It is
                                pretty simple:<br class="">
                                <br class="">
                                We have a new class
                                ‘ExternalRamAllocated’. That does
                                nothing except override the new and
                                new[] operators.<br class="">
                                <br class="">
                                Those operators try to malloc from SPI
                                RAM first. If that doesn’t succeed then
                                they fall back to standard internal RAM.<br
                                  class="">
                                <br class="">
                                The definition of a C++ class can then
                                be changed to make it “: public
                                ExternalRamAllocated”. Once that is
                                done, any objects of that class
                                allocated will try to be placed in
                                external (SPI) RAM.<br class="">
                                <br class="">
                                For other malloc uses, a general purpose
                                'void* ExternalRamMalloc(std::size_t
                                sz)’ function is also provided.<br
                                  class="">
                                <br class="">
                                To test this, I’ve made a one line
                                change to the OvmsCommand class:<br
                                  class="">
                                <br class="">
                                -class OvmsCommand<br class="">
                                +class OvmsCommand : public
                                ExternalRamAllocated<br class="">
                                <br class="">
                                Here is what the memory usage looks
                                like:<br class="">
                                <br class="">
                                With SPI RAM disabled (in menuconfig):<br
                                  class="">
                                <br class="">
                                Free 8-bit 120844/284304, 32-bit
                                30508/57680, SPIRAM 0/0<br class="">
                                --Task--     Total DRAM D/IRAM   IRAM
                                SPIRAM   +/- DRAM D/IRAM   IRAM SPIRAM<br
                                  class="">
                                no task            5312      0      0
                                     0      +5312     +0     +0     +0<br
                                  class="">
                                esp_timer         52328      0    644
                                     0     +52328     +0   +644     +0<br
                                  class="">
                                main              16448      0      0
                                     0     +16448     +0     +0     +0<br
                                  class="">
                                ipc0              11096      0      0
                                     0     +11096     +0     +0     +0<br
                                  class="">
                                Housekeeping      40576   5120      0
                                     0     +40576  +5120     +0     +0<br
                                  class="">
                                tiT                 128      0      0
                                     0       +128     +0     +0     +0<br
                                  class="">
                                Tmr Svc             884   6444      0
                                     0       +884  +6444     +0     +0<br
                                  class="">
                                ipc1                 12      0      0
                                     0        +12     +0     +0     +0<br
                                  class="">
                                AsyncConsole         20      0  26404
                                     0        +20     +0 +26404     +0<br
                                  class="">
                                <br class="">
                                Without deriving OvmsCommand from
                                ExternalRamAllocated:<br class="">
                                <br class="">
                                Free 8-bit 119240/282436, 32-bit
                                424/27596, SPIRAM 4193924/4194252<br
                                  class="">
                                --Task--     Total DRAM D/IRAM   IRAM
                                SPIRAM   +/- DRAM D/IRAM   IRAM SPIRAM<br
                                  class="">
                                tiT                   0      0      0
                                   128         +0     +0     +0   +128<br
                                  class="">
                                Housekeeping      40564   5120      0
                                    12     +40564  +5120     +0    +12<br
                                  class="">
                                no task            5348      0      0
                                     0      +5348     +0     +0     +0<br
                                  class="">
                                esp_timer         52328      0    644
                                     0     +52328     +0   +644     +0<br
                                  class="">
                                main              16448      0      0
                                     0     +16448     +0     +0     +0<br
                                  class="">
                                ipc0              11096      0      0
                                     0     +11096     +0     +0     +0<br
                                  class="">
                                ipc1                 12      0      0
                                     0        +12     +0     +0     +0<br
                                  class="">
                                Tmr Svc             884   6444      0
                                     0       +884  +6444     +0     +0<br
                                  class="">
                                AsyncConsole         20      0  26404
                                     0        +20     +0 +26404     +0<br
                                  class="">
                                <br class="">
                                After deriving OvmsCommand from
                                ExternalRamAllocated:<br class="">
                                <br class="">
                                OVMS > module memory<br class="">
                                Free 8-bit 152308/282432, 32-bit
                                424/27596, SPIRAM 4160852/4194252<br
                                  class="">
                                --Task--     Total DRAM D/IRAM   IRAM
                                SPIRAM   +/- DRAM D/IRAM   IRAM SPIRAM<br
                                  class="">
                                esp_timer         31664      0    644
                                 20664     +31664     +0   +644 +20664<br
                                  class="">
                                tiT                   0      0      0
                                   128         +0     +0     +0   +128<br
                                  class="">
                                Housekeeping      39636      0      0
                                  6060     +39636     +0     +0  +6060<br
                                  class="">
                                no task            5348      0      0
                                     0      +5348     +0     +0     +0<br
                                  class="">
                                main              16448      0      0
                                     0     +16448     +0     +0     +0<br
                                  class="">
                                ipc0              11096      0      0
                                     0     +11096     +0     +0     +0<br
                                  class="">
                                ipc1                 12      0      0
                                     0        +12     +0     +0     +0<br
                                  class="">
                                Tmr Svc            7328      0      0
                                     0      +7328     +0     +0     +0<br
                                  class="">
                                AsyncConsole         20      0  26404
                                     0        +20     +0 +26404     +0<br
                                  class="">
                                <br class="">
                                The advantage of SPI RAM is obvious.
                                30KB of internal RAM saved with just one
                                line changed in a header file. Most of
                                our other objects like that (metrics,
                                configs, etc) could be equally easily
                                moved to SPI RAM. We can make the
                                decision on a class-by-class basis.<br
                                  class="">
                                <br class="">
                                I think this is a pretty good solution.
                                It puts the onus of the decision of
                                whether to put into SPI RAM into the
                                object itself (as presumably the object
                                knows best whether it can actually be
                                put in SPI RAM). It is also extremely
                                simple to define that.<br class="">
                                <br class="">
                                But, it is an experiment. Please let me
                                know what you think.<br class="">
                                <br class="">
                                Regards, Mark.<br class="">
                                <br class="">
                              </blockquote>
_______________________________________________<br class="">
                              OvmsDev mailing list<br class="">
                              <a
                                href="mailto:OvmsDev@lists.teslaclub.hk"
                                class="" moz-do-not-send="true">OvmsDev@lists.teslaclub.hk</a><br
                                class="">
                              <a class="moz-txt-link-freetext"
                                href="http://lists.teslaclub.hk/mailman/listinfo/ovmsdev"
                                moz-do-not-send="true">http://lists.teslaclub.hk/mailman/listinfo/ovmsdev</a><br
                                class="">
                            </blockquote>
                            <br class="">
_______________________________________________<br class="">
                            OvmsDev mailing list<br class="">
                            <a href="mailto:OvmsDev@lists.teslaclub.hk"
                              class="" moz-do-not-send="true">OvmsDev@lists.teslaclub.hk</a><br
                              class="">
                            <a class="moz-txt-link-freetext"
                              href="http://lists.teslaclub.hk/mailman/listinfo/ovmsdev"
                              moz-do-not-send="true">http://lists.teslaclub.hk/mailman/listinfo/ovmsdev</a><br
                              class="">
                          </div>
                        </div>
                      </blockquote>
                    </div>
                    <br class="">
                  </div>
                  <br class="">
                  <fieldset class="mimeAttachmentHeader"></fieldset>
                  <br class="">
                  <pre class="" wrap="">_______________________________________________
OvmsDev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:OvmsDev@lists.teslaclub.hk" moz-do-not-send="true">OvmsDev@lists.teslaclub.hk</a>
<a class="moz-txt-link-freetext" href="http://lists.teslaclub.hk/mailman/listinfo/ovmsdev" moz-do-not-send="true">http://lists.teslaclub.hk/mailman/listinfo/ovmsdev</a>
</pre>
                </blockquote>
                <br class="">
              </div>
              _______________________________________________<br
                class="">
              OvmsDev mailing list<br class="">
              <a href="mailto:OvmsDev@lists.teslaclub.hk" class=""
                moz-do-not-send="true">OvmsDev@lists.teslaclub.hk</a><br
                class="">
              <a class="moz-txt-link-freetext" href="http://lists.teslaclub.hk/mailman/listinfo/ovmsdev">http://lists.teslaclub.hk/mailman/listinfo/ovmsdev</a><br
                class="">
            </div>
          </blockquote>
        </div>
        <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>
  </body>
</html>