Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1256258
  • 博文数量: 548
  • 博客积分: 7597
  • 博客等级: 少将
  • 技术积分: 4224
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-15 13:21
个人简介

嵌入式软件工程师&&太极拳

文章分类

全部博文(548)

文章存档

2014年(10)

2013年(76)

2012年(175)

2011年(287)

分类:

2011-10-14 16:54:07

原文地址:SPI驱动流程(S3C2440) 作者:kgatheko

SPI驱动流程(S3C2440 
2007-12-27 22:50:25

简单的说就是写几个寄存器,其实非常简单的,呵呵
一、配置IO脚为SPI接口
        
我用的是(s3c2440)SPI1通道,所有的IO都在GPG脚上,故配置的是GPGCON
将对应的位置为SPI
             
然后是GPGUP寄存器
二、开始SPI寄存器的配置
       1
SPPRE,设置传送频率,即SPICLK的频率
          SPI_CLK=PCLK/2/(SPPRE+1)
       
根据S3C2440的资料,PCLK48M,我要配置SPI_CLK  1M
       1
482/(SPPRE1)=>  SPPRE23=> SPPRE0x18
    (
个人理解,有错请指出,呵呵)
       2
SPCON 寄存器
          
该寄存器有 7 位,对应的控制包括:SPIMOD65),SCK enable (4)master/slave (3),CPOL(2)CPHA(1)TAGD(0).具体怎么设置根据自己的需要设置就OK
       3
SPPIN 寄存器
        
就三个寄存器,都设置好后就可以写和接收数据 
          
写之前记得要检查SPSTA REDY位是否为 1 .
NOTE
 我的配置好IO之后,发现写SPCON寄存器无效,郁闷了两天终于找到原因,就CLKCON寄存器的SPI位没有
激活,所以写寄存器之前 记得要检查CLKCON的状态

一点点经验,留个记号,呵呵
代码写的有点乱,测试的时 候弄的,不好意思^_^ 
code :

#ifndef MODULE
#define MODULE
#endif

#include
#include
#include
#include  
#include

#include


#define GPG_CON   0x56000060      
#define GPG_DAT   0x56000064     
#define GPG_UP    0x56000068     

#define SPCON_1   0x59000020   
#define SPSTA_1   0x59000024   
#define SPPIN_1      0x59000028   
#define SPPRE_1   0X5900002C   
#define SPTDAT_1  0x59000030   
#define SPRDAT_1  0x59000034   

                       
#define nSS1            (1<<6  | 1<<7)       
#define SPICLK1         (1<<14 | 1<<15)       
#define SPIMOSI1        (1<<12 | 1<<13)       
#define SPIMISO1        (1<<10 | 1<<11)       
#define SPI_USE         (nSS1 | SPICLK1 | SPIMOSI1 |SPIMISO1)


//static int  spi_major;
#define spi_name "S3C2440_SPI"
#define spi_minor       1

#ifdef CONFIG_DEVFS_FS
static devfs_handle_t devfs_spi_dir,devfs_spi_raw;
#endif



MODULE_LICENSE("GPL");

#if 1
#define     SPI_SPPRE1    (*(volatile unsigned long *)SPPRE1)        
#define     SPI_GPGCON      (*(volatile unsigned long *)GPGCON)    
#define     SPI_SPCON1     (*(volatile unsigned long *)SPCON1)   
#define     SPI_SPSTA1     (*(volatile unsigned long *)SPSTA1)   
#define     SPI_SPPIN1     (*(volatile unsigned long *)SPPIN1)   
#define     SPI_SPTDAT1      (*(volatile unsigned long *)SPTDAT1)   
#define     SPI_SPRDAT1      (*(volatile unsigned long *)SPRDAT1)   
#define     SPTDAT1_READ    (*(volatile unsigned long *)SPTDAT1)    
#define     SPI_GPGDAT    (*(volatile unsigned long *)GPGDAT)   

#define     CLKCON        (*(volatile unsigned long *)ADDR_CLKCON)

#endif 


unsigned long     GPGCON;
unsigned long    GPGDAT; 
unsigned long     GPGUP;

