📄 ad_driver.c
字号:
#include <linux/module.h> // Needed by all modules
#include <linux/kernel.h> // Needed for KERN_ALERT
#include <linux/init.h> // Needed for the macros
#include <asm/io.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <sys/syscall.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/unistd.h>
#include <linux/wrapper.h>
#include <asm/uaccess.h>
#define ad_major 151
typedef volatile unsigned int AT91;
//#include <linux/modversions.h>
MODULE_LICENSE("GPL");
static int ad_open(struct inode *,struct file *);
static ssize_t ad_read(struct file *,char *,size_t,loff_t *);
static ssize_t ad_write(struct file *,const char *,size_t,loff_t *);
static int ad_close(struct inode *,struct file *);
static AT91 *SPI_RDR; //SPI接收数据寄存器
static AT91 *SPI_SR=0; //SPI状态寄存器,用于检测TDRE
static AT91 *SPI_TDR=0; //SPI发送数据寄存器
static char value; //用于存放控制字
static int ad_open(struct inode *inode,struct file *file)
{
//PIO A基地址ffff f400
//PMC基地址ffff fc00
AT91 *PIO_PDR=0;
AT91 *PIO_ASR=0;
AT91 *PMC_PCER=0;
PIO_PDR = ioremap((unsigned long)0xfffff404,(unsigned long)1);
PIO_ASR = ioremap((unsigned long)0xfffff470,(unsigned long)1);
*PIO_PDR=0X27; //禁止PA0,1,2,5I/O功能
*PIO_ASR=0X27; //PA0,1,2,5选择外围功能A
PMC_PCER = ioremap((unsigned long)0xfffffc10,(unsigned long)1);
*PMC_PCER=0X2000; //使能SPI外围时钟,SPI外围ID为 13
return 0;
}
static ssize_t ad_write(struct file *file,const char *buffer,size_t count,loff_t *offset)
{
unsigned short int a;
//SPI define,基地址fffe 0000
AT91 *SPI_CR=0; //SPI控制寄存器,使能SPI
AT91 *SPI_MR=0; //SPI模式寄存器,设定主机模式,选择NPCS2
AT91 *SPI_CSR1=0; //SPI片选寄存器,设定数据发送时序
SPI_CSR1 = ioremap((unsigned long)0xfffe0034,(unsigned long)1);
SPI_MR = ioremap((unsigned long)0xfffe0004,(unsigned long)1);
SPI_CR = ioremap((unsigned long)0xfffe0000,(unsigned long)1);
SPI_RDR = ioremap((unsigned long)0xfffe0008,(unsigned long)1);
SPI_SR = ioremap((unsigned long)0xfffe0010,(unsigned long)1);
SPI_TDR = ioremap((unsigned long)0xfffe000c,(unsigned long)1);
*SPI_CSR1=0xa1281; //Tcss约110ns,spck约2.4M
*SPI_MR=0x10001; //选择NPCS1,主机模式
*SPI_CR=0x01; //使能SPI
a=readw(SPI_RDR); //读接收寄存器,清除RDRF标志
get_user(value,buffer);
return (count);
}
static ssize_t ad_read(struct file *file,char *buffer,size_t count,loff_t *offset)
{ unsigned short int b;
char a;
*SPI_TDR=value; //发送控制字
while(1) //等待同步器将转换完成的数据送入SPI_RDR
{ a=readb(SPI_SR);
if((a&0x01)==0x01) //若RDRF置1,读SPI_RDR数据
{ b=readw(SPI_RDR);
break;
}
}
put_user(b,buffer);
b=b>>8;
put_user(b,++buffer);
return(count);
}
static int ad_close(struct inode *inode,struct file *file)
{
return 0;
}
struct file_operations ad_fops ={
open:ad_open,
read:ad_read,
write:ad_write,
release:ad_close,
};
int ad_init(void)
{
int rc;
rc=register_chrdev(ad_major,"spi1",&ad_fops);
if (rc<0)
{
printk(KERN_WARNING "da:can't get major %d\n",ad_major);
return rc;
}
printk(KERN_INFO "da:get major %d\n",ad_major);
return 0;
}
int init_module(void)
{
return ad_init();
}
void cleanup_module(void)
{
unregister_chrdev(ad_major,"spi1");
printk(KERN_ALERT "Goodbye\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -