blob: c752677551b2eb222ebd6d6dd4269fcc225c8ae1 [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>Notes on AVR context switch &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="CEVA" href="../../ceva/index.html" />
<link rel="prev" title="Keeping constants in program memory" href="constants-in-progmem.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 current"><a class="reference internal" href="../../index.html">Supported Platforms</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../../arm/index.html">ARM</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../arm64/index.html">ARM64</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="../index.html">Microchip AVR</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="../at32uc3/index.html">Microchip AT32UC3</a></li>
<li class="toctree-l3"><a class="reference internal" href="../at90usb/index.html">Microchip AT90USB</a></li>
<li class="toctree-l3"><a class="reference internal" href="../atmega/index.html">Microchip Atmega</a></li>
<li class="toctree-l3"><a class="reference internal" href="../avrdx/index.html">Microchip DA/DB family</a></li>
<li class="toctree-l3"><a class="reference internal" href="constants-in-progmem.html">Keeping constants in program memory</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">Notes on AVR context switch</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#used-terms-and-context-switch-basics">Used terms and context switch basics</a><ul>
<li class="toctree-l5"><a class="reference internal" href="#context-creation">Context creation</a></li>
<li class="toctree-l5"><a class="reference internal" href="#task-resumption">Task resumption</a></li>
</ul>
</li>
<li class="toctree-l4"><a class="reference internal" href="#context-switch">Context switch</a><ul>
<li class="toctree-l5"><a class="reference internal" href="#st-combination">1st combination</a></li>
<li class="toctree-l5"><a class="reference internal" href="#nd">2nd</a></li>
<li class="toctree-l5"><a class="reference internal" href="#rd">3rd</a></li>
<li class="toctree-l5"><a class="reference internal" href="#th">4th</a></li>
</ul>
</li>
<li class="toctree-l4"><a class="reference internal" href="#avrdx-core-considerations">AVRDx core considerations</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../../ceva/index.html">CEVA</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../hc/index.html">HC</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../mips/index.html">MIPS</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../misco/index.html">Misoc</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../or1k/index.html">OpenRISC</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../renesas/index.html">Renesas</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../risc-v/index.html">RISC-V</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../sim/index.html">Simulators</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../sim/network_linux.html">Network Support on Linux</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../sim/network_vpnkit.html">Network support with VPNKit</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../sparc/index.html">SPARC</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../tricore/index.html">TriCore</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../x86/index.html">Intel 80x86</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../x86_64/index.html">Intel 80x86_64</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../xtensa/index.html">Xtensa</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../z16/index.html">Z16</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../z80/index.html">Z80</a></li>
</ul>
</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"><a class="reference internal" href="../../../guides/index.html">Guides</a></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">Supported Platforms</a></li>
<li class="breadcrumb-item"><a href="../index.html">Microchip AVR</a></li>
<li class="breadcrumb-item active">Notes on AVR context switch</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/apache/nuttx/blob/master/Documentation/platforms/avr/common/context-switch-notes.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="notes-on-avr-context-switch">
<h1>Notes on AVR context switch<a class="headerlink" href="#notes-on-avr-context-switch" title="Permalink to this heading"></a></h1>
<p>This document describes the ways and circumstances in which context
switches happen in AVR MCUs.</p>
<section id="used-terms-and-context-switch-basics">
<h2>Used terms and context switch basics<a class="headerlink" href="#used-terms-and-context-switch-basics" title="Permalink to this heading"></a></h2>
<section id="context-creation">
<h3>Context creation<a class="headerlink" href="#context-creation" title="Permalink to this heading"></a></h3>
<p>There are two ways context is created when a task is suspended.
Either the task is suspended in response to a hardware interrupt
(context created <code class="docutils literal notranslate"><span class="pre">in-interrupt</span></code> in the following text), or it is
suspended voluntarily, eg. by calling sleep(), read() etc.
(<code class="docutils literal notranslate"><span class="pre">in-task</span></code> context.)</p>
<p>The resulting context is identical and interchangeable with two differences:</p>
<blockquote>
<div><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">SREG</span></code> - <code class="docutils literal notranslate"><span class="pre">in-interrupt</span></code> context has global interrupt enabled (“I”-flag) set</p></li>
<li><p>position in the program where the task resumes running (arbitrary point for <code class="docutils literal notranslate"><span class="pre">in-interrupt</span></code> vs. inside <code class="docutils literal notranslate"><span class="pre">up_switch_context()</span></code> for <code class="docutils literal notranslate"><span class="pre">in-task</span></code></p></li>
</ul>
</div></blockquote>
</section>
<section id="task-resumption">
<h3>Task resumption<a class="headerlink" href="#task-resumption" title="Permalink to this heading"></a></h3>
<p>Task can be resumed in two corresponding situations - context switch
in response to a hardware interrupt (<code class="docutils literal notranslate"><span class="pre">by-interrupt</span></code>) or in response
to other task relinquishing the CPU (<code class="docutils literal notranslate"><span class="pre">by-task</span></code>)</p>
</section>
</section>
<section id="context-switch">
<h2>Context switch<a class="headerlink" href="#context-switch" title="Permalink to this heading"></a></h2>
<p>Two ways of context creation combined with two ways of task resumption
give 4 possibilities of context switch process, two of which are
not interesting:</p>
<section id="st-combination">
<h3>1st combination<a class="headerlink" href="#st-combination" title="Permalink to this heading"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">in-task</span></code> context resumed in <code class="docutils literal notranslate"><span class="pre">by-task</span></code> context switch. Context
to be resumed has “I” flag cleared and SREG is restored with that flag cleared.
The <code class="docutils literal notranslate"><span class="pre">ret</span></code> instruction is used to resume the task,”returning” to the point
where it gave the CPU up, which is inside <code class="docutils literal notranslate"><span class="pre">up_switch_context()</span></code>.</p>
<p>This function is supposed to be executed with interrupt disabled (“This
function is called only from the NuttX scheduling logic. Interrupts
will always be disabled when this function is
called.” <a class="reference external" href="https://nuttx.apache.org/docs/latest/reference/os/arch.html">https://nuttx.apache.org/docs/latest/reference/os/arch.html</a> ) Caller
of the context switch method is therefore responsible
for re-enabling interrupts.</p>
</section>
<section id="nd">
<h3>2nd<a class="headerlink" href="#nd" title="Permalink to this heading"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">in-interrupt</span></code> resumed in <code class="docutils literal notranslate"><span class="pre">by-interrupt</span></code> context switch. The task
essentially (from its point of view) exits interrupt handler after
it entered it. Instruction <code class="docutils literal notranslate"><span class="pre">reti</span></code> is used to return from the handler,
setting “I”-flag in the process.</p>
</section>
<section id="rd">
<h3>3rd<a class="headerlink" href="#rd" title="Permalink to this heading"></a></h3>
<p>Third and fourth combinations are more interesting:</p>
<p><code class="docutils literal notranslate"><span class="pre">in-task</span></code> context resumed in <code class="docutils literal notranslate"><span class="pre">by-interrupt</span></code>. The CPU enters
ISR and regular program flow requires returning from ISR and setting
“I”-flag by <code class="docutils literal notranslate"><span class="pre">reti</span></code> which does not happen. Task is resumed with
interrupts disabled. However, it is resumed inside <code class="docutils literal notranslate"><span class="pre">up_switch_context()</span></code>
and caller of that function will set the “I”-flag at some point.
Task then runs with interrupts enabled, all is well.</p>
</section>
<section id="th">
<h3>4th<a class="headerlink" href="#th" title="Permalink to this heading"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">in-interrupt</span></code> resumed in <code class="docutils literal notranslate"><span class="pre">by-task</span></code>, ie. in <code class="docutils literal notranslate"><span class="pre">up_switch_context()</span></code>.
<code class="docutils literal notranslate"><span class="pre">reti</span></code> is used to resume the task, setting “I”-flag in the process.
This would be incorrect for <code class="docutils literal notranslate"><span class="pre">up_switch_context()</span></code> - it is supposed
to run with interrupts disabled - but the task resumes running
from the point where it was interrupted, which is not inside
of <code class="docutils literal notranslate"><span class="pre">up_switch_context()</span></code>. All is well.</p>
</section>
</section>
<section id="avrdx-core-considerations">
<h2>AVRDx core considerations<a class="headerlink" href="#avrdx-core-considerations" title="Permalink to this heading"></a></h2>
<p>Now, all of the above holds true for eg. ATmega chips which control
interrupt execution solely by the “I”-flag, allowing the code
to not care about where the context switch was triggered. Regardless
of that, the MCU will always end up in correct state even if the
context switch cause doesn’t match the context being restored
(cases 3 and 4.)</p>
<p>This is not the case for AVR Dx family which behaves differently.
The interrupt controller does respect the “I”-flag in a sense where
it considers interrupts disabled when the flag is cleared. However,
it is possible that interrupts are not enabled when the flag is set.
That depends on a logical AND between “I”-flag and “interrupt handler
is not executing” internal state. (Refer to the documentation
for more precise explanation.)</p>
<p>What this means is that if eg. <code class="docutils literal notranslate"><span class="pre">in-task</span></code> context gets
resumed in <code class="docutils literal notranslate"><span class="pre">by-interrupt</span></code> condition (case 3 above), then <code class="docutils literal notranslate"><span class="pre">ret</span></code>
instruction is used
to resume the task. As discussed above, the “I”-flag is not set this
way but that is not a problem, it is eventually set later. However,
the internal state “running the interrupt handler” is not cleared.
This means that the task keeps running with “global interrupts are
enabled” but is actually unable to be interrupted. The context switch
code needs to handle this.</p>
<p>Conversely, there is a similar problem with <code class="docutils literal notranslate"><span class="pre">in-interrupt</span></code> context
being resumed in <code class="docutils literal notranslate"><span class="pre">by-task</span></code> (case 4). Instruction <code class="docutils literal notranslate"><span class="pre">reti</span></code> is used
but there is no internal state to be cleared. Unlike the previous case,
no problem related to this was observed but it still looks like something
the code wants to avoid. It could trigger all sorts of undefined behaviour
in the chip otherwise.</p>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="constants-in-progmem.html" class="btn btn-neutral float-left" title="Keeping constants in program memory" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="../../ceva/index.html" class="btn btn-neutral float-right" title="CEVA" 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>