blob: 4a934fabe24b316f4995f4a530d6dda5ca079bdc [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.19: https://docutils.sourceforge.io/" />
<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/sphinx_collapse.css" />
<link rel="stylesheet" type="text/css" href="../_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.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/design-tabs.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="etc romfs" href="etcromfs.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"><a class="reference internal" href="../debugging/index.html">Debugging</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="nix_flake.html">Nix Flake for Reproducible Development</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="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="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="fortify.html">Fortify</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="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="etcromfs.html">etc romfs</a></li>
<li class="toctree-l2"><a class="reference internal" href="thread_local_storage.html">Thread Local Storage</a></li>
<li class="toctree-l2"><a class="reference internal" href="devicetree.html">Device Tree</a></li>
<li class="toctree-l2"><a class="reference internal" href="changing_systemclockconfig.html">Changing the System Clock Configuration</a></li>
<li class="toctree-l2"><a class="reference internal" href="usingkernelthreads.html">Using Kernel Threads</a></li>
<li class="toctree-l2"><a class="reference internal" href="armv7m_runtimestackcheck.html">ARMv7-M Run Time Stack Checking</a></li>
<li class="toctree-l2"><a class="reference internal" href="include_files_board_h.html">Including Files in board.h</a></li>
<li class="toctree-l2"><a class="reference internal" href="specialstuff_in_nuttxheaderfiles.html">Why can’t I put my special stuff in NuttX header files?</a></li>
<li class="toctree-l2"><a class="reference internal" href="kernel_threads_with_custom_stacks.html">Kernel Threads with Custom Stacks</a></li>
<li class="toctree-l2"><a class="reference internal" href="versioning_and_task_names.html">Versioning and Task Names</a></li>
<li class="toctree-l2"><a class="reference internal" href="logging_rambuffer.html">Logging to a RAM Buffer</a></li>
<li class="toctree-l2"><a class="reference internal" href="ipv6.html">IPv6</a></li>
<li class="toctree-l2"><a class="reference internal" href="integrate_newlib.html">Integrating with Newlib</a></li>
<li class="toctree-l2"><a class="reference internal" href="protected_build.html">NuttX Protected Build</a></li>
<li class="toctree-l2"><a class="reference internal" href="platform_directories.html">Platform Directories</a></li>
<li class="toctree-l2"><a class="reference internal" href="port_drivers_to_stm32f7.html">Porting Drivers to the STM32 F7</a></li>
<li class="toctree-l2"><a class="reference internal" href="semihosting.html">Semihosting</a></li>
<li class="toctree-l2"><a class="reference internal" href="renode.html">Run NuttX on Renode</a></li>
<li class="toctree-l2"><a class="reference internal" href="signal_events_interrupt_handlers.html">Signaling Events from Interrupt Handlers</a></li>
<li class="toctree-l2"><a class="reference internal" href="signaling_sem_priority_inheritance.html">Signaling Semaphores and Priority Inheritance</a></li>
<li class="toctree-l2"><a class="reference internal" href="smaller_vector_tables.html">Smaller Vector Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="port.html">How to port</a></li>
<li class="toctree-l2"><a class="reference internal" href="updating_release_system_elf.html">Updating a Release System with ELF Programs</a></li>
<li class="toctree-l2"><a class="reference internal" href="partially_linked_elf.html">ELF Programs – With Symbol Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="fully_linked_elf.html">ELF Programs – No Symbol Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="building_nuttx_with_app_out_of_src_tree.html">Building NuttX with Applications Outside the Source Tree</a></li>
<li class="toctree-l2"><a class="reference internal" href="building_uclibcpp.html">Building uClibc++</a></li>
<li class="toctree-l2"><a class="reference internal" href="custom_app_directories.html">Custom Application Directories</a></li>
<li class="toctree-l2"><a class="reference internal" href="multiple_nsh_sessions.html">Multiple NSH Sessions</a></li>
<li class="toctree-l2"><a class="reference internal" href="nsh_network_link_management.html">NSH Network Link Management</a></li>
<li class="toctree-l2"><a class="reference internal" href="ram_rom_disks.html">RAM Disks and ROM Disks</a></li>
<li class="toctree-l2"><a class="reference internal" href="reading_can_msgs.html">Reading CAN Messages</a></li>
<li class="toctree-l2"><a class="reference internal" href="remove_device_drivers_nsh.html">Removing Device Drivers with NSH</a></li>
<li class="toctree-l2"><a class="reference internal" href="rust.html">Rust in NuttX</a></li>
<li class="toctree-l2"><a class="reference internal" href="optee.html">Interfacing with OP-TEE</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../standards/index.html">Standards</a></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>
<li class="toctree-l1"><a class="reference internal" href="../_tags/tagsindex.html">Tags</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="https://github.com/apache/nuttx/blob/master/Documentation/guides/stm32ccm.rst" class="fa fa-github"> Edit on GitHub</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="etcromfs.html" class="btn btn-neutral float-right" title="etc romfs" 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>