⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.c

📁 MANTIS是由科罗拉多大学开发的传感器网络嵌入式操作系统。 这是mantis的0.9.5版本的源码。
💻 C
字号:
//  This file is part of MANTIS OS, Operating System//  See http://mantis.cs.colorado.edu/////  Copyright (C) 2003,2004,2005 University of Colorado, Boulder////  This program is free software; you can redistribute it and/or//  modify it under the terms of the mos license (see file LICENSE)/************************************************* Project Mantis  File: clock.c Original Author: Jeff Rose Date: 4/20/04 Heavily Modified and debugged: Brian, Cyrus, Charles, Adam Date: 5/25/04   An alarm timer implementation for the avr *************************************************/#include "mos.h"#include "mutex.h"#include "msched.h"#include "clock.h"#include "printf.h"#include "plat_dep.h"#include "plat_clock.h"#ifdef ARCH_AVR#define TIMER_OCR           OCR3A#define TIMER_INT           OCIE3A#define TIMER_CNT           TCNT3#define TIMER_CNTRLA        TCCR3A#define TIMER_CNTRLB        TCCR3B#define TIMER_FLAG          OCF3A#define TIMER_SIG           SIG_OUTPUT_COMPARE3A/** @brief an arbitrary "short" number of ticks */#define SHORT_TICKS 65static mos_alarm_t *head; // head of the list of alarms// the upper half of our 32 bit timer, since our hardware// timers are only 16 bitsstatic uint16_t elapsed_high_count;static mos_mutex_t clock_mutex;static void set_alarm_timer(uint32_t t);/** @brief Convert ticks to seconds. * * @param ticks Original time in ticks  */#define to_secs(ticks) (ticks / (uint32_t)TICKS_PER_SEC)/** @brief Convert seconds to ticks.  * * @param ticks Original time in seconds */#define to_usecs(ticks) (ticks * (uint32_t)USECS_PER_TICK)/** @brief Reset the timer. */#define clear_timer(void) do { TIMER_CNT = 0;	\      elapsed_high_count = 0;			\   } while(0);#define get_ticks() (TIMER_CNT - 200)/* subtract alarm2 from alarm1 */#define clock_sub(alarm1, alarm2) do { alarm1->ticks -= alarm2->ticks; } while (0)/* add alarm2's time to alarm 1 */#define clock_add(alarm1, alarm2) do { alarm1->ticks += alarm2->ticks; } while (0)#define enable_timer() do {				\      TIMER_CNTRLB |= (1 << CS32);			\      TIMER_CNTRLB &= ~((1 << CS31) | (1 << CS30));	\   } while (0)#define disable_timer() TIMER_CNTRLB &= ~((1 << CS32) | (1 << CS31) | (1 << CS30))void print_clock_list(void){   mos_alarm_t *aptr = head;   uint8_t i = 0;   printf("Clock list: \n");   while(aptr) {      printf("alarm%C: %l\n", i++, aptr->ticks);      aptr = aptr->next;   }  }/* Remove the first instance of alarm on the list */boolean mos_remove_alarm(mos_alarm_t *alarm){   mos_alarm_t *current = head;   mos_alarm_t *prev = NULL;      if(alarm == NULL)      return false;      while(current) {      if(current == alarm) { //remove this alarm	 if(current == head) //removing head element	    head = current->next;	 	 if(prev) { 	    prev->next = current->next;	 }	 if(current->next) { //add relative time to next timer	    clock_add(current->next, current);	 }	 return true;      }      prev = current;      current = current->next;   }   return false;}int8_t mos_alarm (mos_alarm_t *new, uint32_t secs, uint32_t usecs){   // convert the arguments into a tick value   uint32_t ticks = secs * TICKS_PER_SEC + usecs / USECS_PER_TICK;      return mos_alarm_ticks(new, ticks);}int8_t mos_alarm_ticks(mos_alarm_t *new, uint32_t ticks){   mos_alarm_t *aptr, *prev;   // Kill the timer so we don't have it go off while we are here   disable_timer();      new->ticks = ticks;      // the alarm list is empty, insert a new head   if(head == NULL) {      new->next = NULL;      head = new;      set_alarm_timer(head->ticks);   } else {      // initialize aptr for list traversal      aptr = head;      prev = NULL;      // Run through the list to find the correct spot      while(aptr) {	 if(new->ticks < aptr->ticks) {	    // Subtract the new value from the next alarm since it is now	    // relative to the newly inserted value.	    clock_sub(aptr, new);	    // break out if we find the correct spot. that way if	    // the loop hits the end we can add there too	    break;	 }	 // Since we are keeping relative times we need to	 // keep subtracting as we traverse the list.  	 clock_sub(new, aptr);	 	 prev = aptr;	 aptr = aptr->next;      }      // Update the head to be relative to the new alarm if we have      // a new head      if(aptr == head) {	 new->next = head;	 head = new;	 set_alarm_timer(head->ticks);      } else { // or just insert the new alarm	 prev->next = new;	 new->next = aptr;       }   }      // enable the timer once again   enable_timer();   return 0;}/* Set the current real world time. *//*int8_t mos_set_time (mos_time_t *tv){   ctime.sec = tv->sec;   ctime.usec = tv->usec;   return 0;}int8_t mos_get_time (mos_time_t *tv){   tv->sec = ctime.sec;   ctime.usec = tv->usec;   return 0;}*/void clock_init (void){   // correct config for these registers happens to be 0   TIMER_CNTRLA = 0;   TIMER_CNTRLB = 0;      disable_timer ();   clear_timer ();   mos_mutex_init (&clock_mutex);   // set the output compare interrrupt flag   //ETIFR |= (1 << TIMER_FLAG);   ETIMSK |= (1 << TIMER_INT);}/*** Functions private to this file. ***/static uint16_t high_count, low_count; // 16 bit tick countsstatic void set_alarm_timer(uint32_t new_ticks){   // fudge the new ticks a bit to make things more precise   // TODO: is this right?   //new_ticks += 385;   // shift the 32 bit ticks into our two 16 bit counters   high_count = new_ticks >> 16;   low_count = new_ticks & 0xFFFF;   // reset the high bits and counter val   clear_timer();   // if the alarm is long enough to go into the high bits,   // set the counter comparator to maximum (16 bits) so we   // can finagle it to be 32 bits, else set it to the ticks   // of the new alarm   if(high_count > 0) {      TIMER_OCR = 0xffff;      high_count--;   } else {      TIMER_OCR = low_count;      low_count = 0;   }  }// we need to call the alarm's function AFTER removing it// from the list since we may call mos_alarm from inside// this interrupt handlerstatic inline void fire_alarm(void){   mos_alarm_t *temp_aptr;   temp_aptr = head;   if(head) {      head = head->next;      if(temp_aptr->func != NULL)	 temp_aptr->func(temp_aptr->data);   }}/** @brief Alarm interrupt handler */SIGNAL(TIMER_SIG){   if(high_count == 0) { //no overruns left      if(low_count == 0) { //time expired	 	 // reset the high bits 	 elapsed_high_count = 0;	 //always fire the head node	 fire_alarm();	 	 // If we have multiple alarms that overlap exactly then we will need	 // to call all the functions and pull them off the list.	 while(head) {	    if(head->ticks < SHORT_TICKS) {	       fire_alarm();	    } else // no need to keep going since the list is in order	       break;	 }	 //set timer for next alarm	 if(head) {	    set_alarm_timer (head->ticks);	 } else //no more alarms, turn timer off	    disable_timer();	          } else { //low count not zero	 TIMER_OCR = low_count;	 elapsed_high_count++;	 low_count = 0;	 head->ticks -= 0xffff;      }         } else { //high count not zero      TIMER_OCR = 0xffff;      elapsed_high_count++;      high_count--;      head->ticks -= 0xffff;   }}#elseint8_t mos_alarm (mos_alarm_t *new, uint32_t secs, uint32_t usecs){   return 0;}int8_t mos_alarm_ticks(mos_alarm_t *new, uint32_t ticks){   return 0;}#ifdef PLATFORM_TELOSBvoid clock_init(void){   uint16_t old_ccr2_val;   int16_t new_ccr2_val;   uint8_t rsel_val;   uint8_t dco_val;      BCSCTL1 = XT2OFF | DIVA1 | RSEL2 | RSEL0;   BCSCTL2 = 0;   TACTL = TASSEL_2 | TACLR; // clear clock, source is SMCLK   TACTL |= MC1; // start timer in continuous mode   CCTL2 = CM0 | CCIS0 | CAP; // rising edge capture   for(;;) {      while(!(CCTL2 & CCIFG))         ; // wait for capture flag      old_ccr2_val = CCR2;      CCTL2 &= ~CCIFG;      while(!(CCTL2 & CCIFG))         ; // wait for capture flag      CCTL2 &= ~CCIFG;      rsel_val = BCSCTL1;      rsel_val &= (RSEL0 | RSEL1 | RSEL2); // mask out rsel bits      dco_val = DCOCTL;      if(dco_val == 0xff) {         if(rsel_val < 7) {            BCSCTL1++;         } else {            goto err;         }      } else if(dco_val == 0) {         if(rsel_val != 0) {            BCSCTL1--;         } else {            goto err;         }      } else {         new_ccr2_val = CCR2;         new_ccr2_val -= old_ccr2_val;         old_ccr2_val = CCR2;         new_ccr2_val -= (CLOCK_SPEED / (32768 / 4));         if(new_ccr2_val < 0) {            DCOCTL++;            continue;         } else if(new_ccr2_val == 0) {            goto err;         } else {            DCOCTL--;            continue;         }      }      DCOCTL = 0x60; // center dco   }err:   CCTL2 = 0;   return;   }#elsevoid clock_init(void){   }#endifboolean mos_remove_alarm(mos_alarm_t *alarm){   return TRUE;   }#endif/* Delay for the given number of milliseconds * @param usec Number of milliseconds to be delayed */void mos_mdelay(uint16_t msec){   while(msec > 0) {      // account for the instructions of processing the      // 16 bit msec variable      // TODO: is this fudge factor right?      mos_udelay (950);      msec--;   }}/* Delay the current thread for give number of microseconds * @param usec number of microseconds to be delayed */#if defined(CLOCK_SPEED_7_37)void mos_udelay(uint16_t usec){   while(usec > 0) {      asm volatile("nop" ::);      asm volatile("nop" ::);      asm volatile("nop" ::);      asm volatile("nop" ::);      usec--;   }}#elif defined(CLOCK_SPEED_3_68)void mos_udelay(uint16_t usec){   while(usec > 0) {      asm volatile("nop" ::);      usec--;   }}#elif defined(CLOCK_SPEED_4_0)void mos_udelay(uint16_t usec){   while(usec > 0) {      asm volatile("nop" ::);      asm volatile("nop" ::);      usec--;   }}#else#error "Unimplemented clock speed"#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -