Inter-Node Communication � General idea: � Sender: TinyOS Determine when Fill message Specify Pass buffer message buffer Network Communication buffer with data Recipients to OS can be reused Computer Network � Receiver: Programming OS obtains free OS Buffers Signal buffer to store incoming message application with Wenyuan Xu next message in a free buffer new message 1 2 TOS Active Messages TOS Active Messages (continue) � Message is “active” because it typedef struct TOS_Msg { contains the destination address, group ID, and type. // the following are transmitted uint16_t addr; � ‘group’: group IDs create a uint8_t type; virtual network uint8_t group; � an 8 bit value specified in uint8_t length; <tos>/apps/Makelocal int8_t data [TOSH_DATA_LENGTH ]; uint16_t crc; � The address is a 16-bit value specified by “make” // the following are not transmitted � – make install.<id> mica2 uint16_t strength; uint8_t ack; uint16_t time; � “length” specifies the size of the message . uint8_t sendSecurityMode; uint8_t receiveSecurityMode; � “crc” is the check sum } TOS_Msg; Preamble Sync Header (5) Payload (29) CRC (2) 3 4 Receiving a message Sending a message includes Int16Msg; includes Int16Msg; � Define the message � Define the message module ForwarderM { module ForwarderM { Message received format //interface declaration format //interface declaration } } � Define a unique � Define a unique implementation { implementation { active message active message event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr m) event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr m) number number { call Leds.yellowToggle(); { call Leds.yellowToggle(); � How does TOS � How does TOS call SendMsg.send(TOS_BCAST_ADDR, call SendMsg.send(TOS_BCAST_ADDR, know the AM know the AM sizeof(IntMsg), m); sizeof(IntMsg), m); number? number? destination return m; return m; } } length event result_t SendMsg.sendDone(TOS_MsgPtr msg, bool success) event result_t SendMsg.sendDone(TOS_MsgPtr msg, bool success) { call Leds.greenToggle(); { call Leds.greenToggle(); return success; return success; } } } } File: Int16Msg.h File: Int16Msg.h struct Int16Msg { struct Int16Msg { configuration Forwarder { } configuration Forwarder { } uint16_t val; uint16_t val; implementation implementation }; }; { … { … ForwarderM.SendMsg -> Comm.SendMsg[AM_INTMSG]; ForwarderM.SendMsg -> Comm.SendMsg[AM_INTMSG]; enum { enum { ForwarderM.ReceiveMsg -> Comm.ReceiveMsg[AM_INTMSG]; ForwarderM.ReceiveMsg -> Comm.ReceiveMsg[AM_INTMSG]; AM_INTMSG = 47 AM_INTMSG = 47 } } }; }; 5 6
Where exactly is the radio stuff? Spi bus interrupt handler � Connection between Chipcon CC1000 radio and the ATmega128 processor: SPI bus. � Spibus interrupt handler: SpiByteFifo.dataReady() Mica2 � SpiByteFifo.dataReady() will be called every 8 ticks. file:CC1000RadioIntM.nc StdControl async event result_t SpiByteFifo.dataReady(uint8_t data_in) { StdControl … CC1000RadioC switch (RadioState) { BareSendMsg case RX_STATE: {...} case DISABLED_STATE: {…} BareSendMsg ReceiveMsg case IDLE_STATE: {...} case PRETX_STATE: {...} case SYNC_STATE: {...} ReceiveMsg case RX_STATE: {...} return SUCCESS; } CC1000RadioIntM Preamble Sync Header (5) Payload (29) CRC (2) 7 8 Receiving a message (1) Receiving a message (2) SYNC_STATE � RX_STATE � IDLE_STATE � SYNC_STATE � � look for a SYNC_WORD (0x33cc). � Listen to the preamble, if the enough bytes of preamble are received, entering � Save the last received byte and current received byte SYCN_STATE � Use a bit shift compare to find the byte boundary for the sync byte � Retain the shift value and use it to collect all of the packet data file:CC1000RadioIntM.nc async event result_t SpiByteFifo.dataReady(uint8_t data_in) { SYNC_STATE � IDLE_STATE � … � didn't find the SYNC_WORD after a reasonable number of tries, so set the radio switch (RadioState) { state back to idle: … case IDLE_STATE: � RadioState = IDLE_STATE; { if (((data_in == (0xaa)) || (data_in == (0x55)))) { file:CC1000RadioIntM.nc PreambleCount++; async event result_t SpiByteFifo.dataReady(uint8_t data_in) { if (PreambleCount > CC1K_ValidPrecursor) { … PreambleCount = SOFCount = 0; switch (RadioState) { RxBitOffset = RxByteCnt = 0; case SYNC_STATE: … usRunningCRC = 0; { if ( find SYCN_WORD) { rxlength = MSG_DATA_SIZE-2; … RadioState = SYNC_STATE; RadioState = RX_STATE; } } else if ( too many preamble) { } … } … RadioState = IDLE_STATE; } } } … } Preamble Sync Header (5) Payload (29) CRC (2) Preamble Sync Header (5) Payload (29) CRC (2) 9 10 Receiving a message (3) Error Detection – CRC � RX_STATE � IDLE_STATE/SENDING_ACK � CRC – Cyclic Redundancy Check � Keep receiving bytes and calculate CRC until the end of the packet. � The end of the packet are specified by the length in the packet header � Polynomial codes or checksums � Pass the message to the application layer, no matter whether the message passed the CRC check file:CC1000RadioIntM.nc � Procedure: async event result_t SpiByteFifo.dataReady(uint8_t data_in) { … switch (RadioState) { 1. Let r be the degree of the code polynomial. Append r zero bits to … case RX_STATE: the end of the transmitted bit string. Call the entire bit string S(x) { …RxByteCnt++; if (RxByteCnt <= rxlength) { 2. Divide S(x) by the code polynomial using modulo 2 division. usRunningCRC = crcByte(usRunningCRC,Byte); if (RxByteCnt == HEADER_LENGTH_OFFSET) { 3. Subtract the remainder from S(x) using modulo 2 subtraction. rxlength = rxbufptr->length;} } else if (RxByteCnt == rxlength-CRCBYTE_OFFSET) { if (rxbufptr->crc == usRunningCRC) { rxbufptr->crc = 1; } else { � The result is the checksummed message rxbufptr->crc = 0; } … RadioState = IDLE_STATE; post PacketRcvd(); } … Preamble Header (5) Payload (29) CRC (2) Sync 11 12
Generating a CRC – example Decoding a CRC – example � Message : 1011 � Procedure � 1 * x 3 + 0 * x 2 + 1 * x + 1= x 3 + x + 1 1. Let n be the length of the checksummed message in bits � Code Polynomial : x 2 + 1 (101) 2. Divide the checksummed message by the code polynomial using modulo 2 division. If the remainder is zero, there is no error detected. Step 2: Modulo 2 divide Case 1: Case 2: Step 1: Compute S(x) Step 3: Modulo 2 subtract 1001 1000 Checksummed the remainder from S(x) 1001 message (n=6): 101 101101 101 101001 r = 2 101 101100 101 101 S(x) = 101100 101101 101 001 000 101100 001 000 000 - 01 000 010 000 101101 1011 010 000 000 000 101 001 Original message 100 101 000 101 00 01 01 Checksummed Message Remainder = 0 Remainder = 1 (No error detected) (Error detected) Remainder 13 14 CRC in TinyOS � Calculate the CRC byte by byte file: system/crc.h crc=0x0000; uint16_t crcByte(uint16_t crc, uint8_t b) while (more bytes) { { uint8_t i; crc=crc^b<<8; crc = crc ^ b << 8; calculate the high byte of crc i = 8; } do if (crc & 0x8000) � Code Polynomial: CRC-CCITT crc = crc << 1 ^ 0x1021; 0x1021 = 0001 0000 0010 0001 else crc = crc << 1; while (--i); x 16 + x 12 + x 5 + 1 return crc; } Example: 10… 10001 0000 0010 0001 10110110110110110110110110110100 10001000000100001 01111101100101111 00000000000000000 11111011001011111 … 15
Recommend
More recommend