嵌入式家庭网关中SPI接口的软件模拟
Static wait_queue_head_wait; //休眠队列
//读函数
static ssize_t SPI_onlyread(struct file*file,char *buf,size_t count,loff_t *ppos)
{
interruptible_sleep_on(&SPI_wait); //读进程睡眠等待读中断信号
if(count>BUFNUM)count=BUFNUM;
for(num=0;num<count;num++){
for(i=0;i<8;i++){
iopdata=iopdata^0x1000; //时钟输出
SPI_read[num]=SPI_read[num]+((iopdata&0x2000)>>(12-i)); //数据输入
}
}
if(copy_to_user(buf,&SPI_read,count)) //数据从内核空间拷贝到用户这间
return-EFAULT;
return count;
}
//写函数
static ssize_t SPI_onlywrite(struct file *file,const char *buf,size_t count,loff_t *ppos)
{
if(count>BUFNUM)count=BUFNUM;
if(copy_from_user(&SPI_write,buf,count)) //数据从用户空间拷贝到内核空间
return-EFAULT;
for(num=0;num<count;num++){
for(i=0;i<8;i++){
iopdata=((SPI_write[num]&0x1)<<11)+(iopdata&0xfffff7ff);
SPI_write[num]=SPI_write[num]>>1;
iopdata=iopdata^0x1000; //时钟输出
}
}
return count;
}
//中断响应函数
static int SPI_irq(int irq,void *dev_id,struct pt_regs *regs)
{
intpnd=intpnd0X1; //清中断位
wake_up_interruptible(&SPI_wait); //唤醒睡眠队列
return 1;
}
//字符设备驱动接口
static struct file_operations SPI_fops={
owner; THIS_MODULE,
read: SPI_onlyread,
write: SPI_onlywrite,
};
//初始化函数
int_init SPI_init(void)
register_chrdev(29,"SPI"&SPI_fops);//设备注册函数
init_waitqueue_head(&SPI_wait);
if(!request_irq(0,SPI_irq,SA_SAMPLE_RANDOM,"SPI"NULL)){ //中断申请
return-EFAULT;
}
iopmod=(iopmod&0xffffe7ff)=0x1800+iopmod; //设置通用I/O口模式
iopcon=(iopcon&0xffffffe0)+0xle+iopcon;//设置通用I/O模式
enable_irq(0); //开中断
return 0;
}
module_init(SPI_init);
MODULE_LICENSE("GPL);
EXPORT_NO_SYMBOLS;
结语
实验证明,模拟的SPI口接收发送数据准确可靠。用户程序可以以设备文件的形式进行访问,与标准的SPI接口无异。该方案对于嵌入式家庭网关的研究,以及运用uClinux作为操作系统的嵌入式模拟通信接口,有一定的参考价值。