📄 spi.c
字号:
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/config.h> //linux 的配置文件
#include <linux/module.h> //模块化源文件必须带的头文件
#include <linux/moduleparam.h>
#include <linux/kernel.h> //包含printk函数
#include <linux/init.h> //包含module_init(init_function)和module_exit(exit_function)
#include <linux/sched.h> //包含驱动程序需要的大量API函数,包括睡眠函数以及各种变量声明
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/poll.h>
#include <linux/fs.h> /*struct file_operations,register_chrdv()*/
#include <linux/spinlock.h>
#include <linux/interrupt.h> //中断相关函数定义
#include <linux/delay.h>
#include <linux/version.h>
#include <linux/major.h>
#include <linux/capability.h>
#include <linux/smp_lock.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/cdev.h>
#include <linux/devfs_fs_kernel.h> //增加一条2.6内核下的头文件,以支持文件系统
#include <linux/types.h> /*u8,u16,u32...*/ //#include <asm-arm/irq.h> //
#include <asm-arm/ptrace.h> //struct pt_regs 定义
#include <asm/system.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/delay.h>
#include <asm/uaccess.h>/*copy_to_user(),copy_from_user()*/#include <asm-arm/arch-s3c2410/regs-irq.h>#include <asm-arm/arch-s3c2410/irqs.h>//中断号#include <asm-arm/arch-s3c2410/map.h>#include <asm-arm/arch-s3c2410/regs-gpio.h> #define r_CLKCON *(volatile unsigned long *)ioremap(0x4C00000c,4)#define r_SCRPND *(volatile unsigned long *)ioremap(0x4A000000,4)#define r_INTPND *(volatile unsigned long *)ioremap(0x4A000010,4)#define r_INTMSK *(volatile unsigned long *)ioremap(0x4A000008,4)#define spi_gpgcon *(volatile unsigned long *)ioremap(0x56000060,4)
#define spi_gpgdat *(volatile unsigned long *)ioremap(0x56000064,4)
#define spi_gpgup *(volatile unsigned long *)ioremap(0x56000068,4)
#define spi_gpecon *(volatile unsigned long *)ioremap(0x56000040,4)
#define spi_gpedat *(volatile unsigned long *)ioremap(0x56000044,4)
#define spi_gpeup *(volatile unsigned long *)ioremap (0x56000048,4)
#define spi_spcon0 *(volatile unsigned long *)ioremap(0x59000000,4)
#define spi_spsta0 *(volatile unsigned long *)ioremap(0x59000004,4)
#define spi_sppin0 *(volatile unsigned long *)ioremap(0x59000008,4)
#define spi_sppre0 *(volatile unsigned long *)ioremap(0x5900000c,4)
#define spi_sptdat0 *(volatile unsigned long *)ioremap(0x59000010,4)
#define spi_sprdat0 *(volatile unsigned long *)ioremap(0x59000014,4)
#define DEVICE_NAME "SPI" // 设备名
#define spi_minor 1 //次设备号
static int spi_major = 0; //主设备号为0表示动态分配主设备号,自定义次设备号。MKDEV()表示主次合并为设备号
static char dataTx[20];
static char dataRx[20];
static int spi_open(struct inode *inode,struct file *filp)
{ int config;
int value; printk("spi open begin..\n"); r_CLKCON |= 0x40000; value=(int)r_CLKCON; printk("r_CLKCON=0x%x\n",value);
//配置gpg2为nSS0
spi_gpgcon &=0xFFFFFFCF;//GPGCON-2=11 ,配置nSS0
spi_gpgcon |=0x00000030;
value=(int)spi_gpgcon;
printk("spi_gpgcon=0x%x\n",value);
spi_gpgup &= 0xFFFB;//GPGUP-2=1 ,nSS0不上拉
spi_gpgup |=0x0004;
value=(int)spi_gpgup;
printk("spi_gpgup=0x%x\n",value); //spi_gpgdat |=0x0004;
/*配置SCLK0,MOSI0,MISO0*/
spi_gpecon &=0xF03FFFFF;//GPECON-11,12,13=10
spi_gpecon |=0x0A800000;
value=(int)spi_gpecon;
printk("spi_gpecon=0x%x\n",value);
/*上拉MISO0和MOSI0,不上拉SCLK0*/
spi_gpeup &=0xC7FF;//GPGUP-13=1 GPGUP-12,11=0
spi_gpeup |=0x2000;
value=(int)spi_gpeup;
printk("spi_gpeup=0x%x\n",value);
// return 0; //配置SPI printk("config SPI...\n"); disable_irq(IRQ_SPI0);
spi_sppre0=0xFF;//SPI Baud Rate Prescaler Register,Baud Rate=PCLK/2/(Prescaler value+1);
spi_spcon0=(0<<6)|(1<<5)|(0<<4)|(1<<3)|(1<<2)|(0<<1)|(0<<0);
config=(int)spi_spcon0;
printk("spi_spcon0=0x%x\n",config);
//int,en-sck,master,low,format A,Tx auto garbage
spi_sppin0=(1<<2)|(1<<1)|(0<<0);
//Multi Master error detect enable,release
config=(int)spi_sppin0;
printk("spi_sppin0=0x%x\n",config); r_SCRPND|=(1<<22); r_INTPND|=(1<<22); //disable_irq(IRQ_SPI0); //config=(int)r_INTMSK; //printk("r_INTMSK=0x%x\n",config); enable_irq(IRQ_SPI0); /*config=(int)r_INTMSK; printk("r_INTMSK=0x%x\n",config);*/ printk("Open spi successfully\n"); return 0;
}
static int spi_release(struct inode *inode,struct file *filp)
{
printk("s3c2410-spi closed\n");
return 0;
}
/*static ssize_t spi_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_ops)
{
volatile int endSpiTx=0;
volatile char *spiTxData;
spiTxData=dataTx;
while(endSpiTx==0)
{
if((spi_spsta0&0x01)==1) //data Tx/Rx ready
{
if(*spiTxData !='\0')
{
spi_sptdat0=*(spiTxData++); //传送第一个字节,指针指到下一个字节
string=spi_sptdat0; printk("transmit char=%c\n",string); while(!(spi_spsta0&0x01)); dataRx[i]=spi_sprdat0;
printk("receive char=%c\n",dataRx[i]); i++;
}
else
endSpiTx=1;
}
}
spi_spcon0=(0<<5)|(0<<4)|(1<<2)|(0<<1)|(0<<0); //Polling,dis-sck,master,low,format A,nomal
return 0;
}*/
static ssize_t spi_read(struct file *filp,char __user *buf,size_t count,loff_t *f_ops)
{
copy_to_user(buf,dataRx, count);
return 0;
}
static struct file_operations spi_fops = {
.owner = THIS_MODULE,
.open = spi_open,
.release = spi_release,
.read = spi_read,
//.write = spi_write,
}; static void spi_interrupt(int irq,void *dev_id,struct pt_regs *reg) { printk("SPI_INT HAPPEN\n"); //printk("SPI_INT HAPPEN\n"); r_SCRPND|=(1<<22); r_INTPND|=(1<<22); disable_irq(IRQ_SPI0); //spi_spcon0=(0<<6)|(0<<5)|(1<<4)|(0<<3)|(1<<2)|(0<<1)|(1<<0); //polling,en-sck,slave,low,format A,Tx auto garbage //spi_sppin0=(0<<2)|(1<<1)|(0<<0);//Multi Master error detect disable,release int i=0; volatile int endSpiRx=0; while(endSpiRx==0) { while(!(spi_spsta0&0x01)); spi_sptdat0=0xFF; while(!(spi_spsta0&0x01)); dataRx[i]=spi_sprdat0; if((dataRx[i])=='A') endSpiRx=1; printk("receive char=0x%x\n",dataRx[i]); //i++;这里是问题的原因。本来之分配了20个字符的空间,而这里却去不断增加计数器的值,导致溢出 //spi_spcon0=(0<<6)|(1<<5)|(1<<4)|(0<<3)|(1<<2)|(0<<1)|(1<<0); //int,en-sck,slave,low,format A,Tx auto garbage //spi_sppin0=(1<<2)|(1<<1)|(0<<0);//Multi Master error detect enable,release } spi_spcon0=(0<<6)|(1<<5)|(0<<4)|(1<<3)|(1<<2)|(0<<1)|(0<<0);//int,dis-sck,slave,low,format A,Tx auto garbage 中断完毕需要恢复Master模式,以便检测多主机错误 enable_irq(IRQ_SPI0); printk("SPI_INT END\n"); }
static int __init spi_init(void)
{ int ret;
ret=register_chrdev(0,DEVICE_NAME,&spi_fops); //注册设备,返回主设备号,第一个参数为0,表示动态分配主设备号
//2.6内核常用register_chrdev_region()
if(ret < 0){
printk("Can't get major number\n");
return ret;
}
spi_major = ret;
devfs_mk_cdev(MKDEV(spi_major,spi_minor),S_IFCHR | S_IRUSR | S_IWUSR |S_IRGRP,"spi/0"); request_irq(IRQ_SPI0,spi_interrupt,SA_INTERRUPT,DEVICE_NAME,NULL);
printk("Init spi success!\n");
return 0;
}
static void __exit spi_exit(void)
{
free_irq(IRQ_SPI0,NULL);
unregister_chrdev(spi_major,DEVICE_NAME);
}
module_init(spi_init);
module_exit(spi_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("PQbear");
MODULE_DESCRIPTION("SPI_driver for S3C2440");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -