Hi3516A开发--GV7601 硬件设计

GV7601 硬件部分官方手册上有给一些示例,但是不太完整。

这里贴出我们设计的原理图,仅供参考。



网上找到一篇关于GV7601 SPI通信的例子

参看:海思3531 GV7601 SPI通信问题

/*生成ko文件源代码*/
#include  
#include  
#include  
#include  
#include  
#include  
#include  
//#include  
#include 



#include 
#include    //OK
#include   //OK

#include   //OK
//#include   
//#include   //OK  


#include   /**鍐呮牳鐗堟湰2.6.32鍔犱互涓嬪ご鏂囦欢***/
//#include 
#include   //OK
#include   //OK
#include   //OK
#include   //OK
#include   //OK
#include   //OK
#include    //OK
#include   //OK
#include   //OK


#include 
#include 

#define PDEBUG 
#ifdef PDEBUG 
    #define PLOG(fmt,args...) printk(fmt,##args) 
#else 
    #define PLOG(fmt,args...) /*do nothing*/ 
#endif 

#define DEVICE_NAME "GV7601"  
#define GV7601_MAJOR 230  //device num


typedef struct tem{
unsigned short address;
unsigned short value;
}command;

command temp;

//寄存器读写定义
#define HW_REG(reg)  *((volatile unsigned long *)(reg))
#define Hi3516_gpio_cfgpin(addr,dir) HW_REG(addr) = dir
#define Hi3516_gpio_setpin(addr,value) HW_REG(addr) = value
#define Hi3516_gpio_getpin(addr) HW_REG(addr)

//定义地址偏移
#define CPU_BASE 0x200F0000
#define OFFSET_GPIO2_4 0x00A4  //cs
#define OFFSET_GPIO2_5 0x00A8  //SCLK
#define OFFSET_GPIO2_6 0x00AC  //TDI
#define OFFSET_GPIO2_7 0x00B0  //TDO

#define GPIO2_4_SET IO_ADDRESS(0x200F00A4) 
#define GPIO2_5_SET IO_ADDRESS(0x200F00A8)  
#define GPIO2_6_SET IO_ADDRESS(0x200F00AC)
#define GPIO2_7_SET IO_ADDRESS(0x200F00B0)
#define GPIO1_6_SET IO_ADDRESS(0x200F00D4)

#define GPIO2_BASE 0x20170000
#define GPIO1_BASE 0x20160000
#define GPIO_DIR 0x400
#define GPIO_DATA2_4                IO_ADDRESS(0x20170040) //CS   1<<6 IO_ADDRESS(GPIO2_BASE+(1<<4))
#define GPIO_DATA2_5                IO_ADDRESS(0x20170080) //sclk 1<<7
#define GPIO_DATA2_6                IO_ADDRESS(0x20170100) //tdi  1<<8
#define GPIO_DATA2_7                IO_ADDRESS(0x20170200) //tdo  1<<9
#define GPIO_DATA1_6                IO_ADDRESS(0x20160100) //reset 1<<8


#define GPIO2_DIR IO_ADDRESS(0x20170400)
#define GPIO1_DIR IO_ADDRESS(0x20160400)


#define PIN_SDO 9 // 
#define PIN_SDI 8 
#define PIN_SCLK 7 
#define PIN_CS 6 // 

#define SPI_CMD 0 
#define SPI_DATA 1 
#define FUN_GPIO    0 

static int spi_setcs_gv7601(int ) ;
static int spi_sethigh(int );
static int spi_setlow(int ) ;
static unsigned int spi_readIO_gv7601(int ) ;
static int spi_init_gv7601(void) ;
void SPI_send_gv7601(unsigned short,unsigned short ) ;
unsigned short spi_read_gv7601(unsigned short ) ;
static ssize_t spi_write_data_gv7601(struct file *, command __user *, size_t , loff_t *);
static ssize_t spi_read_data_gv7601(struct file *, command __user *, size_t , loff_t *);
static void set_value(void) ;
static int gv7601_ioctl(struct inode *,struct file *,unsigned int ,unsigned long );


