<!DOCTYPE html> <html class="writer-html4" lang="ja" > <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>2週目 — IoT Programming ドキュメント</title> <link rel="stylesheet" href="_static/css/theme.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> <link rel="stylesheet" href="_static/copybutton.css" type="text/css" /> <!--[if lt IE 9]> <script src="_static/js/html5shiv.min.js"></script> <![endif]--> <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> <script type="text/javascript" src="_static/jquery.js"></script> <script type="text/javascript" src="_static/underscore.js"></script> <script type="text/javascript" src="_static/doctools.js"></script> <script type="text/javascript" src="_static/language_data.js"></script> <script type="text/javascript" src="_static/clipboard.min.js"></script> <script type="text/javascript" src="_static/copybutton.js"></script> <script type="text/javascript" src="_static/translations.js"></script> <script type="text/javascript" src="_static/js/theme.js"></script> <link rel="index" title="索引" href="genindex.html" /> <link rel="search" title="検索" href="search.html" /> <link rel="next" title="Frequently-Asked Questions (FAQ: よくある質問)" href="faq.html" /> <link rel="prev" title="1週目" href="week1.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"> IoT Programming </a> <div role="search"> <form id="rtd-search-form" class="wy-form" action="search.html" method="get"> <input type="text" name="q" placeholder="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="main navigation"> <p class="caption"><span class="caption-text">Contents:</span></p> <ul class="current"> <li class="toctree-l1"><a class="reference internal" href="intro.html">実験の目的</a></li> <li class="toctree-l1"><a class="reference internal" href="intro.html#id2">実験のすすめかた</a></li> <li class="toctree-l1"><a class="reference internal" href="intro.html#url">参考URL</a></li> <li class="toctree-l1"><a class="reference internal" href="pre.html">事前準備</a></li> <li class="toctree-l1"><a class="reference internal" href="week1.html">1週目</a></li> <li class="toctree-l1 current"><a class="current reference internal" href="#">2週目</a><ul> <li class="toctree-l2"><a class="reference internal" href="#id2">複数人で書いたプログラムを統合する</a></li> <li class="toctree-l2"><a class="reference internal" href="#id3">タスク</a></li> <li class="toctree-l2"><a class="reference internal" href="#id5">ミューテックスとセマフォ</a></li> <li class="toctree-l2"><a class="reference internal" href="#id6">キュー</a></li> <li class="toctree-l2"><a class="reference internal" href="#freertosrtos">FreeRTOSと、その他のRTOS</a></li> </ul> </li> <li class="toctree-l1"><a class="reference internal" href="faq.html">Frequently-Asked Questions (FAQ: よくある質問)</a></li> </ul> </div> </div> </nav> <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"> <nav class="wy-nav-top" aria-label="top navigation"> <i data-toggle="wy-nav-top" class="fa fa-bars"></i> <a href="index.html">IoT Programming</a> </nav> <div class="wy-nav-content"> <div class="rst-content"> <div role="navigation" aria-label="breadcrumbs navigation"> <ul class="wy-breadcrumbs"> <li><a href="index.html" class="icon icon-home"></a> »</li> <li>2週目</li> <li class="wy-breadcrumbs-aside"> <a href="_sources/week2.rst.txt" rel="nofollow"> View page source</a> </li> </ul> <hr/> </div> <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article"> <div itemprop="articleBody"> <div class="section" id="id1"> <h1>2週目<a class="headerlink" href="#id1" title="このヘッドラインへのパーマリンク">¶</a></h1> <p>1週目で学んだことを活かして、組み合わせてみましょう。</p> <div class="section" id="id2"> <h2>複数人で書いたプログラムを統合する<a class="headerlink" href="#id2" title="このヘッドラインへのパーマリンク">¶</a></h2> <ul class="simple"> <li>Arduino IDEでは、プログラムを複数のファイル(たとえば、main.ino / sub.ino / hoge.cpp / hoge.h ) に分割して記述することができます。複数ファイルに分割することで、関数定義を機能別にまとめることができ、管理しやすくなります。</li> <li>Arduino IDEでは、プログラムを構成する、複数のファイル(スケッチブック)を、1つのフォルダに入れて管理します。(スケッチブックのことを、他のIDEでは「プロジェクト」と呼ぶ場合もある)</li> <li>スケッチブックに別のファイル(hogehoge.ino) を追加するには、右上にあるシリアルモニタをひらくアイコンの、下の「▼」ボタンからメニューをひらき、「新規タブ」を選択し、ファイル名(拡張子.ino をのぞいた、hogehogeの部分のみ)を入力します。</li> <li>スケッチブックをコピーしたいときは、内包するフォルダごとコピーしてください。<strong>その際、フォルダ名と、メインのソースコードファイル名(拡張子以外の部分)は、一致している必要があります。</strong></li> <li>複数のファイルを置いたときの挙動について: <code class="docutils literal notranslate"><span class="pre">***.ino</span></code> ファイルの内容は、単純にメインのタブ(フォルダ名と同じinoファイル)にマージされます。<code class="docutils literal notranslate"><span class="pre">***.cpp</span></code> や <code class="docutils literal notranslate"><span class="pre">***.c</span></code> という拡張子でファイルを作成した場合は、<code class="docutils literal notranslate"><span class="pre">***.h</span></code> を作成する必要があります。<a class="reference external" href="https://arduino.stackexchange.com/questions/50210/properly-using-separate-tabs-with-arduino-ide">参考:Properly using separate tabs with Arduino IDE</a></li> <li>Git を利用すると、複数人で作業したファイルを統合しやすいです。</li> </ul> </div> <div class="section" id="id3"> <h2>タスク<a class="headerlink" href="#id3" title="このヘッドラインへのパーマリンク">¶</a></h2> <p>複数の機能を1つの <code class="docutils literal notranslate"><span class="pre">loop()</span></code> にまとめようとすると、プログラムが複雑になります。タスクを用いると、 <code class="docutils literal notranslate"><span class="pre">loop()</span></code> に相当する関数を複数定義し、並列に動作させることができます。</p> <p><a class="reference internal" href="#task01"><span class="std std-numref">リスト 27</span></a> に、タスクを利用する例を示します。3つの異なるタスクを作成し、それぞれの関数内部で <code class="docutils literal notranslate"><span class="pre">setup()</span></code> と <code class="docutils literal notranslate"><span class="pre">loop()</span></code> に相当する処理を記述しています。 引数の詳細については、<a class="reference external" href="https://lang-ship.com/reference/unofficial/M5StickC/Functions/freertos/task">非公式日本語リファレンス</a> を参照してください。 ここの例では、1つのファイルに記述していますが、タスクごとに別のファイルにすることもできます。 以下の例ではタスク生成時に、タスクハンドル <code class="docutils literal notranslate"><span class="pre">TaskHandle_t</span></code> を設定しています。タスクハンドルは、タスクの一時停止(サスペンド)や、再開(レジューム)、削除のときにタスクを特定するために必要となります。</p> <div class="literal-block-wrapper docutils container" id="task01"> <div class="code-block-caption"><span class="caption-number">リスト 27 </span><span class="caption-text">src/task01.ino</span><a class="headerlink" href="#task01" title="このコードへのパーマリンク">¶</a></div> <div class="highlight-arduino notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf"><M5StickCPlus.h></span><span class="cp"></span> <span class="kr">int</span> <span class="n">interval_msec</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">333</span><span class="p">,</span> <span class="mi">1000</span><span class="p">,</span> <span class="mi">2000</span> <span class="p">};</span> <span class="c1">// Led, Lcd, Beep</span> <span class="hll"><span class="n">TaskHandle_t</span> <span class="n">tH</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> </span> <span class="kr">void</span> <span class="nf">ledTask</span><span class="p">(</span><span class="kr">void</span> <span class="o">*</span><span class="n">pvParam</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/** setup をここに書く **/</span> <span class="n">portTickType</span> <span class="n">lastTime</span><span class="p">;</span> <span class="kr">int</span> <span class="n">PIN</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> <span class="nf">pinMode</span><span class="p">(</span><span class="n">PIN</span><span class="p">,</span> <span class="kr">OUTPUT</span><span class="p">);</span> <span class="c1">// PINのモード設定</span> <span class="kr">int</span> <span class="n">highOrLow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span> <span class="cm">/** loop をここに書く **/</span> <span class="n">lastTime</span> <span class="o">=</span> <span class="n">xTaskGetTickCount</span><span class="p">();</span> <span class="n">vTaskDelayUntil</span><span class="p">(</span><span class="o">&</span><span class="n">lastTime</span><span class="p">,</span> <span class="n">interval_msec</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="p">);</span> <span class="c1">// 第2引数に、実行間隔ミリ秒を指定</span> <span class="nf">digitalWrite</span><span class="p">(</span><span class="n">PIN</span><span class="p">,</span> <span class="n">highOrLow</span><span class="p">);</span> <span class="c1">// HIGH = 1, LOW = 0</span> <span class="n">highOrLow</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">-</span> <span class="n">highOrLow</span><span class="p">;</span> <span class="c1">// HIGH <=> LOW を切り替える</span> <span class="p">}</span> <span class="p">}</span> <span class="kr">void</span> <span class="nf">lcdTask</span><span class="p">(</span><span class="kr">void</span> <span class="o">*</span><span class="n">pvParam</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/** setup をここに書く **/</span> <span class="n">portTickType</span> <span class="n">lastTime</span><span class="p">;</span> <span class="n">M5</span><span class="p">.</span><span class="n">Lcd</span><span class="p">.</span><span class="n">setRotation</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="n">M5</span><span class="p">.</span><span class="n">Lcd</span><span class="p">.</span><span class="n">fillScreen</span><span class="p">(</span><span class="n">GREEN</span><span class="p">);</span> <span class="n">M5</span><span class="p">.</span><span class="n">Lcd</span><span class="p">.</span><span class="n">setTextColor</span><span class="p">(</span><span class="n">WHITE</span><span class="p">,</span> <span class="n">OLIVE</span><span class="p">);</span> <span class="n">M5</span><span class="p">.</span><span class="n">Lcd</span><span class="p">.</span><span class="nf">setTextSize</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span> <span class="n">M5</span><span class="p">.</span><span class="n">Lcd</span><span class="p">.</span><span class="nf">setCursor</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="kr">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span> <span class="cm">/** loop をここに書く **/</span> <span class="n">M5</span><span class="p">.</span><span class="n">Lcd</span><span class="p">.</span><span class="n">printf</span><span class="p">(</span><span class="s">"count=%d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">count</span><span class="p">);</span> <span class="n">count</span><span class="o">++</span><span class="p">;</span> <span class="n">lastTime</span> <span class="o">=</span> <span class="n">xTaskGetTickCount</span><span class="p">();</span> <span class="n">vTaskDelayUntil</span><span class="p">(</span><span class="o">&</span><span class="n">lastTime</span><span class="p">,</span> <span class="n">interval_msec</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="p">);</span> <span class="c1">// 第2引数に、実行間隔ミリ秒を指定</span> <span class="k">if</span> <span class="p">(</span><span class="n">count</span> <span class="o">%</span> <span class="mi">10</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="n">M5</span><span class="p">.</span><span class="n">Lcd</span><span class="p">.</span><span class="n">fillScreen</span><span class="p">(</span><span class="n">GREEN</span><span class="p">);</span> <span class="n">M5</span><span class="p">.</span><span class="n">Lcd</span><span class="p">.</span><span class="nf">setCursor</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="p">}</span> <span class="p">}</span> <span class="p">}</span> <span class="kr">void</span> <span class="nf">beepTask</span><span class="p">(</span><span class="kr">void</span> <span class="o">*</span><span class="n">pvParam</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/** setup をここに書く **/</span> <span class="n">portTickType</span> <span class="n">lastTime</span><span class="p">;</span> <span class="kr">int</span> <span class="n">f</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">262</span><span class="p">,</span> <span class="mi">294</span><span class="p">,</span> <span class="mi">330</span><span class="p">,</span> <span class="mi">349</span><span class="p">,</span> <span class="mi">392</span><span class="p">,</span> <span class="mi">440</span><span class="p">,</span> <span class="mi">494</span><span class="p">,</span> <span class="mi">524</span> <span class="p">};</span> <span class="kr">int</span> <span class="n">note</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span> <span class="cm">/** loop をここに書く **/</span> <span class="n">lastTime</span> <span class="o">=</span> <span class="n">xTaskGetTickCount</span><span class="p">();</span> <span class="c1">// ここでの時刻を変数に保存</span> <span class="n">M5</span><span class="p">.</span><span class="n">Beep</span><span class="p">.</span><span class="nf">tone</span><span class="p">(</span> <span class="n">f</span><span class="p">[</span><span class="n">note</span><span class="p">]</span> <span class="p">);</span> <span class="nf">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span> <span class="c1">//0.5秒鳴らす</span> <span class="n">M5</span><span class="p">.</span><span class="n">Beep</span><span class="p">.</span><span class="n">mute</span><span class="p">();</span> <span class="n">note</span> <span class="o">=</span> <span class="p">(</span><span class="n">note</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">%</span><span class="mi">8</span><span class="p">;</span> <span class="n">vTaskDelayUntil</span><span class="p">(</span><span class="o">&</span><span class="n">lastTime</span><span class="p">,</span> <span class="n">interval_msec</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="p">);</span> <span class="c1">// 途中の処理やdelayは含まず、「保存」時刻の2秒後まで待つ。</span> <span class="p">}</span> <span class="p">}</span> <span class="kr">void</span> <span class="nb">setup</span><span class="p">()</span> <span class="p">{</span> <span class="n">M5</span><span class="p">.</span><span class="nf">begin</span><span class="p">();</span> <span class="hll"> <span class="n">xTaskCreatePinnedToCore</span><span class="p">(</span><span class="n">ledTask</span> <span class="p">,</span> <span class="s">"LedT"</span><span class="p">,</span> <span class="mi">4096</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&</span><span class="n">tH</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="mi">1</span><span class="cm">/*<= CoreNo.*/</span> <span class="p">);</span> </span><span class="hll"> <span class="n">xTaskCreatePinnedToCore</span><span class="p">(</span><span class="n">lcdTask</span> <span class="p">,</span> <span class="s">"LcdT"</span><span class="p">,</span> <span class="mi">4096</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&</span><span class="n">tH</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="mi">1</span><span class="cm">/*<= CoreNo.*/</span> <span class="p">);</span> </span><span class="hll"> <span class="n">xTaskCreatePinnedToCore</span><span class="p">(</span><span class="n">beepTask</span><span class="p">,</span><span class="s">"BeepT"</span><span class="p">,</span> <span class="mi">4096</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&</span><span class="n">tH</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="mi">0</span><span class="cm">/*<= CoreNo.*/</span> <span class="p">);</span> </span><span class="p">}</span> <span class="kr">void</span> <span class="nb">loop</span><span class="p">()</span> <span class="p">{</span> <span class="nf">delay</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> <span class="p">}</span> </pre></div> </td></tr></table></div> </div> <div class="admonition note"> <p class="first admonition-title">注釈</p> <p class="last">参考: <a class="reference external" href="https://qiita.com/hideakitai/items/bd95d0db63097b8808f9">FreeRTOSでマルチタスク (on ESP32)</a></p> </div> <p>タスク生成時に、引数を渡すこともできます。<a class="reference internal" href="#task02"><span class="std std-numref">リスト 28</span></a> に、引数を渡す例を示します。(次で述べるミューテックスを使って、排他制御もしています。)</p> <div class="literal-block-wrapper docutils container" id="task02"> <div class="code-block-caption"><span class="caption-number">リスト 28 </span><span class="caption-text">src/task02.ino</span><a class="headerlink" href="#task02" title="このコードへのパーマリンク">¶</a></div> <div class="highlight-arduino notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="hll"><span class="n">xSemaphoreHandle</span> <span class="n">mutex</span><span class="p">;</span> <span class="c1">//ミューテックス(排他制御用)</span> </span> <span class="kr">void</span> <span class="nf">withArgTask</span><span class="p">(</span><span class="kr">void</span> <span class="o">*</span><span class="n">pvParam</span><span class="p">)</span> <span class="p">{</span> <span class="kr">int</span> <span class="n">num</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kr">int</span><span class="o">*</span><span class="p">)</span> <span class="n">pvParam</span><span class="p">;</span> <span class="c1">// 引数は、グローバル変数のアドレスをポインタで渡す</span> <span class="n">BaseType_t</span> <span class="n">mStatus</span><span class="p">;</span> <span class="hll"> <span class="kr">char</span><span class="o">*</span> <span class="n">tsknm</span> <span class="o">=</span> <span class="n">pcTaskGetTaskName</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span> <span class="c1">//自タスク名を取得するならNULL、他タスク名を取得するならタスクハンドルを引数に指定する。</span> </span> <span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="hll"> <span class="n">mStatus</span> <span class="o">=</span> <span class="n">xSemaphoreTake</span><span class="p">(</span><span class="n">mutex</span><span class="p">,</span> <span class="mi">500</span><span class="p">);</span> <span class="c1">// ミューテックスを取得</span> </span> <span class="k">if</span> <span class="p">(</span><span class="n">mStatus</span> <span class="o">==</span> <span class="n">pdPASS</span><span class="p">)</span> <span class="p">{</span> <span class="nf">Serial</span><span class="p">.</span><span class="nf">println</span><span class="p">(</span><span class="s">"----"</span><span class="p">);</span> <span class="nf">Serial</span><span class="p">.</span><span class="n">printf</span><span class="p">(</span><span class="s">"[%s] "</span><span class="p">,</span> <span class="n">tsknm</span> <span class="p">);</span> <span class="nf">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span> <span class="k">for</span> <span class="p">(</span><span class="kr">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">6</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="nf">Serial</span><span class="p">.</span><span class="n">printf</span><span class="p">(</span><span class="s">"%d "</span><span class="p">,</span> <span class="n">i</span> <span class="o">*</span> <span class="n">num</span><span class="p">);</span> <span class="nf">delay</span><span class="p">(</span><span class="mi">300</span><span class="p">);</span> <span class="p">}</span> <span class="nf">delay</span><span class="p">(</span><span class="mi">300</span><span class="p">);</span> <span class="nf">Serial</span><span class="p">.</span><span class="n">printf</span><span class="p">(</span><span class="s">"done </span><span class="se">\n</span><span class="s">"</span><span class="p">);</span> <span class="nf">delay</span><span class="p">(</span><span class="mi">300</span><span class="p">);</span> <span class="hll"> <span class="n">xSemaphoreGive</span><span class="p">(</span><span class="n">mutex</span><span class="p">);</span> <span class="c1">// ミューテックスを解放</span> </span><span class="hll"> <span class="n">vTaskDelete</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span> <span class="c1">// 自タスクを削除する</span> </span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="nf">delay</span><span class="p">(</span><span class="nf">random</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="mi">100</span><span class="p">));</span> <span class="c1">//ミューテックスがとれなかったらランダムに待つ</span> <span class="p">}</span> <span class="p">}</span> <span class="p">}</span> <span class="kr">int</span> <span class="n">arg</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">11</span><span class="p">}</span> <span class="p">;</span> <span class="kr">char</span> <span class="n">tskname</span><span class="p">[</span><span class="mi">5</span><span class="p">];</span> <span class="kr">void</span> <span class="nb">setup</span><span class="p">()</span> <span class="p">{</span> <span class="nf">Serial</span><span class="p">.</span><span class="nf">begin</span><span class="p">(</span><span class="mi">115200</span><span class="p">);</span> <span class="hll"> <span class="n">mutex</span> <span class="o">=</span> <span class="n">xSemaphoreCreateMutex</span><span class="p">();</span> <span class="c1">// ミューテックス作成</span> </span><span class="p">}</span> <span class="kr">void</span> <span class="nb">loop</span><span class="p">()</span> <span class="p">{</span> <span class="nf">Serial</span><span class="p">.</span><span class="nf">println</span><span class="p">(</span><span class="s">"-------"</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="n">mutex</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// ミューテックスの作成に成功していたら</span> <span class="k">for</span> <span class="p">(</span><span class="kr">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="n">sprintf</span><span class="p">(</span><span class="n">tskname</span><span class="p">,</span> <span class="s">"x%d"</span><span class="p">,</span> <span class="n">arg</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> <span class="hll"> <span class="n">xTaskCreatePinnedToCore</span><span class="p">(</span><span class="n">withArgTask</span><span class="p">,</span> <span class="n">tskname</span><span class="p">,</span> <span class="mi">4096</span><span class="p">,</span> <span class="o">&</span><span class="n">arg</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">NULL</span> <span class="p">,</span> <span class="mi">1</span><span class="p">);</span> </span> <span class="p">}</span> <span class="p">}</span> <span class="nf">delay</span><span class="p">(</span><span class="mi">20</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">);</span> <span class="c1">// 次のタスクの仕込みまで、20秒待つ</span> <span class="p">}</span> </pre></div> </td></tr></table></div> </div> <div class="admonition warning"> <p class="first admonition-title">警告</p> <p class="last">引数をアドレスで渡すとき、関数内で宣言したローカル変数は使えません。グローバルな変数を使用する必要があります。</p> </div> </div> <div class="section" id="id5"> <h2>ミューテックスとセマフォ<a class="headerlink" href="#id5" title="このヘッドラインへのパーマリンク">¶</a></h2> <p>複数のタスクを並列動作させると、リソース(入出力や、メモリ)に複数のタスクが同時アクセスすることで意図しない動作を引き起こすことがあります。 ミューテックス(mutex: mutual exclusion)を用いると、リソースに同時にアクセスするタスクを1つに限定することができます。これを「排他制御」と呼びます。</p> <p><a class="reference internal" href="#task02"><span class="std std-numref">リスト 28</span></a> の例では、ミューテックスをつかって、1つのタスクの動作(シリアルコンソールへの書き込み)が終わるまで、他のタスクが待つ例です。 このように、常時動いているタスクに対して、一時停止したり、処理を制限したりするのがミューテックスの使い方です。 (参考:<a class="reference external" href="https://lang-ship.com/blog/work/esp32-freertos-l06-semaphore-mutex">ESP32のFreeRTOS入門 その6 セマフォとミューテックス</a> )</p> <p>これに対して、セマフォは、基本的には待機・一時停止状態にあるタスクに対して、動作許可を与える用途で使用されます。 動作許可を与える主体・タイミングとしては、他のタスクや、「割り込み(ISR: interrupt service routine)」からになります。 ただし、バイナリセマフォを用いるより、<a class="reference external" href="https://www.freertos.org/RTOS_Task_Notification_As_Binary_Semaphore.html">RTOS Task Notifications</a> を用いたほうが、高速かつメモリ使用量を削減できるようです。</p> <ul class="simple"> <li>バイナリセマフォは、タスク間またはタスクと割り込み間の同期に適しています。</li> <li>バイナリセマフォとミューテックスは似ていますが、いくつか本質的な違いがあります。ミューテックスは優先度を継承する機構が備わっていますが、バイナリセマフォには備わっていません。</li> </ul> <div class="admonition note"> <p class="first admonition-title">注釈</p> <p class="last">参考: <a class="reference external" href="https://www.freertos.org/xSemaphoreCreateBinary.html">RTOS binary semaphore API</a></p> </div> </div> <div class="section" id="id6"> <h2>キュー<a class="headerlink" href="#id6" title="このヘッドラインへのパーマリンク">¶</a></h2> <p>参考:<a class="reference external" href="https://lang-ship.com/blog/work/esp32-freertos-l05-queue">ESP32のFreeRTOS入門 その5 キュー</a></p> </div> <div class="section" id="freertosrtos"> <h2>FreeRTOSと、その他のRTOS<a class="headerlink" href="#freertosrtos" title="このヘッドラインへのパーマリンク">¶</a></h2> <p>今回の実験では、Arduino IDEでのM5StickCPlusプログラミングを行ってきました。これまでArduino IDEでM5StickCPlusに書き込んできたプログラムは、FreeRTOS (RealTime OS) というRTOSの仕組みをつかって動作しています。 いいかえると、ESP32プロセッサ上で、FreeRTOS プログラミングをしていたことになります。ちなみに、M5StickCPlusのような画面やブザー、センサがついていない <a class="reference external" href="https://akizukidenshi.com/catalog/g/gM-15673">ESP32プロセッサ開発ボード</a> も販売されています。</p> <ul class="simple"> <li>MCU RTOS習得(2020年版) <a class="reference external" href="http://happytech.jp/bRTOS.html">http://happytech.jp/bRTOS.html</a></li> </ul> <p>その他のRTOSには、T-Kernel や ThreadX があります。こちらも、限られた資源(メモリやプロセッサ)で、厳密な処理時間管理が行える仕組みが備わっています。</p> <ul class="simple"> <li>参考:<a class="reference external" href="https://cit.istlab.info/ex1">2020年度 情報通信工学実験1 リアルタイムプログラミング【RTP】</a></li> </ul> </div> </div> </div> </div> <footer> <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation"> <a href="faq.html" class="btn btn-neutral float-right" title="Frequently-Asked Questions (FAQ: よくある質問)" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a> <a href="week1.html" class="btn btn-neutral float-left" title="1週目" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a> </div> <hr/> <div role="contentinfo"> <p> © Copyright 2021, Motoki Miura. </p> </div> Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. </footer> </div> </div> </section> </div> <script type="text/javascript"> jQuery(function () { SphinxRtdTheme.Navigation.enable(true); }); </script> </body> </html>