- ベストアンサー
ある関数を通過すると、IOポートが勝手にLOWになってしまう
- H8S_2368マイコンを使用してテンキーパネルの値に基づいてDTMF信号を出力する関数を実行すると、常に特定のIOポートがLOWになる問題が発生します。
- 関数内でOSSemPend(KeyWait,100, &err)関数を実行すると、IOポートがLOWになる原因が不明です。
- 解決策や原因をご存知の方がいらっしゃれば、教えていただけないでしょうか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
場所が特定できたのなら、原因も追跡できるはずです。 err!=0がfalseになる条件、つまりerr==0となるのは何が起こったときでしょう? なお、ソース全体を見ないことにはなんとも言い難いですが、最初のコードのOSSemPend()は直接の原因ではなくて「たまたま時期が一致しているだけ」ではないかと。
その他の回答 (3)
- D-Matsu
- ベストアンサー率45% (1080/2394)
ああ違う。#1補足コードで取ろうとしてるのはセマフォじゃなくてキューですね。 おそらくキー入力がトリガになってキューに何かが入るんじゃないかと。
- D-Matsu
- ベストアンサー率45% (1080/2394)
んー、惜しい! たしかにKeyWaitに関してはそれで正しいですが、errを見ているセマフォはそっちではなく#1補足についてるAudioMsg、つまり > AudioMsg = OSQCreate((void **)&AudioMsgQ[0],3); で作られている方のセマフォです。 こっちを追いかければおそらくキー入力時に何があってこっちのセマフォが取れるようになるのか、というところまで追えるのではないかと。
お礼
回答頂きありがとうございます。本当に助かります。 ちょっと、この質問の趣旨と離れてきている内容になってきており恐縮です。私のRTOS(今回uCOS)に関しての知識不足で、セマフォとかの理解がほとんどない状態でして、質問している中で、なんとなくどのような動作をするものなのかというものがつかめてきてそのことの質問になりつつあるのをお許し下さい。 ただ、RTOSがどうして必要なのかということが”OSSemPend関数”とか”OSSemPost関数”の使い方でわかってきたような気がしております。この関数の機能を理解してくると他のプログラムもどのような意味なのかというのが少しずつわかってきたような気がしています。 ”IOポートが勝手にLOWになってしまう”この問題でわかったことがありまして、この”void pb_select_dial02_kj(void)”関数を呼び出す直前に、このオーディオの音声をDACで出力するためのプログラムを呼び出していて、それをコメントアウトしたところ、このLOWになる現象は無くなりました。”勝手に”というのは間違いでした。 ただ、そのオーディオの関数呼び出しの動作などでプログラムを追っていくとさらに疑問がたくさん出てきてしまいましたので、 特におっしゃられている AudioMsg = OSQCreate((void **)&AudioMsgQ[0],3); Audio = (SAUDIO_PLAY *)OSQPend(AudioExtMsg, 100, &err); これらの”OSQPend関数”と”OSSemPend関数”の使い方の違いなどです。 これらの問題は別の質問として投稿させていただきます。 一旦この質問を終了させていただきます。 本当にありがとうございます。
- D-Matsu
- ベストアンサー率45% (1080/2394)
> OSSemPend(KeyWait,100, &err); のところでポートが変化するのであれば、私ならOSSemPend()で発生しているであろうスリープを解除している場所(※)周辺のコードでポート操作していることを疑います。 ※たぶんOSSemPost()かな?
お礼
回答頂きありがとうございました。 この”#define INT_AMP_EN P2.DR.BIT.B1”のIOポートにかかわるテキストを全ソースから検索してみたところ、下記の関数内にあることがわかり、デバッガでブレークをかけてみたところ通過していることがわかりました。コレガ原因ということがわかりました。 いつもは、 if(err != 0) { //m_pFuncAudio(); continue; } この部分でcontinueに引っ掛かるようで、while(1)に戻り、下は実行されないようなのですが、あの関数を通過すると、このif文を通過してしまうようです。 DECLARE_TASK_FUNC(Audio) { u8 err; int i,j; SAUDIO_PLAY *Audio; parg = parg; LockAudioMsg = OSSemCreate(1); AudioEnd = OSSemCreate(0); AudioMsg = OSQCreate((void **)&AudioMsgQ[0],3); while(1){ Audio = (SAUDIO_PLAY *)OSQPend(AudioMsg, 100, &err); if(err != 0) { //m_pFuncAudio(); continue; } RunAudioTask = TRUE; bPlayAudio = TRUE; INT_AMP_EN = ON; if(Audio->Repeat > 0){ for(i=0 ; i < Audio->Repeat ; i++){ if(bPlayAudio == FALSE)break; for(j=0 ; j < MAX_AUDIO_FILE ; j++){ if(bPlayAudio == FALSE)break; if(Audio->Num[j] == 0) break; else audio_play(Audio->Num[j]-1,Audio->Num[j+1] == 0 ? 1 : 0); if(Audio->Num[j+1] == 0 ) break; } if(Audio->Repeat == 255) if(i > 253 ) i = 250; } } INT_AMP_EN = OFF; bPlayAudio = FALSE; RunAudioTask = FALSE; } }
お礼
回答頂きありがとうございました。 ”err!=0がfalseになる条件、つまりerr==0となるのは何が起こったときでしょう?” このことについて調べてみたところ、次のことがわかりました。 ・テンキーパネルを何も押さない状態の時には、pb_select_dial02_kj(void)関数のwhile(1)ルーチン中の”OSSemPend(KeyWait,100, &err);”は100の値のカウントでタイムアウトするときは、errに0x0Aという値を返していて、次のif文でcontinueに行きそれをずっとループしている。 ・テンキーパネルのどれかのボタンを押すと、”OSSemPend(KeyWait,100, &err);”は0x00という値をerrに入れて、switch(stKey.key)文でキーのコードのところで条件に合うところに行く。 ・OSSemPend(KeyWait,100, &err);関数をググってみたら、http://www.scribd.com/doc/7046520/Ucos-II-Refmanこのサイトにデータシートがあり、 errにはif the semaphore is availableこれなら、”OS_NO_ERR = 0x00”を返して、 タイムアウトしていたら、”OS_TIMEOUT = 0x0a”を返していることが書かれていました。 ・それで、”OS_NO_ERR = 0x00”を返す時というのは下記のテンキーのキースキャンプログラムで、ボタンを押して、離した際に”OSSemPost(KeyWait);”が実行されて、次の瞬間に”pb_select_dial02_kj(void)関数”のOSSemPend(KeyWait,100, &err)がerr=0x00を入れて、動作していることがわかりました。 DECLARE_TASK_FUNC(Key) { u16 cur,old; u8 status; KeyWait = OSSemCreate(0); parg = parg; cur = old = 0x00; stKey.key = 0; stKey.time = 0; status = KEY_ST_NONE; while(1) { cur = key_scan(); if(cur != old) { if(status == KEY_ST_NONE) { status = KEY_ST_PRESS; stKey.key = cur; stKey.time = 0; } else if(cur == KEY_NONE) { OSSemPost(KeyWait); status = KEY_ST_NONE; //debug("key %s\n\r",key_def[key_get_index(stKey.key)].name); } } else { if(status == KEY_ST_PRESS){ stKey.time++; } } old = cur; OSTimeDly(40); } }