// 换成海思的片选信号,两路,低选中一路,高选中一路
static int spi_setcs_gv7601(int number) 
{ 
        switch(number)
                {
                case 1:
                        Hi3516_gpio_setpin(GPIO_DATA2_4,Hi3516_gpio_getpin(GPIO_DATA2_4)&0xFFEF); //拉低
                break;
                case 2:
                        Hi3516_gpio_setpin(GPIO_DATA2_4,Hi3516_gpio_getpin(GPIO_DATA2_4)|0x0010); //拉高
                break; 
                }
    return 0; 
} 


// set gpio pin level, high: 1, low: 0 
// cs    --6
// sclik --7
// tdi         --8
// tdo         --9
// 管脚拉高
static int spi_sethigh(int pin) 
{ 
        Hi3516_gpio_setpin(GPIO2_DIR,Hi3516_gpio_getpin(GPIO2_DIR)|(1<<(pin-2)));
        Hi3516_gpio_setpin(IO_ADDRESS(GPIO2_BASE+(1<0;vsignbit>>=1) 
    {     
                if(address&vsignbit) 
            spi_sethigh(PIN_SDI);
        else 
            spi_setlow(PIN_SDI);
                ndelay(1000);
                spi_setlow(PIN_SCLK);
        ndelay(2000); 
        spi_sethigh(PIN_SCLK); 
        ndelay(1000);        
    } 
        ndelay(1000); 
        spi_setlow(PIN_SCLK);
        //spi_setlow(PIN_SDI);
        //spi_setlow(PIN_SDO);
        udelay(100);
        //写数据 16位        
        for(vsignbit=0x8000;vsignbit>0;vsignbit>>=1) 
    {     
                if(wdata&vsignbit) 
            spi_sethigh(PIN_SDI);
        else 
            spi_setlow(PIN_SDI);
                ndelay(1000);
                spi_setlow(PIN_SCLK);
        ndelay(2000); 
        spi_sethigh(PIN_SCLK); 
        ndelay(1000);   
                
    } 
    //spi_sethigh(PIN_SDI);
    ndelay(1000); 
        spi_setlow(PIN_SCLK);
        //spi_setlow(PIN_SCLK);
        //udelay(300);
        //spi_setlow(PIN_SDI);
        ndelay(1000);
        spi_sethigh(PIN_CS);
}  

unsigned short spi_read_gv7601(unsigned short address) 
{     
    unsigned short vsignbit,r_data=0; 
        //写命令字
        spi_setlow(PIN_CS);
        ndelay(1000);
            for(vsignbit=0x8000;vsignbit>0;vsignbit>>=1) 
    {     
                if(address&vsignbit) 
            spi_sethigh(PIN_SDI);
        else 
            spi_setlow(PIN_SDI);
                ndelay(1000);
                spi_setlow(PIN_SCLK);
        ndelay(2000); 
        spi_sethigh(PIN_SCLK); 
        ndelay(1000);           
    } 
    //spi_sethigh(PIN_SDI);
        ndelay(1000);
        spi_setlow(PIN_SCLK);
        //udelay(300);
        spi_setlow(PIN_SDI);


        udelay(10);
        for(vsignbit=0x8000;vsignbit>0;vsignbit>>=1) 
    { 
                spi_setlow(PIN_SCLK);
                ndelay(1000);

        if(spi_readIO_gv7601(PIN_SDO)) //读 TDO
        {     
            r_data = r_data|vsignbit; 
        } 
                ndelay(1000); 
        spi_sethigh(PIN_SCLK); 
        ndelay(2000);        
    } 
        spi_setlow(PIN_SCLK);
        ndelay(1000);
        spi_sethigh(PIN_CS);
    return r_data;     
} 

//向寄存器写入数据
static ssize_t spi_write_data_gv7601(struct file *pFile, command __user *pData, size_t count, loff_t *off)
{
        printk("in the write function\n");
        
        //加片选?
        //ndelay(100);
        memcpy(&temp,pData,count);
        unsigned short address, wdata;
        address = temp.address;
        unsigned short writecommand = 0x0000;
        wdata = temp.value;
        writecommand = writecommand + address;
        SPI_send_gv7601(writecommand,wdata);
        //udelay(300);
        //SPI_send_gv7601(wdata);
        
        //spi_setlow(PIN_SCLK);
        return count;
}

static ssize_t spi_read_data_gv7601(struct file *pFile, command __user *pData, size_t count, loff_t *off)
{
        //加片选?
        printk("in the read function\n");

        unsigned short writecommand = 0x8000;
        memcpy(&temp,pData,count);
        writecommand = writecommand + temp.address;
        //SPI_send_gv7601(writecommand);
        //udelay(300);
        temp.value=spi_read_gv7601(writecommand);
        int ret;
        ret=copy_to_user(pData, &temp, sizeof(temp));    
    if(ret>0)  
    {  
      printk("copy data failed\n");  
      return -1;  
    }
        
        //spi_setlow(PIN_SCLK);
        return count;
}
static void set_value() 
{ 
    //初始化配置
} 

static int gv7601_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{ 
return 0;   
}

static struct file_operations gv7601_fops = {  
.owner = THIS_MODULE,  
.compat_ioctl = gv7601_ioctl,  
.read = spi_read_data_gv7601,  
.write = spi_write_data_gv7601,
};  

static int __init spi_gv7601_init(void) 
{ 
    int ret;  
    ret = register_chrdev(GV7601_MAJOR, DEVICE_NAME, &gv7601_fops);  
    if (ret < 0) {  
       printk(DEVICE_NAME " can't register major number\n");  
       return ret; 
            }
    printk("Register spi control.\n"); 
    spi_init_gv7601(); 
        //reset the device

        //low
        Hi3516_gpio_setpin(IO_ADDRESS(GPIO1_BASE+(1<<8)),Hi3516_gpio_getpin(IO_ADDRESS(GPIO1_BASE+(1<<8)))&(~(1<<(8-2))));
        udelay(200);
        //high
        Hi3516_gpio_setpin(IO_ADDRESS(GPIO1_BASE+(1<<8)),Hi3516_gpio_getpin(IO_ADDRESS(GPIO1_BASE+(1<<8)))|(1<<(8-2)));
    //spi_setcs_gv7601(1); 
    //ndelay(20);     
    //set_value(); 
    //spi_setcs_gv7601(2); 
    return 0; 
}     
static void __exit spi_gv7601_exit(void) 
{ 
    unregister_chrdev(GV7601_MAJOR, DEVICE_NAME); 
    printk(KERN_INFO "unregister spi control.\n"); 
     
} 
module_init(spi_gv7601_init); 
module_exit(spi_gv7601_exit); 
MODULE_LICENSE("GSPI"); 
MODULE_AUTHOR("Dong 100"); 
MODULE_VERSION("0.1"); 
MODULE_DESCRIPTION("gv7601 control driver"); 
/*读取的测试程序*/
#include   
#include   
#include   
#include   
#include   
#include   
#include   
#include   
#include   
#include   
#include 
typedef struct tem{
unsigned short address;
unsigned short value;
}command;
command temp;

int main(int argc, char *argv[])  
{
        
        //printf("~~~~%s~~~~~",argv[1]);
        //printf("....%c....",*argv[1]+1);


        //printf("the char size is %d",sizeof(char));
        //printf("the number is %d",strlen(argv[1]));
        if (argc<=1||argc>3)
                {
                printf("wrong command \n ./test_spi 000 for read from 000H\n ./test_spi 000 0012 for write 0012 to adress 000H\n");
                return 0;
                }
        else if (argc==2)
                {
                if (strlen(argv[1])>3)
                        {
                        printf("address is too long, 12bits max");
                        return 0;
                        }
        char a;
        int i;
        unsigned short result=0;
                printf("read address command\n");
        for (i=1;i<=strlen(argv[1]);i++)
        {        
        a=*(argv[1]+i-1);

        if (a>='0'&&a<='9')
                a=a-'0';
        else if (a>='a'&&a<='f')
                a=a-'a'+10;
        else if (a>='A'&&a<='F')
                a=a-'A'+10;
        else 
                return 0;
        //printf("now a is %x",a);
        //j=strlen(argv[1])-i;
        result=result+a;
        if (i!=strlen(argv[1]))
                result=result<<4;
        }
        
        printf("read from address%x\n",result);
        int fd;
        fd = open("/dev/spi_g",2);
        printf("open fd is %d\n",fd);
        int ret;
        temp.address=result;
        temp.value=0x0000;
        ret=read(fd,&temp,sizeof(temp));
        printf("read value is %x\n",temp.value);
                }
        else
                {
                
                if (strlen(argv[1])>3)
                        {
                        printf("address is too long, 12bits max");
                        return 0;
                        }
                if (strlen(argv[2])>4)
                        {
                        printf("data is too long, 16bits max");
                        return 0;
                        }
                char a;
                int i;
                unsigned short result,result2=0;
                //printf("read address command");
                printf("write to address comand\n");
                result=0;
                for (i=1;i<=strlen(argv[1]);i++)
                {        
                a=*(argv[1]+i-1);

                if (a>='0'&&a<='9')
                a=a-'0';
                else if (a>='a'&&a<='f')
                a=a-'a'+10;
                else if (a>='A'&&a<='F')
                a=a-'A'+10;
                else 
                return 0;
        //printf("now a is %x",a);
        //j=strlen(argv[1])-i;
                result=result+a;
                if (i!=strlen(argv[1]))
                result=result<<4;
                }

                result2=0;
                for (i=1;i<=strlen(argv[2]);i++)
                {        
                a=*(argv[2]+i-1);

                if (a>='0'&&a<='9')
                a=a-'0';
                else if (a>='a'&&a<='f')
                a=a-'a'+10;
                else if (a>='A'&&a<='F')
                a=a-'A'+10;
                else 
                return 0;
        //printf("now a is %x",a);
        //j=strlen(argv[1])-i;
                result2=result2+a;
                if (i!=strlen(argv[2]))
                result2=result2<<4;
                }
        printf("write to address%x,data is %x\n",result,result2);
        int fd;
        fd = open("/dev/spi_g",2);
        printf("open fd is %d\n",fd);
        int ret;
        temp.address=result;
        temp.value=result2;
        ret=write(fd,&temp,sizeof(temp));
        //printf("read value is %x\n",temp.value);

                        
                }
        
        
        return 0;

}


/*Makefile*/
obj-m += ssp.o
all:    
	arm-hisiv300-linux-gcc -g -Wall -o ssp_test ssp_test.c
	make ARCH=arm CROSS_COMPILE=arm-hisiv300-linux- -C /home/zslf/hi3516a/Hi3516A_SDK_V1.0.5.0/osdrv/opensource/kernel/linux-3.4.y SUBDIRS=$(PWD) modules
	 rm *.o modules.* *.symvers *.mod.c
clean:
	@rm -rf ssp_test 
	make ARCH=arm CROSS_COMPILE=arm-hisiv300-linux- -C /home/zslf/hi3516a/Hi3516A_SDK_V1.0.5.0/osdrv/opensource/kernel/linux-3.4.y SUBDIRS=$(PWD) clean

按源码执行会出现错误:

/home/zslf/hi3516a/Hi3516A_SDK_V1.0.5.0/tools_test/spi测试/ssp.c:334:1: error: unknown field ‘ioctl’ specified in initializer
 .ioctl = gv7601_ioctl,  
 ^

问题是由于2.6.36内核之后 去掉了原来的ioctl,添加两个新的成员,所以会出错
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
所以修改源文件中file_operations内.ioctl 改为 .compat_ioctl 即可OK,编译通过,警告咱就忽略了

你可能感兴趣的:(Hi3516A开发,Hi3516A开发)