<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>