以Freescale公司的i.MX6Q四核处理器及ALTERA EP3C40F324 FPGA为核心的嵌入式硬件平台,介绍i.MX6Q与FPGA基于EIM总线通信接口设计,基于Linux 3.14.28内核开发此接口的驱动程序方法以及基于Linux下从应用到驱动程序的通信实现.该技术已应用到某终端设备研制,实现FPGA芯片与Linux系统的连接,实际测试其与Android应用程序可靠通信,对同类型嵌入式平台的驱动接口设计及开发有借鉴意义.
External Interface Module(EIM)接口是飞思卡尔公司的MCIMX系列芯片的重要接口,是一种并行数据总线接口,主要用于同外设芯片或外部存储器进行数据传输,能异步访问带SRAM接口的器件或者同步访问带NOR Flash或PSRAM接口的器件.介绍了通过EIM接口实现CPU处理器与外设FPGA异步通信的硬件平台和EIM接口的实现原理.论述了Linux操作系统上EIM接口驱动的实现,描述了驱动的示意代码,并通过SignalTapⅡLogic Analyzer进行数据采集和显示屏显示,共同验证EIM接口能够高效地完成数据传输.通过EIM接口对FPGA固定寄存器进行写读操作,写入寄存器的值能够正确无误的读回来,对OLED显示屏进行初始化,大量数据能够正确传输,EIM接口功能完善,传输效率高,能够应用于多种场合.
开发环境Ubuntu14.04
运行环境:IMX6Q
Linux内核版本:3.14.28
总线接口:地址线A0~25 数据线D0~15(复用地址线低16位)
调试完成。
初始化参数代码如下:
/* EIM初始化 */
int uio_eim_async_multiplexed_16bit(struct uio_info *info)
{
unsigned int regs[EIM_REG_NUMS];
uio_read(info, regs, EIM_REG_NUMS);
/**
* PSZ=0 WP=0 GBC=1 AUS=0 CSREC=0 SP=0 DSZ=001
* BCS=0 BCD=0 WC=1 BL=0 CREP=0 CRE=0 RFL=0 WFL=0 MUM=1 SRD=0 SWR=0 CSEN=1
*
*/
#ifndef BIT_32
regs[CS0GCR1] = 0x1010089; /*16 bit port resides on DATA[15:0] 多路复用模式 使能cs0*/
#else
regs[CS0GCR1] = 0x1030089;
#endif
/**
* MUX16_BYP_GRANT=0 DAP=0 DA=0 DAPS=0 ADH=1
*/
regs[CS0GCR2] = 0x00000001;
/**
* RWSC=c
* RADVA RAL RADVN
* OEA OEN RCSA RCSN
*/
regs[CS0RCR1] = 0xC000000;
/**
* APR PAT RL RBEA RBE RBEN
*/
regs[CS0RCR2] = 0x0;
/**
* WAL WBED WWSC=A WADVA WADVN WBEA
* WBEA WBEN WEA WEN WCSA=0 WCSN
*/
regs[CS0WCR1] = 0xA000000;
#ifndef BIT_32
regs[CS1GCR1] = 0x1010089;
#else
regs[CS1GCR1] = 0x1010089;
#endif
regs[CS1GCR2] = 0x00000001;
regs[CS1RCR1] = 0xC000000;
regs[CS1RCR2] = 0x0;
regs[CS1WCR1] = 0xA000000;
uio_write(info, regs, EIM_REG_NUMS);
return 0;
}
————————————————
版权声明:本文为CSDN博主「无语僧314」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wuyusheng314/article/details/79009040
>>>>>FPGA中 EIM接口定义
//EIM interface
input eim_oe ,// A read enable, to drive the data bus, active low
input eim_rw ,// A write enable, to sample the data bus
input eim_cs0 ,// Chip0 Select(Sram), active low
input eim_cs1 ,// Chip1 Select(CSR), active low
input eim_bclk ,// Burst Clock
input eim_lba_b ,// Address Valid
output eim_wait_b ,// Ready/Busy/Wait signal
input eim_eb0 ,// Byte Enable
input eim_eb1 ,// Byte Enable
input [20:0] eim_addr ,// Address Bus
inout [15:0] eim_data ,// Data Bus
output eim_dtack_b ,// Data Acknowledge
output eim_int ,// Interrupt signal
>>>>>读写逻辑、地址数据信号缓存
always @(posedge clk)begin
eim_rd_en_d1 <= ~eim_cs1 & ~eim_oe;
eim_cfg_en <= ~eim_cs1 & ~ eim_rw;
eim_cfg_en_d1 <= eim_cfg_en;
eim_cfg_we <= ~eim_cfg_en & eim_cfg_en_d1;
eim_addr_d1 <= eim_addr;
eim_data_d1 <= eim_data;
eim_addr_d2 <= eim_addr_d1;
eim_data_d2 <= eim_data_d1;
eim_addr_d3 <= eim_addr_d2;
eim_data_d3 <= eim_data_d2;
eim_addr_in <= eim_addr_d3;
eim_data_in <= eim_data_d3;
lens_type_r <= lens_type;
end
///正式从i.MX6Q 读数据写入FPGA
//加载外部校正
always @(posedge clk or negedge power_on_rst_n)begin
if(power_on_rst_n == 1'b0) begin
.....
end
else begin
.......
if(flash_eb_rd_done)begin
flash_eb_rd_start <= 1'b0;
end
else if(eim_cfg_we & eim_addr_in[11:0] == 12'h098)begin
flash_eb_rd_start <= eim_data_in[15];
end
else if(sp_we & sp_addr == 8'h26)begin
flash_eb_rd_start <= sp_wdata[15];
end
//其他配置寄存器配置
if(eim_cfg_we) begin
case(eim_addr_in[11:0])
12'h000 : voff <= eim_data_in[11:0];
12'h004 : vbus <= eim_data_in[11:0];
12'h008 : img_height <= eim_data_in[11:0];
12'h00c : img_width <= eim_data_in[11:0];
12'h010 : left_edge <= eim_data_in[7:0];
12'h014 : top_edge <= eim_data_in[7:0];
12'h018 : img_flip <= eim_data_in[1:0];
12'h01c : data_type <= eim_data_in[3:0];
12'h020 : vsk <= eim_data_in[11:0];
12'h024 : gfid <= eim_data_in[11:0];
12'h028 : gain <= eim_data_in[2:0];
12'h02c : int_time <= eim_data_in[13:0];
12'h03c :begin
img_th <= eim_data_in[15:9];
motor_en <= eim_data_in[8:7];
velocity <= eim_data_in[6:5];
buzzer_ctl <= eim_data_in[4];
laser_ctl <= eim_data_in[3];
// moto_ctl <= eim_data_in[2:1];
af_ctl <= eim_data_in[1];
shutter_ctl <= eim_data_in[0];
end
........
endcase
end
end
///正式从FPGA 写入数据 到i.MX6Q
always @* begin
case(eim_addr[11:2])
10'h000 : csr_rd_data = csr000_000;
10'h001 : csr_rd_data = csr004_001;
10'h002 : csr_rd_data = csr008_002;
10'h003 : csr_rd_data = csr00c_003;
10'h004 : csr_rd_data = csr010_004;
10'h005 : csr_rd_data = csr014_005;
10'h006 : csr_rd_data = csr018_006;
10'h007 : csr_rd_data = csr01c_007;
10'h008 : csr_rd_data = csr020_008;
10'h009 : csr_rd_data = csr024_009;
10'h00a : csr_rd_data = csr028_00a;
10'h00b : csr_rd_data = csr02c_00b;
10'h00c : csr_rd_data = csr030_00c;
10'h00d : csr_rd_data = csr034_00d;
......
endcase
end