PICマイクロコントローラーでのマルチタスク


17

最近ではマルチタスクが重要です。マイクロコントローラや組み込みプログラミングでどのように実現できるのでしょうか。PICマイクロコントローラーをベースにしたシステムを設計しています。Cを使用してMplabX IDEでファームウェアを設計し、C#を使用してVisual Studioでアプリケーションを設計しました。

デスクトップのC#プログラミングでスレッドを使用して並列タスクを実装することに慣れてきたので、マイクロコントローラーコードで同じことを行う方法はありますか?MplabX IDEは提供しますpthreads.hが、実装のない単なるスタブです。FreeRTOSのサポートがあることは知っていますが、それを使用するとコードがより複雑になります。一部のフォーラムでは、割り込みもマルチタスクとして使用できると述べていますが、割り込みはスレッドと同等ではないと思います。

一部のデータをUARTに送信すると同時に、(有線)イーサネット経由でWebサイトにデータを送信する必要があるシステムを設計しています。ユーザーはWebサイトから出力を制御できますが、出力は2〜3秒の遅延でオン/オフになります。それが私が直面している問題です。マイクロコントローラーでマルチタスクを実行するためのソリューションはありますか?


スレッドはプロセスの一部であり、プロセスはOSでのみ使用されるため、スレッドはOSを実行するプロセッサーでのみ使用できます。
TicTacToe

@Zolaはい、そうです。しかし、コントローラーの場合はどうでしょうか?
航空機


1
真のマルチタスクが必要であり、ラウンドロビンタスクアプローチまたはselect()ループなどに基づいてソフトウェアを合理的に実装できない理由を説明できますか?
-whatsisname

2
さて、すでに述べたように、私はuartとデータを送受信し、同時にイーサネットとデータを送受信しています。これとは別に、時間とともにSDカードにデータを保存する必要もあるため、DS1307 RTCが関係し、EEPROMも関係します。今までは1つのUARTしかありませんが、数日後には3つのUARTモジュールからデータを送受信しています。ウェブサイトは、遠隔地に設置された5つの異なるシステムからもデータを受信します。これはすべて並列でなければなりませんが、並列ではなく、数秒の遅延が必要です。!
航空機

回答:


20

マルチタスクオペレーティングシステムには、プリエンプティブと協調の2つの主なタイプがあります。どちらもシステムで複数のタスクを定義できますが、違いはタスクの切り替えがどのように機能するかです。もちろん、単一のコアプロセッサでは、一度に実際に実行されるタスクは1つだけです。

どちらのタイプのマルチタスクOSでも、タスクごとに個別のスタックが必要です。つまり、これは2つのことを意味します。1つ目は、プロセッサがRAMの任意の場所にスタックを配置できるため、スタックポインター(SP)を移動する命令があることです。 PICの。これにより、PIC10、12、および16シリーズは除外されます。

OSはほぼ完全にCで記述できますが、SPが動き回るタスクスイッチャーはアセンブリ内にある必要があります。PIC24、PIC32、8051、および80x86用のタスクスイッチャーを何度も書いてきました。ガッツはすべて、プロセッサのアーキテクチャに応じてまったく異なります。

2番目の要件は、複数のスタックを提供するのに十分なRAMがあることです。通常、スタックには少なくとも数百バイトが必要です。ただし、タスクあたりわずか128バイトでも、8つのスタックには1KバイトのRAMが必要になります。ただし、各タスクに同じサイズのスタックを割り当てる必要はありません。現在のタスク、およびそのネストされたサブルーチンの呼び出しを処理するのに十分なスタックが必要であることに注意してください。

各タスクに使用しているスタックの量を判断するためのかなり簡単な方法があります。たとえば、すべてのスタックを特定の値(0x55など)に初期化し、システムをしばらく実行してから、メモリを停止して調べることができます。

どんな種類のPICを使用したいかは言いません。ほとんどのPIC24とPIC32には、マルチタスクOSを実​​行するための十分なスペースがあります。PIC18(RAMにスタックを持つ唯一の8ビットPIC)の最大RAMサイズは4Kです。だからそれはかなり不確かです。

