Hi3516A开发--GV7601 硬件设计

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

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



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

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

/*生成ko文件源代码*/
#include <linux/module.h> 
#include <linux/types.h> 
#include <linux/kernel.h> 
#include <linux/init.h> 
#include <linux/ioport.h> 
#include <asm/uaccess.h> 
#include <linux/delay.h> 
//#include <bsp.h> 
#include <asm/io.h>



#include <linux/sched.h>
#include <linux/delay.h>   //OK
#include <linux/fs.h>  //OK

#include <asm/irq.h>  //OK
//#include <mach/regs-gpio.h>  
//#include <mach/hardware.h>  //OK  


#include <linux/miscdevice.h>  /**鍐呮牳鐗堟湰2.6.32鍔犱互涓嬪ご鏂囦欢***/
//#include <mach/regs-gpio.h>
#include <linux/mm.h>  //OK
#include <linux/pci.h>  //OK
#include <linux/moduleparam.h>  //OK
#include <linux/slab.h>  //OK
#include <linux/errno.h>  //OK
#include <linux/ioctl.h>  //OK
#include <linux/cdev.h>   //OK
#include <linux/string.h>  //OK
#include <linux/list.h>  //OK


#include <asm/atomic.h>
#include <asm/unistd.h>

#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<<pin)),Hi3516_gpio_getpin(IO_ADDRESS(GPIO2_BASE+(1<<pin)))|(1<<(pin-2)));
    return 0; 
} 

//管脚拉低
static int spi_setlow(int pin) 
{ 
        Hi3516_gpio_setpin(GPIO2_DIR,Hi3516_gpio_getpin(GPIO2_DIR)|(1<<(pin-2)));
        Hi3516_gpio_setpin(IO_ADDRESS(GPIO2_BASE+(1<<pin)),Hi3516_gpio_getpin(IO_ADDRESS(GPIO2_BASE+(1<<pin)))&(~(1<<(pin-2))));
    return 0; 
} 


// cs    --4
// sclik --5
// tdi         --6
// tdo         --7
// 读管脚数据
static unsigned int spi_readIO_gv7601(int pin) 
{ 
        int i;
        Hi3516_gpio_setpin(GPIO2_DIR,Hi3516_gpio_getpin(GPIO2_DIR)&(~(1<<(pin-2))));
        i=Hi3516_gpio_getpin(IO_ADDRESS(GPIO2_BASE+(1<<pin)));
        if (i!=0)
                i=1;
        return i;
} 

// select pin used for gpio 配置管脚为GPIO
// 换成海思的管脚配置即可
static int spi_init_gv7601() 
{ 
        //配置成GPIO口
        Hi3516_gpio_setpin(GPIO2_4_SET,Hi3516_gpio_getpin(GPIO2_4_SET)&0xFFFC);//cs
        Hi3516_gpio_setpin(GPIO2_5_SET,Hi3516_gpio_getpin(GPIO2_5_SET)&0xFFFC);//sclk
        Hi3516_gpio_setpin(GPIO2_6_SET,Hi3516_gpio_getpin(GPIO2_6_SET)&0xFFFC);//tdi
        Hi3516_gpio_setpin(GPIO2_7_SET,Hi3516_gpio_getpin(GPIO2_7_SET)&0xFFFC);//tdo
        Hi3516_gpio_setpin(GPIO1_6_SET,Hi3516_gpio_getpin(GPIO1_6_SET)&0xFFFC);//reset
        
        //配置GPIO输入输出方向
        Hi3516_gpio_setpin(GPIO2_DIR,Hi3516_gpio_getpin(GPIO2_DIR)|0x0070);//cs sclk tdi out
        Hi3516_gpio_setpin(GPIO2_DIR,Hi3516_gpio_getpin(GPIO2_DIR)&0xFF8F);//td0 in
        Hi3516_gpio_setpin(GPIO1_DIR,Hi3516_gpio_getpin(GPIO2_DIR)|0x0040);//reset out
        //除clk以外全部置高
        spi_sethigh(6);
        spi_setlow(7);
        spi_sethigh(8);
        spi_sethigh(9);
    return 0; 
} 

void SPI_send_gv7601(unsigned short address,unsigned short wdata) 
{     
    unsigned short vsignbit; 
        // 写地址   16位
        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);        
    } 
        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 <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <sys/ioctl.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <sys/select.h>  
#include <sys/time.h>  
#include <errno.h>  
#include <string.h>
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,编译通过,警告咱就忽略了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

聚优致成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值