00001 /* 00002 * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors 00003 * to the MC1322x project (http://mc1322x.devl.org) and Contiki. 00004 * 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * 3. Neither the name of the Institute nor the names of its contributors 00016 * may be used to endorse or promote products derived from this software 00017 * without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00022 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00024 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00025 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00026 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00027 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00028 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00029 * SUCH DAMAGE. 00030 * 00031 * This file is part of the Contiki OS. 00032 * 00033 * 00034 */ 00035 00036 #include "mc1322x.h" 00037 00038 #define CRM_DEBUG 1 00039 #if CRM_DEBUG 00040 #define PRINTF(...) printf(__VA_ARGS__) 00041 #else 00042 #define PRINTF(...) 00043 #endif 00044 00045 uint32_t cal_rtc_secs; /* calibrated 2khz rtc seconds */ 00046 00047 void sleep(uint32_t opts, uint32_t mode) 00048 { 00049 00050 /* the maca must be off before going to sleep */ 00051 /* otherwise the mcu will reboot on wakeup */ 00052 // maca_off(); 00053 *CRM_SLEEP_CNTL = opts; 00054 *CRM_SLEEP_CNTL = (opts | mode); 00055 00056 /* wait for the sleep cycle to complete */ 00057 while(!bit_is_set(*CRM_STATUS,0)) { continue; } 00058 /* write 1 to sleep_sync --- this clears the bit (it's a r1wc bit) and powers down */ 00059 set_bit(*CRM_STATUS,0); 00060 00061 /* now we are asleep */ 00062 /* and waiting for something to wake us up */ 00063 /* you did tell us how to wake up right? */ 00064 00065 /* waking up */ 00066 while(!bit_is_set(*CRM_STATUS,0)) { continue; } 00067 /* write 1 to sleep_sync --- this clears the bit (it's a r1wc bit) and finishes the wakeup */ 00068 set_bit(*CRM_STATUS,0); 00069 00070 /* you may also need to do other recovery */ 00071 /* such as interrupt handling */ 00072 /* peripheral init */ 00073 /* and turning the radio back on */ 00074 00075 } 00076 00077 /* turn on the 32kHz crystal */ 00078 /* once you start the 32xHz crystal it can only be stopped with a reset (hard or soft) */ 00079 void enable_32khz_xtal(void) 00080 { 00081 static volatile uint32_t rtc_count; 00082 PRINTF("enabling 32kHz crystal\n\r"); 00083 /* first, disable the ring osc */ 00084 ring_osc_off(); 00085 /* enable the 32kHZ crystal */ 00086 xtal32_on(); 00087 00088 /* set the XTAL32_EXISTS bit */ 00089 /* the datasheet says to do this after you've check that RTC_COUNT is changing */ 00090 /* the datasheet is not correct */ 00091 xtal32_exists(); 00092 00093 /* now check that the crystal starts */ 00094 /* this blocks until it starts */ 00095 /* it would be better to timeout and return an error */ 00096 rtc_count = *CRM_RTC_COUNT; 00097 PRINTF("waiting for xtal\n\r"); 00098 while(*CRM_RTC_COUNT == rtc_count) { 00099 continue; 00100 } 00101 /* RTC has started up */ 00102 PRINTF("32kHZ xtal started\n\r"); 00103 00104 } 00105 00106 void cal_ring_osc(void) 00107 { 00108 uint32_t cal_factor; 00109 PRINTF("performing ring osc cal\n\r"); 00110 PRINTF("crm_status: 0x%0x\n\r",*CRM_STATUS); 00111 PRINTF("sys_cntl: 0x%0x\n\r",*CRM_SYS_CNTL); 00112 *CRM_CAL_CNTL = (1<<16) | (20000); 00113 while((*CRM_STATUS & (1<<9)) == 0); 00114 PRINTF("ring osc cal complete\n\r"); 00115 PRINTF("cal_count: 0x%0x\n\r",*CRM_CAL_COUNT); 00116 cal_factor = (REF_OSC*1000) / *CRM_CAL_COUNT; 00117 cal_rtc_secs = (NOMINAL_RING_OSC_SEC * cal_factor)/100; 00118 PRINTF("cal factor: %d\n\r", cal_factor); 00119 PRINTF("hib_wake_secs: %d\n\r", cal_rtc_secs); 00120 set_bit(*CRM_STATUS,9); 00121 }