unsigned long      SPCON1;
unsigned long      SPSTA1;
unsigned long     SPPIN1;
unsigned long     SPPRE1;
unsigned long    SPTDAT1;
unsigned long     SPRDAT1;
unsigned long   ADDR_CLKCON;
static void get_sys_addr(void)
{
    GPGCON =(unsigned long)ioremap(GPG_CON,4);
    GPGDAT =(unsigned long)ioremap(GPG_DAT,4);
    GPGUP  =(unsigned long)ioremap(GPG_UP,4);
    SPCON1 =(unsigned long)ioremap(SPCON_1,4);
    SPSTA1 =(unsigned long)ioremap(SPSTA_1,4);
    SPPIN1 =(unsigned long)ioremap(SPPIN_1,4);
    SPPRE1 =(unsigned long)ioremap(SPPRE_1,4);
    SPTDAT1=(unsigned long)ioremap(SPTDAT_1,4);
    SPRDAT1=(unsigned long)ioremap(SPRDAT_1,4);
    ADDR_CLKCON=(unsigned long )ioremap(0x4c00000c,4);
}
#if 1

static int spi_open(struct inode *inode,struct file *filp)
{
    unsigned int port_state;
     int i=0;
#if 1

     
    printk("CLKCON: %x \n",(unsigned int )CLKCON);
    if (!(CLKCON&(1<<18)))
        CLKCON|=(1<<18);
    printk("CLKCON: %x \n",(unsigned int )CLKCON);
   

    port_state = readl(GPGCON);   
    printk("<1>only read :port_state= %x \n",port_state);
    port_state &= ~SPI_USE;
    port_state |= SPI_USE;

    
    SPI_GPGCON = port_state;   
//    writel(SPI_USE,GPGCON);

     
    port_state=0x0;
    port_state = readl(GPGUP);    

    port_state &=~(1<<3 | 1<<5 | 1<<6 | 1<<7);

    writel(port_state,GPGUP);    

#endif 

#if 1 

    port_state = readl(SPPRE1);

//    writel(value,SPPRE1);   
    
    SPI_SPPRE1=0x18;   
    
   


    port_state = readl(SPCON1);
    port_state &= ~0x03f;
    port_state |= (0<<0 | 0<<1 | 1<<2 | 1<<3 | 1<<4 | 0<<5 );
           
//    writel(port_state,SPCON1);
    SPI_SPCON1=(0<<0 | 0<<1 | 1<<2 | 1<<3 | 1<<4 | 0<<5 );


    port_state = readl(SPPIN1);
    port_state &= ~(1<<0 | 1<<1 | 1<<2);
    port_state |= (0<<2 | 1<<1 | 0<<0);
   
//    writel(port_state,SPPIN1);
   
    SPI_SPPIN1=(0<<2 | 1<<1 | 0<<0);
    printk("<1>SPI_SPPIN1 = %x \n",(unsigned int )SPI_SPPIN1);
//    SPI_GPGDAT &= ~1<<3;
    printk("SPSTA1=%x \n",readl(SPSTA1));

#if 0   // use for test spi wave ...

    while (1)
    {
//    printk("<1> readl(SPSTA1)&0X01: %x \n",readl(SPSTA1)&0x01);
    if (readl(SPSTA1)&0x01)
    {
    SPTDAT1_READ=0x1234;
//     writel(a,SPTDAT1);
//    SPI_SPTDAT1='a';
    }
    printk("<1>writel \n");
//    printk("<1>readl(SPRDAT1)=%x \n",readl(SPRDAT1));
    printk("<1> readl(SPTDAT1)=%s \n",readl(SPTDAT1));

    i++;
//    printk("<1>readl(SPRDAT1)=%c \n",readl(SPRDAT1));
//    printk("<1> readl(SPTDAT1)=%c \n",readl(SPTDAT1));
    }

#endif // test spi wave 
#endif 
//    writel(~(1<<4),SPCON1);// dis-SCK
//    printk("<1>is the OPEN   readl(GPGUP)=%x \n",readl(GPGUP));
    return 0;

}

