wiki:Watch_dog_for_RPi_ATTiny

Version 3 (modified by aoki, 4 years ago) (diff)

--

ウォッチドック基板のファームウェア

ウォッチドッグ基板上のATTiny85のソースファイルです。

プログラムの大まかな仕様は、

  • プログラムは10mSごとに動作する連続サイクル動作
  • ポート(GPIO)の監視は10mSに1回
  • ポート信号のエッジ検出は、Highの後、連続してLowを9回検出した場合に有効
  • マイコン内が異常ステータスになった場合には、WD_ReBootステータスに移行

となっています。

  • WDtimer.c
    /*************************************
    **  main.c                          **
    **                                  **
    **  Created : 2014/12/18 14:43:39   **
    **  Author  : O.aoki                **
    *************************************/
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdlib.h>
    
    #include "WDtimer.h"
    
    //#define	F_CPU	8000000UL							// 8 MHz
    //#include <util/delay.h>
    
    /*---------------------------------------------------
    	Global variable 
    */
    	volatile unsigned char	IntFlag;
    	volatile unsigned char	LowCounter;
    	volatile unsigned char	HighCounter;
    	volatile unsigned long	GlobalCounter;
    	volatile unsigned long	WDCounter;
    
    /*---------------------------------------------------
    	Timer 
    */
    void Timer_Init() {			// base CK = 8MHz
    	OCR1C = 10;				// 0.0102 sec
    	BitSet(TIFR, TOV1);		// clear overflow flag
    	BitSet(TIMSK, TOIE1);	// Parmit overflow interrupt
    	TCCR1 = 0b11001110;		// Clear timer, PWM Mode, No Output, timer-prescaler 1/8192
    }
    
    /*---------------------------------------------------
    	In-port driver
    */
    /* ---- Watch dog pulse ---- */
    void WD_Port_Read() {
    	if ((~PINB) & (1<<WDpulse)) {
    		HighCounter = 0;
    		if (LowCounter < 250) LowCounter++;
    	} else {
    		if (HighCounter < 250) HighCounter++;
    		LowCounter = 0;
    	}
    }
    
    unsigned char WD_Port_Rise_Edge() {
    	if (HighCounter == 9) return (0xFF);
    	return (0);
    }
    
    unsigned char WD_Port_Fall_Edge() {
    	if (LowCounter == 9) return (0xFF);
    	return (0);
    }
    
    unsigned char WD_Port_Double_Edge() {
    	if (HighCounter == 9) return (0xFF);
    	if (LowCounter  == 9) return (0xFF);
    	return (0);
    }
    
    /* ---- Jumper switch port for LED ---- */
    unsigned char JSW_Port() {
    	if ((~PINB) & (1<<LEDsw)) return (0xFF);
    	return (0);
    }
    
    /*---------------------------------------------------
    	Main Routine
    */
    int	main( void ) {
    	unsigned char	WDstat;
    	unsigned char	preCounter;
    	unsigned char	LEDflag;
    
    	/* ******* 初期化開始 ******* */
    	cli();						// 初期処理中は割り込み禁止
    
    	// ---- 変数初期化
    	GlobalCounter = 0;
    	WDstat = WD_default;
    	WDCounter = 0;
    	preCounter = 0;
    	// ---- ポートB初期化
    	BitSet(MCUCR, PUD);
    	DDRB  = OutPortMask;		// Set to `PB4` `PB1` ouput
    	PORTB = OutPortMask;		// Output default pattern
    	RstLED;
    	// ---- タイマー初期設定
    	Timer_Init();
    
    	sei();						// 割込み許可
    
    	/* ******* 初期化終了 ******* */
    
    	while (1) {	// main loop
    		LEDflag = 0;
    		switch (WDstat) {
    			case WD_ReBoot :
    					if ((GlobalCounter & 0x00000003) == 0) LEDflag = 0xFF;
    					OffFET;
    					if (WDCounter >= WD_RecoveryTime) {
    						WDstat = WD_default;
    						WDCounter = 0;
    					}
    					preCounter = 0;
    					break;
    			case WD_default :
    					if ((GlobalCounter & 0x0000007F) == 0) LEDflag = 0xFF;
    					OnFET;
    					WDCounter = 0;
    					if (WD_Port_Fall_Edge()) {
    						preCounter++;
    						if (preCounter > WD_StartPulseNumber) WDstat = WD_active;
    					}
    					break;
    			case WD_active :
    					if ((GlobalCounter & 0x0000000F) == 0) LEDflag = 0xFF;
    					OnFET;
    					if (WD_Port_Fall_Edge()) WDCounter = 0;
    					if (WDCounter >= WD_TimeOut) {
    						WDstat = WD_ReBoot;
    						WDCounter = 0;
    					}
    					break;
    			default:
    					WDstat = WD_ReBoot;
    					WDCounter = 0;
    					break;
    		}
    		if (!JSW_Port())
    			RstLED;
    		else
    			if (LEDflag) TglLED;
    		IntFlag = 1;
    		while (IntFlag == 1);
    	}
    }
    
    /*------------------------------------------------------
    	Timer Interrupt Sub Routines
     */
    /* -=-=-=-= Timer Overflow ISR =-=-=-=- */
    ISR(SIG_OVERFLOW1) {
    	WD_Port_Read();
    	GlobalCounter++;
    	WDCounter++;
    	IntFlag = 0;
    }
    
  • WDtimer.h
    /*************************************
    **  main.c                          **
    **                                  **
    **  Created  : 2014/12/18 14:43:39  **
    **  Author   : O.aoki               **
    **************************************/
    
    #define __ATtiny85__		1				// チップ環境を"ATtiny85"としてコンパイルする
    
    /* ---- 定数 ---- */
    #define	OutPortMask		(1 << FET) + (1 << LED)		// ポート出力レジスタのマスクパターン
    #define WD_TimeOut		5*100				// ウォッチドッグのタイムアウト[*10mS]
    #define WD_RecoveryTime		10*100				// Raspberry Piのリブート(電源off)時間[*10mS]
    #define WD_StartPulseNumber	5				// ウォッチドッグ開始シグナルのエッジ検出数
    
    /* ---- ウォッチドッグステータス ---- */
    #define	WD_ReBoot		0
    #define	WD_default		1
    #define	WD_active		2
    
    /* -=-=-= Inport =-=-=- */
    /* ---- Watch dog pulse ---- */
    #define	WDpulse			PINB0				// Global : Watch dog pulse port
    /* ---- Jumper switch port for LED ---- */
    #define	LEDsw			PINB3				// Global : jumper sw port
    
    /* -=-=-= Outport =-=-=- */
    /* ---- ビット操作 ---- */
    #define BitRst(addr, bit)	addr &= ~(1<<bit)		// Global : addrのbit番目をLowに
    #define BitSet(addr, bit)	addr |=  (1<<bit)		// Global : addrのbit番目をHighに
    #define BitTgl(addr, bit)	addr ^=  (1<<bit)		// Global : addrのbit番目を反転
    
    /* ---- FET操作 ---- */
    #define	FET			PB4
    #define	OnFET			BitRst(PORTB, FET)		// Global : FETを繋げる
    #define	OffFET			BitSet(PORTB, FET)		// Global : FETを切る
    
    /* ---- LED操作 ---- */
    #define	LED			PB1
    #define	SetLED			BitRst(PORTB, LED)		// Global : LEDを点ける
    #define	RstLED			BitSet(PORTB, LED)		// Global : LEDを消す
    #define	TglLED			BitTgl(PORTB, LED)		// Global : LEDを反転
    
    /* -=-=-= Debug用 =-=-=- */
    /* ---- Debug用LED ---- */
    #define	LED1			1
    #define	SetLED1			BitRst(PORTB, LED1)		// Global : LED1を点ける
    #define	RstLED1			BitSet(PORTB, LED1)		// Global : LED1を消す
    #define	TglLED1			BitTgl(PORTB, LED1)		// Global : LED1を反転