heroMS

heroMS

0个粉丝

3

问答

0

专栏

0

资料

heroMS  发布于  2016-02-18 17:59:23
采纳率 0%
3个问答
10009

海思3531 GV7601 SPI通信问题

 
在调海思3531加GV7601采集SDI的项目,现在遇到了这样的问题:

用海思的硬件SPI去读取7601的寄存器,但是读取的寄存器值总是为0;使用示波器测量DI信号线得到如下波形,前面电平幅值正常的是地址部分,后面电平幅值异常的是数据部分,因为数据部分的电平幅值1V不到,所以被SPI判断为0了。

请问这样的现象可能是什么原因呢?

麻烦论坛里的朋友们帮忙分析下,谢谢了。
我来回答
回答11个
时间排序
认可量排序

heroMS

0个粉丝

3

问答

0

专栏

0

资料

heroMS 2016-02-20 11:52:24
认可0
有懂得朋友可以过来分析下吗?帖子不要就这么沉咯

1305_xiaolong

0个粉丝

3

问答

0

专栏

0

资料

1305_xiaolong 2016-02-22 10:33:04
认可0
gv7601不是应该是四线的spi么?clk cs tdi tdo?地址部分的时候TDO复制TDI的部分(为了实现多片串联),数据部分TDO发送,3531接收。另3531部分的SPI是使用的GPIO模拟还是片上SPI?我回头找找以前3520上写的GPIO模拟的SPI读取GV7601的代码,找到的话发你看看。
在3531端的接收管脚要设置成输入模式啊,是不是因为默认输出低导致GV7601没有拉高?

1305_xiaolong

0个粉丝

3

问答

0

专栏

0

资料

1305_xiaolong 2016-02-22 10:50:13
认可0
还真找到了当时的一点代码,不知道有没有用:
##########生成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<     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<     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<         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,  
.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;

}

heroMS

0个粉丝

3

问答

0

专栏

0

资料

heroMS 2016-02-22 16:36:31
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=25558&ptid=10121]1305_xiaolong 发表于 2016-2-22 10:33[/url]
gv7601不是应该是四线的spi么?clk cs tdi tdo?地址部分的时候TDO复制TDI的部分(为了实现多片串联),数 ...[/quote]

是的,是4线的SPI,地址部分的波形是正常的,问题是数据部分的波形不正常,幅值太低了;3531使用的SPi是片上的SPi;3531端对于SPI的几个引脚复用寄存器都设置好了,还要设置为输入模式吗?这个应该和海思端的配置关系不大吧,因为不正常的数据是由7601发出来的,所以海思这边作为接收端来说,无论怎么配置,波形都不正常的话,SPI应该是读不到数据的,现在就是弄不明白为什么数据部分被拉低了,看了7601的数据手册,里面没有提到这样相关的东西。

终于有人回复我了,非常感谢~

我现在gv7601是能用了,可以采集到SDI视频了,但是SPI总线还是没弄好,没法去配置7601的寄存器。

1305_xiaolong

0个粉丝

3

问答

0

专栏

0

资料

1305_xiaolong 2016-02-23 09:48:45
认可0
本帖最后由 1305_xiaolong 于 2016-2-23 09:50 编辑

[quote][url=forum.php?mod=redirect&goto=findpost&pid=25579&ptid=10121]heroMS 发表于 2016-2-22 16:36[/url]
是的,是4线的SPI,地址部分的波形是正常的,问题是数据部分的波形不正常,幅值太低了;3531使用的SPi是 ...[/quote]

四线的话,那你给的图测的是哪根线呢?是gv7601的DI,还是DO?因为输入输出是分开的啊。如果是DO的话,前半部分是7601复制自己DI输入的地址波形,这时候7601是可以把波形拉高的(即正常的),而后半部分却不能拉高。。这也不好说是硬件的问题啊,毕竟两部分都是7601发出的,硬件问题不能一会可以一会不可以吧。如果是DI的话,更不科学啊,发送完地址应该就一直低了吧?
用的片上SPI确实不需要设置输入了,直接设置成SPI模式就行。用片上SPI是不是得发送保持数据来着?忘记了。。就是发送完地址后发送任意的数据来保持时钟,从设备才能放数据?
当时我是自己用gpio模拟的,照着时序图搞的,我记得当时地址比特数还挺特殊的来着。
另gv7601不配置也是能自动lock识别视频的,但是没有spi不好读取寄存器来识别当前视频的分辨率之类的。
我觉得先分析问题是硬件问题还是软件问题,把DI,DO,clk,cs一起测测看,与手册的图对比对比。cs不是根据spi模式也分两种的么,一种跟随读写高低变化,一种直接拉低就行,已忘记7601是哪种了。。。

heroMS

0个粉丝

3

问答

0

专栏

0

资料

heroMS 2017-12-19 20:47:37
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=25592&ptid=10121]1305_xiaolong 发表于 2016-2-23 09:48[/url]
四线的话,那你给的图测的是哪根线呢?是gv7601的DI,还是DO?因为输入输出是分开的啊。如果是DO的话, ...[/quote]

抱歉这么久才回复;问题最近在项目改版的时候解决了,问题定位是硬件的SPI菊花链使用有误,软件上直接按照SDK驱动来就可以读写寄存器了。感谢你给我的回复。

gcp

0个粉丝

0

问答

12

专栏

0

资料

gcp 2018-03-07 17:40:32
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=82347&ptid=10121]heroMS 发表于 2017-12-19 20:47[/url]
抱歉这么久才回复;问题最近在项目改版的时候解决了,问题定位是硬件的SPI菊花链使用有误,软件上直接按 ...[/quote]

麻烦能把出现这种情况的问题说的具体一点么?我的情况和你一样,SDI视频能够接入,但是读出的gv7601寄存器值全0,而且无法设置寄存器的值。

xmm2018

0个粉丝

1

问答

0

专栏

0

资料

xmm2018 2019-11-08 15:38:35
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=84992&ptid=10121]gcp_2017 发表于 2018-3-7 17:40[/url]
麻烦能把出现这种情况的问题说的具体一点么?我的情况和你一样,SDI视频能够接入,但是读出的gv7601寄存 ...[/quote]

SDK中的SPI DEVADDR是什么意思,怎么会有一个设备地址,SPI设备哪来的设备地址?

hero

0个粉丝

1

问答

0

专栏

0

资料

hero 2017-12-20 13:50:26
认可0
marking.........

gcp

0个粉丝

0

问答

12

专栏

0

资料

gcp 2018-03-01 16:49:02
认可0
学习中。。。。。。

hero

0个粉丝

1

问答

0

专栏

0

资料

hero 2018-03-02 08:16:31
认可0
:victory::victory::victory:
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
相关问答
无更多相似问答 去提问
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区