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

📄 com.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:   com.c   Authors: Jeff Rose & Brian Shucker   Date:   01-18-04  **/#include "mos.h"#ifdef PLATFORM_LINUX#include <signal.h>// So com.c will compile for Linux// TODO maybe Linux needs its own plat_dep.h filetypedef uint8_t handle_t;#endif#include "clock.h"#include "mem.h"#include "led.h"#include "com.h"#include "sem.h"#include "msched.h"#include "mutex.h"#ifdef RADIO_USE_FEC#include "fec.h"// pull these in from cc1000.cextern uint8_t data_fec[FEC_DATA_PARITY_COUNT];extern uint16_t cc1000_fec_error_count;extern uint16_t cc1000_crc_error_count;extern uint16_t cc1000_success_count;#endiftypedef struct {   thread_t *thread_ptr;   boolean timed_out;} timed_thread_t;static comBuf *get_free_buf(void);static void save_full_buf(uint8_t iface, comBuf *buf);static void timeout_callback(void *data); //callback from timer/** @brief Mutexes for sending on each iface. */mos_mutex_t if_send_mutexes[MAX_IFS];	/** @brief Table of thread ids per iface. */static thread_t *if_threads[MAX_IFS];/** @brief The free buffer list. */static comBuf *free_bufs;     /** @brief Separate full lists for each iface. */   static comBuf *if_bufs[MAX_IFS];#ifdef MOS_NO_USE_DYNAMIC_MEMORYstatic comBuf com_bufs[NUM_BUFS];#endif/************ Interfaces for upper layers. *************/uint8_t com_init(void){   uint8_t i;   handle_t int_handle;   comBuf *buf;   int_handle = mos_fast_mutex_lock();      free_bufs = NULL; // Init the empty list      // Clear the function table, init the recv semaphores   // & init the free buf list   for(i = 0; i < MAX_IFS; i++) {      if_threads[i] = NULL;      mos_mutex_init(&if_send_mutexes[i]);      if_bufs[i] = NULL;   }      // Allocate the buffers and create the free buffer list   for(i = 0; i < NUM_BUFS; i++) {#ifdef MOS_NO_USE_DYNAMIC_MEMORY      buf = &com_bufs[i];#else      buf = (comBuf*)mos_mem_alloc(sizeof(comBuf));#endif      if(buf) {	 buf->next = free_bufs;	 free_bufs = buf;      } else {#ifndef PLATFORM_LINUX	 mos_led_display (5);	 mos_mdelay (500);	 mos_led_display (7);	 mos_mdelay (500);	 mos_led_display (5);	 mos_mdelay (500);	 mos_led_display (7);	 mos_mdelay (500);#endif      }   }   mos_fast_mutex_unlock(int_handle);      return 0;}#ifndef PLATFORM_LINUXcomBuf *com_recv_timed(uint8_t iface, uint32_t ticks){   comBuf *buf;   mos_alarm_t timer;   timed_thread_t current;   current.timed_out = false;   current.thread_ptr = mos_thread_current();   handle_t int_handle = mos_fast_mutex_lock();   // Make sure another thread isn't already waiting on this iface   if(if_threads[iface] != NULL) {      mos_fast_mutex_unlock(int_handle);      return NULL;   }   // If we don't have a waiting buf then save the threadID in the table   // and suspend   if(if_bufs[iface] == NULL) {      timer.func = timeout_callback;      timer.data = &current;      mos_alarm_ticks(&timer, ticks);            if_threads[iface] = mos_thread_current();            mos_thread_suspend_noints(int_handle);      int_handle = mos_fast_mutex_lock();   }   if(current.timed_out || !if_bufs[iface]) {      if_threads[iface] = NULL;      mos_fast_mutex_unlock(int_handle);      return NULL;   }   #ifdef RADIO_USE_FEC   uint8_t ret = FEC_UNCORRECTABLE_ERRORS;      if(iface == IFACE_RADIO) {      while(ret == FEC_UNCORRECTABLE_ERRORS) {	 fec_init(FEC_DATA_PARITY_COUNT);	 if((ret = fec_decode(if_bufs[iface]->data,			      if_bufs[iface]->size,			      data_fec)) != FEC_NO_ERRORS) {	    if(ret == FEC_UNCORRECTABLE_ERRORS) {	       cc1000_crc_error_count++;	       com_free_buf(if_bufs[iface]);	       if_bufs[iface] = NULL;	       while(if_bufs[iface] == NULL) {		  if_threads[iface] = mos_thread_current();		  mos_thread_suspend_noints(int_handle);		  int_handle = mos_fast_mutex_lock();	       }	    } else {	       cc1000_fec_error_count++;	    }	 }      }      cc1000_success_count++;   }#endif      // Grab the first buffer on the list and shift the head pointer   buf = if_bufs[iface];   if_bufs[iface] = buf->next;   // Take this thread out of the table and unlock the mutex   if_threads[iface] = NULL;   mos_fast_mutex_unlock(int_handle);      return buf;}#endifcomBuf *com_recv_noblock(uint8_t iface){   comBuf *buf;   handle_t int_handle = mos_fast_mutex_lock();   // Make sure another thread isn't already waiting on this iface   if(if_threads[iface] != NULL) {      mos_fast_mutex_unlock(int_handle);      return NULL;   }   // If we don't have a waiting buf then return NULL   if(if_bufs[iface] == NULL) {      mos_fast_mutex_unlock(int_handle);      return NULL;   }   buf = if_bufs[iface];   mos_fast_mutex_unlock(int_handle);   return buf;}comBuf *com_recv(uint8_t iface){   comBuf *buf;   handle_t int_handle = mos_fast_mutex_lock();   // Make sure another thread isn't already waiting on this iface   if(if_threads[iface] != NULL) {      mos_fast_mutex_unlock(int_handle);      return NULL;   }   // If we don't have a waiting buf then save the threadID in the table   // and suspendtry_recv_again:   if(if_bufs[iface] == NULL) {      if_threads[iface] = mos_thread_current();      mos_thread_suspend_noints(int_handle);      int_handle = mos_fast_mutex_lock();   }#ifdef RADIO_USE_FEC   uint8_t ret = FEC_UNCORRECTABLE_ERRORS;      if(iface == IFACE_RADIO) {      while(ret == FEC_UNCORRECTABLE_ERRORS) {	 fec_init(FEC_DATA_PARITY_COUNT);	 if((ret = fec_decode(if_bufs[iface]->data,			      if_bufs[iface]->size,			      data_fec)) != FEC_NO_ERRORS) {	    if(ret == FEC_UNCORRECTABLE_ERRORS) {	       cc1000_crc_error_count++;	       com_free_buf(if_bufs[iface]);	       if_bufs[iface] = NULL;	       goto try_recv_again;	    } else {	       cc1000_fec_error_count++;	    }	 }      }#ifdef RADIO_EXTRA_CRC      if_bufs[iface]->size -= 2;      uint16_t crc = *(uint16_t *)&if_bufs[iface]->data[if_bufs[iface]->size];      if (crc_compute(if_bufs[iface]->data, if_bufs[iface]->size) != crc) {	 cc1000_crc_error_count++;	 com_free_buf(if_bufs[iface]);	 if_bufs[iface] = NULL;	 goto try_recv_again;      } else#endif	 cc1000_success_count++;   }#endif      // Grab the first buffer on the list and shift the head pointer   buf = if_bufs[iface];   if_bufs[iface] = buf->next;      // Take this thread out of the table and unlock the mutex   if_threads[iface] = NULL;   mos_fast_mutex_unlock(int_handle);      return buf;}//This will flush all of the packets on a particular iface.void com_flush(uint8_t iface){   comBuf *recv;   IF_SET set;   while(1) { //break out of the loop on null recv packet      IF_ZERO(&set);      IF_SET(iface, &set);      com_select(&set, false);      if(IF_ISSET(iface, &set)) {	 recv = com_recv(iface);	 com_free_buf(recv);      } else	 return;   }   }uint8_t com_select(IF_SET *iset, uint32_t msec){   uint8_t i, bit, ifcount;   handle_t int_handle;   uint8_t retval = 0;   IF_SET oset;   IF_ZERO(&oset); // Start with an empty set   ifcount = 0; // So we can return the number of if's with bufs ready   int_handle = mos_fast_mutex_lock();      // Make sure no other threads are holding any of these ifaces or unregistered   for(i = 0; i < 8; i++) {      bit = 1 << i;      if(*iset & bit) { // Check if a given bit is set	 // If one of the ifaces is already taken we return an error	 if (if_threads[i] != NULL)	    retval = SELECT_IFACE_BUSY;	    	 // We check for bufs here too just to save having to do another loop	 if (if_bufs[i] != NULL){	    oset |= bit;	    ifcount++;	 }      }   }   // Just return the error if an iface is already taken   if(retval == SELECT_IFACE_BUSY || retval == IFACE_NOT_REGISTERED) {      mos_fast_mutex_unlock(int_handle);      return retval;   } else if(oset || msec == 0) {      // Otherwise return if their are bufs to be had      *iset = oset;      mos_fast_mutex_unlock(int_handle);      return ifcount;   }   mos_alarm_t com_timer;   timed_thread_t current;   current.timed_out = false;   // If we get here we need to grab all the relevant ifaces and suspend until   // something comes   current.thread_ptr = mos_thread_current();   for(i = 0; i < 8; i++) {      bit = 1 << i;      if(*iset & bit) // Check if a given bit is set	 if_threads[i] = current.thread_ptr;   }   if(msec != 0xffffffff) {      uint32_t secs = msec / 1024;      uint32_t usecs = 1024 * (msec % 1024);      com_timer.func = timeout_callback;      com_timer.data = &current;      mos_alarm(&com_timer, secs, usecs);   }   mos_thread_suspend_noints(int_handle);   int_handle = mos_fast_mutex_lock();      //check to see if com_select timed out   if(msec != 0xffffffff) {      if(current.timed_out) {	 for(i = 0; i < 8; i++) {	    bit = 1 << i;	    if (*iset & bit){ // Check if a given bit is set	       if_threads[i] = NULL;	    }	 }	 *iset = oset;	 mos_fast_mutex_unlock(int_handle);	 return ifcount;      } else { //didn't time out, need to stop alarm	 mos_remove_alarm(&com_timer);      }   }   // We have been woken up so a buf should be available somewhere.  Create the   // IF_SET to send back and get out of here   for(i = 0; i < 8; i++) {      bit = 1 << i;      if(*iset & bit) { // Check if a given bit is set	 if(if_bufs[i] != NULL) {	    oset |= bit;	    ifcount++;	 }	 // Now let go of each iface we had taken	 if_threads[i] = NULL;      }   }   *iset = oset;   mos_fast_mutex_unlock(int_handle);   return ifcount;}void com_free_buf(comBuf *buf){   handle_t int_handle = mos_fast_mutex_lock();   buf->next = free_bufs;   free_bufs = buf;   buf = NULL;   mos_fast_mutex_unlock(int_handle);}/** Interfaces for lower driver layers. **/void com_swap_bufs(uint8_t iface, comBuf *buf, comBuf **ret){   handle_t int_handle = mos_fast_mutex_lock();      if(buf == NULL) { // Just allocate a new buf      *ret = get_free_buf();   } else {      thread_t *p;         // save the buffer to the ifaces list and then wake a      // waiting thread if need be Finally, return a new buffer      save_full_buf(iface, buf);      // If a thread is waiting then wake it up      if(if_threads[iface] != NULL) {	 p = if_threads[iface];	 //mos_thread_resume_noints_nodispatch(p, int_handle);	 mos_thread_resume_noints(p, int_handle);      }	       *ret = get_free_buf();   }   mos_fast_mutex_unlock(int_handle);   return;}/*** Some functions private to this file. ***//** @brief Save a full buffer. * @param iface Interface to use * @param buf Buffer to save */static void save_full_buf(uint8_t iface, comBuf *buf){   comBuf *buf_iter;   buf->next = NULL;   //If its an empty list than save the buf to the head   if(if_bufs[iface] == NULL) {      if_bufs[iface] = buf;      return;   }   // Traverse the list until we hit the end and then save the buf   for(buf_iter = if_bufs[iface]; buf_iter->next != NULL; buf_iter = buf_iter->next)      ;   buf_iter->next = buf;   return;}/** @brief Find a free buffer.  * @return The next free buffer or NULL if they are all full */static comBuf *get_free_buf(void){   comBuf *buf;      if(free_bufs != NULL) {      buf = free_bufs;      free_bufs = buf->next;      return buf;   } else {      return NULL;   }}/** @brief A timed select callback has expired */void timeout_callback(void *data){   timed_thread_t *ptr = (timed_thread_t *)data;   ptr->timed_out = true;   mos_thread_resume(ptr->thread_ptr);   }

⌨️ 快捷键说明

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