📄 deluge_app.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"#ifdef ARCH_AVR#include "msched.h"#include "com.h"#include "node_id.h"#include "clock.h"#include "deluge_impl.h"#include "printf.h"#include "led.h"#include "boot.h"#include "net.h"#include "sem.h"#include "crc.h"#include "atmel-flash.h"#include "simple_fs.h"#include <stdlib.h>#include "deluge_msgs.h"#include "aqueduct_shell.h"/* Protocol state variables: */static comBuf spkt; // comBuf for sendingextern uint8_t deluge_portmap[DELUGE_INSTANCE_COUNT];extern deluge_entry table[DELUGE_INSTANCE_COUNT];#ifdef DELUGE_KEEP_STATSextern uint16_t packet_counts[DELUGE_STATS_COUNT][4];extern uint8_t deluge_recordstats;#endif/* Private functions: */#ifdef DELUGE_SYMMETRIC_LINKSstatic void checkNeighbor(deluge_app* app, uint16_t neighbor){ int8_t i; //uint8_t mask = 1; for (i=0; i<DELUGE_NEIGHBOR_COUNT; i++) { if (neighbor==app->neighbors[i]) { return; } //mask <<= 1; } i = app->nextNeighbor; app->neighbors[i] = neighbor; //mask = 1 << i; app->nextNeighbor = (i + 1) % DELUGE_NEIGHBOR_COUNT; // Our neighbor list changed, this could affect routing //app->detectedInconsistency = 1; //app->symdtbs[i] = 255;} static int8_t checkSymmetry(deluge_app* app, deluge_foot_summary* summary){ uint16_t id = mos_node_id_get(); uint8_t j; for (j=0; j<DELUGE_NEIGHBOR_COUNT; j++) { if (id==summary->neighbors[j]) { /*if (summary->version == app->dcb.version && (summary->highPage > app->dcb.highPage || (app->index != 0 && summary->highPage == app->dcb.highPage))) { app->symdtbs[i] = summary->dtb; }*/ //app->symmetric |= mask; return 1; } } //app->symmetric &= ~mask; // We're not in their list, send a summary //app->detectedInconsistency = 1; return 0;}static void clearSymmetry(deluge_app* app, uint16_t node){ uint8_t i; //uint8_t mask = 1; for (i=0; i<DELUGE_NEIGHBOR_COUNT; i++) { if (node==app->neighbors[i]) { app->neighbors[i] = 0xFFFF; //app->symdtbs[i] = 255; //app->symmetry &= ~mask; // Our neighbor list changed, this could affect routing //app->detectedInconsistency = 1; } //mask <<= 1; }}#elsestatic inline void checkNeighbor(deluge_app* app, uint16_t neighbor) {}#endif#if DELUGE_CACHE_PAGES > 1static int8_t cachedPageIndex(deluge_app* app, int8_t page){ int8_t i; for (i=0; i</*DELUGE_CACHE_PAGES*/app->cacheSize; i++) if (app->cache_map[i] == page) return i; return -1;}static void saveIncomingCachePage(deluge_app* app, int8_t page){ app->cache_map[app->incomingCachePage] = page; app->incomingCachePage = (app->incomingCachePage + 1) % /*DELUGE_CACHE_PAGES*/app->cacheSize;}#endifstatic void setTimeout(deluge_app* app, uint32_t ticks, uint8_t reason){ table[app->index].nextState = reason; mos_alarm_ticks(&table[app->index].alarm, ticks);}static inline void setRequestTimeout(deluge_app* app, uint8_t timeoutState){ #ifdef DELUGE_DTB_REQUEST_TIMEOUT uint32_t reqT = random() % DELUGE_T_R; if (app->dtb > 1) { //printf("#nPacketsRequested: %C\n", app->nPacketsRequested); reqT += app->dtb * (app->nPacketsRequested + DELUGE_OMEGA) * DELUGE_T_TX; } else reqT += DELUGE_OMEGA * DELUGE_T_TX; #else uint32_t reqT = DELUGE_OMEGA * DELUGE_T_TX + random() % DELUGE_T_R; #endif // this timeout will be reset as long as we keep getting data packets setTimeout(app, reqT, timeoutState);}static void clearTimeout(deluge_app* app){ mos_remove_alarm(&table[app->index].alarm);}void stateTransition(deluge_app* app, uint8_t newState){ mos_remove_alarm(&table[app->index].alarm); table[app->index].nextState = newState; table[app->index].copyState = 1; deluge_wakeup(&table[app->index]);}void deluge_saveState(deluge_app* app){ dev_ioctl(DEV_AVR_EEPROM, DEV_LOCK); dev_ioctl (DEV_AVR_EEPROM, DEV_SEEK, DELUGE_CONTROL_BLOCK_ADDR + app->index*DELUGE_CONTROL_BLOCK_SIZE); dev_write (DEV_AVR_EEPROM, (uint8_t *)&app->dcb, DELUGE_CONTROL_BLOCK_SIZE); dev_ioctl(DEV_AVR_EEPROM, DEV_UNLOCK);}static void loadState(deluge_app* app){ dev_ioctl(DEV_AVR_EEPROM, DEV_LOCK); dev_ioctl (DEV_AVR_EEPROM, DEV_SEEK, DELUGE_CONTROL_BLOCK_ADDR + app->index*DELUGE_CONTROL_BLOCK_SIZE); dev_read (DEV_AVR_EEPROM, (uint8_t *)&app->dcb, DELUGE_CONTROL_BLOCK_SIZE); dev_ioctl(DEV_AVR_EEPROM, DEV_UNLOCK);}static void saveBootCB(deluge_app* app, boot_control_block_t* cb){ dev_ioctl(DEV_AVR_EEPROM, DEV_LOCK); dev_ioctl (DEV_AVR_EEPROM, DEV_SEEK, CONTROL_BLOCK_ADDR); dev_write (DEV_AVR_EEPROM, (uint8_t *)cb, sizeof (boot_control_block_t)); dev_ioctl(DEV_AVR_EEPROM, DEV_UNLOCK);}static void loadBootCB(deluge_app* app, boot_control_block_t* cb){ dev_ioctl(DEV_AVR_EEPROM, DEV_LOCK); dev_ioctl (DEV_AVR_EEPROM, DEV_SEEK, CONTROL_BLOCK_ADDR); dev_read (DEV_AVR_EEPROM, (uint8_t *)cb, sizeof (boot_control_block_t)); dev_ioctl(DEV_AVR_EEPROM, DEV_UNLOCK);}static void moveToNextPage(deluge_app* app){ uint8_t index = app->dcb.incomingPage / 8; uint8_t mask = 1 << (app->dcb.incomingPage % 8); // clear bit for page we just finished app->dcb.pagesNeeded[index] &= ~mask; // find the next needed page do { app->dcb.incomingPage++; mask = mask << 1; if (mask == 0) { mask = 1; index++; } if (app->dcb.pagesNeeded[index] & mask) break; } while (app->dcb.incomingPage < app->dcb.goalPage); app->dcb.highPage = app->dcb.incomingPage;}static void findBadPages(deluge_app* app){ uint8_t page = 0; uint8_t index = 0; uint8_t mask = 1; uint16_t crc; dev_ioctl(DEV_AVR_EEPROM, DEV_LOCK); dev_ioctl (DEV_AVR_EEPROM, DEV_SEEK, DELUGE_PAGE_CRC_ADDR); for (; page<app->dcb.goalPage; page++) { dev_read (DEV_AVR_EEPROM, (uint8_t *)&crc, 2); if (crc != mos_file_crc(app->image_file, DELUGE_ADDR(page, 0), (uint32_t)DELUGE_PAGE_SIZE)) { app->dcb.pagesNeeded[index] |= mask; if (app->dcb.incomingPage == app->dcb.goalPage) app->dcb.incomingPage = page; } mask = mask << 1; if (mask == 0) { mask = 1; index++; } } dev_ioctl(DEV_AVR_EEPROM, DEV_UNLOCK); if (app->dcb.incomingPage == app->dcb.goalPage) // The program CRC failed, but we didn't find a page that failed. // This is extremely improbable, but just in case, we start all over: app->dcb.incomingPage = 0; app->dcb.highPage = app->dcb.incomingPage;}typedef void (*reboot_func)(void);void reboot(){ // Jump to bootloader #ifdef DELUGE_PRINT_EVENT printf_P(sReboot); printf_P(sDisplayTime); // display time #endif mos_disable_ints (); SPCR &= (1 << SPE); reboot_func rfunc = (reboot_func)0x1E000; rfunc();}void runReprogram(deluge_app* app){ boot_control_block_t bcb; loadBootCB(app, &bcb); bcb.start_addr = app->image_file->start; bcb.byte_count = app->image_file->length; bcb.reprogram = 1; saveBootCB(app, &bcb); /*#ifdef DELUGE_KEEP_STATS deluge_saveStats(); #endif*/ reboot();}static void doMaintain1(deluge_app* app){ //clearTimeout(app); // beginning of round if (app->detectedInconsistency) { // Rule M.2 table[app->index].roundT = DELUGE_T_L; } else { // Rule M.3 if (table[app->index].roundT < DELUGE_T_H) table[app->index].roundT *= 2; if (table[app->index].roundT > DELUGE_T_H) table[app->index].roundT = DELUGE_T_H; } mos_mutex_lock(&app->delugeLock); app->nSummaries = 0; app->nProfiles = 0; app->detectedInconsistency = 0; if (app->heardRequest) app->heardRequest--; if (app->heardData) app->heardData--; mos_mutex_unlock(&app->delugeLock); //app->state = DELUGE_STATE_MAINTAIN2; // wait until it's time to send our summary app->sumT = (table[app->index].roundT>>1) + random() % (table[app->index].roundT>>1); setTimeout(app, app->sumT, DELUGE_STATE_MAINTAIN2);}static void doMaintain2(deluge_app* app){ // Send a summary or a profile if (app->heardObsolete) { app->heardObsolete = 0; if (app->nProfiles < DELUGE_K) { // Rule M.4 deluge_foot_profile* profile = (deluge_foot_profile*)spkt.data; mos_mutex_lock(&app->delugeLock); profile->crc = app->dcb.programcrc; profile->codeSize = app->dcb.codeSize; profile->version = app->dcb.version; profile->goalPage = app->dcb.goalPage; mos_mutex_unlock(&app->delugeLock); profile->id = mos_node_id_get(); profile->type = DELUGE_PACKET_PROFILE; spkt.size = sizeof(deluge_foot_profile); net_send(&spkt, DELUGE_PROTO_ID, deluge_portmap[app->index], deluge_portmap[app->index]); } } else if (/*(app->index == 0 && */app->nSummaries < DELUGE_K/*) || (app->index != 0 && app->nSummaries < DELUGE_FORWARD_K)*/) { // Rule M.1 deluge_foot_summary* summary = (deluge_foot_summary*)spkt.data; mos_mutex_lock(&app->delugeLock); #ifdef DELUGE_SYMMETRIC_LINKS uint8_t i; for (i = 0; i<DELUGE_NEIGHBOR_COUNT; i++) summary->neighbors[i] = app->neighbors[i]; #endif summary->version = app->dcb.version; summary->highPage = app->dcb.highPage; #ifdef DELUGE_NO_FORWARD summary->dtb = 0; #else if (app->index == 0) { summary->dtb = 0; } else { summary->dtb = app->dtb; } #endif mos_mutex_unlock(&app->delugeLock); summary->id = mos_node_id_get(); summary->type = DELUGE_PACKET_SUMMARY; spkt.size = sizeof(deluge_foot_summary); net_send(&spkt, DELUGE_PROTO_ID, deluge_portmap[app->index], deluge_portmap[app->index]); } // wait till the round is over setTimeout(app, table[app->index].roundT - app->sumT, DELUGE_STATE_MAINTAIN);}static void doRx(deluge_app* app){ if (app->nRequests < DELUGE_LAMBDA) { // Rule R.1 deluge_foot_request* request = (deluge_foot_request*)spkt.data; mos_mutex_lock(&app->delugeLock); request->to = app->updaterNode; request->packets[0] = app->incomingPackets[0]; request->packets[1] = app->incomingPackets[1]; request->packets[2] = app->incomingPackets[2]; request->version = app->dcb.version; request->page = app->dcb.incomingPage; request->rateChange = app->nRequests-1; mos_mutex_unlock(&app->delugeLock); request->id = mos_node_id_get(); request->type = DELUGE_PACKET_REQUEST; spkt.size = sizeof(deluge_foot_request); net_send(&spkt, DELUGE_PROTO_ID, deluge_portmap[app->index], deluge_portmap[app->index]); app->nRequests++; } else { // TODO: check reception rate // Rule R.2 app->nRequests = 0; // Assume parent node is dead; assign the highest possible DTB; // we'll take any node with a lower DTB app->dtb = 0xFF; /*#ifdef DELUGE_LINK_QUALITY app->dtb_votes[app->updater_index] = 0; #endif*/ #ifdef DELUGE_SYMMETRIC_LINKS clearSymmetry(app, app->updaterNode); /*if (nextSymmetric(app) != 255) { app->nRequests = 0; stateTransition(app, DELUGE_STATE_RX); return; }*/ #endif stateTransition(app, DELUGE_STATE_MAINTAIN); return; } // wait a while before requesting again setRequestTimeout(app, DELUGE_STATE_RX);}static void doTx(deluge_app* app){ deluge_foot_data* foot = (deluge_foot_data*)&spkt.data[DELUGE_PACKET_SIZE]; mos_mutex_lock(&app->delugeLock); foot->version = app->dcb.version; #if DELUGE_CACHE_PAGES > 1 int8_t page = (app->index == 0)? app->outgoingPage : app->outgoingCachePage; #else int8_t page = app->outgoingPage; #endif foot->page = app->outgoingPage; foot->id = mos_node_id_get(); foot->type = DELUGE_PACKET_DATA; uint32_t crc_len = (app->outgoingPage == app->dcb.goalPage-1)? app->dcb.codeSize % (uint32_t)DELUGE_PAGE_SIZE : (uint32_t)DELUGE_PAGE_SIZE; uint16_t crc = mos_file_crc(app->image_file, DELUGE_ADDR(page, 0), crc_len); uint16_t txpackets[3] = { app->outgoingPackets[0], app->outgoingPackets[1], app->outgoingPackets[2] }; mos_mutex_unlock(&app->delugeLock); while (app->state == DELUGE_STATE_TX && (txpackets[0] != 0 || txpackets[1] != 0 || txpackets[2] != 0)) { uint8_t i, ih; uint16_t txmask = 1; uint8_t txidx = 0; uint32_t txaddr = DELUGE_ADDR(page, 0); for (i=0; i<DELUGE_PACKETS_PER_PAGE; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -