tag 标签: 链路层协议

相关博文
  • 热度 19
    2013-8-17 11:36
    1205 次阅读|
    0 个评论
    本贴讨论代码实现架构。 1、接收侧 先说接收侧,相对发送侧简单一些。 接收消息的机制一般就分轮询(polling)和回调(callback)(或者叫事件机制(event)或中断方式(interrupt))两种方式。轮询就是定期去查看是否有消息到达,有就处理;回调就是预先设置一个回调函数,当消息到达时(事件发生)由中断服务程序(或消息调度机制)调用该回调函数。这两者各有优缺点,视具体应用需要来选择。 一般来说消息的到达是随机的(如果消息是有规律的则更适合采用轮询方式),主程序并不知道什么时候应该执行消息处理程序,因此要么定期查看,要么先设置回调函数,等待被调用。 当应用对消息处理的实时性(收到消息到开始处理之间的时间差)要求较高时,建议采用回调方式。 modRf链路层采用回调机制。先通过modRfSetRxCallback()设置回调函数,目前只允许设一个。(在Java等面向对象的高级语言中,回调函数相当于Listener类,设置回调函数相当于addListener()操作)。 当消息到达,芯片硬件产生中断,执行中服程序modRfRxFrmDoneIsr()。 1)从RF FIFO中读入分组, 2a)如果是ACK分组,判断是否正确的ACK(ACK分组本身有没有出错,ACK分组内的消息序号是否本节点正在发送的消息的序号),如果是则设置ACK收到标志;(注:802.15.4规范中的ACK分组格式中没有srcId和destId,所以如果不巧别人发的ACK中的序号和你的相同,会产生误操作) 2b)对消息分组,判断CRC校验是否正确,判断目的地址是否本节点地址或广播地址,然后将消息内容、长度及RSSI值作为输入参数传给用户提供的回调函数。 目前的协议实现中没有支持命令分组。   2、发送侧 发送消息的函数可以分为阻塞型和非阻塞型两种,阻塞型是等到发送动作有结果(可能成功可能失败)时才返回,非阻塞型是将消息加入缓冲区就返回(假如缓冲区满会返回失败)。(又,接收侧若采用轮询方式时,接收消息的函数也可以分为阻塞型和非阻塞型两种,阻塞型是等到有数据到达才返回(比如socket的read()函数),非阻塞型是没数据时返回0) modRfSendPkt()是阻塞型的函数实现。因此不需要考虑该函数被调用时,射频是否正在发送消息的问题。 (1)不需要消息确认 不需要消息确认时,实现很简单。 1) 构造分组,将分组数据写入FIFO; 2) 执行发送:   -- 判断信道是否空闲,如果10ms内信道都不空闲,则返回失败;   -- 通知硬件发送消息(ISTXON),等待发送成功标志,如果10ms内标志没有设置,则返回失败;( 注:这个10ms设得太长了,下来要改小 ) (2)需要消息确认 1) 构造分组,将分组数据写入FIFO; 2) 重复以下动作一定次数(3次),如果仍不成功,则返回失败:   -- 执行发送;(内容同上(不需要ACK的2)))   -- 如果发送成功,则在3ms内等待ACK消息,如果收到则返回成功;如果未收到则延时5ms再次尝试;   -- 如果发送不成功,则延时100us再次尝试;   3、讨论 这个实现机制还是有不少问题的。比如: (1)信道空闲后没有随机等待再次判断,会造成多个同时等信道空闲的节点同时发消息。 (2)需要ACK时,假如误码率高,发送函数的阻塞时间会较长。 (3)发送函数不能在消息接收回调函数里面调用,因为回调函数在中断服务程序的线程里。  
  • 热度 11
    2013-8-16 21:32
    1228 次阅读|
    0 个评论
    链路层协议实现两个节点之间的单跳通信。 从最简单的要求说起,链路层协议向上层提供的API接口要实现的最基本功能是发送消息和接收消息。 A节点发送的消息B节点要能收得到,它们需要工作在相同的信道,因此接口中要能够设置信道参数。 要区分A节点发送的消息是给B的还是C的,需要给每个节点分配一个节点地址,同时将目的地址附在消息中;同样的,为了让B知道收到的消息是来自A还是C,需要将源地址附在消息中。 所以,最基本的接口的参数包括,在初始化时提供工作信道和节点地址(modRfInit()),在发送时除了提供消息内容外,还需要提供目的地址(modRfSendPkt())。 从完成的功能上看,modRfSendPkt()实现哪些动作呢?我们可以这样问,当这个函数返回时: 1)消息是否已经从节点硬件发送出去了? 2)消息是否已经被目的节点接收了? 3)消息是否无误地被目的节点接收了? 同样地,对于收到消息的处理接口(modRfRxCallbackFunction()),我们可以问一下以下的问题。当该接口被调用时: 1)收到的消息都是给本节点的吗? 2)收到的消息是正确的吗? 3)收到的消息会有重复吗? 这些问题涉及到链路层通信机制中的检错、确认、重发、过滤、纠错等机制,在不同的应用场景中可以采用不同的机制。   1、错误处理 面对具体应用,问一问:需要由链路层负责保证分组正确到达接收端吗?如果不需要,则链路层代码不需要实现检错、确认、重发及纠错机制。 如果需要,则考虑采用自动重传(ARQ)还是前向纠错(FEC)机制,后者比前者实现复杂,但效率高。 CC2530硬件上支持部分ARQ机制,包括发送时自动添加CRC校验字节,接收时进行CRC校验,接收端可以由硬件自动回送确认消息等。 ARQ机制包括如下内容: 发送侧:在发送消息时添加CRC校验字节,分组Header中的要求确认消息标志为真;消息发送出去后,启动定时; 接收侧:收到消息后,对消息内容进行CRC校验,根据校验结果回送确认消息给发送节点; 发送侧:收到确认消息,如果表示消息出错,则重发原消息;否则返回成功。 发送侧:在定时器Timeout时还没有收到确认消息(包括原来发送的消息没有到达接收节点或者接收节点回送的确认消息没有到达发送节点),对原消息进行重发; 发送侧:重发一定次数仍然失败,则返回失败。 由此可见,采用ARQ机制,接收方有可能收到多个相同的消息。   2、消息过滤机制 消息过滤机制包括几种:1)错误消息过滤;2)目标地址过滤;3)重复消息过滤; CC2530硬件支持前两种,分别有寄存器标志位决定CRC出错的消息、目标地址和芯片网络地址不一致的消息是否传递给应用。 如果需要支持重复消息过滤,则帧结构中需要有序号字段区分不同的消息。   3、MAC媒体接入机制 在发送侧,是上层应用一调用发送函数就把消息发送出去,还是需要判断信道是否空闲;是信道一空闲就可以发送,还是根据某种规则决定发送时间。这些与MAC机制中的接入规则及算法有关。 CC2530提供与CSMA相关的硬件支持,包括信道空闲判断(CCA)、随机等待和自动回退等。   4、发送消息缓冲 在前一消息未发送出去时,是否再次调用发送函数发送另一消息? 在中断服务程序中是否可以调用消息发送函数? 消息缓冲机制也与MAC接入控制机制有关。 如果提供消息缓冲,就需要考虑:缓冲区大小多少,发送成功或失败的结果如何通知应用层,有没有时间发送限制,有没有优先级等等问题。   目前,通信协议栈中的链路层协议实现方式是这样的。 1、错误处理机制 在modRfSendPkt()中提供一个入参供应用决定是否需要确认。 如果需要,则采用ARQ机制,最多重发3次。 2、消息过滤机制 CRC错误的消息硬件不送上来;不采用硬件地址过滤而是在链路层代码中进行比较及过滤。 不支持重复消息过滤,所以如果收到重复消息,都会送给应用。 3、MAC机制 基于CSMA简化,如果信道空闲则立即发送;否则延时一小段时间再判断;重复3次都发不出去,则返回错误。 4、发送消息缓冲机制 不提供。modRfSendPkt()函数是阻塞型函数,函数返回时,要么成功(需要确认时,收到成功确认;不需要确认时,完成发送),要么失败(没收到确认或者没发送出去)。 5、不能在中断服务程序中调用消息发送函数。