This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

am335x的GPMC驱动问题



大家好,我用的是异步传输,地址数据不共用地址数据,单独读写,我在board_am335xevm.c下面修改了如下信息

static struct pinmux_config gpmc_fpga_pin_mux[] = {
{"gpmc_ad0.gpmc_ad0", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad1.gpmc_ad1", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad2.gpmc_ad2", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad3.gpmc_ad3", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad4.gpmc_ad4", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad5.gpmc_ad5", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad6.gpmc_ad6", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad7.gpmc_ad7", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad8.gpmc_ad8", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad9.gpmc_ad9", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad10.gpmc_ad10", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad11.gpmc_ad11", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad12.gpmc_ad12", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad13.gpmc_ad13", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad14.gpmc_ad14", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_ad15.gpmc_ad15", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},

{"gpmc_a1.gpmc_a1", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
{"gpmc_a2.gpmc_a2", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
{"gpmc_a3.gpmc_a3", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
{"gpmc_a4.gpmc_a4", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
{"gpmc_a5.gpmc_a5", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
{"gpmc_a6.gpmc_a6", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
{"gpmc_a7.gpmc_a7", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
{"gpmc_a8.gpmc_a8", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},

{"gpmc_csn1.gpmc_csn1", OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
{"gpmc_oen_ren.gpmc_oen_ren", OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
{"gpmc_wen.gpmc_wen", OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
{"gpmc_clk.gpmc_wait1", OMAP_MUX_MODE2 | AM33XX_PIN_INPUT_PULLUP},
{NULL, 0},
};  //引脚的定义

static void gpmc_fpga_init(void)  
{
//struct gpmc_devices_info gpmc_device[2] ={
//{NULL, GPMC_DEVICE_NOR},

//};
//omap_init_gpmc(gpmc_device,sizeof(gpmc_device));
setup_pin_mux(gpmc_fpga_pin_mux);
//omap_init_elm();
}

{gpmc_fpga_init,   DEV_ON_BASEBOARD,PROFILE_ALL},

6个寄存器的配置如下

#define STNOR_GPMC_CONFIG1 0x00251000 
#define STNOR_GPMC_CONFIG2 0x00080801
#define STNOR_GPMC_CONFIG3 0x00020201
#define STNOR_GPMC_CONFIG4 0x0602c662
#define STNOR_GPMC_CONFIG5 0x01050808
#define STNOR_GPMC_CONFIG6 0x05070142
//#define STNOR_GPMC_CONFIG7 0x00000f50

请问各位在board_am335xevm.c中的static void gpmc_fpga_init(void)  函数里是否应该加上omap_init_gpmc(gpmc_device,sizeof(gpmc_device));和omap_init_elm();

  • 驱动是按照网上的一个帖子写的http://bbs.eeworld.com.cn/thread-333652-1-1.html。做了一点修改该,下面是我的驱动

    #define STNOR_GPMC_CONFIG1 0x00251000 //002a2000,28601000
    #define STNOR_GPMC_CONFIG2 0x00080801//0x00011001
    #define STNOR_GPMC_CONFIG3 0x00020201
    #define STNOR_GPMC_CONFIG4 0x0602c662//0x08031003
    #define STNOR_GPMC_CONFIG5 0x01050808//0x000f1111
    #define STNOR_GPMC_CONFIG6 0x05070142//0x0f030080
    //#define STNOR_GPMC_CONFIG7 0x00000f50
    static const u32 gpmc_nor[7] = {
    STNOR_GPMC_CONFIG1,
    STNOR_GPMC_CONFIG2,
    STNOR_GPMC_CONFIG3,
    STNOR_GPMC_CONFIG4,
    STNOR_GPMC_CONFIG5,
    STNOR_GPMC_CONFIG6,
    //STNOR_GPMC_CONFIG7,
    0,

    };

    int fpga_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
    {
    ssize_t status;
    char write_buff[] = "the gpmc driver is ok!";
    switch(cmd)
    {
    case 0:
    if(down_interruptible(&fpga_dev.sem))
    return -ERESTARTSYS;
    fpga_dev.addr = arg;
    printk("\n*********write add = 0x%x\n",fpga_dev.addr);
    //up(&fpga_dev.sem);
    break;
    case 1:
    if(down_interruptible(&fpga_dev.sem))
    return -ERESTARTSYS;
    if(copy_to_user(((char *)arg),write_buff,sizeof(write_buff)+1))
    {
    status = -EFAULT;
    goto read_done_xd;
    }
    //printk("read_buff_done:%s\n\r",write_buff);
    //up(&fpga_dev.sem);
    break;
    default:
    return ENOTTY;
    }

    read_done_xd:
    {
    printk("ioctl done!!\n\r");
    up(&fpga_dev.sem);
    }
    return status;

    }

    static ssize_t fpga_write(struct file *filp, const char __user *buff, size_t count, loff_t *f_pos)
    {
    ssize_t status;
    size_t len = USER_BUFF_SIZE - 1;
    int i,tmp;

    if (count == 0)
    return 0;

    if (down_interruptible(&fpga_dev.sem))
    return -ERESTARTSYS;

    if (len > count)
    len = count;

    memset(fpga_dev.user_buff, 0, USER_BUFF_SIZE);

    if (copy_from_user(fpga_dev.user_buff, buff, len)) {
    status = -EFAULT;
    goto fpga_write_done;
    }

    /* do something with the user data */

    printk("fpga_write_xd\n");
    for (i = 0; i < len; i=i+2) {
    tmp = fpga_dev.user_buff[i] | fpga_dev.user_buff[i+1] << 8;
    writew(tmp,fpga_base+fpga_dev.addr+fpga_dev.addr); //在指定地址里写入数据16BIT;
    }

    for (i = 0; i < len; i++) {
    printk("0x%x ",fpga_dev.user_buff[i]);
    }

    printk("\n");

    fpga_write_done:
    printk("*******before write up sem******\n");

    up(&fpga_dev.sem);
    printk("*******after write up sem******\n");

    return status;
    }


    static ssize_t fpga_read(struct file *filp, const char __user *buff, size_t count, loff_t *f_pos)
    {
    size_t status;
    size_t len = USER_BUFF_SIZE -1;

    if(count == 0)
    return 0;
    printk("*******before read down sem******\n");
    if(down_interruptible( &fpga_dev.sem))
    return -ERESTARTSYS;
    printk("*******after read down sem******\n");
    if(len>count)
    len = count;

    memset(fpga_dev.user_buff,0,USER_BUFF_SIZE);
    printk("*******before readb******\n");
    fpga_dev.user_buff[0]= readb(fpga_base+fpga_dev.addr+fpga_dev.addr);
    fpga_dev.user_buff[1]= readb(fpga_base+fpga_dev.addr+fpga_dev.addr+1);
    printk("fpga_read_xd len= \n");
    if(copy_to_user(buff,fpga_dev.user_buff,len))
    {
    status = -EFAULT;
    goto fpga_read_done;
    }

    fpga_read_done:
    printk("fpga_read_done_xd\n");
    up(&fpga_dev.sem);

    return status;

    }


    static int fpga_open(struct inode *inode, struct file *filp)
    {
    int status = 0;

    if (down_interruptible(&fpga_dev.sem))
    return -ERESTARTSYS;

    if (!fpga_dev.user_buff)
    {
    fpga_dev.user_buff = kmalloc(USER_BUFF_SIZE, GFP_KERNEL);

    if (!fpga_dev.user_buff)
    {
    printk(KERN_ALERT "fpga_open: user_buff alloc failed\n");
    status = -ENOMEM;
    }
    }

    up(&fpga_dev.sem);

    return status;
    }

    static const struct file_operations fpga_fops = {
    .owner = THIS_MODULE,
    .open = fpga_open,
    .read = fpga_read,
    .write = fpga_write,
    .unlocked_ioctl = fpga_ioctl,
    };

    static int __init fpga_init_cdevice(void)
    {
    int error;
    u32 val;

    fpga_dev.devt = MKDEV(251,0);

    error = alloc_chrdev_region(&fpga_dev.devt,0,1,"fpga");
    if (error)
    {
    printk(KERN_ALERT "alloc_chrdev_region() failed: %d\n", error);
    return error;
    }

    cdev_init(&fpga_dev.cdev, &fpga_fops);
    fpga_dev.cdev.owner = THIS_MODULE;

    error = cdev_add(&fpga_dev.cdev, fpga_dev.devt, 1);
    if (error)
    {
    printk(KERN_ALERT "cdev_add() failed: %d\n", error);
    unregister_chrdev_region(fpga_dev.devt, 1);
    return error;
    }

    printk("Getting Chip Select\n");

    val = gpmc_cs_read_reg(GPMC_CS,GPMC_CS_CONFIG7); //关闭片选
    val &= ~GPMC_CONFIG7_CSVALID;
    gpmc_cs_write_reg(GPMC_CS,GPMC_CS_CONFIG7,val);

    gpmc_cs_configure(GPMC_CS, GPMC_SET_IRQ_STATUS, 0); /*set irq status*/
    gpmc_cs_configure(GPMC_CS, GPMC_ENABLE_IRQ, 0); /*disable irqs*/

    gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG1, gpmc_nor[0]);
    gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG2, gpmc_nor[1]);
    gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG3, gpmc_nor[2]);
    gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG4, gpmc_nor[3]);
    gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG5, gpmc_nor[4]);
    gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG6, gpmc_nor[5]);
    //gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG7, gpmc_nor[6]);

    val = gpmc_cs_read_reg(GPMC_CS, GPMC_CS_CONFIG7);
    printk("GPMC_CS_CONFIG7 value 0x%x\n", val);

    if (gpmc_cs_request(GPMC_CS, SZ_2K, (unsigned long *)&mem_base) < 0)
    {
    printk(KERN_ERR "Failed request for GPMC mem for usrp_e\n");
    return -1;
    }

    printk("Got CS2, address = %lx\n", mem_base);

    if (!request_mem_region(mem_base, SZ_2K, "mem_fpga"))
    {
    printk(KERN_ERR "Request_mem_region failed.\n");
    gpmc_cs_free(GPMC_CS);
    return -1;
    }

    fpga_base = ioremap(mem_base, SZ_2K);

    gpmc_cs_configure(GPMC_CS, GPMC_ENABLE_IRQ, 1);

    val = gpmc_cs_read_reg(GPMC_CS,GPMC_CS_CONFIG7);
    val |= GPMC_CONFIG7_CSVALID;
    gpmc_cs_write_reg(GPMC_CS,GPMC_CS_CONFIG7,val);

    return 0;
    }

    static int __init fpga_init_class(void)
    {
    struct device *device;

    fpga_dev.class = class_create(THIS_MODULE, "fpga");

    if (IS_ERR(fpga_dev.class))
    {
    printk(KERN_ALERT "class_create(fpga) failed\n");
    return PTR_ERR(fpga_dev.class);
    }

    device = device_create(fpga_dev.class, NULL, fpga_dev.devt, NULL, "fpga");

    if (IS_ERR(device))
    {
    class_destroy(fpga_dev.class);
    return PTR_ERR(device);
    }

    return 0;
    }

    static int __init fpga_init(void)
    {
    printk(KERN_INFO "fpga_init()\n");

    memset(&fpga_dev, 0, sizeof(struct fpga_dev));

    sema_init(&fpga_dev.sem, 1);

    if (fpga_init_cdevice())
    goto init_fail_1;

    if (fpga_init_class())
    goto init_fail_2;

    return 0;

    init_fail_2:
    cdev_del(&fpga_dev.cdev);
    unregister_chrdev_region(fpga_dev.devt, 1);

    init_fail_1:

    return -1;
    }
    module_init(fpga_init);

    static void __exit fpga_exit(void)
    {
    printk(KERN_INFO "fpga_exit()\n");

    device_destroy(fpga_dev.class, fpga_dev.devt);
    class_destroy(fpga_dev.class);

    cdev_del(&fpga_dev.cdev);
    unregister_chrdev_region(fpga_dev.devt, 1);

    release_mem_region(mem_base, SZ_2K);
    gpmc_cs_free(GPMC_CS);
    iounmap(fpga_base);

    if (fpga_dev.user_buff)
    kfree(fpga_dev.user_buff);
    }
    module_exit(fpga_exit);



  • int fd,i,res;
    unsigned char buf[PAGE_SIZE];

    unsigned char read_buff[2];

    printf("GPMC Test start\n\r");
    fd=open(FPGA_DEV,O_RDWR);
    if(fd<0)
    {
    printf("Can't Open %s !!!\n\r",FPGA_DEV);
    return -1;
    }


    for(i=0;i<sizeof(buf);i++)
    {
    buf[i] = i%256;
    }

    ioctl(fd,0,0xaa);
    //ioctl(fd,1,read_buff);
    //printf("%s\n\r",read_buff);


    for(i=0;i<100;i++)
    {
    write(fd,&buf,PAGE_SIZE);
    }
    //read(fd,&read_buff,2);
    //printf(" read from gpmc : 0x%x,0x%x\n\r",read_buff[1],read_buff[0]);

    close(fd);
    return 0;

    这个是测试程序,但是每次都只写入一次10个字节,到下一个循环式就卡死了

    在第二fpga_write那里就卡住了。。。

    printk("fpga_write_xd\n");
    for (i = 0; i < len; i=i+2) {
    tmp = fpga_dev.user_buff[i] | fpga_dev.user_buff[i+1] << 8;
    writew(tmp,fpga_base+fpga_dev.addr+fpga_dev.addr); //在指定地址里写入数据16BIT;
    }

    求大家帮忙分析

  • 进一步发现在第二轮写时在写第7第8字节时就卡在了writew。不知道什么原因

  • 很多客户都是参考那个帖子写的FPGA读写代码,能够正常工作的。但是具体FPGA的读写时序和工作方式不一样,需要修改GPMC的配置

  • 谢谢,是config配置的问题,问一下,为什么我每次配置了wait后就传不了数据,就像上面说的一样,数据卡死,取消wait就一切正常

  • 请问如何使用wait信号,是不是只要设置寄存器就可以了,要申请中断号吗?

  • 我们的TRM的7.1.3.3.8.3里面有有关wait信号的使用,应该是不需要中断的,也没看到系统中断list里面有这个中断号。

    其实wait这个信号主要还是接NAND或者NOR才用的

  • 有个中断使能寄存器

    这里也有关于wait信号中断的说明,所以想问是不是只要设置寄存器就可以,不需要自己写中断处理函数,系统会自己插入时钟?

  • jian  你好

    am335x   能和fpga通信吗???    如果能通信., 用什么接口,   用什么方式?  

  • 你好,请问你有没有写相关的博客,刚好做这个方向,一头雾水