加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Contiki学习笔记——SI1000射频驱动移植

(2013-01-21 10:46:45)
标签:

contiki

si1000

无线传感网

uip

si1020

分类: 技术资料
   这是一篇迟到的博文了,之前因为要写毕业论文还有小论文什么的所以耽搁了很久,实在不好意思。前两天把之前基于rime协议的P2P通信丢包问题解决了一下,感觉是应该写一下这篇博文了,也为之后上uIP做好铺垫。
   之前提到过Silicon Labs的Si1000是C8051F930+Si4432的SOC片子,所以这边写射频驱动实际也是在写Si4432的驱动。从另一个角度说,把Si1000的射频驱动写好了,以后其他MCU用Si4432的时候都可以调用这个驱动。
   我做Si1000驱动移植一直以来走的都是非操作系统程序到操作系统程序的路子,射频驱动也不例外。
一、Si4432非操作系统程序调试及驱动编写准备
   Silicon Labs网站上有下EzMACPRO的射频历程,里面程序都写得挺规范的,它已经把Si4432基本功能都已经实现了。但是是需要自己的需求改的,再contiki里面最大问题就是数据包长度问题。要想上uIP一个数据包都是要128byte但是Si4432只有64byte的FIFO。但是网络上面高手云集啊~我这边找到一个扩展FIFO的程序方法。博客不能上传文件这边截个图,大家自己去下载吧。
   调试通过了星状网络和128byte数据包通信问题,就可以开始上Contiki了。
   之前我应该提到过我通过改编example/sensinode自己写了一个si-example的文件夹。现在我就利用里面的rf_test_rx.c和rf_test_tx.c做测试,利用rime当做网络协议,CC2430驱动作为模板进行移植。
   CC2430的射频程序很简单,只用到cc2430_rf.c和cc2430_rf_intr.c。我没做过CC2430的应用所以对这块片子还不是很了解,但是有一点必须注意的:CC2430和CC253x都是基于IEEE802.15.4的,恐怕Contiki大部分的platform都是基于IEEE802.15.4的,因此都有IEEE802154_PANID这个需要考虑,具体原理请见IEEE802.15.4标
http://s7/small/4a9bee5agd3caf72f3bd6&690
准。但是Si4432没有支持这个标准,所以在这点上或许Si1000跟其他片子兼容性上面还是有问题。
   根据CC2430的模板加上EzMACPRO驱动的结合,我在cpu/si1000下面新设了一个radio的文件夹,如右图所示:
    si443x_const_b1.c和EZMacPro_const.c是对射频参数的设置文档;EZMacPro.c是对Si4432芯片各种状态下,程序对应的处理规则;framer-SIMAC.c还没细写,主要是对规定SIMAC10这个版本通信时候的数据包格式的;si1000_rf_intr.c和si1000_rf.c不用多说,跟cc2430一样,前者是处理rf的中断,后者是实现物理层诸如send、prepare、on、off等等API的;timerout.c顾名思义,是保证程序处理时超时处理,这点对Listen before talk特别重要。
二、通信流程理解编写
   以上这些程序都是根据EzMACPRO改写的,下面我就是从上至下说明一下整个通信流程和原理。
   1.应用层:
   从下面的程序可以看出信道现成的流程(以unicast为例):1.开创信道,类似于电脑上打开一个8080端口,这样是为了保证多少个APP在一个节点上协同工作。2.填写目的地地址,我这边用的是2byte的短地址。3.然后就是填写发送内容,发送了。
   这里unicast_open(开创信道)就无需累述了,基本流程就是app_open -> unicast_open -> broadcast_open -> abc_open -> channel_open,这一个流程下来每一步都配合着层的属性设定,比如接收和发射地址什么的,最后channel层则是定义了这个信道的号码同时把这个信道加入信道列表中。
http://s16/mw690/4a9bee5agd3c82345faff&690
   unicast_send才是关键。unicast_send(&uc, &addr);函数输入信道属性和发射地址。函数内容如下:
int unicast_send(struct unicast_conn *c, const rimeaddr_t *receiver)
{
  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, receiver);//设置目的地址
  return broadcast_send(&c->c);//继续交给broadcast层
}
   2.MAC层:
   这里一路的XXX_send,直到abc层的rime_output:
int rime_output(struct channel *c)
{
  RIMESTATS_ADD(tx);//rime状态采集
  if(chameleon_create(c)) {//数据包建立
    packetbuf_compact();//判断packetbuf是否关联了外部数据

    NETSTACK_MAC.send(packet_sent, c);
    return 1;
  }
  return 0;
}
   关于chameleon在Jelline的博客中说明的很详细,包括这里关于rime的所有细节都可以到他的博客里面找。这里向大神拜一下~http://www/uc/myshow/blog/misc/gif/E___7414ZH00SIGG.gif
   所以中间的种种过程我就不多说了,不然写三天都写不完。咋们直接说RDC和物理层。
   3.RDC和物理层:
   为了调试方便,我直接使用nullrdc做rdc层。这样就简单了,send_packet进去就判断数据包是否建立成功,然后就直接用NETSTACK_RADIO.send发射了。
   NETSTACK_RADIO就是Si4432的物理层驱动,物理层几个主要元素如下图:
http://s2/mw690/4a9bee5agd3cbc00a8071&690
   init就是对Si4432的初始化;prepare是发射之前的准备,诸如数据包缓冲填充、芯片状态准备;transmit就是发射了;send是个API,包括了transmit和prepare;read是对接收到并保持在缓冲里的数据进行读取;channel_clear、receiving_packet、pending_packet都未用到,等用到再填吧;on和off是用于低功耗模式,表示射频的开与关。
http://s5/mw690/4a9bee5ag7b94671abc44&690
   再来看si1000_rf_intr.c由于Si4432涉及到Listen before talk(LBT)、数据包同步、应答等等,多个状态之间切换复杂。所以我这边学习cc2430的样子,采用事件形式处理中断,这样也是为了减少堆栈开销。
   所以自此驱动就这么写完了,说说简单但还是花了我不少功夫。这里有个小插曲:之前通信成功了,但是很奇怪的是之前小于5秒发包的时候,数据丢包严重。我以为是射频驱动问题,后来发现是rtimer驱动没写好。因为LBT要用到rtimer做监听时间,这里是0.5mS。结果发现rtimer在时间太短的情况下会出现随机定时的问题,原因还没发现。
   这次博文说实话没写好,隔得太久了,很多关键点要写的实在想不起来了~下次注意吧~
http://s4/small/4a9bee5agd3cc524d6183&690
   最后做个小小的广告
   这幅图是SIMAC10,就是我现在在移植的片子做的最小系统板,芯片用的是Si1000,64kflash加4kram。虽然还没有ping通板子但在无操作系统的情况下已经测试通过。通信距离可以到1km左右哦~(测试环境是马路)



http://s12/small/4a9bee5agd3cc3bf35c2b&690
   这幅图是我新做回来的板子是SIMAC20是以Si1020为核心做的,128k flash加4k ram,还自带段式液晶驱动,射频部分跟SIMAC10一样。目的就是怕SIMAC10资源不够用所以搞的。现在测试能够下载,但其他几个功能还没测试。Si1020最让人头疼的是芯片不好焊接,所以必须得找好点的贴片厂家焊接才行。


0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有