Вариант 1

Запускаем внешний кварц, выдерживаем паузу на устаканивание и проверяем флаг. Если флаг сброшен, то все нормально - MCLK и SMCLK тактируются от кварца. В противном случае, делаем еще несколько попыток и переключаемся на тактирование от внутреннего DCO.

Частота сохраняется в глобальной переменной unsigned long xtal_freq; (модификация только в этом модуле)

Состояние в глобальном флаге g.bOscFault;

Полезно в главном цикле программы периодически проверять этот флаг и в случае возникновения сбоя обрабатывать (переинициализация периферии/сигнализация/журналирование)

/**
* @file	xtal.c
* @brief XTAL Module
*
* @author      Rustem Kalimullin
* @par E-mail:
*              hellos@mail.ru
* @par Copyright:
*              (c) Kurt, 2006
*/
 
#include "common.h"
 
#ifndef KR_EXT_XTAL_FREQ
#define KR_EXT_XTAL_FREQ 4608000L
#endif
#ifndef KR_DCO_XTAL_FREQ
#define KR_DCO_XTAL_FREQ 713200L
#endif
 
 
//---------------------------------------------------------
// Initialize HI-Speed XTAL
int setup_XTAL2( void )
{
	IE1 &= ~OFIE;                     // disable OSC_Fault interrupt
	BCSCTL1 &= ~XT2OFF;               // start XT2CLK
	unsigned int k = 0x10;            // # try
	do {
		IFG1 &= ~OFIFG;           // Clear OSCFault flag
		for(unsigned int i = 0xFFF; i; --i) __no_operation();  // Time for flag to set
		if( !(IFG1 & OFIFG) ) break; // OSCFault is clear?
	} while( --k );
 
	if( k == 0 ) {
		g.bOscFault = 1;
		BCSCTL1 |= XT2OFF;        // stop XT2CLK
		BCSCTL2 = SELM_0;         // MCLK = SMCLK = DCOCLK
		xtal_freq = KR_DCO_XTAL_FREQ;
		return 0;
	}
 
	g.bOscFault = 0;
	BCSCTL2 = SELM_2+SELS;            // MCLK Source Select 2: XT2CLK/LFXTCLK, SMCLK = XT2CLR
	xtal_freq = KR_EXT_XTAL_FREQ;
	IE1 |= OFIE;                      // enable OSC_Fault interrupt
	return 1;
}
 
//---------------------------------------------------------
// Oscill fault interrupt handler. Try to restore synchronization
#pragma vector=NMI_VECTOR
__interrupt void NMI_handler(void)
{
	if ( IFG1 & OFIFG ) {
		IE1 &= ~OFIE;                      // disable OSC_Fault interrupt
		IFG1 &= ~OFIFG;                    // Clear OSCFault flag
		for(unsigned int i = 0xFF; i; --i) __no_operation(); 
 
		if( (IFG1 & OFIFG) ) {
			BCSCTL1 |= XT2OFF;           // stop XT2CLK
			BCSCTL2 = SELM_0;            // MCLK = SMCLK = DCOCLK
			g.bOscFault = 1;
		}
		IFG1 &= ~OFIFG;
		IE1 |= OFIE;                       // enable OSC_Fault interrupt	
	} else if( IFG1 & NMIIFG ) {
		IFG1 &= ~NMIIFG;                   // Reclear NMI flag in case bounce
	} else if( IFG1 & WDTIFG ) {
		IFG1 &= ~WDTIFG;
	}
}

forum

 
sources/xtal.txt · Последние изменения: 2021/10/09 14:22 kurt