- 写在前面
最近根本搞定了CC2500在linux下面的驱动,在这个过程中遇到了许多问题,特此总结出来和咱们共享。可是需求留意的作业是:
榜首,本文不担任程序的详细解说,比方每一行程序都讲什么:这个在程序的晒干有注释。本篇文章更侧重于从全体结构上让咱们关于linux下的CC2500DE驱动有一个全体的了解,假如到时分需求深入研究的时分,再来看详细的代码;
第二,许多师弟师妹没有习气在linux下编程,或曰,在操作系统下面写程序;而且,关于本专业的东西了解并不厚实。可是,文章中不行能就每一个触及到的概念都大加解说。因而,这篇文章仍是需求有一些根底才能来阅览的,假如遇到什么不明白的当地,请及时来问我,或许跟帖,或许自己查资料。究竟,这个驱动花费了我半个多月的时刻,其间遇到的问题,不行能在一篇文章中就讲得清清楚楚。
-
布景常识
假如咱们看过实验室的WSN方面的程序,或许会被其间的架构搞得暗无天日。这儿,简略的协助咱们把实验室的WSN的软件、硬件方面捋一捋。
提到软件,就不能不说硬件。咱们的节点由两部分组成,一个是单片机,一个是CC2500的射频模块。射频模块经过SPI接口和单片机进行通讯。除了SPI模块用到的4条线,实际上CC2500还需求告知单片机“我接纳到一个数据”,这个当地CC2500能够经过装备GDO来完结。咱们这儿选用的CC2500的GDO0作为单片机的一个外部中止,当接纳到数据的时分,GDO0就会变为低电平,然后触发CC2500的中止,然后接纳数据。
那么,CC2500究竟是怎么来进行数据发送、接纳的呢?其实很简略。假如咱们略微用过一点能够操控的芯片就会知道,许多芯片内部都有寄存器,CC2500之所以能够完结发送、接纳的功用,便是经过装备寄存器来完结的。比较重要的装备有信道、波特率、信号强度等等,别的,CC2500还有64bytes的RXFIFO和64bytes的TXFIFO,他们的效果便是用来发送和接纳。当装备CC2500完毕之后,假如用来发送,那么就把数据放在TXFIFO晒干,然后把CC2500的状况变为发射状况,数据就主动发送出去了。相同的道理,当RXFIFO晒干接纳到了数据之后,CC2500就会如前所说,宣布一个中止,告知单片机来读取数据。
单片机经过SPI接口读出了CC2500中的数据,就需求进行简略的处理了。咱们的节点是遵从802.15.4协议的,假如有爱好,咱们能够去看一看这个协议的内容。关于咱们来说,比较重要的便是帧的结构。下面这个是物理层帧的结构:
字节:4
|
1
|
1
|
可变
|
|
先导码
|
帧定界符
|
帧长度(7位) | 保存位(1位) |
负载内容
|
同步头 | PHY头 | PHY负载 |
简略的讲,咱们是无线通讯,没有一个时钟的存在,因而本质上一切的无线通讯都是一个异步的通讯。那么,就需求发送和接纳的两边首要对数据进行同步——这个便是同步头的效果。随后的是PHY的头,很简略,便是一个长度。换句话说,每个帧不能够超越2的8次方减一个数据(127个)。随后便是负载的内容了,简略吧?别的,咱们CC2500是一个802.15.4兼容的芯片,这一部分内容都现已固化在芯片晒干了,像同步头这种东西,都是芯片帮咱们完结(当然也能够自行装备)。咱们只需求把写入的数据巨细和数据内容写入即可。
尽管简略,可是还有一个问题:每次从CC2500中读取了数据,寄存到哪里呢?有的同学或许想的比较简略,比方树立一个大数组,收到多少个数,放在晒干就行了。可是,这样就会遇到问题:假如收到了两个包,上层来不及处理怎么办?树立两个大数组?更多的包呢?当然,咱们能够经过树立许多个数组来处理这个问题。可是,从功率上讲,这个是十分笨的一个办法。因而,咱们树立了一个环形缓冲区PHY_RX_BUFFER,来处理这个问题。环形缓冲区的详细原理不过多触及,能够自行百度。
别的一个问题便是,假如咱们从CC2500中接纳到了数据,那么应该怎样才能告知上层来进行处理呢?这儿就要用到操作系统的音讯机制了。假如结语接纳到了一个数据,那么就给上层发送一个音讯,来告知上层。上层接纳到这个音讯,就会知道接纳到了数据。
当从CC2500读取到了数据,咱们物理层没有什么东西,咱们就直接告知MAC层来处理数据。MAC层的结构如下:
字节:2
|
1
|
0/2
|
0/2/8
|
0/2
|
0/2/8
|
可变
|
2
|
帧操控域
|
序列号
|
意图PAN怂恿符
|
意图地址
|
源PAN怂恿符
|
源地址
|
帧负载
|
FCS
|
地址域
|
|||||||
MAC帧头
|
MAC负载
|
MFR
|
详细内容能够拜见教师的《无线传感器网络技能与工程运用》这本书,这儿不再详细的讲,大约内容便是,会有一系列的帧头,然后是帧数据,最终有校验。而咱们最关怀的便是帧的内容。可是,帧头也比较费事,因而咱们需求首要对帧头进行处理,把数据给“剥离”出来,这也是根本上一切的协议栈解析协议的办法。
-
硬件结构
硬件上,咱们选用的是mini2440开发板,和实验室的CC2500节点(把单片机焊掉,然后把mini2440的相应管脚接到上面)。
Mini2440方面,咱们用的是CON8这个引脚,详细连线如下:
EINT8对应S3C2440的GPG0引脚,衔接到了CC2500的GDO2
EINT11对应S3C2440的GPG3引脚,衔接到了CC2500的CSN
EINT13对应S3C2440的GPG5引脚,衔接到了CC2500的SO
EINT14对应S3C2440的GPG6引脚,衔接到了CC2500的SI
EINT15对应S3C2440的GPG7引脚,衔接到了CC2500的CLK
EINT19对应S3C2440的GPG11引脚,衔接到了CC2500的GDO0
除此之外,还有3.3V电源和GND
-
Linux下驱动编写
为什么要用驱动呢?简略的说,便是为了在linux下完结用户空间和内核空间的交互。本质上,驱动便是完结了两件作业:榜首,初始化SPI接口,而且经过SPI和CC2500完结通讯。第二,完结读写函数,read和write,经过读写函数的接口来对CC2500进行操作。
附件晒干有几个文件,这儿简略解说一下:
Common.h主要是包含了许多linux的头文件,而且对一些数据类型做了界说
CC2500.h晒干主要是对CC2500的寄存器做了一些界说,没啥东西
Driver.h主要是界说了许多和CC2500进行通讯,而且运用CC2500进行发送和接纳的内容
Phy.h主要是完结了一些比方信道设定、通讯速率等功用,而且把CC2500里的数据读到环形缓冲区晒干
CC2500.c这个便是完结设备注册、读写函数、iocontrol等功用
这样有了一个全体的掌握之后,不必看许多代码,学会运用就好。
-
驱动接口运用
那么,这个驱动怎样运用呢?主要是经过read/write/ioctl三个接口来完结的。
在运用程序中read/dev/CC2500这个文件,假如有数据,会回来相应的数据。其间,回来的数据中榜首个字节为数据的长度(不包括该字节自身),后边为相应的数据。
假如是写文件的话,只需求向/dev/CC2500中写入相应的数据即可。写入的时分需求留意,榜首个字节相同为数据长度(不包括该字节自身),后边跟相应的数据。当写入的字节适宜的时分,驱动会主动碑文发送函数。假如写入的字节数量和写入的数据榜首个字节不匹配的时分,会回来过错。
ioctl主要有这样几种指令:
CC2500_IOC_PHY_DETECT_STATUS
一共将CC2500的状况变为RX
CC2500_IOC_PHY_GET_BAUDRATE
读取CC2500的波特率,回来的是1,2,3,4,分别是2.4k,10k,250k,500k的波特率
CC2500_IOC_PHY_SET_BAUDRATE
设定CC2500的波特率,后边的参数是1,2,3,4,分别是2.4k,10k,250k,500k的波特率
CC2500_IOC_PHY_GET_TXPOWER
获取发送功率,回来的是在发送功率表{0x00, 0x50, 0x44, 0xC0, 0x84, 0x81, 0x46, 0x93, 0x55, 0x8D, 0xC6,0x97, 0x6E, 0x7F, 0xA9, 0xBB, 0xFE, 0xFF }中的数组下标
CC2500_IOC_PHY_SET_TXPOWER
设定发送功率,参数的是在发送功率表{0x00, 0x50, 0x44, 0xC0, 0x84, 0x81, 0x46, 0x93, 0x55, 0x8D, 0xC6,0x97, 0x6E, 0x7F, 0xA9, 0xBB, 0xFE, 0xFF }中的数组下标
CC2500_IOC_PHY_GET_CHANNEL
获取频段,参数是频段表{0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0,0xB0, 0xC0, 0xD0, 0xE0, 0xF0 }中的数组下标
CC2500_IOC_PHY_SET_CHANNEL
设定频段,参数是频段表{0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0,0xB0, 0xC0, 0xD0, 0xE0, 0xF0 }中的数组下标
-
运用层程序编写
这儿的运用层主要是将mac层完结了。其实,mac层的效果也很简略,主要是对要发送的包进行封装,接纳回来的包进行包的解析。这一部分的内容还不全面,仅仅是将本来的程序移植过来,还有许多需求改动的当地,有待弥补。因而,这儿仅仅供给源代码,详细的阐明请拜见程序内部
-
怎么装备内核文件
1首要修正/opt/FriendlyARM/mini2440/linux-2.6.32.2/drivers/char/Kconfig
参加如下几句话:
config CC2500_DRIVER
tristate “CC2500 driverfor FriendlyARM Mini2440 development boards”
depends on MACH_MINI2440
default m if MACH_MINI2440
help
this is CC2500 driver forFriendlyARM Mini2440 development boards
2修正Makefile,让CC2500的驱动能够编译。
参加如下几句话:
obj-$(CONFIG_CC2500_DRIVER) +=CC2500inuse.o
CC2500inuse-objs :=./CC2500.in_use/cc2500.o ./CC2500.in_use/phy.o./CC2500.in_use/driver.o
其间,CONFIG_CC2500_DRIVER需求和Kconfig中的configCC2500_DRIVER
保持一致。
CC2500inuse-objs这句话,意思是CC2500inuse.ko是由哪几个文件组成的。这样就完结了模块化的处理。
需求留意的是,CC2500inuse-objs和冒号之间需求有个空格,否则会出过错。这个当地我搞了良久。
详细的Makefile的格局也能够参阅这两篇文章:
http://blog.csdn.net/tommy_wxie/article/details/7282463
http://hi.baidu.com/wjq_qust/blog/item/97ddbdfdfb2e541309244d30.html
-
调试过程中的一些问题
CC2500驱动调试的过程中,遇到的一些问题
榜首,在调试的过程中,发现板子和2500没有办法进行通讯。一开始怀疑是2500芯片的问题,后来结语2500芯片没有问题之后,用示波器看了一下波形,发现SPI引脚上没有输出。轿车发现,对SPI寄存器进行读写的时分,不管写入是什么,读出的都是0。后来发现,本来是PCLK(也便是SPI模块的时钟)没有使能,囧。设置了寄存器之后,问题就处理了。
第二,CC2500驱动没有办法主动在/dev/目录下面创立节点。这个问题能够参阅下面几篇文章:
http://blog.csdn.net/cjok376240497/article/details/6848536
全体来说,创立节点的作业是这样的:
咱们经过udev来创立节点。可是,udev是运用层的东东,不要小事在内核的装备选项里找到它;参加对udev的支撑很简略,只需在驱动初始化的代码里调用class_create为该设备创立一个class,再为每个设备调用class_device_create创立对应的设备。
换句话说,首要要为每一个设备创立一个类。然后用这个类去请求一个设备节点。
第三,在调试的过程中,发现只需一发动CC2500,那么液晶屏就平息了。调试了半响也没有找到原因。
最终发现,在装备S3C2440中GPGCON寄存器的时分,对寄存器直接进行了掩盖性的修正;而该寄存器还办理着LCD的电源…所以,对寄存器进行掩盖性修正的时分,悲惨剧了…
总结一下吧,在linux下2500驱动编写的过程中,假如触及到寄存器等级的操作,和单片机相同,有必要十分留意各个模块之间的联系,以及相关模块的寄存器装备,不要以为linux会悉数给你配好!