協調マルチタスク(2つのうちの単純なもの)では、タスクの切り替えは、タスクがその制御を「放棄」してOSに戻るときにのみ行われます。これは、タスクがOSルーチンを呼び出して、I / O要求やタイマー呼び出しなど、待機する機能を実行する必要がある場合に発生します。これにより、OSがスタックを切り替えるのが容易になります。すべてのレジスタと状態情報を保存する必要がないため、SPを別のタスクに切り替えることができます(実行するタスクが他にない場合、アイドルスタックは与えられた制御)。現在のタスクがOS呼び出しを行う必要はないが、しばらく実行されている場合は、システムの応答性を維持するために、自発的に制御を放棄する必要があります。

協調マルチタスクの問題は、タスクが制御を決して放棄しない場合、システムを独占する可能性があることです。それと制御が与えられた割り込みルーチンのみが実行できるため、OSはロックアップしているように見えます。これは、これらのシステムの「協力的な」側面です。タスク切り替えが実行されたときにのみリセットされるウォッチドッグタイマーが実装されている場合、これらの誤ったタスクをキャッチすることができます。

Windows 3.1以前は協同運用システムであったため、パフォーマンスがそれほど優れていなかった理由の1つです。

プリエンプティブマルチタスクは実装がより困難です。ここでは、タスクは手動で制御を放棄する必要はありませんが、代わりに各タスクに最大実行時間(10ミリ秒など)を与えることができます。次に、タスクがあれば、次の実行可能なタスクに切り替えられます。これには、タスクを任意に停止し、すべての状態情報を保存してから、SPを別のタスクに切り替えて開始する必要があります。これにより、タスクスイッチャーがより複雑になり、より多くのスタックが必要になり、システムの速度が少し低下します。

協調的マルチタスクとプリエンプティブマルチタスクの両方で、実行中のタスクを一時的に横取りする割り込みがいつでも発生する可能性があります。

supercatがコメントで指摘しているように、協調マルチタスクの利点の1つは、リソースの共有が容易なことです(たとえば、マルチチャネルADCなどのハードウェアやリンクリストの変更などのソフトウェア)。2つのタスクが同時に同じリソースにアクセスしたい場合があります。プリエンプティブスケジューリングを使用すると、OSはリソースを使用して1つのタスクの途中でタスクを切り替えることができます。そのため、別のタスクが入って同じリソースにアクセスするのを防ぐためにロックが必要です。協調マルチタスクでは、タスクがいつそれをOSに解放するかを制御するため、これは必要ありません。


3
協調型マルチタスクの利点は、ほとんどの場合、ロックを使用してリソースへのアクセスを調整する必要がないことです。タスクが制御を放棄するたびに、タスクが常に共有可能な状態のままになるようにするだけで十分です。タスクが別のタスクに必要なリソースのロックを保持している間にタスクが切り替えられる可能性がある場合、プリエンプティブマルチタスクははるかに複雑です。いくつかのケースでは、2番目のタスクは、ロックを保持しているタスクは、システムの...捧げているであろうから、それは、協力体制の下にあったであろうよりも長いためにブロックされたばかり終わる可能性があります
supercat

1
...(プリエンプティブシステム上で)ロックが必要だったアクションを完了するためのリソースをすべて確保し、2番目のタスクで保護されたオブジェクトを利用できるようにします。
supercat

1
協調型マルチタスカーには規律が必要ですが、タイミング要件が満たされるようにすることは、協調型マルチタスカーの方がプリエンプティブなマルチタスカーよりも簡単な場合があります。タスクスイッチを介して保持する必要があるロックはほとんどないため、タスクが降伏せずに10ミリ秒を超えないようにする必要がある5タスクラウンドロビンタスクスイッチシステムは、「タスクXが緊急に実行する必要があり、次に実行する必要があります」、タスクXが実行される前にシグナルを送信してから10ミリ秒以上待機する必要がないようにします 対照的に、タスクがロックを必要とする場合、タスクX
...-supercat

