Hi3516A开发--GV7601 硬件设计
生活随笔
收集整理的這篇文章主要介紹了
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 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);//csHi3516_gpio_setpin(GPIO2_5_SET,Hi3516_gpio_getpin(GPIO2_5_SET)&0xFFFC);//sclkHi3516_gpio_setpin(GPIO2_6_SET,Hi3516_gpio_getpin(GPIO2_6_SET)&0xFFFC);//tdiHi3516_gpio_setpin(GPIO2_7_SET,Hi3516_gpio_getpin(GPIO2_7_SET)&0xFFFC);//tdoHi3516_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 outHi3516_gpio_setpin(GPIO2_DIR,Hi3516_gpio_getpin(GPIO2_DIR)&0xFF8F);//td0 inHi3516_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//lowHi3516_gpio_setpin(IO_ADDRESS(GPIO1_BASE+(1<<8)),Hi3516_gpio_getpin(IO_ADDRESS(GPIO1_BASE+(1<<8)))&(~(1<<(8-2))));udelay(200);//highHi3516_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.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) modulesrm *.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开发--GV7601 硬件设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 产品新人如何快速成长?
- 下一篇: WIN10下怎么找到MYSQL5.7数据