Upma Xmac 测试 03
一、分析内容:
这次主要分析:从上层的AMSender.send发送packet到Xmac将packet发送出去的流程。
二、
找到upma/apps/tests/TestXmac/SendingC$SendTimer$startPeriodic事件,代码如下:
event void SendTimer.fired() { if(sends) { call Leds.led2On(); call AMSender.send(AM_BROADCAST_ADDR, &packet, 2 * sizeof(uint8_t)); } }
call AMSender.send(AM_BROADCAST_ADDR, &packet, 2 * sizeof(uint8_t));的实现代码如下(/opt/tinyos-2.1.2/tos/system/AMQueueEntryP.nc文件):
command error_t AMSend.send(am_addr_t dest, message_t* msg, uint8_t len) { // printf("AMSend.send!!!\r\n"); call AMPacket.setDestination(msg, dest); //设置packet的目的地址 call AMPacket.setType(msg, amId); //设置packet的类型 return call Send.send(msg, len); //发送packet }
call Send.send(msg, len);的实现代码如下:(/opt/tinyos-2.1.2/tos/system/AMQueueImplP.nc)
/** * Accepts a properly formatted AM packet for later sending. * Assumes that someone has filled in the AM packet fields * (destination, AM type). * * @param msg - the message to send * @param len - the length of the payload * */ command error_t Send.send[uint8_t clientId](message_t* msg, uint8_t len) { //printf("Send.send !!! numClients=%d clientId=%d\r\n",numClients,clientId); if (clientId >= numClients) { //numClients=1, clientId=0,具体什么意义暂时不了解 return FAIL; } if (queue[clientId].msg != NULL) { return EBUSY; } dbg("AMQueue", "AMQueue: request to send from %hhu (%p): passed checks\n", clientId, msg); //printf("msg=%s !!!\r\n",msg); queue[clientId].msg = msg; call Packet.setPayloadLength(msg, len); //在头部加入CC2420_SIZE的大小的头 if (current >= numClients) { // queue empty //current=1 error_t err; am_id_t amId = call AMPacket.type(msg); //amId=240 new AMSenderC(240) am_addr_t dest = call AMPacket.destination(msg); //dest=-1,广播目的节点为-1? // printf("current=%d amId=%d,dest=%d!!!\r\n",current,amId,dest); dbg("AMQueue", "%s: request to send from %hhu (%p): queue empty\n", __FUNCTION__, clientId, msg); current = clientId; //printf("AMQueueImplP\r\n"); err = call AMSend.send[amId](dest, msg, len); if (err != SUCCESS) { //printf("underlying send failed\r\n"); dbg("AMQueue", "%s: underlying send failed.\n", __FUNCTION__); current = numClients; queue[clientId].msg = NULL; } //printf("SUCCESS\r\n"); return err; } else { dbg("AMQueue", "AMQueue: request to send from %hhu (%p): queue not empty\n", clientId, msg); } return SUCCESS; }
err = call AMSend.send[amId](dest, msg, len);由/opt/tinyos-2.1.2/wustl/upma/chips/cc2420/CC2420ActiveMessageP.nc实现,代码如下:
/***************** AMSend Commands ****************/ command error_t AMSend.send[am_id_t id](am_addr_t addr, message_t* msg, uint8_t len) { cc2420_header_t* header = call CC2420PacketBody.getHeader( msg ); if (len > call Packet.maxPayloadLength()) { return ESIZE; } header->type = id; //header->type就是new AMSenderC(240)这里的240 header->dest = addr; //header->dest=-1,由于是广播 header->destpan = call CC2420Config.getPanAddr(); //header->destpan header->src = call AMPacket.address(); //header->src packet源地址 // printf("header->type=%d,header->dest=%d,header->destpan=%d,header->src=%d,\r\n", // header->type,header->dest,header->destpan,header->src); //printf("CC2420ActiveMessageP\r\n"); if (call RadioResource.immediateRequest() == SUCCESS) { //立即请求radio资源,经调试,一般都会成功 error_t rc; signal SendNotifier.aboutToSend[id](addr, msg); //为什么AMQueueImplP没有实现该事件。 //printf("CC2420ActiveMessageP\r\n"); rc = call SubSend.send( msg, len ); if (rc != SUCCESS) { call RadioResource.release(); } return rc; } else { pending_length = len; pending_message = msg; return call RadioResource.request(); } }
rc = call SubSend.send( msg, len );由/opt/tinyos-2.1.2/tos/chips/cc2420/lowpan/ CC2420TinyosNetworkP.nc实现,源码如下:
command error_t ActiveSend.send(message_t* msg, uint8_t len) { //printf("CC2420TinyosNetworkP\r\n"); call CC2420Packet.setNetwork(msg, TINYOS_6LOWPAN_NETWORK_ID); m_busy_client = CLIENT_AM; return call SubSend.send(msg, len); }
call SubSend.send(msg, len); 由/opt/tinyos-2.1.2/tos/chips/cc2420/unique/UniqueSendP.nc实现,源码如下:
/***************** Send Commands ****************/ /** * Each call to this send command gives the message a single * DSN that does not change for every copy of the message * sent out. For messages that are not acknowledged, such as * a broadcast address message, the receiving end does not * signal receive() more than once for that message. */ command error_t Send.send(message_t *msg, uint8_t len) { error_t error; //printf("UniqueSendP Send.send\r\n"); if(call State.requestState(S_SENDING) == SUCCESS) { (call CC2420PacketBody.getHeader(msg))->dsn = localSendId++; if((error = call SubSend.send(msg, len)) != SUCCESS) { call State.toIdle(); } return error; } return EBUSY; }
error = call SubSend.send(msg, len)的由/opt/tinyos-2.1.2/wustl/upma/system/AsyncSendAdapterP.nc实现,源码如下:
command error_t Send.send(message_t * msg, uint8_t len) { printf("AsyncSendAdapterP Send.send\r\n"); return call AsyncSend.send(msg, len); }
call AsyncSend.send(msg, len)由/opt/tinyos-2.1.2/wustl/upma/lib/macs/xmac/XmacSenderP.nc实现,终于快到目的地了,源码如下:
async command error_t Send.send(message_t * msg, uint8_t len) { //printf("XmacSenderP Send.send\r\n"); if(call SendState.getState() == S_STOPPED) return EOFF; // Make sure that the radio isn't off // Try to move to the preamble state if(call SendState.requestState(S_PREAMBLE) == SUCCESS) { call FixedSleepLplListener.cancelTimeout(); atomic { msg_ = msg; len_ = len; } post doStart(); return SUCCESS; // Save the parameters and start the radio } return FAIL; }
总结:本想着一步一步深入了解每个步骤的内容,花了不少时间,但是还是想不通每行代码的意义,所以直接跳到XmacSenderP的实现,这里必须一步一步分析。