⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.c

📁 GEC2440与TMS2407的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 + -