diff --git a/cpu/mc1322x/Makefile.mc1322x b/cpu/mc1322x/Makefile.mc1322x index 185077562..05f936439 100644 --- a/cpu/mc1322x/Makefile.mc1322x +++ b/cpu/mc1322x/Makefile.mc1322x @@ -10,7 +10,7 @@ CONTIKI_CPU=$(CONTIKI)/cpu/mc1322x CONTIKI_CPU_DIRS = . lib src board dev ../arm/common/dbg-io -MC1322X = debug-uart.c rtimer-arch.c watchdog.c contiki-crm.c contiki-maca.c contiki-misc.c leds-arch.c leds.c contiki-uart.c slip-uart1.c init.c config.c +MC1322X = debug-uart.c rtimer-arch.c watchdog.c contiki-maca.c contiki-misc.c leds-arch.c leds.c contiki-uart.c slip-uart1.c init.c config.c DBG_IO = dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c diff --git a/cpu/mc1322x/clock.c b/cpu/mc1322x/clock.c index e6990e731..611a90251 100644 --- a/cpu/mc1322x/clock.c +++ b/cpu/mc1322x/clock.c @@ -36,93 +36,52 @@ #include #include #include -#include "dev/leds.h" +#include #include "contiki-conf.h" #include "mc1322x.h" -#include "contiki-conf.h" - #define MAX_TICKS (~((clock_time_t)0) / 2) static volatile clock_time_t current_clock = 0; volatile unsigned long seconds = 0; -#define TCF 15 -#define TCF1 4 -#define TCF2 5 +static struct rtimer rt_clock; +/* the typical clock things like incrementing current_clock and etimer checks */ +/* are performed as a periodically scheduled rtimer */ void -clock_init() +rt_do_clock(struct rtimer *t, void *ptr) { - /* timer setup */ - /* CTRL */ -#define COUNT_MODE 1 /* use rising edge of primary source */ -#define PRIME_SRC 0xf /* Perip. clock with 128 prescale (for 24Mhz = 187500Hz)*/ -#define SEC_SRC 0 /* don't need this */ -#define ONCE 0 /* keep counting */ -#define LEN 1 /* count until compare then reload with value in LOAD */ -#define DIR 0 /* count up */ -#define CO_INIT 0 /* other counters cannot force a re-initialization of this counter */ -#define OUT_MODE 0 /* OFLAG is asserted while counter is active */ + rtimer_set(t, RTIMER_TIME(t) + (rtc_freq/CLOCK_CONF_SECOND) , 1, + (rtimer_callback_t)rt_do_clock, ptr); - *TMR_ENBL = 0; /* tmrs reset to enabled */ - *TMR0_SCTRL = 0; - *TMR0_CSCTRL =0x0040; - *TMR0_LOAD = 0; /* reload to zero */ - *TMR0_COMP_UP = 1875; /* trigger a reload at the end */ - *TMR0_CMPLD1 = 1875; /* compare 1 triggered reload level, 10HZ maybe? */ - *TMR0_CNTR = 0; /* reset count register */ - *TMR0_CTRL = (COUNT_MODE<<13) | (PRIME_SRC<<9) | (SEC_SRC<<7) | (ONCE<<6) | (LEN<<5) | (DIR<<4) | (CO_INIT<<3) | (OUT_MODE); - *TMR_ENBL = 0xf; /* enable all the timers --- why not? */ + current_clock++; + + if((current_clock % CLOCK_CONF_SECOND) == 0) { + seconds++; + } + + if(etimer_pending() && + (etimer_next_expiration_time() - current_clock - 1) > MAX_TICKS) { + etimer_request_poll(); + } - enable_irq(TMR); -/* Do startup scan of the ADC */ -#if CLOCK_CONF_SAMPLEADC - adc_reading[8]=0; - adc_init(); - while (adc_reading[8]==0) adc_service(); -#endif } -void tmr0_isr(void) { - if(bit_is_set(*TMR(0,CSCTRL),TCF1)) { - current_clock++; - if((current_clock % CLOCK_CONF_SECOND) == 0) { - seconds++; -#if BLINK_SECONDS - leds_toggle(LEDS_GREEN); -#endif -/* ADC can be serviced every tick or every second */ -#if CLOCK_CONF_SAMPLEADC > 1 - adc_service(); -#endif - } -#if CLOCK_CONF_SAMPLEADC == 1 - adc_service(); -#endif - if(etimer_pending() && - (etimer_next_expiration_time() - current_clock - 1) > MAX_TICKS) { - etimer_request_poll(); - } - - /* clear the compare flags */ - clear_bit(*TMR(0,SCTRL),TCF); - clear_bit(*TMR(0,CSCTRL),TCF1); - clear_bit(*TMR(0,CSCTRL),TCF2); - return; - } else { - /* this timer didn't create an interrupt condition */ - return; - } +/* RTC MUST have been already setup by mc1322x init */ +void +clock_init(void) +{ + rtimer_set(&rt_clock, RTIMER_NOW() + rtc_freq/CLOCK_CONF_SECOND, 1, (rtimer_callback_t)rt_do_clock, NULL); } clock_time_t clock_time(void) { - return current_clock; + return current_clock; } unsigned long @@ -134,8 +93,8 @@ clock_seconds(void) void clock_wait(clock_time_t t) { - clock_time_t endticks = current_clock + t; - while ((signed long)(current_clock - endticks) < 0) {;} + clock_time_t endticks = current_clock + t; + while ((signed long)(current_clock - endticks) < 0) {;} } /*---------------------------------------------------------------------------*/ /** @@ -146,17 +105,17 @@ clock_wait(clock_time_t t) void clock_delay_usec(uint16_t howlong) { - if(howlong<2) return; + if(howlong<2) return; #if 0 - if(howlong>400) { - volatile register uint32_t i=*MACA_CLK+howlong/4; - while (i > *MACA_CLK) ; - return; - } + if(howlong>400) { + volatile register uint32_t i=*MACA_CLK+howlong/4; + while (i > *MACA_CLK) ; + return; + } #endif - /* These numbers at 25MHz, gcc -Os */ - volatile register uint32_t i=4000*howlong/2301; - while(--i); + /* These numbers at 25MHz, gcc -Os */ + volatile register uint32_t i=4000*howlong/2301; + while(--i); } /*---------------------------------------------------------------------------*/ /** @@ -165,7 +124,7 @@ clock_delay_usec(uint16_t howlong) void clock_delay_msec(uint16_t howlong) { - while(howlong--) clock_delay_usec(1000); + while(howlong--) clock_delay_usec(1000); } /*---------------------------------------------------------------------------*/ /** @@ -176,8 +135,8 @@ clock_delay_msec(uint16_t howlong) void clock_delay(unsigned int howlong) { - if(howlong--) return; - clock_delay_usec((283*howlong)/100); + if(howlong--) return; + clock_delay_usec((283*howlong)/100); } /*---------------------------------------------------------------------------*/ /** diff --git a/cpu/mc1322x/contiki-crm.c b/cpu/mc1322x/contiki-crm.c deleted file mode 100644 index 41c36d679..000000000 --- a/cpu/mc1322x/contiki-crm.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2010, Mariano Alvira and other contributors - * to the MC1322x project (http://mc1322x.devl.org) and Contiki. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. - * - * This file is part of the Contiki OS. - * - * - */ - -#include "mc1322x.h" - -#define CRM_DEBUG 1 -#if CRM_DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif - -uint32_t cal_rtc_secs; /* calibrated 2khz rtc seconds */ - -void sleep(uint32_t opts, uint32_t mode) -{ - - /* the maca must be off before going to sleep */ - /* otherwise the mcu will reboot on wakeup */ -// maca_off(); - *CRM_SLEEP_CNTL = opts; - *CRM_SLEEP_CNTL = (opts | mode); - - /* wait for the sleep cycle to complete */ - while(!bit_is_set(*CRM_STATUS,0)) { continue; } - /* write 1 to sleep_sync --- this clears the bit (it's a r1wc bit) and powers down */ - set_bit(*CRM_STATUS,0); - - /* now we are asleep */ - /* and waiting for something to wake us up */ - /* you did tell us how to wake up right? */ - - /* waking up */ - while(!bit_is_set(*CRM_STATUS,0)) { continue; } - /* write 1 to sleep_sync --- this clears the bit (it's a r1wc bit) and finishes the wakeup */ - set_bit(*CRM_STATUS,0); - - /* you may also need to do other recovery */ - /* such as interrupt handling */ - /* peripheral init */ - /* and turning the radio back on */ - -} - -/* turn on the 32kHz crystal */ -/* once you start the 32xHz crystal it can only be stopped with a reset (hard or soft) */ -void enable_32khz_xtal(void) -{ - static volatile uint32_t rtc_count; - PRINTF("enabling 32kHz crystal\n\r"); - /* first, disable the ring osc */ - ring_osc_off(); - /* enable the 32kHZ crystal */ - xtal32_on(); - - /* set the XTAL32_EXISTS bit */ - /* the datasheet says to do this after you've check that RTC_COUNT is changing */ - /* the datasheet is not correct */ - xtal32_exists(); - - /* now check that the crystal starts */ - /* this blocks until it starts */ - /* it would be better to timeout and return an error */ - rtc_count = *CRM_RTC_COUNT; - PRINTF("waiting for xtal\n\r"); - while(*CRM_RTC_COUNT == rtc_count) { - continue; - } - /* RTC has started up */ - PRINTF("32kHZ xtal started\n\r"); - -} - -void cal_ring_osc(void) -{ - uint32_t cal_factor; - PRINTF("performing ring osc cal\n\r"); - PRINTF("crm_status: 0x%0x\n\r",*CRM_STATUS); - PRINTF("sys_cntl: 0x%0x\n\r",*CRM_SYS_CNTL); - *CRM_CAL_CNTL = (1<<16) | (20000); - while((*CRM_STATUS & (1<<9)) == 0); - PRINTF("ring osc cal complete\n\r"); - PRINTF("cal_count: 0x%0x\n\r",*CRM_CAL_COUNT); - cal_factor = (REF_OSC*1000) / *CRM_CAL_COUNT; - cal_rtc_secs = (NOMINAL_RING_OSC_SEC * cal_factor)/100; - PRINTF("cal factor: %d\n\r", cal_factor); - PRINTF("hib_wake_secs: %d\n\r", cal_rtc_secs); - set_bit(*CRM_STATUS,9); -} diff --git a/cpu/mc1322x/contiki-mc1322x-conf.h b/cpu/mc1322x/contiki-mc1322x-conf.h index da8f6582a..b88331413 100644 --- a/cpu/mc1322x/contiki-mc1322x-conf.h +++ b/cpu/mc1322x/contiki-mc1322x-conf.h @@ -55,4 +55,8 @@ typedef unsigned short uip_stats_t; typedef uint32_t clock_time_t; -#endif \ No newline at end of file +/* Core rtimer.h defaults to 16 bit timer unless RTIMER_CLOCK_LT is defined */ +typedef unsigned long rtimer_clock_t; +#define RTIMER_CLOCK_LT(a,b) ((signed long)((a)-(b)) < 0) + +#endif diff --git a/cpu/mc1322x/init.c b/cpu/mc1322x/init.c index 00019c407..c14b3f9ea 100644 --- a/cpu/mc1322x/init.c +++ b/cpu/mc1322x/init.c @@ -102,6 +102,7 @@ void buck_setup(void) { CRM->VREG_CNTLbits.VREG_1P5V_SEL = 3; CRM->VREG_CNTLbits.VREG_1P5V_EN = 3; CRM->VREG_CNTLbits.VREG_1P8V_EN = 1; + while(CRM->STATUSbits.VREG_1P5V_RDY == 0) { continue; } while(CRM->STATUSbits.VREG_1P8V_RDY == 0) { continue; } @@ -149,6 +150,7 @@ void rtc_setup(void) { PRINTF("RTC calibrated to %d Hz\r\n", rtc_freq); } else { PRINTF("32kHz xtal started\n\r"); + rtc_freq = 32768; } } @@ -167,13 +169,11 @@ void mc1322x_init(void) { PRINTF("mc1322x init\n\r"); adc_init(); - clock_init(); ctimer_init(); process_init(); process_start(&etimer_process, NULL); process_start(&contiki_maca_process, NULL); buck_setup(); - rtc_setup(); /* start with a default config */ @@ -196,6 +196,11 @@ void mc1322x_init(void) { set_demodulator_type(mc1322x_config.flags.demod); set_prm_mode(mc1322x_config.flags.autoack); + /* must be done AFTER maca_init */ + /* the radio calibration appears to clobber the RTC trim caps */ + rtc_setup(); + rtimer_init(); + clock_init(); } diff --git a/cpu/mc1322x/lib/rtc.c b/cpu/mc1322x/lib/rtc.c index 7387352a9..1b69b5215 100644 --- a/cpu/mc1322x/lib/rtc.c +++ b/cpu/mc1322x/lib/rtc.c @@ -72,7 +72,7 @@ void rtc_init_osc(int use_32khz) continue; /* RTC has started up */ - rtc_freq = 32000; + rtc_freq = 32768; } else { @@ -168,7 +168,7 @@ void rtc_calibrate(void) uint32_t count; if (__use_32khz) { - rtc_freq = 32000; + rtc_freq = 32768; return; } diff --git a/cpu/mc1322x/rtimer-arch.c b/cpu/mc1322x/rtimer-arch.c index f85fb15a2..c62092a75 100644 --- a/cpu/mc1322x/rtimer-arch.c +++ b/cpu/mc1322x/rtimer-arch.c @@ -57,18 +57,41 @@ #define PRINTF(...) #endif -void rtc_isr(void) { - PRINTF("rtc_wu_irq\n\r"); - PRINTF("now is %u\n", rtimer_arch_now()); - disable_rtc_wu(); - disable_rtc_wu_irq(); +static uint32_t last_rtc; + +void +rtc_isr(void) +{ + /* see note in table 5-13 of the reference manual: it takes at least two RTC clocks for the EVT bit to clear */ + if ((CRM->RTC_COUNT - last_rtc) <= 2) { + CRM->STATUS = ~0; /* Clear all events */ + +// CRM->STATUSbits.RTC_WU_EVT = 1; + return; + } + + last_rtc = CRM->RTC_COUNT; + + /* Clear all events (for paranoia) */ + /* clear RTC event flag (for paranoia)*/ +// CRM->STATUSbits.RTC_WU_EVT = 1; + CRM->STATUS = ~0; + rtimer_run_next(); - clear_rtc_wu_evt(); + } void rtimer_arch_init(void) { + last_rtc = CRM->RTC_COUNT; + /* enable timeout interrupts */ + /* RTC WU is the periodic RTC timer */ + /* TIMER WU is the wakeup timers (clocked from the RTC source) */ + /* it does not appear you can have both enabled at the same time */ + CRM->WU_CNTLbits.RTC_WU_EN = 1; + CRM->WU_CNTLbits.RTC_WU_IEN = 1; + enable_irq(CRM); } void @@ -76,23 +99,52 @@ rtimer_arch_schedule(rtimer_clock_t t) { volatile uint32_t now; now = rtimer_arch_now(); - PRINTF("rtimer_arch_schedule time %u; now is %u\n", t,now); + PRINTF("rtimer_arch_schedule time %u; now is %u\n", t, now); -#if 1 -/* If specified time is always in the future, counter can wrap without harm */ - *CRM_RTC_TIMEOUT = t - now; -#else /* Immediate interrupt if specified time is before current time. This may also happen on counter overflow. */ - if(now>t) { - *CRM_RTC_TIMEOUT = 1; + if(now > t) { + CRM->RTC_TIMEOUT = 1; } else { - *CRM_RTC_TIMEOUT = t - now; + CRM->RTC_TIMEOUT = t - now; } -#endif - - clear_rtc_wu_evt(); - enable_rtc_wu(); - enable_rtc_wu_irq(); - PRINTF("rtimer_arch_schedule CRM_RTC_TIMEOUT is %u\n", *CRM_RTC_TIMEOUT); } + +void +rtimer_arch_sleep(rtimer_clock_t howlong) +{ + CRM->WU_CNTLbits.TIMER_WU_EN = 1; + CRM->WU_CNTLbits.RTC_WU_EN = 0; + CRM->WU_TIMEOUT = howlong; + + /* the maca must be off before going to sleep */ + /* otherwise the mcu will reboot on wakeup */ + maca_off(); + + CRM->SLEEP_CNTLbits.DOZE = 0; + CRM->SLEEP_CNTLbits.RAM_RET = 3; + CRM->SLEEP_CNTLbits.MCU_RET = 1; + CRM->SLEEP_CNTLbits.DIG_PAD_EN = 1; + CRM->SLEEP_CNTLbits.HIB = 1; + + /* wait for the sleep cycle to complete */ + while((*CRM_STATUS & 0x1) == 0) { continue; } + /* write 1 to sleep_sync --- this clears the bit (it's a r1wc bit) and powers down */ + *CRM_STATUS = 1; + + /* asleep */ + + /* wait for the awake cycle to complete */ + while((*CRM_STATUS & 0x1) == 0) { continue; } + /* write 1 to sleep_sync --- this clears the bit (it's a r1wc bit) and finishes wakeup */ + *CRM_STATUS = 1; + + CRM->WU_CNTLbits.TIMER_WU_EN = 0; + CRM->WU_CNTLbits.RTC_WU_EN = 1; + + /* reschedule clock ticks */ + clock_init(); + clock_adjust_ticks((CRM->WU_COUNT*CLOCK_CONF_SECOND)/rtc_freq); +} + + diff --git a/cpu/mc1322x/rtimer-arch.h b/cpu/mc1322x/rtimer-arch.h index 3b4e932de..2e8f4acce 100644 --- a/cpu/mc1322x/rtimer-arch.h +++ b/cpu/mc1322x/rtimer-arch.h @@ -47,15 +47,15 @@ #include "sys/rtimer.h" /* mc1322x */ -#include "crm.h" -#include "utils.h" +#include "mc1322x.h" #if USE_32KHZ_XTAL #define RTIMER_ARCH_SECOND 32768 #else -#define RTIMER_ARCH_SECOND 18778 /* close --- should get calibrated */ +#define RTIMER_ARCH_SECOND 2000 #endif -#define rtimer_arch_now() (*CRM_RTC_COUNT) +#define rtimer_arch_now() (CRM->RTC_COUNT) + #endif /* __RTIMER_ARCH_H__ */ diff --git a/platform/econotag/contiki-conf.h b/platform/econotag/contiki-conf.h index f4de30e5f..11bf24221 100644 --- a/platform/econotag/contiki-conf.h +++ b/platform/econotag/contiki-conf.h @@ -106,10 +106,6 @@ #define PLATFORM_HAS_LEDS 1 #define PLATFORM_HAS_BUTTON 1 -/* Core rtimer.h defaults to 16 bit timer unless RTIMER_CLOCK_LT is defined */ -typedef unsigned long rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((signed long)((a)-(b)) < 0) - #define RIMEADDR_CONF_SIZE 8 #if WITH_UIP6