From 58298f59dbd8bed06ca1b384153f49fe5bd19b73 Mon Sep 17 00:00:00 2001 From: David Kopf Date: Tue, 10 Jan 2012 12:42:27 -0500 Subject: [PATCH] Add F_CPU=0x800000 option with phase lock to external 32768 Hz crystal Add MCU_CONF_LOW_WEAR option to avoid eeprom writes during development. --- cpu/avr/dev/clock.c | 45 +++++++++++++++++++++++++ cpu/avr/dev/rs232_atmega1284.h | 18 ++++++++-- cpu/avr/radio/rf230bb/hal.h | 4 +++ cpu/avr/rtimer-arch.h | 8 ++++- platform/avr-raven/contiki-conf.h | 6 ++++ platform/avr-raven/contiki-raven-main.c | 9 ++++- platform/avr-raven/params.h | 10 +++++- 7 files changed, 95 insertions(+), 5 deletions(-) diff --git a/cpu/avr/dev/clock.c b/cpu/avr/dev/clock.c index 1c5db991a..42a2c00a8 100644 --- a/cpu/avr/dev/clock.c +++ b/cpu/avr/dev/clock.c @@ -93,6 +93,50 @@ ISR(AVR_OUTPUT_COMPARE_INT) scount = 0; seconds++; } + +#if F_CPU == 0x800000 && USE_32K_CRYSTAL +/* Special routine to phase lock CPU to 32768 watch crystal. + We are interrupting 128 times per second. + If RTIMER_ARCH_SECOND is a multiple of 128 we can use the residual modulo + 128 to determine whether the clock is too fast or too slow. + E.g. for 8192 the phase should be constant modulo 0x40 + OSCCAL is started in the lower range at 90, allowed to stabilize, then + rapidly raised or lowered based on the phase comparison. + It gives less phase noise to do this every tick and doesn't seem to hurt anything. +*/ +#include "rtimer-arch.h" +{ +volatile static uint8_t lockcount; +volatile static int16_t last_phase; +volatile static uint8_t osccalhigh,osccallow; + if (seconds < 60) { //give a minute to stabilize + if(++lockcount >= 8192UL*128/RTIMER_ARCH_SECOND) { + lockcount=0; + rtimer_phase = TCNT3 & 0x0fff; + if (seconds < 2) OSCCAL=100; + if (last_phase > rtimer_phase) osccalhigh=++OSCCAL; else osccallow=--OSCCAL; + last_phase = rtimer_phase; + } + } else { +#if TICK_MODULO + static uint8_t lock_clock; + if (++lock_clock>=TICK_MODULO) { + lock_clock=0; +#endif + uint8_t error = (TCNT3 - last_phase) & 0x3f; + if (error == 0) { + } else if (error<32) { + OSCCAL=osccallow-1; + } else { + OSCCAL=osccalhigh+1; + } +#if TICK_MODULO + } +#endif + } +} +#endif + #if RADIO_CONF_CALIBRATE_INTERVAL if (++calibrate_interval==0) { rf230_calibrate=1; @@ -198,6 +242,7 @@ clock_seconds(void) } #ifdef HANDLE_UNSUPPORTED_INTERRUPTS /* Ignore unsupported interrupts, optionally hang for debugging */ +/* BADISR is a gcc weak symbol that matches any undefined interrupt */ ISR(BADISR_vect) { //static volatile uint8_t x;while (1) x++; } diff --git a/cpu/avr/dev/rs232_atmega1284.h b/cpu/avr/dev/rs232_atmega1284.h index 262d974ca..07e81d2bc 100644 --- a/cpu/avr/dev/rs232_atmega1284.h +++ b/cpu/avr/dev/rs232_atmega1284.h @@ -86,9 +86,23 @@ #define USART_BAUD_230400 1 #define USART_BAUD_250000 1 #define USART_BAUD_500000 0 +#elif F_CPU == 0x800000UL +/* 8192 KHz with external 32768 crystal */ +#define USART_BAUD_38400 12 +#define USART_BAUD_57600 8 +#define USART_BAUD_115200 4 #else -#error "Please define the baud rates for your CPU clock: ATmega128 handbook p. \ -195-198 or set the rate in contiki-conf.h" +/* UBRR = F_CPU/(16*BAUD) - 1 */ +#warning "Unusual CPU Clock Rate!!!!" +#warning "You may have to tune the UBRR regisgers for the correct baud rates" +#warning "See ATmega128 handbook p. 195-198 or set the rate in contiki-conf.h" +#ifndef USART_BAUD_38400 +#define USART_BAUD_38400 F_CPU/(16*38400) - 1 +#endif +#ifndef USART_BAUD_57600 +#define USART_BAUD_57600 F_CPU/(16*57600) - 1 +#endif + #endif diff --git a/cpu/avr/radio/rf230bb/hal.h b/cpu/avr/radio/rf230bb/hal.h index 03a715434..c50b9a513 100644 --- a/cpu/avr/radio/rf230bb/hal.h +++ b/cpu/avr/radio/rf230bb/hal.h @@ -402,6 +402,10 @@ #define HAL_TCCR1B_CONFIG ( ( 1 << ICES1 ) | ( 1 << CS12 ) ) #define HAL_US_PER_SYMBOL ( 1 ) #define HAL_SYMBOL_MASK ( 0xFFFFffff ) +#elif ( F_CPU == 0x800000UL ) + #define HAL_TCCR1B_CONFIG ( ( 1 << ICES1 ) | ( 1 << CS11 ) | ( 1 << CS10 ) ) + #define HAL_US_PER_SYMBOL ( 2 ) + #define HAL_SYMBOL_MASK ( 0x7FFFffff ) #elif ( F_CPU == 8000000UL ) #define HAL_TCCR1B_CONFIG ( ( 1 << ICES1 ) | ( 1 << CS11 ) | ( 1 << CS10 ) ) #define HAL_US_PER_SYMBOL ( 2 ) diff --git a/cpu/avr/rtimer-arch.h b/cpu/avr/rtimer-arch.h index b53387c4d..cf726b383 100644 --- a/cpu/avr/rtimer-arch.h +++ b/cpu/avr/rtimer-arch.h @@ -28,7 +28,6 @@ * * This file is part of the Contiki operating system. * - * $Id: rtimer-arch.h,v 1.5 2010/02/18 17:21:44 dak664 Exp $ */ #ifndef __RTIMER_ARCH_H__ @@ -42,6 +41,13 @@ * Setting RTIMER_ARCH_PRESCALER to 0 will leave Timers alone. * rtimer_arch_now() will then return 0, likely hanging the cpu if used. * Timer1 is used if Timer3 is not available. + * + * Note the rtimer tick to clock tick conversion will be nominally correct only + * when the same oscillator is used for both clocks. + * When an external 32768 watch crystal is used for clock ticks my raven CPU + * oscillator is 1% slow, 32768 counts on crystal = ~7738 rtimer ticks. + * For more accuracy define F_CPU to 0x800000 and optionally phase lock CPU + * clock to 32768 crystal. This gives RTIMER_ARCH_SECOND = 8192. */ #ifndef RTIMER_ARCH_PRESCALER #define RTIMER_ARCH_PRESCALER 1024UL diff --git a/platform/avr-raven/contiki-conf.h b/platform/avr-raven/contiki-conf.h index 0bf0329e5..4ddcbfe91 100644 --- a/platform/avr-raven/contiki-conf.h +++ b/platform/avr-raven/contiki-conf.h @@ -49,6 +49,11 @@ #ifndef F_CPU #define F_CPU 8000000UL #endif + +/* MCU_CONF_LOW_WEAR will remove the signature and eeprom from the .elf file */ +/* This reduces reprogramming wear during development */ +#define MCU_CONF_LOW_WEAR 0 + #include typedef int32_t s32_t; @@ -76,6 +81,7 @@ unsigned long clock_seconds(void); /* The 1284p can use TIMER2 with the external 32768Hz crystal to keep time. Else TIMER0 is used. */ /* The sleep timer in raven-lcd.c also uses the crystal and adds a TIMER2 interrupt routine if not already define by clock.c */ +/* If F_CPU is 0x800000 the clock tick interrupt routine will (attempt to) keep the cpu clock phase locked to the crystal. */ #define AVR_CONF_USE32KCRYSTAL 1 /* Rtimer is implemented through the 16 bit Timer1, clocked at F_CPU through a 1024 prescaler. */ diff --git a/platform/avr-raven/contiki-raven-main.c b/platform/avr-raven/contiki-raven-main.c index 915623716..1d939ebc9 100644 --- a/platform/avr-raven/contiki-raven-main.c +++ b/platform/avr-raven/contiki-raven-main.c @@ -65,7 +65,6 @@ unsigned char debugflowsize,debugflow[DEBUGFLOWSIZE]; #include "loader/symbols-def.h" #include "loader/symtab.h" -#include "params.h" #if RF230BB //radio driver using contiki core mac #include "radio/rf230bb/rf230bb.h" #include "net/mac/frame802154.h" @@ -109,6 +108,8 @@ unsigned char debugflowsize,debugflow[DEBUGFLOWSIZE]; #include "net/rime.h" +#include "params.h" + /* Get periodic prints from idle loop, from clock seconds or rtimer interrupts */ /* Use of rtimer will conflict with other rtimer interrupts such as contikimac radio cycling */ /* STAMPS will print ENERGEST outputs if that is enabled. */ @@ -143,8 +144,10 @@ SIGNATURE = { }; #endif +#if !MCU_CONF_LOW_WEAR /* JTAG, SPI enabled, Internal RC osc, Boot flash size 4K, 6CK+65msec delay, brownout disabled */ FUSES ={.low = 0xe2, .high = 0x99, .extended = 0xff,}; +#endif /* Get a pseudo random number using the ADC */ uint8_t @@ -193,6 +196,10 @@ void initialize(void) if(MCUSR & (1<