日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

am3358——GPMC——参考网上驱动

發布時間:2023/12/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 am3358——GPMC——参考网上驱动 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:chenzhufly QQ:36886052 ( 轉載請注明出處)

轉自:?http://bbs.eeworld.com.cn/thread-333652-1-1.html


1.?參考資料

  • AM335x ARM? Cortex?-A8 Microprocessors Technical Reference Manual
  • BeagleBone_revA3_SCH.pdf
  • BeagleBone_revA3_SRM.pdf
  • BeagleBone_revA3_BOM.xls


2.?測試的硬件環境: Beaglebone + EE_FPGA



3. 硬件連接圖:用的是GPMC to 16-Bit Nonmultiplexed Memory

?

4. 設計思路

  • 初始化GPMC相關引腳
  • 完成GPMC驅動設計
  • 完成GPMC應用設計

5.?初始化相關代碼,主要修改并編譯

/linux-3.1.0-psp04.06.00.03.sdk/arch/arm/mach-omap2/board-am335xevm.c

配置相關引腳

  • /* Pin mux for fpga module */
    static struct pinmux_config 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},

    {"lcd_data0.gpmc_a0", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_data1.gpmc_a1", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_data2.gpmc_a2", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_data3.gpmc_a3", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_data4.gpmc_a4", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_data5.gpmc_a5", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_data6.gpmc_a6", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_data7.gpmc_a7", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_vsync.gpmc_a8", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_hsync.gpmc_a9", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_pclk.gpmc_a10", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_ac_bias_en.gpmc_a11", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_data8.gpmc_a12", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_data9.gpmc_a13", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_data10.gpmc_a14", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"lcd_data11.gpmc_a15", OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT?
    | AM33XX_PULL_DISA},?
    {"gpmc_advn_ale.gpmc_advn_ale", 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_ben0_cle.gpmc_ben0_cle", OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
    {"gpmc_csn1.gpmc_csn1", OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
    {"gpmc_clk.gpmc_clk", OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
    {NULL, 0},
    };
  • 復制代碼


  • static void evm_fpga_init(int evm_id, int profile)
    {
    setup_pin_mux(fpga_pin_mux);
    }
  • 復制代碼


  • /* Beaglebone Rev A3 and after */
    static struct evm_dev_cfg beaglebone_dev_cfg[] = {
    {mii1_init, DEV_ON_BASEBOARD, PROFILE_NONE},
    {usb0_init, DEV_ON_BASEBOARD, PROFILE_NONE},
    {usb1_init, DEV_ON_BASEBOARD, PROFILE_NONE},
    {mmc0_init, DEV_ON_BASEBOARD, PROFILE_NONE},
    {evm_fpga_init, DEV_ON_BASEBOARD, PROFILE_NONE},
    {NULL, 0, 0},
  • 復制代碼


    6.?GPMC驅動設計


  • /*
    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 <plat/gpmc.h>
    #include "plat/gpio.h"
    #include "plat/dma.h"

    #include "asm/uaccess.h"
    #include "asm/io.h"
    #include "asm/atomic.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
    #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
    static const u32 gpmc_nor[7] = {
    STNOR_GPMC_CONFIG1,
    STNOR_GPMC_CONFIG2,
    STNOR_GPMC_CONFIG3,
    STNOR_GPMC_CONFIG4,
    STNOR_GPMC_CONFIG5,
    STNOR_GPMC_CONFIG6, 0
    };

    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;?
    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)
    {
    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;

    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;

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

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




    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("chenzhufly");
    MODULE_DESCRIPTION("fpga driver");
    MODULE_LICENSE("Dual BSD/GPL");
    MODULE_VERSION("0.1");
  • 復制代碼


    7. GPMC應用程序設計,目前只實現了beaglebone向FPGA寫的流程

  • #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <errno.h>

    #define FPGA_DEV "/dev/fpga"
    #define PAGE_SIZE 10


    int main(void)
    {
    int fd,i,res;
    unsigned char buf[PAGE_SIZE];

    printf("GPMC Test version 1.0-BeagleBone Build on %s %s\n\r",__DATE__,__TIME__);?
    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;
    }

    write(fd,&buf,PAGE_SIZE);

    close(fd);
    return 0;

    }
  • 復制代碼


    8. FPGA相關設計

    ARM和FPGA的管腳分配如下圖所示?
    FPGA簡要代碼如下所示:
  • module interface_test
    (
    input clk,
    input ebgcs,?
    input eboe,?
    input ebwe,?
    input [11:0]ebaddr,

    input [15:0]ebdata,

    output led,
    output led1

    );


    wire [15:0] ram_q;
    wire ram_wren;
    wire ram_rden;

    assign ram_wren = ((ebgcs == 1'b0) && (ebwe == 1'b0)) ? 1'b1 : 1'b0;
    assign ram_rden = ((ebgcs == 1'b0) && (eboe == 1'b0)) ? 1'b1 : 1'b0;

    TestRam testram_inst (
    .clock ( clk),
    .data ( ebdata[15:0] ),
    .rdaddress ( ebaddr[11:1] ),
    .rden ( ram_rden ),
    .wraddress ( ebaddr[11:1] ),
    .wren ( ram_wren ),
    .q ( ram_q[15:0] )
    );

    wire ARM_READ_REG_EN;
    assign ARM_READ_REG_EN = ((ebgcs == 1'b0) && (eboe == 1'b0) && (ebaddr[11:1] == 11'b111_1111_1111)) ? 1'b1 : 1'b0;
    assign led1 = ARM_READ_REG_EN ? 1'b1 :
    ram_rden ? ram_q[0] : 1'bz;

    endmodule
  • 復制代碼

    FPGA管腳分配如下所示:
  • set_location_assignment PIN_89 -to ebaddr[0]
    set_location_assignment PIN_90 -to ebaddr[1]
    set_location_assignment PIN_87 -to ebaddr[2]
    set_location_assignment PIN_88 -to ebaddr[3]
    set_location_assignment PIN_84 -to ebaddr[4]
    set_location_assignment PIN_86 -to ebaddr[5]
    set_location_assignment PIN_81 -to ebaddr[6]
    set_location_assignment PIN_82 -to ebaddr[7]
    set_location_assignment PIN_63 -to ebaddr[8]
    set_location_assignment PIN_67 -to ebaddr[9]
    set_location_assignment PIN_64 -to ebaddr[10]
    set_location_assignment PIN_68 -to ebaddr[11]


    set_location_assignment PIN_60 -to ebdata[0]
    set_location_assignment PIN_59 -to ebdata[1]
    set_location_assignment PIN_28 -to ebdata[2]
    set_location_assignment PIN_30 -to ebdata[3]
    set_location_assignment PIN_58 -to ebdata[4]
    set_location_assignment PIN_57 -to ebdata[5]
    set_location_assignment PIN_24 -to ebdata[6]
    set_location_assignment PIN_27 -to ebdata[7]
    set_location_assignment PIN_47 -to ebdata[8]
    set_location_assignment PIN_40 -to ebdata[9]
    set_location_assignment PIN_41 -to ebdata[10]
    set_location_assignment PIN_45 -to ebdata[11]
    set_location_assignment PIN_39 -to ebdata[12]
    set_location_assignment PIN_37 -to ebdata[13]
    set_location_assignment PIN_44 -to ebdata[14]
    set_location_assignment PIN_43 -to ebdata[15]

    set_location_assignment PIN_61 -to ebgcs
    set_location_assignment PIN_33 -to eboe
    set_location_assignment PIN_35 -to ebwe


    set_location_assignment PIN_23 -to clk
    set_location_assignment PIN_31 -to led
    set_location_assignment PIN_34 -to led1
  • 復制代碼

    9. 測試結果BeagleBone向EE_FPGA寫0,1,2,3,4,5,6,7,8,9;通過signaltap抓的結果。?

    備注: 實際項目中只使用了其初始化,應用程序只操作內存就好。GPMC其實很簡單,就是只要向相應的GPMC_CS所申請的內存中丟數據,GPMC相應的片選會自動拉低。


    總結

    以上是生活随笔為你收集整理的am3358——GPMC——参考网上驱动的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。