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接口与FPGA通讯驱动问题

Other Parts Discussed in Thread: AM3358, SYSCONFIG

我使用AM3358通过GPMC与FPG使用异步通讯方式通讯,参考网上资料blog.chinaunix.net/uid-24159092-id-3355612.html。将GPMC驱动程序添加到board-am335xevm.c文件中,调试时出现问题:驱动程序中包含module_init(fpga_init);时,Linux无法正确启动,打印信息为:starting kernel  .....     uncompressing linux..done, booting the kernel.程序运行到这里,卡住。当注释掉module_init(fpga_init);,linux可以正确启动,求解。

  • 一步一步做应该是没问题的,我按照那个步骤做过

    没出现你说的这个问题

    你是怎么把GPMC驱动程序添加到board-am335xevm.c文件中的

  • pinmux初始化是要放在board-am335xevm.c中的。

    整个驱动加载是要按照Linux的驱动加载方法做的,建议你去网上找一些驱动加载的例程学习下

  • 你好,我将pinmux初始化添加到board-am335xev.c中,在/driver目录下新建文件夹fpga,在里面添加fpga.c  Kconfig   Makefile三个文件。

    fpag.c内容为:

    /*
    Char device driver fpga.
    Do a global replace of 'fpga' with your driver name.
    */

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/fs.h>
    #include <linux/cdev.h>
    #include <asm/uaccess.h>
    #include <linux/string.h>
    #include <linux/kernel.h>
    #include <linux/device.h>
    #include <linux/slab.h>
    #include <linux/gpio.h>

    #include <plat/gpmc.h>
    #include "plat/gpio.h"
    #include "plat/dma.h"

    #include "asm/uaccess.h"
    #include "asm/io.h"
    #include "asm/atomic.h"

    #include <linux/io.h>
    #include <linux/delay.h>
    #include <linux/types.h>
    #include <mach/gpio.h>
    #include <plat/mux.h>


    #define USER_BUFF_SIZE 128


    struct fpga_dev {
    dev_t devt;
    struct cdev cdev;
    struct semaphore sem;
    struct class *class;
    char *user_buff;
    };

    static struct fpga_dev fpga_dev;

    unsigned long mem_base;
    static void __iomem *fpga_base;
    static void __iomem *gpmc_base;

    /* GPMC register offsets */
    #define GPMC_REVISION 0x00
    #define GPMC_SYSCONFIG 0x10
    #define GPMC_SYSSTATUS 0x14
    #define GPMC_IRQSTATUS 0x18
    #define GPMC_IRQENABLE 0x1c
    #define GPMC_TIMEOUT_CONTROL 0x40
    #define GPMC_ERR_ADDRESS 0x44
    #define GPMC_ERR_TYPE 0x48
    #define GPMC_CONFIG 0x50
    #define GPMC_STATUS 0x54
    #define GPMC_PREFETCH_CONFIG1 0x1e0
    #define GPMC_PREFETCH_CONFIG2 0x1e4
    #define GPMC_PREFETCH_CONTROL 0x1ec
    #define GPMC_PREFETCH_STATUS 0x1f0
    #define GPMC_ECC_CONFIG 0x1f4
    #define GPMC_ECC_CONTROL 0x1f8
    #define GPMC_ECC_SIZE_CONFIG 0x1fc
    #define GPMC_ECC1_RESULT 0x200
    #define GPMC_ECC_BCH_RESULT_0 0x240

    #define GPMC_BASE_ADDR 0x50000000
    #define GPMC_CS 1
    #define GPMC_CS0 0x60
    #define GPMC_CS_SIZE 0x30
    #if 0
    #define STNOR_GPMC_CONFIG1 0x28601000
    #define STNOR_GPMC_CONFIG2 0x00011001
    #define STNOR_GPMC_CONFIG3 0x00020201
    #define STNOR_GPMC_CONFIG4 0x08031003
    #define STNOR_GPMC_CONFIG5 0x000f1111
    #define STNOR_GPMC_CONFIG6 0x0f030080
    #endif
    #define STNOR_GPMC_CONFIG1 0x00000000
    #define STNOR_GPMC_CONFIG2 0x001e1f00
    #define STNOR_GPMC_CONFIG3 0x001f1f00
    #define STNOR_GPMC_CONFIG4 0x1f03ff31
    #define STNOR_GPMC_CONFIG5 0x001c1f1f
    #define STNOR_GPMC_CONFIG6 0x8f070080
    #define STNOR_GPMC_CONFIG7 0x00000050
    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
    };

    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 \n");
    for (i = 0; i < len; i=i+2) {
    //tmp = fpga_dev.user_buff | fpga_dev.user_buff[i+1] << 8;
    tmp = fpga_dev.user_buff[i];
    writew(tmp,fpga_base+i);
    }

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

    printk("\n");

    fpga_write_done:

    up(&fpga_dev.sem);

    return status;
    }

    static ssize_t fpga_read(struct file *filp, char __user *buff,
    size_t count, loff_t *offp)
    {
    printk("fpga_read \n");
    ssize_t status;
    size_t len;
    // int i,tmp;

    /*
    Generic user progs like cat will continue calling until we
    return zero. So if *offp != 0, we know this is at least the
    second call.
    */
    if (*offp > 0)
    return 0;

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

    strcpy(fpga_dev.user_buff, "fpga driver data goes here\n");

    len = strlen(fpga_dev.user_buff);

    if (len > count)
    len = count;

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

    fpga_read_done:

    up(&fpga_dev.sem);

    return status;
    }

    static int fpga_open(struct inode *inode, struct file *filp)
    {
    int status = 0;
    printk(KERN_ALERT "dan fpga_open()\n");
    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,
    };

    static int __init fpga_init_cdev(void)
    {
    int error;
    u32 val;
    printk(KERN_ALERT"dan_fpga_init_cdev()\n");
    fpga_dev.devt = MKDEV(0, 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 = 0xf64;
    // gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG7, val);
    //gpmc_base = ioremap(GPMC_BASE_ADDR, SZ_4K);
    if (gpmc_cs_request(GPMC_CS, SZ_4K, (unsigned long *)&mem_base) < 0){
    printk(KERN_ERR "Failed request for GPMC mem for usrp_e\n");
    return -1;
    }
    printk("Got CS0, address = %lx\n", mem_base);

    val = gpmc_read_reg(GPMC_REVISION);
    printk("GPMC revision %d.%d\n", (val >> 4) & 0x0f, val & 0x0f);


    gpmc_write_reg(GPMC_IRQENABLE, 0);
    gpmc_write_reg(GPMC_TIMEOUT_CONTROL, 0);


    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]);

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

    #if 0
    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 CS0, address = %lx\n", mem_base);
    #endif
    #if 0
    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;
    }
    #endif
    fpga_base = ioremap(mem_base, SZ_4K);




    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_cdev())
    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);


    MODULE_AUTHOR("dan");
    MODULE_DESCRIPTION("fpga driver");
    MODULE_LICENSE("Dual BSD/GPL");
    MODULE_VERSION("0.1");

    Kongfig中内容为:

    menu MENU_FPGA
    config FPGA
    tristate "Fpga"
    ---help---
    This is ARM Fpga driver file
    endmenu

    Makefile中内容为:

    obj-$(CONFIG_FPGA)          += fpga.o

    然后修改/drivers中的Kcongfig和Makefile文件。

    在menuconfig图形配置界面中选中添加的fpga驱动

    运行:make ARCH=arm CROSS_COMPILE=arm-arago-linux-gnueabi- uImage

    将生成的uImage拷贝到SD卡中,结果出现以下错误

    Unable to handle kernel NULL pointer dereference at virtual address 00000010
    [ 1.041913] pgd = c0004000
    [ 1.044746] [00000010] *pgd=00000000
    [ 1.048478] Internal error: Oops: 5 [#1]
    [ 1.052562] Modules linked in:
    [ 1.055750] CPU: 0 Not tainted (3.2.0 #9)
    [ 1.060305] PC is at gpmc_cs_request+0x68/0x160
    [ 1.065037] LR is at fpga_init+0x100/0x298
    [ 1.069306] pc : [<c0021abc>] lr : [<c05c1ba8>] psr: 80000013
    [ 1.069313] sp : cf81df18 ip : cf81df60 fp : cf81df5c
    [ 1.081273] r10: 01000000 r9 : 00000000 r8 : 00000000
    [ 1.086717] r7 : c0640c6c r6 : c06648e8 r5 : 00000000 r4 : 00000001
    [ 1.093518] r3 : 00000001 r2 : c06648e8 r1 : 00000000 r0 : 00000001
    [ 1.100322] Flags: Nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
    [ 1.107939] Control: 10c5387d Table: 80004019 DAC: 00000015
    [ 1.113926] Process swapper (pid: 1, stack limit = 0xcf81c2f0)
    [ 1.120004] Stack: (0xcf81df18 to 0xcf81e000)
    [ 1.124544] df00: 00000000 00000000
    [ 1.133071] df20: 00000000 c05c1aa8 cf81df4c cf81df38 c042186c c0664890 00000001 c055c928
    [ 1.141599] df40: 00000000 00000000 00000000 c05c1aa8 cf81df84 cf81df60 c05c1ba8 c0021a60
    [ 1.150126] df60: c055b3f8 00000000 c0640700 c05d9644 cf81c000 00000000 cf81dfdc cf81df88
    [ 1.158654] df80: c000876c c05c1ab4 c0074ecc c00f6a80 0000007f c00f68fc cf81dfbc 32318e78
    [ 1.167181] dfa0: 00000037 00000000 cf81dfc4 0000018c c06078e0 c05d954c c05d9644 c0040388
    [ 1.175708] dfc0: 00000013 00000000 00000000 00000000 cf81dff4 cf81dfe0 c059c884 c000873c
    [ 1.184235] dfe0: 00000000 c059c7e8 00000000 cf81dff8 c0040388 c059c7f4 afe7ef95 cb83f1ce
    [ 1.192755] Backtrace:
    [ 1.195316] [<c0021a54>] (gpmc_cs_request+0x0/0x160) from [<c05c1ba8>] (fpga_init+0x100/0x298)
    [ 1.204301] [<c05c1aa8>] (fpga_init+0x0/0x298) from [<c000876c>] (do_one_initcall+0x3c/0x180)
    [ 1.213185] r7:00000000 r6:cf81c000 r5:c05d9644 r4:c0640700
    [ 1.219113] [<c0008730>] (do_one_initcall+0x0/0x180) from [<c059c884>] (kernel_init+0x9c/0x130)
    [ 1.228195] [<c059c7e8>] (kernel_init+0x0/0x130) from [<c0040388>] (do_exit+0x0/0x67c)
    [ 1.236444] r5:c059c7e8 r4:00000000
    [ 1.240178] Code: e1a0aa13 e35a0201 83e0800b 8afffff1 (e5952010)
    [ 1.246581] ---[ end trace 1987bd5a2a5c8fca ]---
    [ 1.251405] Kernel panic - not syncing: Attempted to kill init!
    [ 1.257584] Backtrace:
    [ 1.260162] [<c0017978>] (dump_backtrace+0x0/0x110) from [<c04216a0>] (dump_stack+0x18/0x1c)
    [ 1.268967] r6:c05fc1f4 r5:c05fc1f4 r4:c0641648 r3:c05fabc8
    [ 1.274902] [<c0421688>] (dump_stack+0x0/0x1c) from [<c0421710>] (panic+0x6c/0x1a0)
    [ 1.282900] [<c04216a4>] (panic+0x0/0x1a0) from [<c0040934>] (do_exit+0x5ac/0x67c)
    [ 1.290788] r3:cf81bd24 r2:cf81dcfc r1:cf81dcfc r0:c050df10
    [ 1.296710] r7:cf81bc00
    [ 1.299357] [<c0040388>] (do_exit+0x0/0x67c) from [<c0017c68>] (die+0x128/0x2d8)
    [ 1.307072] r7:cf81dd6a
    [ 1.309722] [<c0017b40>] (die+0x0/0x2d8) from [<c001a2f4>] (__do_kernel_fault+0x7c/0x8c)
    [ 1.318172] [<c001a278>] (__do_kernel_fault+0x0/0x8c) from [<c001a458>] (do_page_fault+0x154/0x1f0)
    [ 1.327608] r8:00000005 r7:00000005 r6:00000010 r5:cf81ded0 r4:00000000
    [ 1.334437] r3:cf81ded0
    [ 1.337177] [<c001a304>] (do_page_fault+0x0/0x1f0) from [<c001a604>] (do_translation_fault+0xa4/0xa8)
    [ 1.346804] [<c001a560>] (do_translation_fault+0x0/0xa8) from [<c00083a4>] (do_DataAbort+0x3c/0xa0)
    [ 1.356240] r7:00000005 r6:c05e06bc r5:00000010 r4:00000005
    [ 1.362169] [<c0008368>] (do_DataAbort+0x0/0xa0) from [<c0013e58>] (__dabt_svc+0x38/0x60)
    [ 1.370701] Exception stack(0xcf81ded0 to 0xcf81df18)
    [ 1.375975] dec0: 00000001 00000000 c06648e8 00000001
    [ 1.384512] dee0: 00000001 00000000 c06648e8 c0640c6c 00000000 00000000 01000000 cf81df5c
    [ 1.393047] df00: cf81df60 cf81df18 c05c1ba8 c0021abc 80000013 ffffffff
    [ 1.399939] r8:00000000 r7:cf81df04 r6:ffffffff r5:80000013 r4:c0021abc
    [ 1.406963] [<c0021a54>] (gpmc_cs_request+0x0/0x160) from [<c05c1ba8>] (fpga_init+0x100/0x298)
    [ 1.415957] [<c05c1aa8>] (fpga_init+0x0/0x298) from [<c000876c>] (do_one_initcall+0x3c/0x180)
    [ 1.424850] r7:00000000 r6:cf81c000 r5:c05d9644 r4:c0640700
    [ 1.430771] [<c0008730>] (do_one_initcall+0x0/0x180) from [<c059c884>] (kernel_init+0x9c/0x130)
    [ 1.439855] [<c059c7e8>] (kernel_init+0x0/0x130) from [<c0040388>] (do_exit+0x0/0x67c)
    [ 1.448115] r5:c059c7e8 r4:00000000

    程序失败,请问是什么原因,谢谢。

  • xiangzhen meng 你好,问题解决了吗?我现在也遇到同样的问题,另我用的是CS2-FPGA, CS0-NAND;

    CS2的CONFIG配置如下:

    #define STNOR_GPMC_CONFIG1 0x00001010 
    #define STNOR_GPMC_CONFIG2 0x0002020f 
    #define STNOR_GPMC_CONFIG3 0x0002020f 
    #define STNOR_GPMC_CONFIG4 0x000f000f
    #define STNOR_GPMC_CONFIG5 0x00031f1f 
    #define STNOR_GPMC_CONFIG6 0x04000fc2
    #define STNOR_GPMC_CONFIG7 0x00000f40

    一当去加载fpga.ko模块式在执行gpmc_cs_request后就出现同样的奔溃问题

    Unable to handle kernel NULL pointer dereference at virtual address 00000010

    ....

    请问改怎么解决呀

  • 能说的详细一点吗?

  • 这种情况一般是和NAND的空间分配出现冲突,最好能把FPGA分配到的基地址打印出来

  • 比较命令啊 你的代码中有空指针啊

    Unable to handle kernel NULL pointer dereference at virtual address 00000010