static int spi_release(struct inode *inode,struct file *filp)
{
//    MOD_DEC_USE_COUNT;
    printk("<1> release \n");
    return 0;
}
#endif 
#if 1
static ssize_t spi_write(struct file *filp,const char *buf,size_t count,loff_t *f_ops)
{
    int i=0;
//    int config;
    char string;
    char str[20];
    char *txStr,*rxStr;
    volatile char *spiTxStr,*spiRxStr;
    volatile int endSpiTx;
    unsigned int port_state=0;

    endSpiTx=0;
    spiTxStr="spi123456test";
    spiRxStr=str;
    txStr=(char *)spiTxStr;
    rxStr=(char *)spiRxStr;
   
#if 0 // init spi in open ()
    port_state = readl(SPPRE1);
    writel(0x18,SPPRE1); 
    
    printk("<1> spi_write\n");
    
   

    port_state = readl(SPCON1);
    port_state &= ~0x07f;
    port_state |= (0<<0 | 0<<1 | 1<<2 | 1<<3 | 1<<4 | 0<<5);
           
    writel(port_state,SPCON1);
    printk("<1>set SPCON1\n");
   
    port_state = readl(SPPIN1);
    port_state &= ~(1<<0 | 1<<1 | 1<<2);
    port_state |= (1<<2 | 0<<1 | 1<<0);
        writel(port_state,SPPIN1);
    printk("<1>set SPCON1 \n");
#endif // init spi in open()
    while (endSpiTx == 0)
    {
        printk("SPSTA1=%x \n",readl(SPSTA1));
        if((readl(SPSTA1) & 0X01) == 0)
        {
            if (*spiTxStr != '\0')
            {
                writel(*spiTxStr,SPTDAT1);
                string = readl(SPTDAT1);
                spiTxStr++;
            }
            else 
            {
                endSpiTx=1;
            }    
            str[i]=readl(SPRDAT1);
            printk("receive char = %c \n",str[i]);
            i++;
        }
    }
    port_state = readl(SPCON1);
    port_state &= ~0x07f;
    port_state |= (0<<1 | 0<<1 | 1<<2 | 0<<4 | 0<<5 );
    writel(port_state,SPCON1);
    *(spiRxStr-1)='\0';
    printk("<1> Tx string : %s \n",txStr);
    printk("<1> Rx string : %s \n",rxStr);
    return 0;
}
#endif 

static struct file_operations spi_fops ={
    .owner   = THIS_MODULE,
    .open     = spi_open,
    .release = spi_release,
    .write     = spi_write,
};

static struct miscdevice spi_dev=
{
    123,
    "spi",
    &spi_fops,
};

static int __init spi_init(void)
{
//    unsigned int value;
//    int ret;
    get_sys_addr();

    misc_register(&spi_dev);
#if 0
    ret = register_chrdev(0,spi_name,&spi_fops);
    if(ret<0)
    {
        printk("<1> cannot get major number \n");
        return ret;
    }
    spi_major=ret;
#ifdef CONFIG_DEVFS_FS
    devfs_spi_dir = devfs_mk_dir(NULL,"spi",NULL);
    devfs_spi_raw = devfs_register(devfs_spi_dir,"0",DEVFS_FL_DEFAULT,spi_major,spi_minor,S_IFCHR | S_IRUSR | S_IWUSR,&spi_fops,NULL);
#endif
#endif      
    
    printk(KERN_ALERT "hello,world \n");
    printk("<1> readl(SPTDAT1)=%x ,  SPTDAT1_READ = %x \n",readl(SPTDAT1),(unsigned int)SPTDAT1_READ);

    return 0;
}

static void __exit spi_exit(void)
{
#if 0
#ifdef CONFIG_DEVFS_FS
    devfs_unregister(devfs_spi_raw);
    devfs_unregister(devfs_spi_dir);
#endif 
    unregister_chrdev(spi_major,spi_name);
#endif 
    misc_deregister(&spi_dev);
    printk(KERN_ALERT "goodbye ,cruel world \n");
}

module_init(spi_init);
module_exit(spi_exit);

 

原文地址:http://blog.sina.com.cn/s/blog_5f46d33a0100ol6z.html

 

阅读(409) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~