1
...必要になりますが、それをリリースする前にプリエンプティブスイッチャーによって切り替えられるため、XはCPUスケジューラーが最初のタスクを実行するまで何の役にも立たないかもしれません。優先順位の反転を認識して処理するロジックがスケジューラに含まれていない限り、最初のタスクがビジネスを終了してロックを解除するまでに時間がかかる場合があります。そのような問題は解決不可能ではありませんが、それらを解決するには、協調システムでは回避できた多くの複雑さが必要です。協調システムは、1つの落とし穴を除いて優れた機能を発揮します:...
落とし穴発揮し。...– supercat

3
連続してコーディングする場合、協調して複数のスタックを必要としません。本質的に、コードは関数に分割されvoid foo(void* context)、コントローラーロジック(カーネル)は、キューのポインターと関数ポインターのペアを1つずつ取り出し、一度に1つずつ呼び出します。この関数は、コンテキストを使用して変数などを保存し、キューに継続を追加することができます。これらの関数は、他のタスクにCPUでの瞬間を許可するために、すばやく戻る必要があります。これは、単一のスタックのみを必要とするイベントベースのメソッドです。
ラチェットフリーク

16

スレッドはオペレーティングシステムによって提供されます。組み込みの世界では、通常OS(「ベアメタル」)はありません。そのため、次のオプションが残ります。

  • 古典的なメインポーリングループ。メイン関数には、タスク1を実行してからタスク2を実行するwhile(1)があります...
  • メインループ+ ISRフラグ:タイムクリティカルな機能を実行し、タスクにサービスが必要であることをフラグ変数を介してメインループに警告するISRがあります。おそらく、ISRは新しい文字を循環バッファーに入れて、準備ができたらデータを処理するようにメインループに指示します。
  • すべてのISR:ここのロジックの多くはISRから実行されます。複数の優先度レベルを持つARMなどの最新のコントローラー。これは強力な「スレッドのような」スキームを提供しますが、デバッグが混乱する可能性があるため、重要なタイミング制約のためにのみ予約する必要があります。
  • RTOS:RTOSカーネル(タイマーISRによって促進される)は、実行の複数のスレッド間の切り替えを可能にします。FreeRTOSについて言及しました。

上記のスキームのうち、アプリケーションで機能する最も簡単なスキームを使用することをお勧めします。あなたの説明から、メインループでパケットを生成し、それらを循環バッファーに配置します。次に、バッファが送信されるまで前のバイトの送信が完了するたびに起動するUART ISRベースのドライバを用意し、その後、さらにバッファの内容を待ちます。イーサネットの同様のアプローチ。


3
これは、問題の根源(ソリューションとしてのスレッドではなく、小さな組み込みシステムでマルチタスクを行う方法)に対処するため、非常に有用な回答です。元の質問にどのように適用できるかについてのパラグラフは素晴らしいでしょう。おそらくシナリオのそれぞれの長所と短所が含まれます。
デビッド

8

シングルコアプロセッサのように、実際のソフトウェアマルチタスクを実行することはできません。そのため、複数のタスクを一方向に切り替えるよう注意する必要があります。さまざまなRTOSがそれを処理します。それらにはスケジューラがあり、システムティックに基づいて、異なるタスクを切り替えてマルチタスク機能を提供します。

そのために必要な概念(コンテキストの保存と復元)は非常に複雑であるため、これを手動で行うことはおそらく困難であり、コードがより複雑になります。ここでの私のアドバイスは、FreeRTOSと同様にテスト済みのRTOSを使用することです。

あなたは、割り込みがマルチタスクのレベルを提供すると述べました。これは一種の真実です。割り込みは、任意の時点で現在のプログラムを中断し、そこでコードを実行します。これは、1つのタスクの優先度が低く、スケジューラの1つのタイムスライス内で終了する優先度の高い2つのタスクシステムに相当します。

したがって、UARTを介していくつかのパケットを送信する繰り返しタイマーの割り込みハンドラーを作成し、プログラムの残りを数ミリ秒実行して、次の数バイトを送信します。そうすれば、限られたマルチタスク機能を得ることができます。しかし、あなたはまた、悪いことかもしれないかなり長い割り込みを持っているでしょう。

