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
- Hi3516A开发--GV7601 SPI通信问题
- Hi3516A开发--I2C/SPI读写命令
- DM8168平台中完成gv7601的spi总线驱动笔记
- stm8s开发(七) SPI的使用:SPI主机通信!
- Hi3516A开发--内存换算
- Hi3516A开发--根文件系统
- Hi3516A开发--目录分析
- Hi3516A开发--以太网
- Hi3516A开发--接触
- Hi3516A开发--/etc/passwd
- Hi3516A开发--RTC电路
- Hi3516A开发--视频接口
- Hi3516A开发--视频接口
- Hi3516A开发-- 常见问题FAQs
- Hi3516A编译内核问题
- SPI通信
- SPI通信
- spi通信
- LeetCode OJ-23-Merge k Sorted Lists
- 经典SQL语句大全——(三)经典-数据开发
- 天坦android端架构设计
- java集合包总结(添加、删除等操作实现原理)
- 剑指offer--面试题13:在O(1)时间删除链表节点
- Hi3516A开发--GV7601 SPI通信问题
- 流媒体协议介绍(rtp/rtcp/rtsp/rtmp/mms/hls)【转】
- REST学习
- 博客搬家啦
- Swift和Objective-C中的属性特性
- Android安全加密:Https编程
- Android 插件化 热修复 动态部署 2016 Android插件化框架和热修复技术的资料收集和汇总
- c++指针基础总结
- python3抓取糗百图片