OS がないため、PIC18のプログラミング中に並列で実行されるスレッドをどのように作成しますか?
13 に答える
スレッドを使用せず、イベントループを使用してください。
PIC18は小さなプロセッサであり、イベントループベースのスタイルであるため、多くの深いスタックをぶら下げておく必要はありません。イベントループの観点からコードを書く必要がありますが、それはおそらく合理的です。
長時間実行されるタスクがある場合は、タイマーを使用してさまざまな割り込み優先度レベルを設定し、優先度の高いイベントループが優先度の低いイベントループをプリエンプトし、適切な種類の作業を適切なイベントキューに配置できるようにします。
Cooperative multitaskingを試すことができます。
PIC が解決するタイプの問題については、複数のスレッドの代わりに割り込みまたはポーリングを使用する別の設計を試したほうがよいでしょう。
そこに RTOS を配置できます (非公式の ucOS ポートがあるか、 FreeRTOS の PIC18 ポートをチェックアウトできます)。
それ以外の場合は、 and を使用して C でコルーチンを実装してみてください。setjmp
longjmp
OS がまったくない場合は、(明らかに) 必要な機能を自分で再作成する必要があります。
最も簡単な方法は、おそらく適切な周波数で実行されるタイマー割り込みをインストールすることです (おそらく実際のクロック速度に依存しますが、おそらく 100 ~ 1000 Hz の範囲内です)。割り込みハンドラーでは、現在のスレッドの状態を検査し、切り替えが発生するかどうかを判断する必要があります。
秘訣は、必要に応じて切り替えを行い、割り込みハンドラーから別のスレッドに戻ることです。
もちろん、スレッド自体が割り込みを使用する可能性があるときにこれを機能させることは、必ずしも簡単ではありません。
おそらくContiki などのカーネルのインストールを検討することもできます。
これは PIC18 の「 protothreads」の例で、妥当な量のコードのように見えます。ただし、セマンティクスについてはわかりません。
更新: これにはおそらく、アセンブラーで最低レベルのコードを実行する必要があります (PIC で C を使用したことがないため、正確にどれだけ制御できるかわかりません)。プログラムカウンターのレジスターを制御する必要がありますが、それらは C の概念ではありません。
マイクロコントローラーでは、一部の「スレッド」は特定の割り込みハンドラーによっても処理できるため、メインイベントループと「並列」で実行されることに注意してください。
たとえば、ADC 変換をトリガーする外部イベントがある場合、ADC-conversion-done ハンドラーはその値を取得し、いくつかの計算を実行してから、いくつかの出力ビットを設定して、ADC 値に従って制御出力を適応させることができます。割り込みハンドラーで発生する可能性があるすべてのことは、他のすべてと並行して発生します。
並行して実行する必要がある内容に応じて、複数の手法を組み合わせて、意図したとおりに並行して動作させることができます。
組み込みシステム プログラミングに関するこの記事をお読みになることをお勧めします: 超シンプルなタスカーを構築する
8051 では、単純なスタック スイッチャーを使用してデュアル タスクを実行しました。各タスクが 16 レベルのスタックしか使用しない場合、PIC でも同じことができると思います。コードは次のようになります (_altSP が共通バンクにあると仮定)
_InitTask2: movff _STKPTR,_altSP 動く 16 movwf_STKPTR,c goto _Task2Start _タスクスイッチ: movf _altSP,w,c movff _STKPTR,_altSP movwf_STKPTR,c 戻る
メイン タスクは _InitTask2 を呼び出して、2 番目のタスクを開始する必要があります。2 番目のタスクは _TaskSwitch が呼び出されるまで実行され、メイン タスクは _InitTask2 を呼び出した命令に従って実行を再開します。以降、タスクが _TaskSwitch を呼び出すたびに、他のタスクは最後に _TaskSwitch を呼び出した場所から実行を再開します。
このアプローチを使用する場合、_InitTask2 または _TaskSwitch の呼び出しによってすべてのレジスタが破棄される可能性があることをコンパイラに通知する必要があります。また、_Task2Start とそれが呼び出す関数には、メイン タスクとは別の変数スペースを割り当てる必要があることも通知する必要があります。
コンパイラを満足させるために何を伝える必要があるのか はわかりませんが、協調的なデュアルタスクにより、いくつかのことが非常にうまく機能する可能性があると言えます。
The CCS compiler includes an RTOS. I haven't used it, but from the compiler manual:
The CCS Real Time Operating System (RTOS) allows a PIC micro controller to run regularly scheduled tasks without the need for interrupts. This is accomplished by a function (RTOS_RUN()) that acts as a dispatcher. When a task is scheduled to run, the dispatch function gives control of the processor to that task. When the task is done executing or does not need the processor anymore, control of the processor is returned to the dispatch function which then will give control of the processor to the next task that is scheduled to execute at the appropriate time. This process is called cooperative multi-tasking.
Just a word of warning - check their forums for info about the specific features you're looking for. Apparently CCS has a habit of releasing new features before they're fully tested. That's one reason I'm still using the older version (v3.249).
マイクロコントローラーでタスクを管理するために、私の小さなカーネルを C プログラミング言語で共有したいと思います。期間を指定してタスクを作成し、いつでもタスクの期間を一時停止、再開、および変更できます。このカーネルは、必要に応じてすべてのタスクを削除して、別のシーケンサーを作成できます。TickGet 関数は、必要に応じてすべてのタイマーを管理するためにカーネルによって提供されます。割り込み関数を 1 つだけ作成し、関数 Timer() を置き換えて、独自のアプリケーション用の小さなカーネルを取得する必要があります。このカーネルを再開するには、循環リンク リストに基づいて、タスクごとにタスクを切り替えます。人々が自分自身のアプリケーション用にカスタマイズするのを助けるために、一般的な方法で喜んで書かれています。ラウンド ロビン タスク スケジューリングのようなタスク間の優先度はありません。そして、このソース コードは、MISRA ガイドライン (自動車の基準) を考慮して作成しました。ここからダウンロードできます。
人々がマイクロコントローラーでタスクを管理するのを助けたいと思っています。
私はndimに同意します-各割り込みハンドラは「スレッド」のようなものと考えることができます。実行する必要のあるすべてのタスクは、外部イベントと内部イベントによってトリガーされる割り込みハンドラーによって処理できる場合があります。「メインループ」は、何もしないアイドルループです。
PIC18には「OSがない」という考えをどこから得ているのかわかりません。PIC18にはかなりの数のPIC固有のマルチスレッドライブラリと「マルチタスクオペレーティングシステムカーネル」があり、それらの多くは無料でオープンソースです。PICList:「PICマイクロコントローラー固有のマルチタスク方法」を参照してください。
これはまさにそのタスク ループを実行するだけでなく、タスクの優先度をプロビジョニングし、長時間実行される関数をスライスに分割する単純なコーディングが好きです。