Skip to content

Instantly share code, notes, and snippets.

@ossicode
Created January 17, 2013 12:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ossicode/4555484 to your computer and use it in GitHub Desktop.
Save ossicode/4555484 to your computer and use it in GitHub Desktop.
MSP430F1611 Watchdog timer testcode
/*
* clock.c
*
* Created on: 2013. 1. 14.
* Author: OSSI
*/
#include"clock.h"
// main clock will be shared via system
static volatile uint8_t clockMode;
uint8_t clock_getMode(void)
{
return clockMode;
}
uint8_t clock_setDefaultDCO(void)
{
// Chage DCO_DELTA to change default DCO frequency
// default DCO_DELTA = 255 and fDCO ~ 1MHz
uint16_t Compare, Oldcapture = 0;
_DINT();
BCSCTL1 |= DIVA_3; // ACLK= LFXT1CLK/8
CCTL2 = CM_1 + CCIS_1 + CAP; // CAP, ACLK
TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, cont-mode, clear
while (1)
{
while (!(CCIFG & CCTL2)); // Wait until capture occured
CCTL2 &= ~CCIFG; // Capture occured, clear flag
Compare = CCR2; // Get current captured SMCLK
Compare = Compare - Oldcapture; // SMCLK difference
Oldcapture = CCR2; // Save current captured SMCLK
if (DCO_DELTA == Compare) break; // If equal, leave "while(1)"
else if (DCO_DELTA < Compare) // DCO is too fast, slow it down
{
DCOCTL--;
if (DCOCTL == 0xFF)
{
if (!(BCSCTL1 == (XT2OFF + DIVA_3)))
BCSCTL1--; // Did DCO roll under?, Sel lower RSEL
}
}
else
{
DCOCTL++;
if (DCOCTL == 0x00)
{
if (!(BCSCTL1 == (XT2OFF + DIVA_3 + 0x07)))
BCSCTL1++; // Did DCO roll over? Sel higher RSEL
}
}
}
CCTL2 = 0; // Stop CCR2
TACTL = 0;
BCSCTL1 &= ~DIVA_3; // Back to ACLK= LFXT1CLK
_EINT();
return 1;
}
uint8_t clock_setup(void)
{
// We want to use LFXT1CLK for 32.768kHz / XT2CLK for 8MHz or 7.3728MHz
// after POR, default DCO frequency is 800kHz
// default mode
// CLOCK_XT2_LFXT1 mode
// LFXT1CLK source select first and 32.768kHz crystal needs long startup time
BCSCTL1 &= ~XTS; // default value is 0 but to make sure
// To change MCLK source from DCO to XT2CLK, we need to do following procedure
// Switch on the XT2
BCSCTL1 &= ~XT2OFF;
// when do while is executed, MCLK = default DCO = 800kHz
// timeout *250 delay cycles / 800kHz + other instruction cycles /800kHz = timeout time
// timeout = 1450 -> timeout time ~500 ms
volatile uint16_t timeout = 1450;
// Check oscillator fault with timeout
do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
// need to have some delay in between checks
__delay_cycles(250);
}
while ((IFG1 & OFIFG)&& --timeout); // OSCFault flag still set?
// Add timeout to prevent hang in case osc fails.
// Switch to DCO when XT2 failed
// if failed change to CLOCK_DCO_LFXT1
// Let system know that clock is switched
// check temperature effect on clocks if possible
if(timeout)
{
// when there's no fault, proceed to select source
// MCLK = SMCLK = XT2 (safe)
BCSCTL2 |= SELM_2 + SELS;
clockMode = CLOCK_XT2_LFXT1;
return CLOCK_XT2_LFXT1;
}
else
{
// CLOCK_DCO_LFXT1 mode DCOCLK = ~1MHz ACLK = 32.768kHz
// Set DCO frequency in case XT2 fails
BCSCTL1 &= ~XTS; // default value is 0 but to make sure
BCSCTL1 |= XT2OFF; // XT2 OFF
BCSCTL2 = 0x00; // reset BCSCTL2
clock_setDefaultDCO();
clockMode = CLOCK_DCO_LFXT1;
return CLOCK_DCO_LFXT1;
}
}
void clock_dividerSetup(uint8_t MCLKDividerSelect, uint8_t SMCLKDividerSelect, uint8_t ACLKDividerSelect)
{
// reset divider first
// reset ACLK divider
BCSCTL1 &= 0xCF; // Clear BIT5 and BIT4
// select ACLK Divider
BCSCTL1 |= ACLKDividerSelect;
// reset MCLK, SMCLK divider
BCSCTL2 &= 0xC9; // Clear BIT5,BIT4, BIT2, BIT1
// select MCLK Divider
BCSCTL2 |= MCLKDividerSelect;
// select SMCLK Divider
BCSCTL2 |= SMCLKDividerSelect;
}
/*
* clock.h
*
* Created on: 2013. 1. 14.
* Author: OSSI
*/
/* Clock setting for OSSI MSP430F1611
*
* default: CLOCK_XT2_LFXT1
* XT2 ON: 7.3728 MHz or 8 MHz
* LFXT1 Low Power Mode: 32.768 kHz
* MCLK = XT2CLK / SMCLK = XT2CLK / ACLK = LFXT1
*
* alternative 1: CLOCK_DCO_LFXT1
* XT2 OFF: DCO set to ~ 1MHz
* LFXT1 Low Power Mode: 32.768 kHz
* MCLK = DCOCLK / SMCLK = DCOCLK / ACLK = LFXT1
*
*
* alternative 2: CLOCK_DCO_DCO
* DCO set to ~ 1MHz
* MCLK = DCOCLK / SMCLK = DCOCLK / ACLK = DCOCLK / 30
*
*/
#ifndef CLOCK_H_
#define CLOCK_H_
#include "msp430f1611.h"
#include "ossitypes.h"
#include "debug.h"
#define CLOCK_XT2_LFXT1 (0)
#define CLOCK_DCO_LFXT1 (1)
#define CLOCK_DCO_DCO (2)
#define CLOCK_XT2_FREQ_8MHz (0)
#define CLOCK_XT2_FREQ_7_3728MHz (1)
#define CLOCK_DCO_FREQ_1MHz (2)
//#define DELTA 900 // target DCO = DELTA*(4096) = 3686400
//#define DELTA 70 // target DCO = DELTA*(4096) = 286720
#define DCO_DELTA (245) // target DCO = DELTA*(4096) = 1003275
#define MCLK_DIVIDED_BY_1 DIVM_0 /* MCLK Divider 0: /1 */
#define MCLK_DIVIDED_BY_2 DIVM_1 /* MCLK Divider 1: /2 */
#define MCLK_DIVIDED_BY_4 DIVM_2 /* MCLK Divider 2: /4 */
#define MCLK_DIVIDED_BY_8 DIVM_3 /* MCLK Divider 3: /8 */
#define SMCLK_DIVIDED_BY_1 DIVS_0 /* SMCLK Divider 0: /1 */
#define SMCLK_DIVIDED_BY_2 DIVS_1 /* SMCLK Divider 1: /2 */
#define SMCLK_DIVIDED_BY_4 DIVS_2 /* SMCLK Divider 2: /4 */
#define SMCLK_DIVIDED_BY_8 DIVS_3 /* SMCLK Divider 3: /8 */
#define ACLK_DIVIDED_BY_1 DIVA_0 /* ACLK Divider 0: /1 */
#define ACLK_DIVIDED_BY_2 DIVA_1 /* ACLK Divider 1: /2 */
#define ACLK_DIVIDED_BY_4 DIVA_2 /* ACLK Divider 2: /4 */
#define ACLK_DIVIDED_BY_8 DIVA_3 /* ACLK Divider 3: /8 */
uint8_t clock_getMode(void);
uint8_t clock_setup(void);
void clock_dividerSetup(uint8_t MCLKDividerSelect, uint8_t SMCLKDividerSelect, uint8_t ACLKDividerSelect);
#endif /* CLOCK_H_ */
/* --COPYRIGHT--,BSD
* Copyright (c) 2012, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
//*****************************************************************************
//
//debug.h - Macros for assisting debug of the driver library.
//
//
//This is part of revision 0001 of the MSP430 Peripheral Driver Library.
//
//*****************************************************************************
#ifndef __DEBUG_H__
#define __DEBUG_H__
//*****************************************************************************
//
//Prototype for the function that is called when an invalid argument is passed
//to an API. This is only used when doing a DEBUG build.
//
//*****************************************************************************
extern void __error__ (char *pcFilename, unsigned long ulLine);
//*****************************************************************************
//
//The ASSERT macro, which does the actual assertion checking. Typically, this
//will be for procedure arguments.
//
//*****************************************************************************
#ifdef DEBUG
#define ASSERT(expr) { \
if (!(expr)) \
{ \
__error__(__FILE__, __LINE__); \
} \
}
#else
#define ASSERT(expr)
#endif
#endif //__DEBUG_H__
#include "ossiobc.h"
#include "wdt.h"
/*
* main.c
*/
int main(void)
{
// stop wdt in the beginning
wdt_hold();
// ACLK = 32.768kHz / 8 = 4096Hz
clock_setup();
clock_dividerSetup(MCLK_DIVIDED_BY_1, SMCLK_DIVIDED_BY_1, ACLK_DIVIDED_BY_8);
// after system clock set, do wdt clock setup
// wdt clock = ACLK = 4096Hz, wdt clock divider = 8192
// PUC happens after wdt start 8192 / 4096 = 2 sec
wdt_init(WDT_CLOCKSOURCE_ACLK, WDT_CLOCKDIVIDER_8192);
wdt_start();
volatile uint16_t i;
P2DIR |= BIT1;
P2OUT &= ~BIT1;
// 1sec delay
for (i = 0; i < 1000 ; i++)
{
__delay_cycles(7372);
}
P2DIR |= BIT1;
P2OUT |= BIT1;
while(1)
{
// keep resetting the wdt in the code
// to prevent the system from PUC reset
wdt_reset();
// 1sec delay
for (i = 0; i < 1000 ; i++)
{
__delay_cycles(7372);
}
}
}
/*
* ossiobc.h
*
* Created on: 2013. 1. 6.
* Author: OSSI
*/
#ifndef OSSIOBC_H_
#define OSSIOBC_H_
#include "msp430f1611.h"
#include "ossitypes.h"
#include "clock.h"
#include "debug.h"
#endif /* OSSIOBC_H_ */
/*
* ossitypes.h
*
* Created on: 2012. 12. 22.
* Author: OSSI
*/
#ifndef OSSITYPES_H_
#define OSSITYPES_H_
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short int uint16_t;
typedef signed short int int16_t;
typedef unsigned long int uint32_t;
typedef signed long int int32_t;
#endif /* OSSITYPES_H_ */
/*
* wdt.c
*
* Created on: 2013. 1. 17.
* Author: OSSI
*/
#include "wdt.h"
void wdt_hold(void)
{
volatile uint8_t wdtStatus = (WDTCTL & 0x0F) | WDTHOLD;
// Stop watchdog timer
WDTCTL = WDTPW + wdtStatus ;
}
void wdt_init(uint8_t clockSelect, uint8_t clockDividerSelect)
{
// reset wdt counter, wdt stop
// reset wdt clock, wdt clock dividier
WDTCTL = WDTPW + WDTCNTCL + WDTHOLD+ clockSelect + clockDividerSelect;
}
void wdt_start(void)
{
volatile uint8_t wdtStatus = (WDTCTL & 0x0F) & ~(WDTHOLD);
// Start watchdog timer
WDTCTL = WDTPW + wdtStatus ;
}
void wdt_reset(void)
{
// reset wdt counter
volatile uint8_t wdtStatus = (WDTCTL & 0x0F) | WDTCNTCL;
WDTCTL = WDTPW + wdtStatus ;
}
/*
* wdt.h
*
* Created on: 2013. 1. 17.
* Author: OSSI
*/
#ifndef WDT_H_
#define WDT_H_
#include "msp430f1611.h"
#include "ossitypes.h"
#include "debug.h"
#define WDT_CLOCKSOURCE_SMCLK (0)
#define WDT_CLOCKSOURCE_ACLK (WDTSSEL)
#define WDT_CLOCKDIVIDER_32768 (0)
#define WDT_CLOCKDIVIDER_8192 (WDTIS0)
#define WDT_CLOCKDIVIDER_512 (WDTIS1)
#define WDT_CLOCKDIVIDER_64 (WDTIS0 + WDTIS1)
void wdt_hold(void);
void wdt_init(uint8_t clockSelect, uint8_t clockDividerSelect);
void wdt_start(void);
void wdt_reset(void);
#endif /* WDT_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment