bombilla.nc
来自「用于传感器网络的节点操作系统 TinyOS 结构设计非常有意思」· NC 代码 · 共 1,584 行 · 第 1/4 页
NC
1,584 行
capsules[BOMB_CAPSULE_CLOCK_INDEX].capsule.version = 0; analyzeCapsuleVars(capsules, BOMB_CAPSULE_CLOCK_INDEX); analyzeCapsuleVars(capsules, BOMB_CAPSULE_SEND_INDEX); analyzeCapsuleVars(capsules, BOMB_CAPSULE_RECV_INDEX); res1 = call StdControlPhoto.start(); res2 = call StdControlTemp.start(); /* EEPROM functionality is currently not implemented. */ // call StdControlEEPROM.start(); res3 = call StdControlNetwork.start(); call ClockTimer.start(TIMER_REPEAT, 1024); call PropagateTimer.start(TIMER_REPEAT, BOMB_PROPAGATE_TIMER); return rcombine3(res1, res2, res3); } command result_t StdControl.stop() { result_t res1, res2, res3; res1 = call StdControlPhoto.stop(); res2 = call StdControlTemp.stop(); /* EEPROM functionality is currently not implemented. */ // call StdControlEEPROM.stop(); res3 = call StdControlNetwork.stop(); return rcombine3(res1, res2, res3); } command result_t BombillaError.error(BombillaContext* context, uint8_t cause) { inErrorState = TRUE; dbg(DBG_ERROR|DBG_USR1, "VM: Entering ERROR state. Context: %i, cause %i\n", (int)context->which, (int)cause); call Leds.redOn(); call Leds.greenOn(); call Leds.yellowOn(); errorContext = context; errorMsg.context = context->which; errorMsg.reason = cause; errorMsg.capsule = context->capsule->capsule.type; errorMsg.instruction = context->pc - 1; return SUCCESS; } task void clockErrorTask() { dbg(DBG_USR1|DBG_ERROR, "VM: ERROR\n"); call Leds.redToggle(); call Leds.greenToggle(); call Leds.yellowToggle(); nmemcpy(errorContext->msg.data, &errorMsg, sizeof(BombillaErrorMsg)); if (errorFlipFlop) { call SendError.send(TOS_UART_ADDR, sizeof(BombillaErrorMsg), (TOS_MsgPtr)&errorContext->msg); } else { call SendError.send(TOS_BCAST_ADDR, sizeof(BombillaErrorMsg), (TOS_MsgPtr)&errorContext->msg); } errorFlipFlop = !errorFlipFlop; } task void clockEventTask() { if (clockContext.state == BOMB_STATE_HALT) { initializeContext(&clockContext); resumeContext(&clockContext, &clockContext); } else { uint8_t code = 0; if (clockContext.state == BOMB_STATE_SENSE_WAIT) { code = 1; } else if (clockContext.state == BOMB_STATE_LOCK_WAIT) { code = 2; } else if (clockContext.state == BOMB_STATE_SEND_WAIT) { code = 3; } //if (code & 0x1) {call Leds.redToggle();} //if (code & 0x2) {call Leds.greenToggle();} } } event result_t ClockTimer.fired() { dbg(DBG_USR1, "VM: Clock event fired.\n"); if (inErrorState) { post clockErrorTask(); } else { post clockEventTask(); } return SUCCESS; } void analyzeCapsuleVars(BombillaCapsuleBuffer* buffers, uint8_t which) { int i; BombillaCapsuleBuffer* buf = &(buffers[(int)which]); buf->usedVars = 0; for (i = 0; i < BOMB_PGMSIZE; i++) { if (call Instruction.isVClass(buf->capsule.code[i])) { uint8_t arg = (buf->capsule.code[i]) & 0xf; buf->usedVars |= (1 << arg); } } } void analyzeCapsuleCalls(BombillaCapsuleBuffer* buffers, uint8_t which) { int i; BombillaCapsuleBuffer* buf = &(buffers[(int)which]); for (i = 0; i < BOMB_PGMSIZE; i++) { if ((buf->capsule.code[i] & 0xfc) == OPcall0) { uint8_t arg = (buf->capsule.code[i]) & 0x3; buf->usedVars |= buffers[(int)arg].usedVars; } } } void executeSense(BombillaContext* context, uint8_t type) { BombillaQueue* queue = &senseWaitQueue; cli(); if (sensingContext != NULL) { call Stacks.pushValue(context, type); context->state = BOMB_STATE_SENSE_WAIT; call Queue.enqueue(context, queue, context); sei(); } else { sei(); switch(type) { // Be sure to handle sensingContext/senseQueue properly // so that sense done events don't traverse a null pointer. case BOMB_DATA_PHOTO: dbg(DBG_USR1, "VM (%i): Sensing photo.\n", (int)context->which); if (call PhotoADC.getData() == SUCCESS) { sensingContext = context; context->state = BOMB_STATE_SENSE; } else { // re-issue the instruction call Stacks.pushValue(context, type); context->pc--; } break; case BOMB_DATA_TEMP: dbg(DBG_USR1, "VM (%i): Sensing temperature.\n", (int)context->which); if (call TempADC.getData() == SUCCESS) { sensingContext = context; context->state = BOMB_STATE_SENSE; } else { // re-issue the instruction call Stacks.pushValue(context, type); context->pc--; } break; default: dbg(DBG_ERROR, "VM (%i): Sensor type %i not supported yet.\n", (int)context->which, (int)type); } } } void executeAdd(BombillaContext* context, BombillaStackVariable* arg1, BombillaStackVariable* arg2) { if ((arg1->type == BOMB_TYPE_VALUE) && (arg2->type == BOMB_TYPE_VALUE)) { dbg(DBG_USR1, "VM (%i): Executing add of two values: %i + %i == %i\n", (int)context->which, (int)arg1->value.var, (int)arg2->value.var, (int)arg1->value.var + arg2->value.var); call Stacks.pushValue(context, arg1->value.var + arg2->value.var); } else if (arg1->type == BOMB_TYPE_BUFFER) { if (arg2->type != BOMB_TYPE_BUFFER) { dbg(DBG_USR1, "VM (%i): Prepend value onto buffer.\n", (int)context->which); call Buffer.prepend(context, arg1->buffer.var, arg2); } else { dbg(DBG_USR1, "VM (%i): Concatenating buffers.\n", (int)context->which); call Buffer.concatenate(context, arg2->buffer.var, arg1->buffer.var); } call Stacks.pushBuffer(context, arg1->buffer.var); } else if (arg2->type == BOMB_TYPE_BUFFER) { call Buffer.append(context, arg2->buffer.var, arg1); call Stacks.pushBuffer(context, arg2 ->buffer.var); } else { call BombillaError.error(context, BOMB_ERROR_TYPE_CHECK); dbg(DBG_USR1, "VM (%i): Invalid add.\n", (int)context->which); } } void executeSendr(BombillaContext* context, BombillaStackVariable* arg) { if ((context->which != BOMB_CAPSULE_SEND) || (!checkTypes(context, arg, BOMB_VAR_V))) { context->state = BOMB_STATE_HALT; return; } else { uint16_t addr = arg->value.var; uint8_t size; arg = call Stacks.popOperand(context); if (!checkTypes(context, arg, BOMB_VAR_B)) {return;} size = arg->buffer.var->size; size += sizeof(arg->buffer.var->type); size += sizeof(arg->buffer.var->size); nmemcpy(context->msg.data, arg->buffer.var, size); if (call SendPacket.send(addr, size, &context->msg)) { sendingContext = context; context->state = BOMB_STATE_SENDING; } else { // Back up context so on being resumed it will try to send again context->pc--; call Stacks.pushOperand(context, arg); call Stacks.pushValue(context, addr); call Queue.enqueue(context, &sendWaitQueue, context); context->state = BOMB_STATE_SEND_WAIT; } } call Synch.releaseLocks(context, context, locks); yieldContext(context); return; } bool areEqual(BombillaStackVariable* arg1, BombillaStackVariable* arg2) { if (arg1->type != arg2->type) {return FALSE;} if (arg1->type == BOMB_TYPE_SENSE) { return ((arg1->sense.type == arg2->sense.type) && (arg1->sense.var == arg2->sense.var)); } else if (arg1->type == BOMB_TYPE_VALUE) { return (arg1->value.var == arg2->value.var); } else if (arg1->type == BOMB_TYPE_BUFFER) { return (arg1->buffer.var == arg2->buffer.var); } else { return FALSE; } } bool typeEqual(BombillaStackVariable* arg1, BombillaStackVariable* arg2) { return (arg1->type == arg2->type); } void ledOP(uint16_t arg) { uint8_t op = (arg >> 3) & 3; uint8_t led = arg & 7; switch (op) { case 0: /* set */ if (led & 1) call Leds.redOn(); else call Leds.redOff(); if (led & 2) call Leds.greenOn(); else call Leds.greenOff(); if (led & 4) call Leds.yellowOn(); else call Leds.yellowOff(); break; case 1: /* OFF 0 bits */ if (!(led & 1)) call Leds.redOff(); if (!(led & 2)) call Leds.greenOff(); if (!(led & 4)) call Leds.yellowOff(); break; case 2: /* on 1 bits */ if (led & 1) call Leds.redOn(); if (led & 2) call Leds.greenOn(); if (led & 4) call Leds.yellowOn(); break; case 3: /* TOGGLE 1 bits */ if (led & 1) call Leds.redToggle(); if (led & 2) call Leds.greenToggle(); if (led & 4) call Leds.yellowToggle(); break; default: dbg(DBG_ERROR, ("VM: LED command had unknown operations.\n")); } } result_t forwardCapsule(uint8_t which) { // Capsule does nothing ... don't forward it if ((capsules[which].capsule.code[0] == OPhalt) || ((capsules[which].capsule.options & BOMB_OPTION_FORWARD) == 0)) { return SUCCESS; } else { nmemcpy(forwardingBuffer.data, &(capsules[which].capsule), sizeof(BombillaCapsule)); dbg(DBG_USR3, "VM: Forwarding capsule %i.\n"); return call SendCapsule.send(TOS_BCAST_ADDR, sizeof(BombillaCapsule), &forwardingBuffer); } } /** * Decides whether to forward a capsule, forwarding if necessary. * * Compute a random number. Take lower 7 bits (0-127). Measure * network activity; take 64 and subtract it; this gives a rough * estimate of the network business, with low numbers being busy. If * the random number is lower than the business number, forward a * capsule. * */ task void forwardCapsuleTask() { uint16_t activity = call networkActivity(); uint16_t randVal = call Random.rand(); if (!tryingToForward) { activity = BOMB_MAX_NET_ACTIVITY - activity; if (activity <= 0) {activity = 1;} if ((randVal & 0x7f) >= activity){return;} // Too busy -- don't forward // Which capsule? randVal = call Random.rand(); randVal %= BOMB_CAPSULE_NUM; forwardingCapsule = randVal; } if (forwardCapsule(forwardingCapsule) == SUCCESS) { tryingToForward = FALSE; } else { tryingToForward = TRUE; } } event result_t PropagateTimer.fired() { post forwardCapsuleTask(); return SUCCESS; } event result_t TimeoutTimer.fired() { return SUCCESS; } inline result_t senseReady(uint16_t datum) { BombillaContext* senser; BombillaQueue* queue = &senseWaitQueue; dbg(DBG_USR1, "VM: Sensor reading: %i\n", (int)datum); if (sensingContext != NULL) { // Resume the sensing context sensingContext->state = BOMB_STATE_RUN; resumeContext(sensingContext, sensingContext); call Stacks.pushReading(sensingContext, BOMB_DATA_PHOTO, datum); sensingContext = NULL; } if (!call Queue.empty(queue)) { senser = call Queue.dequeue(&clockContext, queue); if (senser->state != BOMB_STATE_SENSE_WAIT) { call BombillaError.error(senser, BOMB_ERROR_QUEUE_INVALID); } senser->state = BOMB_STATE_RUN; resumeContext(senser, senser); } return SUCCESS; } event result_t PhotoADC.dataReady(uint16_t datum) { return senseReady(datum); } event result_t TempADC.dataReady(uint16_t datum) { return senseReady(datum); } /* Acceleration sensor not supported yet event result_t AccelXADC.dataReady(uint16_t data) { return SUCCESS; } event result_t AccelYADC.dataReady(uint16_t data) { return SUCCESS; } */ event result_t SendCapsule.sendDone(TOS_MsgPtr msg, result_t success) { BombillaContext* sender = sendingContext; dbg(DBG_USR1, "VM: SendCapsule.sendDone event fired.\n"); if (sender == NULL) {return FAIL;} sendingContext = NULL; if (sender->state != BOMB_STATE_SENDING) { call BombillaError.error(sender, BOMB_ERROR_QUEUE_INVALID); return FAIL; } resumeContext(sender, sender); return SUCCESS; } event result_t SendPacket.sendDone(TOS_MsgPtr msg, result_t success) { BombillaContext* sender = sendingContext; dbg(DBG_USR1, "VM: SendPacket.sendDone event fired.\n"); if (sender == NULL) {return FAIL;} sendingContext = NULL; if (sender->state != BOMB_STATE_SENDING) { call BombillaError.error(sender, BOMB_ERROR_QUEUE_INVALID); return FAIL; } resumeContext(sender, sender); return SUCCESS; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?