Previous: 11.2. 無限ループの例(変数型の設定ミス) |
Up: 11. 独立型ウォッチドッグタイマ |
Next: 12. DAC |
サンプルプログラム |
iwdg_interrupt_timeover |
0.5秒毎に画面に複数個のフェイスマークを表示させるプログラムです。マイコンボードへの回路の接続は不要です。
最初に表示されるのは3個ですが、i又はdをタイプすると、個数を増減させることができます。
このサンプルプログラムでは、タイマ割込み(TIM3)を利用してウォッチドッグカウンタのリセットを行っています。フェイスマークの表示処理もタイマ割込(TIM1)です。TIM1の割り込み優先度をTIM3よりも高くしていますので、もしTIM1の割込みハンドラが無限ループに陥って、割り込み優先度が低いTIM3が実行されなくなると、ウォッチドッグカウンタがアンダーフローしてリセットされます。
void TIM3_IRQHandler(void) { ? if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) ? { ??? /* Clear TIM3 update interrupt pending bit*/ ??? TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
??? /* Reload IWDG counter */ ??? IWDG_ReloadCounter();
? } } |
タイマ割込を使用してウォッチドッグカウンタのリセットを行うようにすると、定期的にカウンタがリセットされることが確保できますから、タイミングの制御が行いやすくなります。カウンタリセットのための割込みの優先度を最低にしておけば、他の割込みルーチンで無限ループ等が発生した時には、カウンタリセットが行われず、ウォッチドッグリセットが発生します。ただし割込みですのでメインルーチンよりは優先しますから、メインルーチンで発生した不具合には対応できないということになります。
さてこのサンプルプログラムでは個数を増やす分にはよいのですが、個数を減らしていき、表示される個数が0になった後、もう一度dを押すと、画面に無数のフェイスマークが表示され、リセットされます。プログラムをトレースして原因を突き止めてみてください。
プログラムの欠陥としては2つ有り、まずはフェイスマークの表示個数のカウント用変数のnumberがunsigned型になっているという点です。
uint16_t number = 3; |
unsigned型は負数を表現できず、0を割り込む減算を行うと、ビット幅の最大値+1から減算を行ったのと同じになります。uint16_t型であれば0から1を引くと、演算結果は65535です。フェイスマークを65535回も表示させている間、ウォッチドッグカウンタのリセットを行うことができないため、ウォッチドッグカウンタがアンダーフローし、システムがリセットされます。
もう一つの欠陥は、変数numberを増減させるときに、その時点での値をチェックしていないという点です。0の時は減算しないというルーチンが追加されていれば先述のような事態は防ぐことができます。
RxData = (int8_t)RECEIVE_DATA; switch(RxData) { ? case ‘i’: ??? number++; ??? break; ? case ‘d’: ??? number--; ??? break; } |
Previous: 11.2. 無限ループの例(変数型の設定ミス) |
Up: 11. 独立型ウォッチドッグタイマ |
Next: 12. DAC |