AM3359与FPGA的GPMC通信

在beaglebone上实现AM3359与FPGA的GPMC通信

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相关设计

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抓的结果。(l略)

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GPMC即组策略管理控制台,与windows 2000/2003 Server上传统的组策略编辑器截然不同,由一个全新的MMC管理单元及一整套脚本化的接口组成,提供了集中的组策略管理方案,可以大大减少不正确的组策略可能导致的网络问题并简化组策略相关的安全问题,解决组策略部署中的难点,   减轻了IT管理员们在实施组策略时所承担的沉重包袱。   组策略概述   相信"组策略"(Group Policy)这个名词已经为广大的Windows用户所知晓。微软在Windows NT 4.0中早就有了基于策略的管理--策略编辑器--一个深受NT管理员欢迎的实用程序,但它个并不为大多数用户所掌握并加以应用。为此,微软在 Windows 2000中不但彻底更新了目录服务,而且推出了与这个目录完全集成的策略管理--组策略对象(GPO)。随着Windows 2000的深入应用,组策略的应用也随之遍地开花,影响力远远超过了它的前身。可以说,组策略配置的正确与否将与您整个网络息息相关--虽然您可以完全放弃它,然而,作为一种手段,组策略的成功应用将起到事半功倍的效果。   GPMC的起源   当然,并不是每个人都成功了。随着组策略的深入应用,对这些组策略的管理成了用户最大的负担,而部分用户根本无法预料他所配置的组策略会产生什么样的后果,很多时候结果大大出乎他们的意料。在微软新闻组里,恐怕最著名的组策略问题就是"本地策略不允许您交互式登录"。GPMC(Group Policy Management Console,组策略管理控制台)就是微软在汲取遍布全球的合作伙伴及大量客户反馈的基础上酝酿而成的。   GPMC由一个全新MMC管理单元及一整套脚本化的接口组成,提供了集中的组策略管理方案,可以大大减少不正确的组策略可能导致的网络问题并简化组策略相关的安全问题,解决组策略部署中的难点,减轻了IT管理员们在实施组策略时所承担的沉重包袱

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值