<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>README</title>
<style>
html {
color: #1a1a1a;
background-color: #fdfdfd;
}
body {
margin: 0 auto;
max-width: 36em;
padding-left: 50px;
padding-right: 50px;
padding-top: 50px;
padding-bottom: 50px;
hyphens: auto;
overflow-wrap: break-word;
text-rendering: optimizeLegibility;
font-kerning: normal;
}
@media (max-width: 600px) {
body {
font-size: 0.9em;
padding: 12px;
}
h1 {
font-size: 1.8em;
}
}
@media print {
html {
background-color: white;
}
body {
background-color: transparent;
color: black;
font-size: 12pt;
}
p, h2, h3 {
orphans: 3;
widows: 3;
}
h2, h3, h4 {
page-break-after: avoid;
}
}
p {
margin: 1em 0;
}
a {
color: #1a1a1a;
}
a:visited {
color: #1a1a1a;
}
img {
max-width: 100%;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 1.4em;
}
h5, h6 {
font-size: 1em;
font-style: italic;
}
h6 {
font-weight: normal;
}
ol, ul {
padding-left: 1.7em;
margin-top: 1em;
}
li > ol, li > ul {
margin-top: 0;
}
blockquote {
margin: 1em 0 1em 1.7em;
padding-left: 1em;
border-left: 2px solid #e6e6e6;
color: #606060;
}
code {
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
font-size: 85%;
margin: 0;
hyphens: manual;
}
pre {
margin: 1em 0;
overflow: auto;
}
pre code {
padding: 0;
overflow: visible;
overflow-wrap: normal;
}
.sourceCode {
background-color: transparent;
overflow: visible;
}
hr {
background-color: #1a1a1a;
border: none;
height: 1px;
margin: 1em 0;
}
table {
margin: 1em 0;
border-collapse: collapse;
width: 100%;
overflow-x: auto;
display: block;
font-variant-numeric: lining-nums tabular-nums;
}
table caption {
margin-bottom: 0.75em;
}
tbody {
margin-top: 0.5em;
border-top: 1px solid #1a1a1a;
border-bottom: 1px solid #1a1a1a;
}
th {
border-top: 1px solid #1a1a1a;
padding: 0.25em 0.5em 0.25em 0.5em;
}
td {
padding: 0.125em 0.5em 0.25em 0.5em;
}
header {
margin-bottom: 4em;
text-align: center;
}
#TOC li {
list-style: none;
}
#TOC ul {
padding-left: 1.3em;
}
#TOC > ul {
padding-left: 0;
}
#TOC a:not(:hover) {
text-decoration: none;
}
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
/* The extra [class] is a hack that increases specificity enough to
override a similar rule in reveal.js */
ul.task-list[class]{list-style: none;}
ul.task-list li input[type="checkbox"] {
font-size: inherit;
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
/* CSS for syntax highlighting */
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { color: #008000; } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { color: #008000; font-weight: bold; } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
</head>
<body>
<header id="title-block-header">
<h1 class="title">README</h1>
</header>
<h1 id="simple-periodic-time-slice-scheduler">Simple periodic time slice
scheduler</h1>
<p><a href="https://bues.ch/">Project home</a></p>
<p><a href="https://bues.ch/cgit/timeslicers.git">Git repository</a></p>
<p><a href="https://github.com/mbuesch/timeslicers">Github
repository</a></p>
<p>A simple multi-core scheduler that provides a trait to the
application. This trait, if implemented for an application specific
object, can be used to get periodic calls from the scheduler. The
application trait object has to be registered to the scheduler to get
the periodic calls.</p>
<p>Task methods of the scheduler trait are optional to implement, if one
or more methods is not needed for a particular application object.</p>
<h2 id="restrictions">Restrictions</h2>
<p>To keep things simple, the scheduler has a couple of
restrictions:</p>
<ul>
<li>All task periods must be multiples of the smallest task period.</li>
<li>All tasks run with the same OS priority. Therefore, the tasks won’t
interrupt each other.</li>
<li>The order of execution of the tasks is undefined.</li>
<li>The number of application objects that can be registered to the
scheduler is compile time constant.</li>
</ul>
<h2 id="supported-platforms">Supported platforms</h2>
<ul>
<li>esp-idf-hal: ESP32 with IDF.</li>
</ul>
<h1 id="cargo.toml">Cargo.toml</h1>
<div class="sourceCode" id="cb1"><pre
class="sourceCode toml"><code class="sourceCode toml"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">[dependencies]</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="dt">timeslice</span> <span class="op">=</span> <span class="op">{ </span><span class="dt">version</span><span class="op"> =</span> <span class="st">"0.4"</span><span class="op">, </span><span class="dt">features</span><span class="op"> =</span> <span class="op">[</span> <span class="st">"hal-espidf"</span><span class="op">,</span> <span class="st">"meas"</span> <span class="op">] }</span></span></code></pre></div>
<h1 id="example-code">Example code</h1>
<p>A simple usage example can look like this:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Here we define the scheduler, its tasks and behavior.</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="pp">timeslice::define_timeslice_sched!</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> name<span class="op">:</span> sched_main<span class="op">,</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> num_objs<span class="op">:</span> <span class="dv">1</span><span class="op">,</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> tasks<span class="op">:</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <span class="op">{</span> name<span class="op">:</span> task_10ms<span class="op">,</span> period<span class="op">:</span> <span class="dv">10</span> ms<span class="op">,</span> cpu<span class="op">:</span> <span class="dv">0</span><span class="op">,</span> stack<span class="op">:</span> <span class="dv">16</span> kiB <span class="op">},</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="op">{</span> name<span class="op">:</span> task_50ms<span class="op">,</span> period<span class="op">:</span> <span class="dv">50</span> ms<span class="op">,</span> cpu<span class="op">:</span> <span class="dv">0</span><span class="op">,</span> stack<span class="op">:</span> <span class="dv">3</span> kiB <span class="op">},</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="op">{</span> name<span class="op">:</span> task_100ms<span class="op">,</span> period<span class="op">:</span> <span class="dv">100</span> ms<span class="op">,</span> cpu<span class="op">:</span> <span class="dv">1</span><span class="op">,</span> stack<span class="op">:</span> <span class="dv">16</span> kiB <span class="op">},</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="co">// This structure belongs to your application. It contains application state.</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> MyThing <span class="op">{</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> <span class="co">// ...</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> MyThing <span class="op">{</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a> <span class="kw">fn</span> new() <span class="op">-></span> <span class="dt">Self</span> <span class="op">{</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a> <span class="dt">Self</span> <span class="op">{</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a> <span class="co">// ...</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a><span class="co">// Implement the scheduler's tasks for your application.</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> <span class="pp">sched_main::</span>Ops <span class="cf">for</span> <span class="dt">Box</span><span class="op"><</span>MyThing<span class="op">></span> <span class="op">{</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a> <span class="kw">fn</span> task_10ms(<span class="op">&</span><span class="kw">self</span>) <span class="op">{</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a> <span class="co">// Called every 10 ms.</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a> <span class="co">// ... Put your code here ...</span></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a> <span class="kw">fn</span> task_50ms(<span class="op">&</span><span class="kw">self</span>) <span class="op">{</span></span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a> <span class="co">// Called every 50 ms.</span></span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a> <span class="co">// ... Put your code here ...</span></span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a> <span class="kw">fn</span> task_100ms(<span class="op">&</span><span class="kw">self</span>) <span class="op">{</span></span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a> <span class="co">// Called every 100 ms.</span></span>
<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a> <span class="co">// ... Put your code here ...</span></span>
<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb2-41"><a href="#cb2-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-42"><a href="#cb2-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-43"><a href="#cb2-43" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb2-44"><a href="#cb2-44" aria-hidden="true" tabindex="-1"></a> <span class="co">// Initialize the application.</span></span>
<span id="cb2-45"><a href="#cb2-45" aria-hidden="true" tabindex="-1"></a> <span class="kw">use</span> <span class="pp">std::sync::</span>Arc<span class="op">;</span></span>
<span id="cb2-46"><a href="#cb2-46" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> thing <span class="op">=</span> <span class="pp">Arc::</span>new(<span class="dt">Box</span><span class="pp">::</span>new(<span class="pp">MyThing::</span>new()))<span class="op">;</span></span>
<span id="cb2-47"><a href="#cb2-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-48"><a href="#cb2-48" aria-hidden="true" tabindex="-1"></a> <span class="co">// Initialize the scheduler and register your application.</span></span>
<span id="cb2-49"><a href="#cb2-49" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> obj <span class="op">=</span> <span class="pp">Arc::</span>clone(<span class="op">&</span>thing)<span class="op">;</span></span>
<span id="cb2-50"><a href="#cb2-50" aria-hidden="true" tabindex="-1"></a> <span class="pp">sched_main::</span>init([obj])<span class="op">;</span></span>
<span id="cb2-51"><a href="#cb2-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-52"><a href="#cb2-52" aria-hidden="true" tabindex="-1"></a> <span class="co">// ...</span></span>
<span id="cb2-53"><a href="#cb2-53" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>See the documentation for more complex examples.</p>
<h1 id="backend-selection">Backend selection</h1>
<p>One backend has to be selected via <code>feature</code> flags. The
following backends are available:</p>
<ul>
<li><code>hal-espidf</code>: Use <code>esp-idf-hal</code> and
<code>esp-idf-svc</code> hal backend. Select this, if you use an ESP
microcontroller.</li>
<li><code>hal-dummy</code>: Backend for testing only. It does nothing.
You should never select it.</li>
</ul>
<p>Only one of the hal backend <code>feature</code> flags can be
selected.</p>
<h2 id="esp-idf-hal-and-esp-idf-svc-versions">esp-idf-hal and
esp-idf-svc versions</h2>
<p>The <code>hal-espidf</code> backend depends on the following
crates:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode toml"><code class="sourceCode toml"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">esp-idf-hal</span> <span class="op">=</span> <span class="st">"0.44"</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="dt">esp-idf-svc</span> <span class="op">=</span> <span class="st">"0.49"</span></span></code></pre></div>
<h1 id="features">Features</h1>
<ul>
<li><code>meas</code>: If the <code>meas</code> feature is enabled, then
functions for run time measurements will be enabled. If this feature
flag is not given, then the run time measurement functions will be empty
dummies.</li>
</ul>
<h1 id="internals">Internals</h1>
<h2 id="esp-idf-implementation-details">ESP-IDF implementation
details</h2>
<p>On <code>hal-espidf</code> each task runs as a
<code>std::thread</code> that is pinned to the specified CPU core. The
threads wait for a trigger signal from a periodic ESP timer. On
triggering, the trait methods are executed, if the time slice is
due.</p>
<h2 id="memory-safety">Memory safety</h2>
<p>This crate does not use <code>unsafe</code> code.</p>
<h1 id="license">License</h1>
<p>Copyright 2023-2024 Michael Büsch <a href="mailto:m@bues.ch"
class="email">m@bues.ch</a></p>
<p>Licensed under the Apache License version 2.0 or the MIT license, at
your option.</p>
<p>SPDX-License-Identifier: Apache-2.0 OR MIT</p>
</body>
</html>