質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
RTOS

RTOS(リアルタイムOS)は、リアルタイムシステムのためのOSです。実時間システムや実時間OSとも呼ばれ、時間的な制限のある処理を行うための機能・特性を備えています。組み込みシステムの制御に多く用いられています。

同期

複数のディレクトリに存在するファイルを更新した場合に、すべてのファイルにも更新が行われる事、又は、同じ記憶領域に同時にアクセスして内容の整合性が失われてしまう事をを防ぐ制御などを同期と呼びます。

Q&A

解決済

1回答

894閲覧

RTOSを使用した組込みソフトでタスク間で同期する方法(イベント通知が使えない制約下)

drao0113

総合スコア11

RTOS

RTOS(リアルタイムOS)は、リアルタイムシステムのためのOSです。実時間システムや実時間OSとも呼ばれ、時間的な制限のある処理を行うための機能・特性を備えています。組み込みシステムの制御に多く用いられています。

同期

複数のディレクトリに存在するファイルを更新した場合に、すべてのファイルにも更新が行われる事、又は、同じ記憶領域に同時にアクセスして内容の整合性が失われてしまう事をを防ぐ制御などを同期と呼びます。

0グッド

0クリップ

投稿2018/07/25 16:55

RTOSを使用して組み込みソフトの設計をしています。
タスク間でのデータの同期方法で分からないことがあるので、
教えていただけないでしょうか。

下記のようなタスクが存在するとします。

タスクA 10ms周期 データD,Eを10ms周期で更新
タスクB 100ms周期 データD,EをタスクB先頭でラッチ

※タスクBはイベントによる起床は許されないとする(過去のソースコード資産を流用するため)

質問1
以下の考え方は一般的ですか?
もっといい方法があれば知りたいです。

タスクB先頭でデータD,Eをラッチするのは、
タスクB実行中にデータD,Eのどちらかが更新され、
新旧混在したデータD,EがタスクBで使用されることを防ぐため

具体的に書くと、
前周期のデータDと今周期のデータEをもとに
制御ゲインを演算すると制御が破綻するようなケースがあり、
これを避けるため上記のような方法をとっています。

質問2
データDが0,1の2値をとる場合(例えば0:正常, 1:異常を表すような異常情報)、
下記のようにデータDが0から1に変化したことを、タスクBで確実に補足する良い方法はありますか?

データDが0から1に変化した場合に
タスクAからタスクBへイベントで通知するような方法が考えられますが、
タスクBはイベントによる起床は許されない場合、こうするのが一般的というような方法はありますか?

データDをタスクB起床までラッチしておくための別変数を定義し(データD’とする)、
タスクAでデータDが0から1に変化したときにデータD’=1とし、
タスクBでデータD'を参照後、データDが0であればデータD’=0とする、
のようにすれえば実現可能と思いますが、もっといい方法はないでしょうか?

経過時間: データD
0ms: データD=0
10ms: データD=0
20ms: データD=1
30ms: データD=1
40ms: データD=1
50ms: データD=1
60ms: データD=0
70ms: データD=0
80ms: データD=0
90ms: データD=0
100ms: タスクB起床

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

回答1:
データの整合性をとるために、先頭で一気にデータを取得するということはあり得ることです。
ただ、タスクの優先度や割り込みの発生可能性などで、タスクB実行中にデータD,Eが変更されないことが保証されているのなら、「先頭で取得する」必要はないですね。つまり、タスクBの方がタスクAより優先度が高く、タスクBの実行中にタスクAがデータD、Eを書き換えることがないなら、問題ないわけです。
ただし、関連性の強い二つのデータをわざわざ別々に取得する必要もなく、特に問題が無ければ、タスクBの先頭で両データを取得する方がわかりやすいと思います。

タスクAがデータDを変更後、タスクBが動き出すことはないですか?それを防ぐことはできますか?

回答2:
100ms周期以外でタスクBが動いてはマズイと言うことなのでしょう。
イベントフラグは使えないのですか?
タスクAがイベントフラグを送る。
タスクBは100ms起動ごとにイベントフラグをチェックする(フラグ待ちにはしないで、読み出すだけにする)
が出来るのではないでしょうか?

投稿2018/07/26 01:54

編集2018/07/26 01:59
nob.

総合スコア711

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

drao0113

2018/07/26 04:04

回答ありがとうございます。 さきに回答2の回答させてください。 おっしゃるととおりです。 タスクBは100ms周期以外では動いてはいけないです。 イベントフラグのフラグ待ちをしない方法があるのですね。 イベントフラグを使用した場合でも、 データDがイベントフラグに置き換わるのみで、タスクBで取り漏らす可能性がありますよね。 データキュー等、 使用すればいいのでしょうか? データD'を1から0にするタイミングを どのように判断するかが、わかっていません。 もう少し考えてみます。
drao0113

2018/07/26 14:05

回答1の回答をします。 すみません、タスクの優先度を記載してませんでした。 タスクAの優先度>タスクBの優先度です。 タスクBを実行中に、タスクAがデータD,Eを書き換える可能性があるので、 タスクBでデータD,Eを取得するときだけ、ミューテックス等で排他制御が必要になりますね。 データD,Eをばらばらで取得すると、それだけ排他制御される期間が増えるので、 できるだけ1か所で取得したほうがいいですね
drao0113

2018/07/26 14:15

回答2の回答の続きです。 メッセージバッファを使用すれば問題なさそうですね。 データEが変化したタイミングでタスクAからタスクBへメッセージ送信し、 タスクBで受けたメッセージを使用してデータD’を作ってやればいいですね。 タスクBを実行するまでに、データEが0->1->0と変化した場合には、 メッセージバッファでタスクBは1と0を受け取るので、これをもとに、 今周期はデータD'=1とし、次の周期でデータD'=0にすれば、 タスクBでデータDの変化を取り漏らすことはなさそうですね。 あとは、メッセージバッファがあふれることを考慮しないとダメですね。。 次の周期のタスクBが実行されるまでに、 データDがハンチングして0と1を行ったり来たりすると、メッセージバッファがふれるリスクが高まります。 タスクBが周期実行を前提としている場合、 メッセージバッファのサイズを決めるのが難しいように思うのですが、 ここらへんの設計指針はありますでしょうか?
nob.

2018/07/27 01:45

仕様をよく理解していませんが・・・ 10msごとのデータ×10回 分をタスクBで100msごとに処理しよう ということなのでしょうか? バッファのサイズは10回分、タスクの起動遅れが最大どの程度かによりますが、11回分あれば大丈夫なようなきがします。 というか、10回分のデータが必要なのですか? 100msごとのデータとその間にエラーが発生したかどうかが分かればいいのなら、セマフォで排他制御すればいいような気がしますが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問