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