blob: 5557ad5d8c827d0bce3526095ec2c46859fed085 [file] [log] [blame]
<!--
Documentation/_templates/layout.html
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. The
ASF licenses this file to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
-->
<!DOCTYPE html>
<html class="writer-html5" lang="en">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>STM32 CCM Allocator &mdash; NuttX latest documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css" />
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css" />
<link rel="stylesheet" type="text/css" href="../_static/custom.css" />
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<script src="../_static/jquery.js"></script>
<script src="../_static/_sphinx_javascript_frameworks_compat.js"></script>
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<script src="../_static/clipboard.min.js"></script>
<script src="../_static/copybutton.js"></script>
<script src="../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Run time stack statistics" href="stackrecord.html" />
<link rel="prev" title="STM32 Null Pointer Detection" href="stm32nullpointer.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../index.html" class="icon icon-home"> NuttX
</a>
<!-- this version selector is quite ugly, should be probably replaced by something
more modern -->
<div class="version-selector">
<select onchange="javascript:location.href = this.value;">
<option value="../../latest" selected="selected">latest</option>
<option value="../../10.0.0" >10.0.0</option>
<option value="../../10.0.1" >10.0.1</option>
<option value="../../10.1.0" >10.1.0</option>
<option value="../../10.2.0" >10.2.0</option>
<option value="../../10.3.0" >10.3.0</option>
<option value="../../11.0.0" >11.0.0</option>
<option value="../../12.0.0" >12.0.0</option>
<option value="../../12.1.0" >12.1.0</option>
<option value="../../12.2.0" >12.2.0</option>
<option value="../../12.2.1" >12.2.1</option>
<option value="../../12.3.0" >12.3.0</option>
<option value="../../12.4.0" >12.4.0</option>
<option value="../../12.5.0" >12.5.0</option>
<option value="../../12.5.1" >12.5.1</option>
<option value="../../12.6.0" >12.6.0</option>
<option value="../../12.7.0" >12.7.0</option>
<option value="../../12.8.0" >12.8.0</option>
<option value="../../12.9.0" >12.9.0</option>
<option value="../../12.10.0" >12.10.0</option>
<option value="../../12.11.0" >12.11.0</option>
</select>
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Table of Contents</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../index.html">Home</a></li>
<li class="toctree-l1"><a class="reference internal" href="../introduction/index.html">Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="../quickstart/index.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="../contributing/index.html">Contributing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../introduction/inviolables.html">The Inviolable Principles of NuttX</a></li>
<li class="toctree-l1"><a class="reference internal" href="../platforms/index.html">Supported Platforms</a></li>
<li class="toctree-l1"><a class="reference internal" href="../components/index.html">OS Components</a></li>
<li class="toctree-l1"><a class="reference internal" href="../applications/index.html">Applications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../implementation/index.html">Implementation Details</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/index.html">API Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="../faq/index.html">FAQ</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Guides</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="nfs.html">NFS Client How-To</a></li>
<li class="toctree-l2"><a class="reference internal" href="usbtrace.html">USB Device Trace</a></li>
<li class="toctree-l2"><a class="reference internal" href="simulator.html">Simulator</a></li>
<li class="toctree-l2"><a class="reference internal" href="qemugdb.html">How to debug NuttX using QEMU and GDB</a></li>
<li class="toctree-l2"><a class="reference internal" href="rndis.html">How to use RNDIS</a></li>
<li class="toctree-l2"><a class="reference internal" href="drivers.html">Drivers</a></li>
<li class="toctree-l2"><a class="reference internal" href="tasktrace.html">Task Trace</a></li>
<li class="toctree-l2"><a class="reference internal" href="cpp_cmake.html">C++ Example using CMake</a></li>
<li class="toctree-l2"><a class="reference internal" href="pysimcoder.html">pysimCoder integration with NuttX</a></li>
<li class="toctree-l2"><a class="reference internal" href="customboards.html">Custom Boards How-To</a></li>
<li class="toctree-l2"><a class="reference internal" href="customapps.html">Custom Apps How-to</a></li>
<li class="toctree-l2"><a class="reference internal" href="citests.html">Running CI Test Locally</a></li>
<li class="toctree-l2"><a class="reference internal" href="zerolatencyinterrupts.html">High Performance: Zero Latency Interrupts, Maskable nested interrupts</a></li>
<li class="toctree-l2"><a class="reference internal" href="kasan.html">The Kernel Address Sanitizer (KASAN)</a></li>
<li class="toctree-l2"><a class="reference internal" href="nestedinterrupts.html">Nested Interrupts</a></li>
<li class="toctree-l2"><a class="reference internal" href="cortexmhardfaults.html">Analyzing Cortex-M Hardfaults</a></li>
<li class="toctree-l2"><a class="reference internal" href="coredump.html">Core Dump</a></li>
<li class="toctree-l2"><a class="reference internal" href="coresight.html">Coresight - HW Assisted Tracing on ARM</a></li>
<li class="toctree-l2"><a class="reference internal" href="gdbserver.html">gdbserver</a></li>
<li class="toctree-l2"><a class="reference internal" href="gdbwithpython.html">GDB with Python</a></li>
<li class="toctree-l2"><a class="reference internal" href="ofloader.html">Open Flash Loader</a></li>
<li class="toctree-l2"><a class="reference internal" href="testingtcpip.html">Testing TCP/IP Network Stacks</a></li>
<li class="toctree-l2"><a class="reference internal" href="automounter.html">Auto-Mounter</a></li>
<li class="toctree-l2"><a class="reference internal" href="stm32nullpointer.html">STM32 Null Pointer Detection</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">STM32 CCM Allocator</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#ccm-memory">CCM Memory</a></li>
<li class="toctree-l3"><a class="reference internal" href="#config-stm32-ccmexclude">CONFIG_STM32_CCMEXCLUDE</a></li>
<li class="toctree-l3"><a class="reference internal" href="#ccm-allocator">CCM Allocator</a></li>
<li class="toctree-l3"><a class="reference internal" href="#ccm-stacks">CCM Stacks</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="stackrecord.html">Run time stack statistics</a></li>
<li class="toctree-l2"><a class="reference internal" href="etcromfs.html">etc romfs</a></li>
<li class="toctree-l2"><a class="reference internal" href="thread_local_storage.html">Thread Local Storage</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../glossary.html">Glossary</a></li>
<li class="toctree-l1"><a class="reference internal" href="../logos/index.html">NuttX Logos</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">NuttX</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="index.html">Guides</a></li>
<li class="breadcrumb-item active">STM32 CCM Allocator</li>
<li class="wy-breadcrumbs-aside">
<a href="../_sources/guides/stm32ccm.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="stm32-ccm-allocator">
<h1>STM32 CCM Allocator<a class="headerlink" href="#stm32-ccm-allocator" title="Permalink to this heading"></a></h1>
<section id="ccm-memory">
<h2>CCM Memory<a class="headerlink" href="#ccm-memory" title="Permalink to this heading"></a></h2>
<p>The STM32 F2, F3, and F4 families have a special block of SRAM available called
CCM (Core Coupled Memory). This memory has the drawback that it cannot be used
for STM32 DMA operations.</p>
<p>By default, the CCM memory is lumped in with the rest of memory when the NuttX
heaps are created. But this can be a problem because it will be a toss of the
coin if non-DMA-able CCM memory or other DMA-able memory gets returned when
<code class="docutils literal notranslate"><span class="pre">malloc()</span></code> is called. That usually does not matter but it certainly does make
a difference if you are allocating memory that will be used for DMA! In that
case, getting CCM memory for your DMA buffer will cause a failure.</p>
</section>
<section id="config-stm32-ccmexclude">
<h2>CONFIG_STM32_CCMEXCLUDE<a class="headerlink" href="#config-stm32-ccmexclude" title="Permalink to this heading"></a></h2>
<p>There is a configuration option called <code class="docutils literal notranslate"><span class="pre">CONFIG_STM32_CCMEXCLUDE</span></code> that can be
used to exclude CCM memory from the heap. That solves the problem of getting
CCM memory when you want to allocate a DMA buffer. But then what do you do
with the CCM memory? Do you let it go unused?</p>
</section>
<section id="ccm-allocator">
<h2>CCM Allocator<a class="headerlink" href="#ccm-allocator" title="Permalink to this heading"></a></h2>
<p>In order to make use of the CCM memory, a CCM memory allocator is available.
This memory allocator is automatically enabled when the following options are set:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_STM32_CCMEXCLUDE</span></code> CCM memory is excluded from the normal heap, and</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_MM_MULTIHEAP</span></code> Support for multiple heaps is enabled.</p></li>
</ul>
<p>Under those conditions, the CCM memory allocator is enabled and the allocator
interfaces prototyped in the <code class="docutils literal notranslate"><span class="pre">arch/arm/src/stm32/stm32_ccm.h</span></code> are available.</p>
<p>NOTE: These interfaces are, technically, not prototyped since they are really
provided via C pre-processor macros.</p>
<p>NOTE: In order to use the CCM memory allocator functions, you must first call
<code class="docutils literal notranslate"><span class="pre">ccm_initialize()</span></code> somewhere in your early boot-up logic.</p>
<p>With these interfaces you have a (nearly) standard way to manage memory from a
heap that consists of the the CCM SRAM. And, since the CCM memory is no longer
a part of the normal heap, all allocated I/O buffers will be DMA-able (unless you
have included other non-DMA-able memory regions in the stack).</p>
</section>
<section id="ccm-stacks">
<h2>CCM Stacks<a class="headerlink" href="#ccm-stacks" title="Permalink to this heading"></a></h2>
<p>One particular problem that has been reported by Petteri Aimonen requires some
additional work-arounds. The STM32 SPI driver supports DMA and with SPI it is
sometimes necessary to do some very small transfers for which there is no real
gain from using DMA. In this case, Petteri has devised a clever way to both 1) make
use of the CMM memory and 2) to force fallback to non-DMA transfers for these small
stack transfers.</p>
<p>Here is what Petteri has done:</p>
<ol class="arabic">
<li><p>First, he has modified <code class="docutils literal notranslate"><span class="pre">arch/arm/src/common/up_createstack.c</span></code> and
<code class="docutils literal notranslate"><span class="pre">up_releasestack.c</span></code> so that stacks are allocated from CCM memory. That
allocation is something like the following:</p>
<div class="highlight-C notranslate"><div class="highlight"><pre><span></span><span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ccm_zalloc</span><span class="p">(</span><span class="n">size</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">result</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="cm">/* Fall back to main heap */</span>
<span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zalloc</span><span class="p">(</span><span class="n">size</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
</pre></div>
</div>
<p>With the matching:</p>
<div class="highlight-C notranslate"><div class="highlight"><pre><span></span><span class="k">if</span><span class="w"> </span><span class="p">(((</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">p</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="mh">0xF0000000</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mh">0x10000000</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">ccm_free</span><span class="p">(</span><span class="n">p</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="k">else</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">free</span><span class="p">(</span><span class="n">p</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
</pre></div>
</div>
</li>
<li><p>Then Petteri added special DMA support enabled with <code class="docutils literal notranslate"><span class="pre">CONFIG_STM32_DMACAPABLE</span></code>.
That option enables an option in all of the DMA logic called:</p>
<div class="highlight-C notranslate"><div class="highlight"><pre><span></span><span class="kt">bool</span><span class="w"> </span><span class="nf">stm32_dmacapable</span><span class="p">(</span><span class="kt">uint32_t</span><span class="w"> </span><span class="n">maddr</span><span class="p">);</span>
</pre></div>
</div>
<p>That will return true if it is possible to do DMA from the address and false
if not.</p>
</li>
<li><p>Finally, Petteri added logic to the STM32 SPI driver that use <code class="docutils literal notranslate"><span class="pre">stm32_dmacapable()</span></code>:
If the address is not DMA capable, then the SPI driver will fall back to
non-DMA operation.</p>
<p>With Petteri’s changes all of the large I/O buffers will be allocated from
DMA-able memory. All stacks will be allocated from non-DMA-able CCM memory
(provided that there is space). Small SPI DMA buffers on the non-DMA-able stack
will be detected by <code class="docutils literal notranslate"><span class="pre">stm32_dmacapable()</span></code> and in that case, the STM32 SPI driver
will fall back and use non-DMA-transfers.</p>
<p>From all reports this works quite well.</p>
</li>
</ol>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="stm32nullpointer.html" class="btn btn-neutral float-left" title="STM32 Null Pointer Detection" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="stackrecord.html" class="btn btn-neutral float-right" title="Run time stack statistics" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, The Apache Software Foundation.</p>
</div>
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>