Hi3516A开发--GV7601 SPI通信问题

来源:互联网 发布:小型企业网络设计方案 编辑:程序博客网 时间:2024/06/05 17:07

网上找到一篇关于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 numtypedef 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.oall:    arm-hisiv300-linux-gcc -g -Wall -o ssp_test ssp_test.cmake 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.cclean:@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,编译通过,警告咱就忽略了

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 牙齿咬到舌头了怎么办 舌头起了好多泡怎么办 舌头尖起泡很痛怎么办 舌头上起泡怎么办很疼 月经来了二十多天还不干净怎么办 三岁宝宝缺锌怎么办 无舌苔,舌头很红怎么办 嘴唇上肿了一块怎么办 下嘴唇突然肿了怎么办 上嘴唇突然肿厚怎么办 舌尖上火了好疼怎么办 舌头针扎似的疼怎么办 手麻了怎么办小妙招 月子生气奶少了怎么办 颈椎会引起脸麻怎么办 脑梗引起的手麻怎么办 着凉引起的腰疼怎么办 受凉引起的腰疼怎么办 着凉了腰疼厉害怎么办 腰疼压迫神经腿麻木怎么办 运动后小腿变粗怎么办 跑步后小腿变粗怎么办 嘴腮里面肉肿了怎么办 左胳膊左腿发麻怎么办 右胳膊和右腿麻怎么办 站久了腿肿胀疼怎么办 坐电脑前脖子疼怎么办 一做颈椎就疼怎么办 出了月子腿疼怎么办 坐久了屁股麻木怎么办 搬东西把腰扭了怎么办 蹲时间长了脚麻怎么办 马桶坐久了腿麻怎么办 睡觉手麻怎么办小妙招 手麻了怎么办小妙招吗 腰疼的不能动怎么办 三岁宝宝腿抽筋怎么办 腿抽筋后一直疼怎么办 小腿筋疼怎么办腿无力 小腿里面的筋疼怎么办 腿抽筋,第二天疼怎么办