シングルコアMCUで複数のタスクを同時に実行する唯一の現実的な方法は、コアとは独立して動作するDMAとペリフェラルを使用することです(DMAとMCUは同じバスを共有するため、動作が少し遅くなります)両方ともアクティブです)。したがって、DMAがUARTにバイトをシャッフルしている間、コアはイーサネットにデータを自由に送信できます。


2
おかげで、DMAはおもしろそうです。間違いなく検索します。!
航空機

すべてのシリーズのPICにDMAがあるわけではありません。
マットヤング

1
私はPIC32を使用しています;)
航空機

6

他の回答では、最もよく使用されるオプション(メインループ、ISR、RTOS)について既に説明しました。妥協案としてもう1つのオプション、Protothreadsがあります。基本的にスレッド用の非常に軽量なライブラリであり、メインループといくつかのCマクロを使用してRTOSを「エミュレート」します。もちろん、完全なOSではありませんが、「単純な」スレッドには便利です。


Windows用のソースコードはどこからダウンロードできますか?Linuxでしか利用できないと思います!
航空機

@CZAbhinav OSに依存しないはずです。最新のダウンロードはこちらから入手できます
エレボス

私は今窓にいて、MplabXを使用していますが、ここでは役に立たないと思います。とりあえずありがとう。!
航空機

プロトスレッドについて聞いたことがない、面白いテクニックのように聞こえます。
アーセナル

@CZAbhinav何言ってるの?Cコードであり、オペレーティングシステムとは関係ありません。
マットヤング

3

最小限のタイムスライスRTOSの私の基本的な設計は、いくつかのマイクロファミリであまり変わりません。基本的には、ステートマシンを駆動するタイマー割り込みです。割り込みサービスルーチンはOSカーネルであり、メインループのswitchステートメントはユーザータスクです。デバイスドライバは、I / O割り込み用の割り込みサービスルーチンです。

基本的な構造は次のとおりです。

unsigned char tick;

void interrupt HANDLER(void) {
    device_driver_A();
    device_driver_B();
    if(T0IF)
    {
        TMR0 = TICK_1MS;
        T0IF = 0;   // reset timer interrupt
        tick ++;
    }
}

void main(void)
{
    init();

    while (1) {
        // periodic tasks:
        if (tick % 10 == 0) { // roughly every 10 ms
            task_A();
            task_B();    
        }
        if (tick % 55 == 0) { // roughly every 55 ms
            task_C();
            task_D();    
        }

        // tasks that need to run every loop:
        task_E();
        task_F();
    }
}

これは基本的に、協調的なマルチタスクシステムです。タスクは無限ループに入らないように記述されていますが、タスクはイベントループ内で実行されるため、無限ループは暗黙的であるため、気にしません。これは、javascriptやgoなどのイベント指向/非ブロック言語に似たプログラミングスタイルです。

私のRC送信機ソフトウェアでこのスタイルのアーキテクチャの例を見ることができます(はい、私は実際にRC飛行機を飛ばすためにそれを使用していますので、飛行機をcrash落させ、潜在的に人々を殺すのを防ぐためにいくらか安全が重要です):https : //github.com / slebetman / pic-txmod。基本的に3つのタスクがあります-ステートフルデバイスドライバーとして実装された2つのリアルタイムタスク(ppmioを参照)と、ミキシングロジックを実装した1つのバックグラウンドタスク。したがって、基本的には2つのI / Oスレッドがあるという点でWebサーバーに似ています。


1
複数のことをしなければならない他のマイクロコントローラープログラムと実際には実質的に変わらないので、私はそれを「協調的マルチタスク」とは本当に呼びません。
-whatsisname

2

質問が組み込みRTOSの使用について具体的に尋ねていることを感謝していますが、尋ねられるより広範な質問は「組み込みプラットフォームでマルチタスクを達成する方法」であると思います。

少なくとも当面は、組み込みRTOSの使用を忘れることを強くお勧めします。これは、単純なタスクスケジューラとステートマシンで構成される非常に単純なプログラミング手法を使用して、タスクの「同時実行」を実現する方法を最初に学ぶことが不可欠だと思うためです。

