AM335x 通过GPMC 与 FPGA 之间通信

news/2024/11/19 6:28:07/

AM335x 是一款A8的CPU ,其片上的资源是有限的,有时候我们需要外扩的功能有很多,比如 16个串口,4个LAN,IRIG,IO设备等。但是CPU 直接出来的 UART 和 LAN口不够用呀,这时候我们可以直接通过 am335x GPMC 总线上来扩展,如果还是不够用呢,那就需要FPGA 来译码达到更多的设备支持。

AM335X 上面有7个片选,我的设计将CS0 分给了 16个串口,CS3分给了IRIG 和 Nodeid. GPMC 总线上是支持 8bit 和 16 bit 模式的,正常情况下,如果选用8 bit , 那8位数据线一定是接到低8位的,否则读写错误是会出错的,如果选用16bit,要用到16位的数据线,一次读写可以进行读写2个字节的数据,这样就很方便。不过有时间我们引脚资源会很紧张,可能16位数据线上会被其他引脚给复用到,这时候我们就需要考虑到底如何配置才能在总线数据位不足的情况,正常读写呢?

下面这张图基本就将整个逻辑设计都讲清楚了

 

我们可以在 board-generic.c 中进行初始化配置总线的时序,然后注册 UART 设备,最后会与 8250的串口驱动进行匹配。

//------------------------------------------------------------------------------
//   += CS Setting
//------------------------------------------------------------------------------// CS0 for TL16C752C
#define TL16C752C_UARTCLK               (14745600)// CS0 A16/A15/A12/A9  4 address line --> 2^4=16 devices
#define CONFIG_TL16C752C_0_BASE  0x01000000
#define CONFIG_TL16C752C_1_BASE  0x01000200
#define CONFIG_TL16C752C_2_BASE  0x01001000
#define CONFIG_TL16C752C_3_BASE  0x01001200
#define CONFIG_TL16C752C_4_BASE  0x01008000
#define CONFIG_TL16C752C_5_BASE  0x01008200
#define CONFIG_TL16C752C_6_BASE  0x01009000
#define CONFIG_TL16C752C_7_BASE  0x01009200#define CONFIG_TL16C752C_8_BASE  0x01010000
#define CONFIG_TL16C752C_9_BASE  0x01010200
#define CONFIG_TL16C752C_10_BASE 0x01011000
#define CONFIG_TL16C752C_11_BASE 0x01011200
#define CONFIG_TL16C752C_12_BASE 0x01018000
#define CONFIG_TL16C752C_13_BASE 0x01018200
#define CONFIG_TL16C752C_14_BASE 0x01019000
#define CONFIG_TL16C752C_15_BASE 0x01019200static struct plat_serial8250_port tl16c752c_platform_data[] = {{.mapbase = CONFIG_TL16C752C_0_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_1_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_2_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_3_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_4_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_5_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_6_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_7_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_8_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_9_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_10_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_11_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_12_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_13_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_14_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{.mapbase = CONFIG_TL16C752C_15_BASE,.irqflags = IRQF_TRIGGER_HIGH,.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SHARE_IRQ,.iotype = UPIO_MEM,.regshift = 6,.uartclk = TL16C752C_UARTCLK},{}
};static struct platform_device tl16c752c_device = {.name = "serial8250",.id = PLAT8250_DEV_PLATFORM,.dev = {.platform_data = tl16c752c_platform_data,},
};#define TL16C752C_SHARE_IRQ_GPIO                GPIO_TO_PIN(0, 2)static struct gpio tl16c752c_uart_gpios[] __initdata = {{ TL16C752C_SHARE_IRQ_GPIO, GPIOF_IN, "uart_irq" },
};static int __init tl16c752c_uarts_init(void)
{int ret;ret = gpio_request_array(tl16c752c_uart_gpios, ARRAY_SIZE(tl16c752c_uart_gpios));if (ret < 0) {printk(KERN_ERR "Failed to request GPIO for UART IRQ\n");return -1;}tl16c752c_platform_data[0].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[1].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[2].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[3].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[4].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[5].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[6].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[7].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[8].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[9].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[10].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[11].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[12].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[13].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[14].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);tl16c752c_platform_data[15].irq = gpio_to_irq(TL16C752C_SHARE_IRQ_GPIO);platform_device_register(&tl16c752c_device);return 0;
}// TL16C752C CS0 config
#define TL16C752C_GPMC_CONFIG1          0x00001000 //16 bit width
//#define TL16C752C_GPMC_CONFIG1                0x00000000 //8 bit width// Configure GPMC registers for TL16C752D UART
static void gpmc_tl16c752c_config(void)
{struct gpmc_timings t;u32 tl16c752c_gpmc_config[6] = {0,};memset(&t, 0, sizeof(t));/* Read timings */t.cs_on = 0;t.adv_on = t.cs_on;t.adv_rd_off = 1;t.oe_on = t.adv_rd_off + 1;t.oe_off = t.oe_on + 6;t.cs_rd_off = t.oe_off + 2;t.access = t.cs_rd_off;t.rd_cycle = t.access + 1;/* Write timings */t.adv_wr_off = 1;t.we_on = t.adv_wr_off + 1;t.we_off = t.we_on + 6;t.cs_wr_off = t.we_off + 1;t.wr_cycle = t.cs_wr_off;// GPMC_CONFIG1tl16c752c_gpmc_config[0] = TL16C752C_GPMC_CONFIG1;// GPMC_CONFIG2 CS timingtl16c752c_gpmc_config[1] = t.cs_on | (t.cs_rd_off << 8) | (t.cs_wr_off << 16);// GPMC_CONFIG3 nADV / ALE timingtl16c752c_gpmc_config[2] = t.adv_on | (t.adv_rd_off << 8) | (t.adv_wr_off << 16);// GPMC_CONFIG4 nWE / nOE timingtl16c752c_gpmc_config[3] = t.oe_on | (t.oe_off << 8) | (t.we_on << 16) | (t.we_off << 24);// GPMC_CONFIG5 RdAccessTime / CycleTime timingtl16c752c_gpmc_config[4] = t.rd_cycle | (t.wr_cycle << 8) | (t.access << 16) | (t.page_burst_access << 24);// GPMC_CONFIG6 WrAccessTime / WrDataOnADmuxBus timingtl16c752c_gpmc_config[5] = (( ((u32)1) << 0 )               // Bus turn around latency between successive accesses to the same CS (read to write) or to a different CS (read to read and read to write)| ( ((u32)1) << 6 )     // Add CYCLE2CYCLEDELAY between successive accesses to a different CS (any access type)| ( ((u32)1) << 7 )     // Add CYCLE2CYCLEDELAY between successive accesses to the same CS (any access type)| ( ((u32)4) << 8 )     // CYCLE2CYCLEDELAY Chip-select high pulse delay between successive accesses (0..15 clk)| ( ((u32)8) << 16 )    // WRDATAONADMUXBUS (1 clk after ADV off, at which address is latched)//| ( ((u32)1) << 24 )  // Write access time [clk 0..31] from start of cycle -> used as wait time in async mode);setup_gpmc_cs_config(tl16c752c_gpmc_config, 0, 0x01000000, GPMC_SIZE_16M);
}

 

 


