blob: 9e4d9ca6ccd99e54bd38cd241b68e33da1e2d233 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- This is broken by doc revisioning.
-->
<link rel="shortcut icon" href="../../../img/favicon.ico">
<title>Tasks lesson - Apache Mynewt</title>
<link href="../../../css/bootstrap-3.0.3.min.css" rel="stylesheet">
<link rel="stylesheet" href="../../../css/highlight.css">
<link href="../../../css/base.css" rel="stylesheet">
<link href="../../../css/custom.css" rel="stylesheet">
<link href="../../../css/v2.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<script>
(function(i, s, o, g, r, a, m) {
i["GoogleAnalyticsObject"] = r;
(i[r] =
i[r] ||
function() {
(i[r].q = i[r].q || []).push(arguments);
}),
(i[r].l = 1 * new Date());
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m);
})(window, document, "script", "//www.google-analytics.com/analytics.js", "ga");
ga("create", "UA-72162311-1", "auto");
ga("send", "pageview");
</script>
</head>
<body class="Tasks lesson">
<div class="container">
<div class="row v2-main-banner">
<a class="logo-cell" href="/">
<img class="logo" src="/img/logo.png">
</a>
<div class="tagline-cell">
<h4 class="tagline">An OS to build, deploy and securely manage billions of devices</h4>
</div>
<div class="news-cell">
<div class="well">
<h4>Latest News:</h4> <a href="/download">Apache Mynewt 1.11.0, Apache NimBLE 1.6.0 </a> released (September 7, 2023)
</div>
</div>
</div>
</div>
<nav id="navbar" class="navbar navbar-inverse affix-top" data-spy="affix" data-offset-top="150" role="navigation">
<div class="container">
<!-- Collapsed navigation -->
<div class="navbar-header">
<!-- Expander button -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Expanded navigation -->
<div class="navbar-collapse collapse">
<!-- Main navigation -->
<ul class="nav navbar-nav navbar-right">
<li
class=""
>
<a href="/"><i class="fa fa-home" style="font-size: larger;"></i></a>
</li>
<li
class="important"
>
<a href="/quick-start/">Quick Start</a>
</li>
<li
class=""
>
<a href="/about/">About</a>
</li>
<li
class=""
>
<a href="/talks/">Talks</a>
</li>
<li
class="active"
>
<a href="/documentation/">Documentation</a>
</li>
<li
class=""
>
<a href="/download/">Download</a>
</li>
<li
class=""
>
<a href="/community/">Community</a>
</li>
<li
class=""
>
<a href="/events/">Events</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-md-3 v2-sidebar sidebar-container"><div id="docSidebar" class="hidden-print" role="complementary">
<div class="top">
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../../search.html" method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search documentation" />
</div>
</form>
</div>
</div>
<ul class="toc-nav">
<li class="doc-version"><select class="form-control" onchange="if (this.value) window.location.href=this.value">
<option value="/latest">
Version: master
</option>
<option value="/v1_11_0/" >
Version: 1.11.0
</option>
<option value="/v1_10_0/" >
Version: 1.10.0
</option>
<option value="/v1_9_0/" >
Version: 1.9.0
</option>
<option value="/v1_8_0/" >
Version: 1.8.0
</option>
<option value="/v1_7_0/" >
Version: 1.7.0
</option>
<option value="/v1_6_0/" >
Version: 1.6.0
</option>
<option value="/v1_5_0/" >
Version: 1.5.0
</option>
<option value="/v1_4_0/" >
Version: 1.4.0
</option>
<option value="/v1_3_0/os/introduction" >
Version: 1.3.0
</option>
<option value="/v1_2_0/os/introduction" >
Version: 1.2.0
</option>
<option value="/v1_1_0/os/introduction" >
Version: 1.1.0
</option>
<option value="/v1_0_0/os/introduction" >
Version: 1.0.0
</option>
<option value="/v0_9_0/os/introduction" selected="selected" >
Version: 0.9.0
</option>
</select></li>
<li ><a href="../../introduction/">Mynewt Documentation</a>
</li>
<li><a href="
../../../faq/how_to_edit_docs/
">Appendix</a>
</li>
</ul>
</div></div>
<div class="col-md-9" role="main">
<div class="doc-header">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="/documentation/">Docs</a></li>
<li>&raquo; Tasks lesson</li>
</ul>
</div>
</div>
<div class="alert alert-warning">
<p>
Version 0.9.0 is not the most recent version of the Apache Mynewt
documentation. Click <a href="/latest">here</a> to read the latest
version.
</p>
</div>
<h1 id="core-os-lesson-tasks-and-priority-management">Core OS Lesson: Tasks and Priority Management</h1>
<p><strong>Target Platform: Arduino M0 Pro</strong> (or legacy Arduino Zero or Zero Pro, but not Arduino M0)</p>
<p>This lesson is designed to teach core OS concepts and strategies encountered when
building applications using Mynewt. Specifically, this lesson will cover tasks,
simple multitasking, and priority management running on an Arduino M0 Pro.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>Before starting, you should read about Mynewt in the <a href="http://mynewt.apache.org/os/introduction/"><em>Introduction</em></a>
section and complete the <a href="http://mynewt.apache.org/os/get_started/get_started/"><em>QuickStart</em></a>
guide and the <a href="http://mynewt.apache.org/os/tutorials/arduino_zero/"><em>Blinky</em></a> tutorial.
Furthermore, it may be helpful to take a peek at the <a href="http://mynewt.apache.org/os/core_os/task/task/"><em>task documentation</em></a>
for additional insights.</p>
<h2 id="equipment">Equipment</h2>
<p>You will need the following equipment:</p>
<ul>
<li>Arduino M0 Pro (or legacy Arduino Zero or Zero Pro, but not Arduino M0)</li>
<li>Computer with Mynewt installed</li>
<li>USB to Micro USB Cable</li>
</ul>
<h2 id="build-your-application">Build Your Application</h2>
<p>To save time, we will simply modify the Blinky app. We'll add the Task Management code to
the Blinky app. Follow the <a href="http://mynewt.apache.org/os/tutorials/arduino_zero/"><em>Arduino Zero Blinky tutorial</em></a>
to create a new project and build your bootloader and application. Finally, build and
load the application to your Arduino to verify that everything is in order. Now let’s get started!</p>
<h2 id="create-a-new-task">Create a New Task</h2>
<p>The purpose of this section is to give an introduction to the important aspects of tasks
and how to properly initialize them. First, let’s define a second task called <code>work_task</code>
in main.c (located in apps/blinky/src):</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_task</span> <span style="color: #000000">work_task</span>;
</code></pre></div>
<p>A task is represented by the <a href="http://mynewt.apache.org/os/core_os/task/task/#data-structures"><em>os_task</em></a><br />
struct which will hold the task’s information (name, state, priority, etc.). A task is made up of two
main elements, a task function (also known as a task handler) and a task stack.</p>
<p>Next, let’s take a look at what is required to initialize our new task.</p>
<h3 id="task-stack">Task Stack</h3>
<p>The task stack is an array of type <code>os_stack_t</code> which holds the program stack frames. Mynewt gives
us the ability to set the stack size for a task giving the application developer room to optimize
memory usage. Since we’re not short on memory, our <code>blinky_stack</code> and <code>work_stack</code> are plenty large
for the purpose of this lesson. Notice that the elements in our task stack are of type <code>os_stack_t</code>
which are generally 32 bits, making our entire stack 1024 Bytes.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> <span style="color: #633820">#define WORK_STACK_SIZE OS_STACK_ALIGN(256)</span>
<span style="color: #000000">os_stack_t</span> <span style="color: #000000">work_stack</span>[<span style="color: #000000">WORK_STACK_SIZE</span>];
</code></pre></div>
<p>Note: The <code>OS_STACK_ALIGN</code> macro is used to align the stack based on the hardware architecture.</p>
<h3 id="task-function">Task Function</h3>
<p>The task function is essentially an infinite loop which waits for some “event” to wake it up. In our
Blinky app the task function, named <code>blinky_task_handler()</code>, is initially called when we call <code>os_start()</code>
in <code>main()</code>. In general, the task function is where the majority of work is done by a task. Let’s write
a task function for <code>work_task</code> called <code>work_task_handler()</code>:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">void</span>
<span style="color: #000000">work_task_handler</span>(<span style="color: #A90D91">void</span> <span style="color: #000000">*arg</span>)
{
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_task</span> <span style="color: #000000">*t</span>;
<span style="color: #000000">g_led_pin</span> <span style="color: #000000">=</span> <span style="color: #000000">LED_BLINK_PIN</span>;
<span style="color: #000000">hal_gpio_init_out</span>(<span style="color: #000000">g_led_pin</span>, <span style="color: #1C01CE">1</span>);
<span style="color: #A90D91">while</span> (<span style="color: #1C01CE">1</span>) {
<span style="color: #000000">t</span> <span style="color: #000000">=</span> <span style="color: #000000">os_sched_get_current_task</span>();
<span style="color: #000000">assert</span>(<span style="color: #000000">t-&gt;t_func</span> <span style="color: #000000">==</span> <span style="color: #000000">work_task_handler</span>);
<span style="color: #177500">/* Do work... */</span>
}
}
</code></pre></div>
<p>The task function is called when the task is initially put into the <em>running</em> state by the scheduler.
We use an infinite loop to ensure that the task function never returns. Our assertion that the current
task's handler is the same as our task handler is for illustration purposes only and does not need to
be in most task functions.</p>
<h3 id="task-priority">Task Priority</h3>
<p>As a preemptive, multitasking RTOS, Mynewt decides which tasks to run based on which has a higher
priority; the highest priority being 0 and the lowest 255. Thus, before initializing our task, we
must choose a priority defined as a macro variable.</p>
<p>Let’s set the priority of <code>work_task</code> to 0, because everyone knows that work is more important than blinking.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> <span style="color: #633820">#define WORK_TASK_PRIO (0)</span>
</code></pre></div>
<h3 id="initialization">Initialization</h3>
<p>To initialize a new task we use <a href="http://mynewt.apache.org/os/core_os/task/os_task_init/"><em>os_task_init()</em></a>
which takes a number of arguments including our new task function, stack, and priority. Much like <code>blinky_task</code>,
we’re going to initialize <code>work_task</code> inside <code>init_tasks</code> to keep our main function clean.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">int</span>
<span style="color: #000000">init_tasks</span>(<span style="color: #A90D91">void</span>)
{
<span style="color: #177500">/* … */</span>
<span style="color: #000000">os_task_init</span>(<span style="color: #000000">&amp;work_task</span>, <span style="color: #C41A16">&quot;work&quot;</span>, <span style="color: #000000">work_task_handler</span>, <span style="color: #A90D91">NULL</span>,
<span style="color: #000000">WORK_TASK_PRIO</span>, <span style="color: #000000">OS_WAIT_FOREVER</span>, <span style="color: #000000">work_stack</span>,
<span style="color: #000000">WORK_STACK_SIZE</span>);
<span style="color: #000000">tasks_initialized</span> <span style="color: #000000">=</span> <span style="color: #1C01CE">1</span>;
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">0</span>;
}
</code></pre></div>
<p>And that’s it! Now run your application using the newt run command.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>$ newt run arduino_blinky 0.0.0
</code></pre></div>
<p>When GDB appears press C then Enter to continue and … <em>wait, why doesn't our LED blink anymore?</em></p>
<h4 id="review">Review</h4>
<p>Before we run our new app, let’s review what we need in order to create a task. This is a general case for a new task called mytask:</p>
<p><strong>1)</strong> Define a new task, task stack, and priority:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #177500">/* My Task */</span>
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_task</span> <span style="color: #000000">mytask</span>
<span style="color: #177500">/* My Task Stack */</span>
<span style="color: #633820">#define MYTASK_STACK_SIZE OS_STACK_ALIGN(256)</span>
<span style="color: #000000">os_stack_t</span> <span style="color: #000000">mytask_stack</span>[<span style="color: #000000">MYTASK_STACK_SIZE</span>];
<span style="color: #177500">/* My Task Priority */</span>
<span style="color: #633820">#define MYTASK_PRIO (0)</span>
</code></pre></div>
<p><strong>2)</strong> Define task function:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">void</span>
<span style="color: #000000">mytask_handler</span>(<span style="color: #A90D91">void</span> <span style="color: #000000">*arg</span>)
{
<span style="color: #A90D91">while</span> (<span style="color: #1C01CE">1</span>) {
<span style="color: #177500">/* ... */</span>
}
}
</code></pre></div>
<p><strong>3)</strong> Initialize task before calling <code>os_start()</code>:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #000000">os_task_init</span>(<span style="color: #000000">&amp;mytask</span>, <span style="color: #C41A16">&quot;mytask&quot;</span>, <span style="color: #000000">mytask_handler</span>, <span style="color: #A90D91">NULL</span>,
<span style="color: #000000">MYTASK_PRIO</span>, <span style="color: #000000">OS_WAIT_FOREVER</span>, <span style="color: #000000">mytask_stack</span>,
<span style="color: #000000">MYTASK_STACK_SIZE</span>);
</code></pre></div>
<h2 id="task-priority-preempting-and-context-switching">Task Priority, Preempting, and Context Switching</h2>
<p>A preemptive RTOS is one in which a higher priority task that is <em>ready to run</em> will preempt (i.e. take the
place of) the lower priority task which is <em>running</em>. When a lower priority task is preempted by a higher
priority task, the lower priority task’s context data (stack pointer, registers, etc.) is saved and the new
task is switched in.</p>
<p>In our example, <code>work_task</code> has a higher priority than <code>blinky_task</code> and, because it is never put into a
<em>sleep</em> state, holds the processor focus on its context. Let’s give <code>work_task</code> a delay and some simulated
work to keep it busy. Because the delay is measured in os ticks, the actual number of ticks per second is
dependent on the board. Therefore, we multiply <code>OS_TICKS_PER_SEC</code>, which is defined in the MCU, by the
number of seconds we wish to delay.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">void</span>
<span style="color: #000000">work_task_handler</span>(<span style="color: #A90D91">void</span> <span style="color: #000000">*arg</span>)
{
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_task</span> <span style="color: #000000">*t</span>;
<span style="color: #000000">g_led_pin</span> <span style="color: #000000">=</span> <span style="color: #000000">LED_BLINK_PIN</span>;
<span style="color: #000000">hal_gpio_init_out</span>(<span style="color: #000000">g_led_pin</span>, <span style="color: #1C01CE">1</span>);
<span style="color: #A90D91">while</span> (<span style="color: #1C01CE">1</span>) {
<span style="color: #000000">t</span> <span style="color: #000000">=</span> <span style="color: #000000">os_sched_get_current_t:ask</span>();
<span style="color: #000000">assert</span>(<span style="color: #000000">t-&gt;t_func</span> <span style="color: #000000">==</span> <span style="color: #000000">work_task_handler</span>);
<span style="color: #177500">/* Do work... */</span>
<span style="color: #A90D91">int</span> <span style="color: #000000">i</span>;
<span style="color: #A90D91">for</span>(<span style="color: #000000">i</span> <span style="color: #000000">=</span> <span style="color: #1C01CE">0</span>; <span style="color: #000000">i</span> <span style="color: #000000">&lt;</span> <span style="color: #1C01CE">1000000</span>; <span style="color: #000000">++i</span>) {
<span style="color: #177500">/* Simulate doing a noticeable amount of work */</span>
<span style="color: #000000">hal_gpio_set</span>(<span style="color: #000000">g_led_pin</span>);
}
<span style="color: #000000">os_time_delay</span>(<span style="color: #1C01CE">3</span><span style="color: #000000">*OS_TICKS_PER_SECOND</span>);
}
}
</code></pre></div>
<p>In order to notice the LED changing, modify the time delay in <code>blinky_task_handler()</code> to blink at a higher frequency.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #000000">os_time_delay</span>(<span style="color: #000000">OS_TICKS_PER_SEC/</span><span style="color: #1C01CE">10</span>);
</code></pre></div>
<p>Before we run the app, let’s predict the behavior. With the newest additions to <code>work_task_handler()</code>,
our first action will be to sleep for three seconds. This will allow <code>blinky_task</code> to take over the CPU
and blink to its heart’s content. After three seconds, <code>work_task</code> will wake up and be made <em>ready to run</em>,
causing it to preempt <code>blinky_task</code>. The LED will then remain lit for a short period while <code>work_task</code>
loops, then blink again for another three seconds while <code>work_task</code> sleeps. </p>
<p>Voila, you should see that our prediction was correct! </p>
<h3 id="priority-management-considerations">Priority Management Considerations</h3>
<p>When projects grow in scope, from blinking LEDs into more sophisticated applications, the number of
tasks needed increases alongside complexity. It remains important, then, that each of our tasks is
capable of doing its work within a reasonable amount of time.</p>
<p>Some tasks, such as the Shell task, execute quickly and require almost instantaneous response. Therefore,
the Shell task should be given a high priority. On the other hand, tasks which may be communicating over
a network, or processing data, should be given a low priority in order to not hog the CPU.</p>
<p>The diagram below showcases the different scheduling patterns we. would expect from swapping blinky and
work tasks priorities.</p>
<p><img alt="Task Scheduling" src="pics/task_lesson.png" /></p>
<p>In the second case where <code>blinky_task</code> has a higher priority, the “work” done by <code>work_task</code> would be
executed during the millisecond delays in <code>blinky_task</code>, saving us idle time compared to the first case.</p>
<p><strong>Note:</strong> Defining the same priority for two tasks leads to somewhat undefined behavior and should be avoided.</p>
<h2 id="comparing-priority-strategies">Comparing Priority Strategies</h2>
<p>Instead of stepping through a bunch of changes to our blinky app, clone my task lesson application from
github and copy an existing target.</p>
<p>Change directory into apps and clone the repository to get our new
files:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>$ cd apps
$ git clone https://github.com/bgiori/mynewt_tasks_lesson.git
</code></pre></div>
<p>Change directory back to your project root and copy the arduino_blinky target to a new target called task_tgt.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #000000">$</span> <span style="color: #000000">newt</span> <span style="color: #000000">target</span> <span style="color: #000000">copy</span> <span style="color: #000000">arduino_blinky</span> <span style="color: #000000">task_tgt</span>
</code></pre></div>
<p>Set a new app location.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #000000">$</span> <span style="color: #000000">newt</span> <span style="color: #000000">target</span> <span style="color: #000000">set</span> <span style="color: #000000">task_tgt</span> <span style="color: #000000">app=apps/mynewt_tasks_lesson</span>
</code></pre></div>
<p>Now let’s take a look at our new code. First, notice that we have abandoned blinking, instead choosing t
o use the <a href="http://mynewt.apache.org/latest/os/modules/console/console/"><em>console</em></a> and <a href="http://mynewt.apache.org/latest/os/modules/shell/shell/"><em>shell</em></a>
to follow our tasks through execution.</p>
<p>Additionally, we have a number of different tasks:</p>
<ul>
<li>
<p><strong>Task A</strong> (<code>a_task</code>):</p>
<ul>
<li><strong>Priority</strong>: 3 → 2</li>
<li><strong>Description</strong>: Task A is supposed to represent a task which frequently does a small amount
of work, such as one which rapidly polls a sensor for data. Much like <code>blinky_task</code>, Task A will
loop 10,000 times then wait 1 millisecond. Priority is changed by <code>timer_task</code> after the first simulation.</li>
</ul>
</li>
<li>
<p><strong>Task B</strong> (<code>b_task</code>):</p>
<ul>
<li><strong>Priority</strong>: 2 → 3</li>
<li><strong>Description</strong>: Task B is supposed to represent a task which does a large amount of work
relatively infrequently, such as one which sends/receives data from the cloud. Like work_task,
Task B will loop 1,000,000 times then wait 3 seconds. Priority is changed by timer_task after
the first simulation.</li>
</ul>
</li>
<li>
<p><strong>Timer Task</strong> (<code>timer_task</code>):</p>
<ul>
<li><strong>Priority</strong>: 1</li>
<li><strong>Description</strong>: With default settings, Timer Task will wait 20 seconds then print the first
simulations data for Task A and B. Timer task will then swap A and B’s priorities and restart the
simulation. After the second simulation, timer will again print simulation data then compare the
two and calculate a final speedup (simulation2 / simulation1).</li>
</ul>
</li>
<li>
<p><strong>Shell Task</strong>:</p>
<ul>
<li><strong>Priority</strong>: 0</li>
<li><strong>Description</strong>: Task used by Shell behind the scenes to communicate with the serial port.</li>
</ul>
</li>
</ul>
<h3 id="connecting-to-the-serial-console">Connecting to the Serial Console</h3>
<p>Before running our new app, we must first connect to the serial console. First make sure the
mynewt_arduino_zero repository is set to the develop branch. (Remove once changes have been
moved to master). </p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>$ cd repos/mynewt_arduino_zero
$ git checkout develop
</code></pre></div>
<p>Open a new terminal window and list your serial connections to find our Arduino.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #000000">$</span> <span style="color: #000000">ls</span> <span style="color: #000000">/dev/tty</span>.<span style="color: #000000">*</span>
<span style="color: #000000">/dev/tty</span>.<span style="color: #000000">Bluetooth-Incoming-Port</span> <span style="color: #000000">/dev/tty</span>.<span style="color: #000000">usbmodem14132</span>
</code></pre></div>
<p>In the same window, connect to the serial port using a serial communication program.
In this case I’ll be using mincom as it can scroll through output.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #000000">$</span> <span style="color: #000000">minicom</span> <span style="color: #000000">-D</span> <span style="color: #000000">/dev/tty</span>.<span style="color: #000000">usbmodem14132</span> <span style="color: #000000">-b</span> <span style="color: #1C01CE">115200</span>
</code></pre></div>
<p>If you see minicom welcome you, you’re ready to move on!</p>
<h3 id="output-analysis">Output Analysis</h3>
<p>Run our new target, task_tgt, and you should see an output similar to this:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>Starting First Simulation...
1: Task B: 0%
78: Task B: 1%
155: Task B: 2%
257: Task B: 3%
359: Task B: 4%
461: Task B: 5%
&lt;snip&gt;
========== Timer Expired ==========
&gt;&gt;&gt; Task A &lt;&lt;&lt;
Priority: 3
Loop count: 162849
Cycle count: 16.28
Run time: 1.40 sec
&gt;&gt;&gt; Task B &lt;&lt;&lt;
Priority: 2
Loop count: 1345852
Cycle count: 1.34
Run time: 17.0 sec
Total loops: 1508709
20023: Switching priorities and restarting...
20111: Task A looped
20113: Task B: 0%
20191: Task B: 1%
20297: Task A looped
20356: Task B: 2%
20483: Task A looped
20545: Task B: 3%
20669: Task A looped
20734: Task B: 4%
20855: Task A looped
20923: Task B: 5%
&lt;snip&gt;
========== Timer Expired ==========
&gt;&gt;&gt; Task A &lt;&lt;&lt;
Priority: 2
Loop count: 1080000
Cycle count: 108.0
Run time: 9.28 sec
&gt;&gt;&gt; Task B &lt;&lt;&lt;
Priority: 3
Loop count: 830356
Cycle count: 0.83
Run time: 10.72 sec
Total loops: 1910404
40058:
Final Speedup (Sim2 / Sim1): 1.26
</code></pre></div>
<p>The console output reaffirms our previous prediction and makes both the scheduling differences
and subsequent efficiency boost far more apparent. Let’s take a look at scheduling differences
before we delve into efficiency.</p>
<p>In the first case, where Task B’s priority is higher than that of Task A, we see A get starved
by Task B’s long execution time. <strong>Starvation</strong> occurs when one task hogs the processor, essentially
“starving” other tasks which also need to run. At the end of the first 20 second simulation period,
Task A has only run for 1.4 seconds compared to task B’s 17 second running time – ouch. As explained
before, processes which are expected to run for long periods of time (e.g. network communication,
data processing) should be given higher priorities in order to combat starvation.</p>
<p>In the second simulation with priorities swapped, we can see Task B only running during the
millisecond delays when Task A is <em>sleeping</em>. Although having Task B only run during these
delays slows its execution time, we benefit from un-starving Task A and using the processor
at a higher efficiency.</p>
<p>The bottom line speedup gives us an immediate and clear indication that we have improved our
ability to process work (i.e throughput). In our second run, we processed an additional 400,000
loop iterations, equating to a 26% increase in efficiency. On a standard multi-core processor
found in every modern PC, a 1.26 speedup would be an ok result to adding multithreading capabilities
to a serial program. However, we accomplished this by simply setting priorities on a single core
processor – not bad!</p>
<p>NOTE: Usually the the term “speedup” is used within a parallel programming context and refers
to the change in execution time between a serial and parallel program executing over the same
problem. In this case we’re using the term loosely to illustrate the priority change’s effect
on scheduling and throughput in our specific context.</p>
<h3 id="efficiency-isnt-everything">Efficiency Isn’t Everything</h3>
<p>Using the processor during every OS tick isn’t always the best course of action. If we modify
Task A’s delay to a tenth of a millisecond and turn off the console output, we can boost our
speedup to 1.44. This, however, reduces our ability to process work from Task B who ends up
only completing 18% of its work cycle after the second simulation. That would mean, at that
rate, Task B would take over a minute to finish one cycle.</p>
<p>Feel free to play around with the testing parameters to study the different changes yourself!</p>
<h2 id="conclusion">Conclusion</h2>
<p>Moving forward, tasks are just the tip of the iceberg. The <a href="http://mynewt.apache.org/latest/os/core_os/context_switch/context_switch/"><em>scheduler</em></a>,
<a href="http://mynewt.apache.org/latest/os/core_os/event_queue/event_queue/"><em>event queues</em></a>,
<a href="http://mynewt.apache.org/latest/os/core_os/semaphore/semaphore/"><em>semaphores</em></a>, and
<a href="http://mynewt.apache.org/latest/os/core_os/mutex/mutex/"><em>mutexes</em></a> also add to tasks functionality,
increasing our ability as the developer to control greater numbers of tasks more intricately. For
example, when we switch the tasks priority, we have to tell the scheduler that our tasks priorities
have changed, allowing us us to use priorities dynamically. When running multiple tasks, logging
through either the built-in <a href="http://mynewt.apache.org/latest/os/modules/logs/logs/"><em>Logs</em></a> module
(not covered in this lesson) or through the serial console/shell can be very useful for debugging
your application. In the end, the way you manage your tasks depends on the context of your
application. You should assign priorities based on execution time, urgency, and frequency, among
other things.</p>
<p>Keep blinking and happy hacking!</p>
<div class="row">
<ul class="nav nav-pills" style="margin-bottom: 10px">
<li>
</li>
<li class="pull-right">
</li>
</ul>
</div>
<footer class="row">
<div class="col-xs-12">
<p class="copyright">Apache Mynewt (incubating) is available under Apache License, version 2.0.</p>
</div>
<div class="col-xs-12">
<div class="logos">
<a href="https://www.apache.org/">
<img src="/img/asf_logo_wide_small.png" alt="Apache" title="Apache">
</a>
<p>
Copyright © 2015-2021 The Apache Software Foundation.<br>
<small class="footnote">
Apache Mynewt, Mynewt, Apache, the Apache feather logo, and the Apache Mynewt
project logo are either registered trademarks or trademarks of the Apache
Software Foundation in the United States and other countries.
</small>
</p>
<a href="">
<img src="https://www.countit.com/images/add_to_slack.png" alt="Slack Icon" title="Join our Slack Community" />
</a>
</div>
</div>
<a href="https://www.apache.org/licenses/">
<button class="button-footer-asf">
License
</button>
</a>
<a href="https://www.apache.org/foundation/sponsorship.html">
<button class="button-footer-asf">
Sponsorship
</button>
</a>
<a href="https://www.apache.org/foundation/thanks.html">
<button class="button-footer-asf">
Thanks
</button>
</a>
<a href="https://www.apache.org/security/">
<button class="button-footer-asf">
Security
</button>
</a>
<a href="https://apache.org/events/current-event">
<button class="button-footer-asf">
ASF Events
</button>
</a>
</footer>
</div>
</div>
</div>
<script src="../../../js/jquery-1.10.2.min.js"></script>
<script src="../../../js/bootstrap-3.0.3.min.js"></script>
<script src="../../../js/highlight.pack.js"></script>
<script src="../../../js/base.js"></script>
<script src="../../../js/custom.js"></script>
<script src="search/main.js"></script>
</body>
</html>