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

📄 deluge_proto.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)#include "mos.h"#if defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)#include "com.h"#include "deluge_impl.h"#include "printf.h"#include "led.h"#include "net.h"#include "sem.h"#include "mutex.h"#include "rwlock.h"#include "cond.h"#include "reprogram_commands.h"#include "node_id.h"#include <string.h>#include "deluge_msgs.h"#include "aqueduct_shell.h"#define debugLeds	0#ifdef DELUGE_KEEP_STATS// log packets for each id (0 through DELUGE_STATS_COUNT-2,// id DELUGE_STATS_COUNT-1 for anything greater) and typeuint16_t packet_counts[DELUGE_STATS_COUNT][4];uint8_t deluge_recordstats = 0;#endifmos_sem_t dispatch_sem;mos_cond_t suspend_cond;mos_mutex_t suspend_lock;mos_rwlock_t applist_lock;static volatile uint8_t suspended = 0;//static uint8_t dropped;static uint8_t deluge_stack[192];uint8_t deluge_portmap[DELUGE_INSTANCE_COUNT];deluge_entry table[DELUGE_INSTANCE_COUNT];#define N_LOADED 2// We need to hold a read lock while accessing an element of this list// and a write lock when modifying the listdeluge_app apps[N_LOADED];static uint8_t next_app_idx = 0;static deluge_app* last_app;static uint8_t next_disp_inst = 0;static uint8_t next_recv_inst = 0;// Alarms call this functionvoid deluge_wakeup(deluge_entry* entry){	//mos_sem_post(&entry->app_sem);	entry->copyState = 1;	mos_sem_post(&dispatch_sem);}#ifdef DELUGE_KEEP_STATSvoid deluge_saveStats(){	dev_ioctl(DEV_AVR_EEPROM, DEV_LOCK);	dev_ioctl(DEV_AVR_EEPROM, DEV_SEEK, DELUGE_STATS_ADDR);	dev_write(DEV_AVR_EEPROM, (uint8_t*)packet_counts, sizeof(packet_counts));	dev_ioctl(DEV_AVR_EEPROM, DEV_UNLOCK);}#endifstatic deluge_app* loadApp(int8_t index){	//printf("loading %C\n", index);	// The caller needs to hold a write lock on applist_lock, 	// so we don't unload an application's entry while it is being used	if (apps[next_app_idx].index != -1) {		deluge_saveState(&apps[next_app_idx]);		table[apps[next_app_idx].index].app = NULL;	}	deluge_app* app = &apps[next_app_idx];	next_app_idx = (next_app_idx + 1) % N_LOADED;		deluge_app_init(app, index);	return app;}static void dispatchThread(){	while(1)	{		// Wait for something to happen (timeout or a change of state)		mos_sem_wait(&dispatch_sem);		// Check if we are suspended		mos_mutex_lock(&suspend_lock);		while (suspended) mos_cond_wait(&suspend_cond, &suspend_lock);		mos_mutex_unlock(&suspend_lock);		//printf("dt1\n");		// Grab a read lock on the application list		rwlock_rdlock(&applist_lock);		mos_led_toggle(1);		// Quickly check the last application we used, it's most likely to be		// the one with the event		deluge_app* app = last_app;		//if (SEM_SUCCESS == mos_sem_try_wait(&table[last_app->index].app_sem)) {		/*if (table[app->index].nextState != DELUGE_STATE_IGNORE) {			//printf("%C -> %C\n", last_app->state, table[last_app->index].nextState);			app->state = table[app->index].nextState;			table[app->index].nextState = DELUGE_STATE_IGNORE;			deluge_dispatch(app);			rwlock_unlock(&applist_lock);			continue;		}*/				// Check everybody else		uint8_t appid;		uint8_t i;		for (i=0; i<DELUGE_INSTANCE_COUNT; i++) {			appid = (next_disp_inst + i) % DELUGE_INSTANCE_COUNT;			//if (SEM_SUCCESS == mos_sem_try_wait(&table[appid].app_sem))			if (table[appid].copyState && table[appid].nextState != DELUGE_STATE_IGNORE)				break;		}		if (i == DELUGE_INSTANCE_COUNT) {			rwlock_unlock(&applist_lock);			continue;		}		// See if the Deluge instance is already loaded			while (!table[appid].app) 		{			// Unlock the read lock and grab the write lock			rwlock_unlock(&applist_lock);			rwlock_wrlock(&applist_lock);			// Load the Deluge instance			loadApp(appid);			// Unlock the write lock and grab the read lock			rwlock_unlock(&applist_lock);			rwlock_rdlock(&applist_lock);			// Between the time we released the write lock and when we got the			// read lock, someone else could have unloaded our instance,			// so we loop and check that it's still loaded		}		last_app = app = table[appid].app;		next_disp_inst = (appid + 1) % DELUGE_INSTANCE_COUNT;		//printf("%C -> %C\n", app->state, table[appid].nextState);		app->state = table[appid].nextState;		table[appid].nextState = DELUGE_STATE_IGNORE;		table[appid].copyState = 0;				//printf("dispatch %C\n", appid);		deluge_dispatch(app);		rwlock_unlock(&applist_lock);	}}/* Net device interface functions */int8_t deluge_send(comBuf *pkt, va_list args){	if (debugLeds) mos_led_toggle(0);	uint8_t port = va_arg(args, int);	uint8_t type = pkt->data[pkt->size - 1];	uint16_t sender = *(uint16_t*)&pkt->data[pkt->size - 3];		#ifdef DELUGE_KEEP_STATS	if (deluge_recordstats && type<5)		packet_counts[sender<DELUGE_STATS_COUNT-1?sender:DELUGE_STATS_COUNT-1][type-1]++;	#endif		#ifdef DELUGE_PRINT_PACKETS	printf_P(sPktPortType, port, sender, type);	switch (type)	{		case DELUGE_PACKET_SUMMARY: {			deluge_foot_summary* summary = (deluge_foot_summary*)pkt->data;			#ifdef DELUGE_SYMMETRIC_LINKS			#if DELUGE_NEIGHBOR_COUNT != 5			#error This code needs to be updated			#endif			printf_P(sSendNList,				summary->neighbors[0], summary->neighbors[1], 				summary->neighbors[2], summary->neighbors[3], 				summary->neighbors[4]);			#endif			printf_P(sSendSumm, summary->version, summary->highPage, summary->dtb);		} break;		case DELUGE_PACKET_PROFILE: {			deluge_foot_profile* profile = (deluge_foot_profile*)pkt->data;			printf_P(sSendProf, profile->codeSize, profile->crc, profile->version, profile->goalPage);		} break;		case DELUGE_PACKET_REQUEST: {			deluge_foot_request* request = (deluge_foot_request*)pkt->data;			printf_P(sSendReq, request->packets[2], request->packets[1], request->packets[0], request->to, request->version, request->page, request->rateChange);		} break;		case DELUGE_PACKET_DATA: {			deluge_foot_data* data = (deluge_foot_data*)&pkt->data[DELUGE_PACKET_SIZE];			printf_P(sSendData, data->version, data->page, data->packet);		} break;		#ifdef DELUGE_COMMANDER		case DELUGE_PACKET_COMMAND: {			deluge_foot_command* command = (deluge_foot_command*)&pkt->data[pkt->size-sizeof(deluge_foot_command)];			printf_P(sSendComm, command->seq, command->command, command->to);		} break;		#endif	}	#endif		#ifdef AQUEDUCT_SHELL	uint8_t len;	switch (type)	{		case DELUGE_PACKET_SUMMARY:			len = sizeof(deluge_foot_summary);			pkt->data[len] = port;			aqshell_send(AQSHELL_SUMMARY_SEND, pkt->data, len+1);			break;		case DELUGE_PACKET_PROFILE:			len = sizeof(deluge_foot_profile);			pkt->data[len] = port;			aqshell_send(AQSHELL_PROFILE_SEND, pkt->data, len+1);			break;		case DELUGE_PACKET_REQUEST:			len = sizeof(deluge_foot_request);			pkt->data[len] = port;			aqshell_send(AQSHELL_REQUEST_SEND, pkt->data, len+1);			break;		case DELUGE_PACKET_DATA:			len = sizeof(deluge_foot_data);			pkt->data[DELUGE_PACKET_SIZE+len] = port;			aqshell_send(AQSHELL_DATA_SEND, &pkt->data[DELUGE_PACKET_SIZE], len+1);			break;	}	#endif		return 0;}boolean deluge_recv(comBuf *pkt, uint8_t **footer, uint8_t port){	if (suspended) {		//dropped++;		return 0;	}	//printf("%d\n", __LINE__);	uint16_t sender = *(uint16_t*)&pkt->data[pkt->size - 3];	#ifdef DELUGE_FORCE_MULTIHOP	uint16_t me = mos_node_id_get();	if (sender != me+1 && sender != me-1) return 0;	#endif	//printf("%d\n", __LINE__);		// Grab a read lock on the application list	rwlock_rdlock(&applist_lock);	mos_led_toggle(2);	// Quickly check the last application we used, it's most likely to be	// the one using this port	deluge_app* app = last_app;	//if (deluge_portmap[app->index] != port)	//{		// Find Deluge entry for this port		uint8_t appid;		uint8_t i;		for (i=0; i<DELUGE_INSTANCE_COUNT; i++) {			appid = (next_recv_inst + i) % DELUGE_INSTANCE_COUNT;			if (deluge_portmap[appid] == port)				break;		}	//printf("%d\n", __LINE__);		if (i == DELUGE_INSTANCE_COUNT) {			rwlock_unlock(&applist_lock);			return 0;		}	//printf("%d\n", __LINE__);			// See if the Deluge instance is already loaded				while (!table[appid].app) 		{			// Unlock the read lock and grab the write lock			rwlock_unlock(&applist_lock);			rwlock_wrlock(&applist_lock);			// Load the Deluge instance			loadApp(appid);			// Unlock the write lock and grab the read lock			rwlock_unlock(&applist_lock);			rwlock_rdlock(&applist_lock);			// Between the time we released the write lock and when we got the			// read lock, someone else could have unloaded our instance,			// so we loop and check that it's still loaded		}		last_app = app = table[appid].app;		//printf("recv %C\n", appid);		next_recv_inst = (appid + 1) % DELUGE_INSTANCE_COUNT;	//}	//printf("%d\n", __LINE__);		uint8_t type = pkt->data[pkt->size - 1];	#ifdef DELUGE_KEEP_STATS	if (deluge_recordstats && type<5 && (type != DELUGE_PACKET_REQUEST ||		(type==DELUGE_PACKET_REQUEST && 		((deluge_foot_request*)pkt->data)->to == mos_node_id_get())))		packet_counts[sender<DELUGE_STATS_COUNT-1?sender:DELUGE_STATS_COUNT-1][type-1]++;	#endif	//printf("%d\n", __LINE__);		#ifdef DELUGE_PRINT_PACKETS	printf_P(sPktPortType, port, sender, type);	#endif	//printf("%d\n", __LINE__);		switch (type)	{		case DELUGE_PACKET_SUMMARY: {	//printf("%d\n", __LINE__);			deluge_foot_summary* summary = (deluge_foot_summary*)pkt->data;			#ifdef DELUGE_PRINT_PACKETS			#ifdef DELUGE_SYMMETRIC_LINKS			#if DELUGE_NEIGHBOR_COUNT != 5			#error This code needs to be updated			#endif			printf_P(sRecvNList,				summary->neighbors[0], summary->neighbors[1], 				summary->neighbors[2], summary->neighbors[3], 				summary->neighbors[4]);			#endif			printf_P(sRecvSumm, summary->version,				summary->highPage, summary->dtb);			#endif			aqshell_send(AQSHELL_SUMMARY, pkt->data, sizeof(deluge_foot_summary)+1);			handleSummary(app, summary);		} break;		case DELUGE_PACKET_PROFILE: {	//printf("%d\n", __LINE__);			deluge_foot_profile* profile = (deluge_foot_profile*)pkt->data;			#ifdef DELUGE_PRINT_PACKETS			printf_P(sRecvProf, profile->codeSize, profile->crc, 				profile->version, profile->goalPage);			#endif			aqshell_send(AQSHELL_PROFILE, pkt->data, sizeof(deluge_foot_profile)+1);			handleProfile(app, profile);		} break;		case DELUGE_PACKET_REQUEST: {	//printf("%d\n", __LINE__);			deluge_foot_request* request = (deluge_foot_request*)pkt->data;			#ifdef DELUGE_PRINT_PACKETS			printf_P(sRecvReq, request->packets[2], 				request->packets[1], request->packets[0], request->to, 				request->version, request->page, request->rateChange);			#endif			aqshell_send(AQSHELL_REQUEST, pkt->data, sizeof(deluge_foot_request)+1);			handleRequest(app, request);		} break;		case DELUGE_PACKET_DATA: {	//printf("%d\n", __LINE__);			deluge_foot_data* data = (deluge_foot_data*)&pkt->data[DELUGE_PACKET_SIZE];			#ifdef DELUGE_PRINT_PACKETS			printf_P(sRecvData,				data->version, data->page, data->packet);			#endif			aqshell_send(AQSHELL_DATA, (uint8_t*)data, sizeof(deluge_foot_data)+1);			handleData(app, data, pkt->data);		} break;		#ifdef DELUGE_COMMANDER		case DELUGE_PACKET_COMMAND:	//printf("%d\n", __LINE__);			handleCommand(app, pkt, port);			break;		#endif	}	rwlock_unlock(&applist_lock);	return 0;}int8_t deluge_ioctl(uint8_t request, va_list args){	// TODO maybe this should be the way other applications control Deluge	// and adjust its settings	return -1;}/* Public interface functions: */void deluge_suspend(){	mos_mutex_lock(&suspend_lock);	suspended = 1;	//dropped = 0;	mos_mutex_unlock(&suspend_lock);	//mos_sem_post(&dispatch_sem);	// Give dispatch thread a chance to finish what it's doing	mos_thread_sleep(250);}void deluge_resume(){	// May need to reopen image file for home application	loadApp(0);		mos_mutex_lock(&suspend_lock);	suspended = 0;	mos_cond_broadcast(&suspend_cond);	mos_mutex_unlock(&suspend_lock);}int8_t deluge_init(){	aqshell_init();	#ifdef DELUGE_PRINT_EVENT	printf_P(sInitDeluge);	printf_P(sDisplayTime);		// display time	#endif	aqshell_send(AQSHELL_START, NULL, 0);		mos_sem_init(&dispatch_sem, 0);	mos_cond_init(&suspend_cond);	mos_mutex_init(&suspend_lock);	rwlock_init(&applist_lock);	suspended = 0;	// Load stats that were saved before rebooting	#ifdef DELUGE_KEEP_STATS	deluge_recordstats = 0;	memset(packet_counts, 0, sizeof(packet_counts));	//dev_ioctl(DEV_AVR_EEPROM, DEV_LOCK);	//dev_ioctl(DEV_AVR_EEPROM, DEV_SEEK, DELUGE_STATS_ADDR);	//dev_read(DEV_AVR_EEPROM, (uint8_t*)packet_counts, sizeof(packet_counts));	//dev_ioctl(DEV_AVR_EEPROM, DEV_UNLOCK);	#endif	// Load port map	dev_ioctl(DEV_AVR_EEPROM, DEV_LOCK);	dev_ioctl (DEV_AVR_EEPROM, DEV_SEEK, DELUGE_DIRECTORY_ADDR);	dev_read (DEV_AVR_EEPROM, deluge_portmap, sizeof (deluge_portmap));	dev_ioctl(DEV_AVR_EEPROM, DEV_UNLOCK);	// Initialize table of applications	uint8_t i;	for (i=0; i<DELUGE_INSTANCE_COUNT; i++) {		table[i].app = NULL;		//mos_sem_init(&table[i].app_sem, 0);		table[i].copyState = 0;		table[i].nextState = DELUGE_STATE_IGNORE;		table[i].alarm.func = (void(*)(void*))deluge_wakeup;		table[i].alarm.data = &table[i];		table[i].roundT = DELUGE_T_L;	}	deluge_app_staticinit();	// Initialized table of loaded Deluge instances	for (i=0; i<N_LOADED; i++) {		apps[i].index = -1;	}	next_app_idx = 0;	next_disp_inst = 0;	next_recv_inst = 0;	// Go ahead and load the home Deluge instance	last_app = loadApp(0);	net_proto_register(DELUGE_PROTO_ID, deluge_send, deluge_recv, deluge_ioctl);	mos_thread_new_havestack(dispatchThread, 192, deluge_stack, PRIORITY_NORMAL);		return 0;}#endif

⌨️ 快捷键说明

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