http://www.ppmy.cn/news/404553.html

相关文章

STM32驱动AD7366-5/AD7367-5芯片

目录 芯片介绍 芯片引脚定义 芯片电路图 根据时序写驱动代码 运行环境 时序与代码讲解 完整的代码 在实验室项目上&#xff0c;根据需求最终选用到了这款AD7367-5&#xff0c;在此记录一下这款AD芯片的驱动调试过程。目前仅用到了AD7367-5的第一组通道&#xff08;A1和B1…

一、正确安装 Keras TensorFlow 并调用 TensorBoard 绘制训练曲线

本博客主要内容为使用Keras实例化深度学习模型&#xff0c;并对在这个过程中遇到的问题进行总结&#xff0c;主要参考《Keras中文文档》&#xff0c;在配置环境、安装软件以及调试的过程中遇到的各种问题主要参考各个网页&#xff0c;这些网页会在必要时给出参考。 如本篇博客没…

ac3165无线网卡驱动linux,英特尔ac3165驱动下载

ac3165网卡驱动是支持英特尔双频带Wireless-AC3165无线网卡的安装程序&#xff0c;让用户的台式电脑也可以接受wifi&#xff0c;并且不卡顿的玩游戏和浏览网页&#xff0c;低延迟、高速率&#xff0c;同插网线一样的网速效果&#xff0c;有该产品的可以试试&#xff0c;安装傻瓜…

关于GTPU

GTP协议 GTP&#xff08;GPRS隧道协议(GPRS Tunneling Protocol)&#xff09;&#xff0c;可以分解成三种独立的协议&#xff0c;GTP-C、GTP-U及GTP。GTP-U用于在GPRS核心网内&#xff0c;无线接入网与核心网之间传送用户数据。 GTP可以用在UDP或TCP上&#xff0c;GTP v1仅用于…

python-文件操作指针

文件操作指针 文章目录 文件操作指针1. 文件指针的概念和作用&#xff1a;2. 移动文件指针的位置&#xff1a;3. 获取当前文件指针的位置&#xff1a;4. 文件指针的影响&#xff1a; 文件操作指针是在进行文件读写操作时用于标识当前位置的一个概念。它记录了文件中读写操作将要…

【OpenMMLab AI实战营二期笔记】第十天 底层视觉与MMEditing

1.图像超分辨率 1.1 什么是图像超分辨率&#xff1f; 根据从低分辨率图像重构高分辨率图像 1.2 目标&#xff1a; 提高图像的分辨率高分图像符合低分图像的内容恢复图像的细节、产生真实的内容 1.3 应用&#xff1a; 经典游戏高清重制动画高清重制照片修复节约传输高清图…

LuaJIT Bytecode结构布局

一、Bytecode的存储结构 LuaJIT的Bytecode位宽为32位&#xff0c;在parse阶段用结构体BCInsLine表示&#xff0c;ins表示32位长的字字节码指令&#xff0c;line表示字节码的行号&#xff1a; typedef struct BCInsLine {BCIns ins; /* Bytecode instruction. */BC…

JUC高级-0614

5.LockSupport与线程中断 5.1 线程中断 蚂蚁金服面试题&#xff1a;如何中等一个线程&#xff0c;如何停止一个线程什么是中断机制 首先&#xff1a;一个线程不应该由其他线程来强制中断或停止&#xff0c;而是应该由线程自己自行停止。所以&#xff0c;Thread.stop, Thread.…