contiki的rime协议分析-abc

前言

        一直在关注contiki,特别是对里面的网络部分特别感兴趣。这里要提及2个人:

1,Jelline大神,帖子比较详细介绍了contiki的资料,入门是够了。

2,原同事,他的帖子对contiki的一些app应用以及移植也介绍比较详细,对于网络的应用和IOT(物联网)讲的比较多。

大家都可以去他们的帖子参考学习下。我这里就会记录一些我对rime学习的一些心得。

rime协议学习

在此之前,把jelline关于rime介绍的帖子里面的资料都详细看了一边,知道了一些大概的概念,然后在cooja上仿真了example_abc.c的例子。从abc.c的源码开始往下层分析。

abc模块

abc模块实现了一种匿名广播功能,里面的函数都类似与socket套接字的方式定义的,我们这里分析一下abc的结构体:
/**
 * \brief     Callback structure for abc
 *
 */
struct abc_callbacks {
  /** Called when a packet has been received by the abc module. */
  void (* recv)(struct abc_conn *ptr);
  void (* sent)(struct abc_conn *ptr, int status, int num_tx);
};

struct abc_conn {
  struct channel channel;
  const struct abc_callbacks *u;
};
我们可以看到,abc_conn结构体包含了2个变量。
一个指针u,指针指向的abc_callbacks这个结构体里面包括了发送、接收2种回调函数。这2个回调函数都通过钩子函数的形式来实现。
通过下面这个函数,我们可以看到一些具体的实现:
void abc_open(struct abc_conn *c, uint16_t channelno, const struct abc_callbacks *callbacks)
另外还有一个变量channel,这个接着往下看。

channel模块

首先我们看一下channel这个结构体的定义:
struct channel {
    struct channel *next;
    uint16_t channelno;
    const struct packetbuf_attrlist *attrlist;
    uint8_t hdrsize;
};
next   指向channel结构体的指针
channelno    应该定义了信道,资料上显示从128开始(0-127是被系统占用的)
attrlist  指向packetbuf_attrlist结构体的指针
hdrsize   头长度
这里除了packetbuf_attrlist这个结构体暂时还不清楚,其他应该都可以理解了。
然后channel模块就5个函数:
struct channel *channel_lookup(uint16_t channelno); // 从channel_list链表里面查找信道为channelno的channel

void channel_set_attributes(uint16_t channelno,
                            const struct packetbuf_attrlist attrlist[]); //从channel_list链表里查找信道为channelno的channel,然后修改它的属性

void channel_open(struct channel *c, uint16_t channelno);  //指定c的信道,添加入channel_list链表里

void channel_close(struct channel *c);   // 关闭指定的channel,从channel_list链表里移除

void channel_init(void);  //初始化channel_list的链表
我们从channel_set_attributes()这个函数往下走,进入到chameleon模块。

chameleon模块

chamelon模块做的工作是把原始数据进行了封装,因为很多数据段都是以属性的形式存在的,存在与databuf里,然后通过包头处理,把这些属性填充到databuf里面。
当然这中间调用了很多压缩与解压缩的工作。我们可以看一下它的结构体:
struct chameleon_module {
  struct channel *(* input)(void);
  int (* output)(struct channel *);
  int (* hdrsize)(const struct packetbuf_attrlist *);
};
我们可以看到,这个结构体定义了3种接口,它的具体实现被放到了chamelon-bitopt模块里面。
chanmelon的工作就是把rime协议的顶层数据与底层硬件连接起来,通过定义好的接口,通过设置packbuf里面不同的packetbuf_attr属性来决定包里面填充的内容,来达到不同底层硬件协议的实现。

chameleon-bitopt模块

这里做的工作就是把chamelon模块的内部功能实现,我们可以在chameleon-bitopt.h里面找到:
extern CC_CONST_FUNCTION struct chameleon_module chameleon_bitopt;
在chamelon.c里面找到:
#define CHAMELEON_MODULE chameleon_bitopt
由此我们可以知道chamelon的具体内容填充工作是在这里实现的。具体内部的实现就是通过压缩字节来实现的,通过定义好的packetbuf_attr长度把数据压缩在一起。我只是看了一个大概,大家可以仔细研读这部分代码。

databuf模块

databuf设置了一个大的数组,然后分为2部分:header和data,从字面意思就可以很容易理解。
另外在databuf.h里面还设置了一个枚举变量:定义了databuf的属性,通过设置数据的属性,来区分不同类型的数据字段,这些在协议里面都是很容易理解的。
还有要注意的一点,这个databuf是一次只能使用一次的。所以在设计顶层流程的时候需要考虑到数据发送的生存周期。

总结

上面从abc模块-->channel模块-->chamelon模块-->chamelon-bitopt模块-->databuf模块,从上至下分析了rime协议最简单的匿名广播(abc)的发送流程,这里我们可以看到rime协议栈很好的分层结构,然后通过一个chamelon抽象层,把硬件相关的都剥离开来。这是我们今后在开发过程中可以借鉴的。


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值