#include<linux/module.h>
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/config.h>
#include<linux/fs.h>
#include<asm/uaccess.h>
#include<linux/version.h>
#include<linux/irq.h>
#include<linux/poll.h>
#include<linux/delay.h>
#include<asm/arch/irq.h>
#include<asm/hardware.h>
#include<linux/spinlock.h>
#include<asm/arch/S3C2440.h> //为了使用GPIO端口定义
#include<linux/devfs_fs_kernel.h> //为了使用devfs_register和devfs_unregister函数
MODULE_LICENSE("GPL");
#define DEVICE_NAME "nRF2401"
#define MAJOR_NUM 233
#define MINOR_NUM 0
static devfs_handle_t devfs_handle=NULL;
static devfs_handle_t devfs_nRF2401_dir=NULL; //在/dev下建立相应的目录
#define DEV_DIR "nRF2401"
static DECLARE_WAIT_QUEUE_HEAD(nRF2401_wait);
static int ready=0;
#define DR1 GPIO_G9 //定义GPIO口与NRF2440的接口
#define PWR_UP GPIO_B6
#define CLK1 GPIO_G7
#define MISO GPIO_G5
#define MOSI GPIO_G6
#define CE GPIO_E13
#define CS GPIO_E12
#define LED GPIO_F4
#define PACKETLEN 22
unsigned char RData[PACKETLEN]; //指向驱动程序申请的用于存放接收数据的内存区域
static struct nRF2401Config{
unsigned char n; //配置字长度
unsigned char buf[15];//配置字数组
}config={15,
{
0x00, //接收通道2有效数据长度
0xB0, //接收通道1有效数据长度
0x00,0x00,0x00,0x00,0x00, //接收通道2地址,最长5字节,缺少位用0填
0x00,0xcc,0xcc,0xcc,0xcc, //接收通道1地址,最长5字节,缺少位用0填
0x83, //32位地址长度(bit7-bit2);16bit CRC(bit1);CRC enable
0x4f,//单通道接收(bit7);ShockBrust(bit6);速率(bit5);晶振频率(bit4-bit2);功率(bit2-bit0)
0x01 //频道(bit7-bit1);发送/接收(bit0:0/1)
}
};
static void SPI_init(void){
//IO initial
set_gpio_ctrl(DR1|GPIO_MODE_ALT0);//设置为DR1为中断模式
set_gpio_ctrl(CE|GPIO_MODE_OUT|GPIO_PULLUP_EN);
set_gpio_ctrl(CS|GPIO_MODE_OUT|GPIO_PULLUP_EN);
set_gpio_ctrl(PWR_UP|GPIO_MODE_OUT|GPIO_PULLUP_EN);
set_gpio_ctrl(CLK1|GPIO_MODE_ALT1|GPIO_PULLUP_EN);//设置引脚为SPI
set_gpio_ctrl(MISO|GPIO_MODE_ALT1|GPIO_PULLUP_EN);
set_gpio_ctrl(MOSI|GPIO_MODE_ALT1|GPIO_PULLUP_EN);
set_gpio_ctrl(LED|GPIO_MODE_OUT|GPIO_PULLUP_EN);//设置LED引脚
write_gpio_bit(PWR_UP,0);//初始化nFR2401引脚
write_gpio_bit(CE,0);
write_gpio_bit(CS,0);
write_gpio_bit(LED,1);//关LED
//REGISTER initial
SPPRE1=0xff; //设置波特率为132,300bps
SPCON1=0x18;//设置为查询方式
printk("SPI configured\n");
}
static void SPI_poll_done(void){
int ncount=0;
while(!(SPSTA1&0x01)){ //判断SPI发送寄存器是否已经准备好
ncount++;
if(ncount>=5000){
printk("SPI state poll failed\n");
// return -1;
break;
}
}
//return 0;
}
static void SPI_tx_data(unsigned char data){ //通过SPI发送数据
SPI_poll_done();
SPTDAT1=data;
SPI_poll_done();
}
void RX_Packet(void)
{ //读取数据包
unsigned char i;
for(i=0;i<PACKETLEN;i++)
{
SPI_tx_data(0xff);
RData[i]=SPRDAT1;
}
printk("recevie RX_Packet\n");
}
static void nRF2401_ON(void)
{ //nRF2401上电
write_gpio_bit(CE,0);
write_gpio_bit(CS,0);
write_gpio_bit(PWR_UP,1);
mdelay(3);//延时3ms,nrf2401进入待机模式
printk("nRF2401 on\n");
}
static void nRF2401_Config(void)
{ //nRF2401配置
unsigned char i;
write_gpio_bit(CE,0);
write_gpio_bit(CS,1);
udelay(10); //延时10us
for(i=0;i<config.n;i++){
SPI_tx_data(config.buf[i]);
}
write_gpio_bit(CS,0);
write_gpio_bit(CE,1);//激活接收模式,经过202us内部延时后进入接收模式
printk("nRF2401 configed\n");
}
static void nRF2401_Close(void)//关闭nRF2401
{
write_gpio_bit(CE,0);
write_gpio_bit(CS,0);
write_gpio_bit(PWR_UP,0);
printk("nRF2401 close\n");
}
static void nRF2401_irq(int irq,void *dev_id,struct pt_regs *reg)
{
unsigned int flags;
write_gpio_bit(LED,0);//开LED,表示接收到数据
save_flags(flags); //中断处理时禁止再次中断
cli();
//printk("nRF2401have prepared the datas!\n"); //中断处理函数
//mdelay(1000);
RX_Packet();
restore_flags(flags);
write_gpio_bit(LED,1);//关LED,表示读完数据
ready=1;
wake_up_interruptible(&nRF2401_wait); //通知应用程序有数据可读
}
static int requestb_irq(void) //中断申请函数
{
set_external_irq(IRQ_EINT17,EXT_RISING_EDGE,GPIO_PULLUP_DIS);//DR1上升沿触发
if(request_irq(IRQ_EINT17,&nRF2401_irq,SA_INTERRUPT,DEVICE_NAME,&nRF2401_irq)){
printk(DEVICE_NAME" request_irq failed!\n");
return -1;
}
printk("irq succes!\n");
return 0;
}
static void freeb_irq(void)
{
free_irq(IRQ_EINT17,nRF2401_irq);
}
static int nRF2401_open(struct inode *inode,struct file *file)
{
ready=0;
nRF2401_ON();
nRF2401_Config();
printk(DEVICE_NAME" open\n");
MOD_INC_USE_COUNT;
return 1;
}
static int nRF2401_release(struct inode *inode,struct file *file)
{ nRF2401_Close();
printk(DEVICE_NAME" release\n");
MOD_DEC_USE_COUNT;
return 1;
}
static ssize_t nRF2401_read(struct file *file,char *buf,size_t len,loff_t *off)
{
__copy_to_user(buf,RData,sizeof(RData));
ready=0;
return sizeof(RData);
}
/*static ssize_t nRF2401_write(struct file *file,const char *buf,size_t len,loff_t *off)
{
__copy_from_user(&,buf,sizeof());
return sizeof();
}*/
static unsigned int nRF2401_select(struct file *file,struct poll_table_struct *wait)
{ //printk("poll ready is%d\n",ready);
if(ready)return 1;
poll_wait(file,&nRF2401_wait,wait);//使外部应用程序阻塞,等待数据准备好
return 0;
}
static struct file_operations nRF2401_fops={
owner: THIS_MODULE,
open:nRF2401_open,
release:nRF2401_release,
//ioctl:nRF2401_ioctl,
read:nRF2401_read,
// write:nRF2401_write,
poll:nRF2401_select,
};
static int nRF2401_init(void)
{
int ret;
ret=register_chrdev(MAJOR_NUM,DEVICE_NAME,&nRF2401_fops);
if(ret)
{
printk(DEVICE_NAME" register failure\n");
return ret;
}
else
printk(DEVICE_NAME" register success\n");
ret=requestb_irq();
if(ret){
ret=unregister_chrdev(MAJOR_NUM,DEVICE_NAME);
if(ret)
{
printk(DEVICE_NAME" unregister failure\n");
}
else printk(DEVICE_NAME" unregister success\n");
return ret;
}
devfs_nRF2401_dir=devfs_mk_dir(NULL,DEV_DIR,NULL);
devfs_handle=devfs_register(devfs_nRF2401_dir,DEVICE_NAME,DEVFS_FL_DEFAULT,MAJOR_NUM,MINOR_NUM,S_IFCHR|S_IRUSR|S_IWUSR,&nRF2401_fops,NULL);
SPI_init();
return ret;
}
static void nRF2401_exit(void)
{
int ret;
devfs_unregister(devfs_handle);
freeb_irq();
ret=unregister_chrdev(MAJOR_NUM,DEVICE_NAME);
if(ret)
{
printk(DEVICE_NAME" unregister failure\n");
}
else
printk(DEVICE_NAME" unregister success\n");
}
module_init(nRF2401_init);
module_exit(nRF2401_exit);