概念を非常に簡単に説明するために、実行する必要がある作業の各モジュール(つまり、各「タスク」)には、そのモジュールが何らかの処理を行うために定期的に呼び出す(「チェック」)必要がある特定の機能があります。モジュールは独自の現在の状態を保持します。次に、モジュール関数を呼び出すメインの無限ループ(スケジューラー)を作成します。

粗図:

for(;;)
{
    main_lcd_ui_tick();
    networking_tick();
}


...

// In your LCD UI module:
void main_lcd_ui_tick(void)
{
    check_for_key_presses();
    update_lcd();
}

...

// In your networking module:
void networking_tick(void)
{
    //'Tick' the TCP/IP library. In this example, I'm periodically
    //calling the main function for Keil's TCP/IP library.
    main_TcpNet();
}

メインスケジューラーループからメインステートマシン関数を定期的に呼び出すこのようなシングルスレッドプログラミング構造は、組み込みプログラミングのいたるところにあります。そのため、OPを使用する前に、まずOPに慣れて快適になることを強くお勧めします。 RTOSタスク/スレッド。

私は、ハードウェアLCDインターフェイス、内部Webサーバー、電子メールクライアント、DDNSクライアント、VOIP、および他の多くの機能を備えたタイプの組み込みデバイスで作業しています。RTOS(Keil RTX)を使用しますが、使用される個々のスレッド(タスク)の数は非常に少なく、上記のように「マルチタスク」のほとんどが達成されます。

この概念を示すライブラリの例をいくつか示します。

  1. Keilネットワークライブラリ。TCP / IPスタック全体をシングルスレッドで実行できます。main_TcpNet()を定期的に呼び出します。これにより、TCP / IPスタックと、ライブラリ(Webサーバーなど)からコンパイルしたその他のネットワークオプションが繰り返されます。http://www.keil.com/support/man/docs/rlarm/rlarm_main_tcpnet.htmを参照してください。確かに、状況によっては(おそらくこの回答の範囲外)、スレッドを使用することが有益または必要になり始めるポイントに到達します(特にブロッキングBSDソケットを使用している場合)。(さらに注意:新しいV5 MDK-ARMは実際に専用のイーサネットスレッドを生成します-しかし、私は単に図を提供しようとしています。)

  2. Linphone VOIPライブラリ。linphoneライブラリ自体はシングルスレッドです。iterate()十分な間隔で関数を呼び出します。http://www.linphone.org/docs/liblinphone-javadoc/org/linphone/core/LinphoneCore.html#iterate()を参照してください。(これは組み込みLinuxプラットフォームでこれを使用し、linphoneの依存ライブラリが間違いなくスレッドを生成するので、まずい例ですが、これもまたポイントを説明するためです。)

OPで概説された特定の問題に戻ると、問題は、一部のネットワーク(TCP / IPを介したパケットの送信)と同時にUART通信を行わなければならないという事実のようです。実際に使用しているネットワークライブラリはわかりませんが、頻繁に呼び出す必要があるメイン関数があると思います。メイン関数への定期的な呼び出しによって反復できる状態マシンとして、同様の方法で構造化されるように、UARTデータの送受信を処理するコードを記述する必要があります。


2
この素晴らしい説明のおかげで、マイクロチップが提供するTCP / IPライブラリを使用していますが、これは非常に巨大で複雑なコードです。どうにかしてそれをパーツに分割し、自分の要件に従って使用できるようにしました。私は間違いなくあなたのアプローチのいずれかを試します。
航空機

楽しんでください:) RTOSを使用すると、多くの状況で間違いなく生活が楽になります。私の考えでは、スレッド(タスク)を使用すると、タスクをステートマシンに分割する必要がなくなるため、ある意味でプログラミング作業がはるかに簡単になります。代わりに、C#プログラムで行うのと同じようにタスクコードを記述するだけで、タスクコードは存在する唯一のものであるかのように作成されます。両方のアプローチを検討することが不可欠であり、組み込みプログラミングをさらに行うにつれて、各アプローチがどのアプローチが最適であるかの感覚をつかみ始めます。
トレバーページ

また、スレッドオプションを使用することを好みます。:)
航空機
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.