引言

之前,我们在讨论基于ORPSoC的ipcore设计时提到过DMA的问题,当时我们实现DMA的功能时,访问的是local memory,并没有使用主存(即外部的SDRAM),使用的是本地的一块存储区域。所以也就不存在虚实地址转换的问题。但是,要想实现一个规范的,通用的,真正意义上的附带有DMA功能的ipcore,虚实地址转换就是必须要解决的问题了。

比如,软件要vga controller通过DMA显示一帧图片,软件必须把这帧图片的物理地址告诉vga controller,但是软件中使用的都是虚拟地址,所以就必须做虚实地址转换操作才行,当然,vga controller模块有local TLB的除外,这里介绍的是外部ipcore共用主TLB。

关于之前带有DMA功能的ipcore的设计,请参考:

http://blog.csdn.net/rill_zhen/article/details/8784510

本小节就解决这个问题。

1,基本思想

1>整体介绍

本小节实现一个ipcore,实现与软件的存储器访问共享。

2>验证步骤

1》软件(驱动)使用virt_adr=kmalloc(4,GFP_DMA);获得一个虚拟地址。

2》将这个虚拟地址转换为物理地址:phy_adr=virt_to_phys(virt_adr);

3》软件向这个虚拟地址写值:*virt_adr=0x6789bcdf;

3》软件将这个物理地址发送给ipcore。

4》ipcore根据这个物理地址进行读取,获得这个地址的值

5》将两个值进行比较,确认虚拟地址和物理地址是否是同一块SDRAM区域。

6》将上述过程反过来,ipcore向物理地址写值(这个值软件事先知道),软件读对应的虚拟地址,然后进行对比。

2,硬件部分

1>硬件组成与操作步骤

基于ORPSoC平台,

1》编写slave模块,接受软件的指令,控制master模块;

2》编写master模块根据slave的控制来访存;

3》编写顶层模块mycore,instanceslave和master两个模块;

4》修改orpsoc_top.v例化mycore。

5》以上步骤在前面的blog中有详细的介绍,请参考,这里不再赘述。

2>代码实现

下面是RTL实现代码:

1》myslave.v

/*
*
* rill create 130618
* rillzhen@gmail.com
*/
module myslave
(
wb_clk,
wb_rst, wb_dat_i,
wb_adr_i,
wb_sel_i,
wb_cti_i,
wb_bte_i,
wb_we_i,
wb_cyc_i,
wb_stb_i, wb_dat_o,
wb_ack_o,
wb_err_o,
wb_rty_o, address_o,
value_o,
write_o,
read_o,
write_ack,
read_ack,
value_ack
); input wb_clk;
input wb_rst; input [31:0] wb_adr_i;
input wb_stb_i;
input wb_cyc_i;
input [2:0] wb_cti_i;
input [1:0] wb_bte_i;
input [31:0] wb_dat_i;
input [3:0] wb_sel_i;
input wb_we_i; output reg [31:0] wb_dat_o;
output reg wb_ack_o;
output wb_err_o;
output wb_rty_o; output reg [31:0] address_o;
output reg [31:0] value_o;
output reg write_o;
output reg read_o;
input write_ack;
input read_ack;
input [31:0] value_ack; parameter address_adr =8'h04;
parameter value_adr =8'h08;
parameter wr_adr =8'h18;
parameter write_done_adr =8'h0c;
parameter read_done_adr =8'h10;
parameter value_ack_adr =8'h14;
parameter err_code =32'habcd_1234; parameter read_command =32'h0000_0002;
parameter write_command =32'h0000_0001; parameter s_idle =9'b000000001;
parameter s_write_done =9'b000000010;
parameter s_read_done =9'b000000100;
parameter s_read =9'b000001000;
parameter s_write =9'b000010000;
parameter s_read_pause =9'b000100000;
parameter s_write_pause1 =9'b001000000;
parameter s_write_pause2 =9'b010000000;
parameter s_write_pause3 =9'b100000000; reg [8:0] state,next_state;
reg [31:0] value_reg;
reg write_done;
reg read_done;
reg [31:0] address_reg;
reg [31:0] value_i_reg;
reg [31:0] wr_reg; assign wb_err_o=0;
assign wb_rty_o=0; always @(posedge wb_clk)
if(wb_rst)
state<=s_idle;
else
state<=next_state; always @(*)
begin
case(state)
s_idle:
begin
if(write_ack)
next_state=s_write_done;
else if(read_ack)
next_state=s_read_done;
else if(wb_stb_i && wb_cyc_i && wb_we_i)
next_state=s_write;
else if(wb_stb_i && wb_cyc_i && !wb_we_i)
next_state=s_read;
else
next_state=s_idle;
end
s_write_done:
begin
next_state=s_idle;
end
s_read_done:
begin
next_state=s_idle;
end
s_write:
begin
next_state=s_write_pause1;
end
s_write_pause1:
begin
next_state=s_write_pause2;
end
s_read:
begin
next_state=s_read_pause;
end
s_read_pause:
begin
next_state=s_idle;
end
s_write_pause2:
begin
next_state=s_write_pause3;
end
s_write_pause3:
begin
next_state=s_idle;
end
default:
begin
next_state=s_idle;
end
endcase
end always @(posedge wb_clk)
if(wb_rst)
begin
address_o<=0;
value_o <=0;
write_o <=0;
read_o <=0; value_reg<=0;
read_done<=0;
write_done<=0;
address_reg<=0;
value_i_reg<=0;
wr_reg <=0; wb_dat_o<=0;
wb_ack_o<=0;
end
else
begin
case(next_state)
s_idle:
begin
address_o<=0;
value_o <=0;
write_o <=0;
read_o <=0; wb_dat_o<=0;
wb_ack_o<=0;
end
s_read_done:
begin
address_o<=0;
value_o <=0;
write_o <=0;
read_o <=0; wb_dat_o<=0;
wb_ack_o<=0; read_done<=1'b1;
value_reg<=value_ack; end
s_write_done:
begin
address_o<=0;
value_o <=0;
write_o <=0;
read_o <=0; wb_dat_o<=0;
wb_ack_o<=0; write_done<=1'b1; end
s_read:
begin
if(wb_adr_i[7:0] == value_ack_adr)
wb_dat_o<={value_reg[7:0],value_reg[15:8],value_reg[23:16],value_reg[31:24]};
else if(wb_adr_i[7:0] == write_done_adr)
wb_dat_o<=write_done;
else if(wb_adr_i[7:0] == read_done_adr)
wb_dat_o<=read_done;
else if(wb_adr_i[7:0] == address_adr)
wb_dat_o<={address_reg[7:0],address_reg[15:8],address_reg[23:16],address_reg[31:24]};
else if(wb_adr_i[7:0] == wr_adr)
wb_dat_o<=wr_reg;
else if(wb_adr_i[7:0] == value_adr)
wb_dat_o<=value_i_reg;
else
wb_dat_o<=wb_adr_i; wb_ack_o<=0; address_o<=0;
value_o <=0;
write_o <=0;
read_o <=0;
end
s_read_pause:
begin
wb_dat_o<=wb_dat_o;
wb_ack_o<=1'b1; address_o<=0;
value_o <=0;
write_o <=0;
read_o <=0;
end
s_write:
begin
if(wb_adr_i[7:0]== address_adr)
address_reg<={wb_dat_i[7:0],wb_dat_i[15:8],wb_dat_i[23:16],wb_dat_i[31:24]};
else if(wb_adr_i[7:0] == value_adr)
value_i_reg<=wb_dat_i;
else if(wb_adr_i[7:0] == wr_adr)
wr_reg <= wb_dat_i; wb_ack_o <=0;
wb_dat_o <=0; address_o<=0;
value_o <=0;
write_o <=0;
read_o <=0;
end
s_write_pause1:
begin
if(wr_reg == read_command)
begin
read_o<=1'b1;
address_o<=address_reg;
// wb_ack_o<=1'b1;
// wb_dat_o<=0;
// address_reg<=0;
// wr_reg<=0;
// value_reg<=0;
// read_done<=0;
end
else if(wr_reg == write_command)
begin
write_o<=1'b1;
// address_o<={address_reg[7:0],address_reg[15:8],address_reg[23:16],address_reg[31:24]};
address_o<=address_reg;
value_o<=value_i_reg;
// wb_ack_o<=1'b1;
// wb_dat_o<=0;
// value_i_reg<=0;
// address_reg<=0;
// wr_reg <=0;
// write_done<=0;
end
else
begin
write_o<=0;
read_o<=0;
// wb_ack_o<=1'b1;
// wb_dat_o<=0;
address_o<=0;
value_o<=0;
end
end
s_write_pause2:
begin
if(wr_reg == read_command)
begin
read_o<=1'b1;
address_o<=address_reg;
// wb_ack_o<=1'b1;
// wb_dat_o<=0;
// address_reg<=0;
// wr_reg<=0;
// value_reg<=0;
// read_done<=0;
end
else if(wr_reg == write_command)
begin
write_o<=1'b1;
// address_o<={address_reg[7:0],address_reg[15:8],address_reg[23:16],address_reg[31:24]};
address_o<=address_reg;
value_o<=value_i_reg;
// wb_ack_o<=1'b1;
// wb_dat_o<=0;
// value_i_reg<=0;
// address_reg<=0;
// wr_reg <=0;
// write_done<=0;
end
else
begin
write_o<=0;
read_o<=0;
// wb_ack_o<=1'b1;
// wb_dat_o<=0;
address_o<=0;
value_o<=0;
end
end
s_write_pause3:
begin
if(wr_reg == read_command)
begin
read_o<=0;
address_o<=0; wb_ack_o<=1'b1;
wb_dat_o<=0; address_reg<=0;
wr_reg<=0;
value_reg<=0;
read_done<=0;
end
else if(wr_reg == write_command)
begin
write_o<=0;
address_o<=0;
value_o<=0; wb_ack_o<=1'b1;
wb_dat_o<=0; address_reg<=0;
wr_reg<=0;
value_i_reg<=0;
write_done<=0;
end
else
begin
write_o<=0;
read_o<=0; wb_ack_o<=1'b1;
wb_dat_o<=0; address_o<=0;
value_o<=0;
end end default:
begin
address_o<=0;
value_o <=0;
write_o <=0;
read_o <=0; value_reg<=0;
read_done<=0;
write_done<=0;
address_reg<=0;
value_i_reg<=0;
wr_reg <=0; wb_dat_o<=0;
wb_ack_o<=0;
end
endcase
end
endmodule

2》mymaster.v

/*
*
* rill create 130618
* rillzhen@gmail.com
*/ module mymaster
(
wb_clk,
wb_rst, wb_adr_o,
wb_dat_o,
wb_sel_o,
wb_we_o,
wb_cyc_o,
wb_stb_o,
wb_cti_o,
wb_bte_o, wb_dat_i,
wb_ack_i,
wb_err_i,
wb_rty_i, write_i ,
read_i ,
address_i,
value_i ,
write_ack ,
read_ack,
value_o ); //wishbone interface
input wb_clk;
input wb_rst; input wb_ack_i;
input wb_err_i;
input wb_rty_i;
input [31:0] wb_dat_i; output reg [31:0] wb_adr_o;
output reg [31:0] wb_dat_o;
output reg wb_cyc_o;
output reg wb_stb_o;
output reg [3:0] wb_sel_o;
output reg wb_we_o;
output reg [2:0] wb_cti_o;
output reg [1:0] wb_bte_o;
input write_i;
input read_i;
input [31:0] address_i;
input [31:0] value_i;
output reg [31:0] value_o;
output reg write_ack;
output reg read_ack; parameter m_idle = 9'b000000001;
parameter m_write_ready = 9'b010000000;
parameter m_read_ready = 9'b100000000;
parameter m_write_begin = 9'b000000010;
parameter m_write_wait = 9'b000000100;
parameter m_write_done = 9'b000001000;
parameter m_read_begin = 9'b000010000;
parameter m_read_wait = 9'b000100000;
parameter m_read_done = 9'b001000000;
parameter cti_default = 3'b000;
parameter bte_default = 2'b00;
parameter sel_default = 4'b1111; reg [8:0] state,next_state; always @(posedge wb_clk)
if(wb_rst)
state<=m_idle;
else
state<=next_state; always @(*)
case(state)
m_idle:
begin
if(write_i)
next_state=m_write_ready;
else if(read_i)
next_state=m_read_ready;
else
next_state=m_idle;
end
m_write_ready:
begin
next_state=m_write_begin;
end
m_read_ready:
begin
next_state=m_read_begin;
end
m_write_begin:
begin
next_state=m_write_wait;
end
m_write_wait:
begin
if(wb_ack_i)
next_state=m_write_done;
else
next_state=m_write_wait;
end
m_write_done:
begin
next_state=m_idle;
end
m_read_begin:
begin
next_state=m_read_wait;
end
m_read_wait:
begin
if(wb_ack_i)
next_state=m_read_done;
else
next_state=m_read_wait;
end
m_read_done:
begin
next_state=m_idle;
end
default:
begin
next_state=m_idle;
end
endcase always @ (posedge wb_clk)
if(wb_rst)
begin
wb_adr_o<=0;
wb_dat_o<=0;
wb_sel_o<=sel_default;
wb_we_o<=0;
wb_cyc_o<=0;
wb_stb_o<=0;
wb_cti_o<=cti_default;
wb_bte_o<=bte_default;
write_ack<=0;
read_ack<=0;
value_o <=0;
end
else
begin
case(next_state)
m_idle:
begin
wb_adr_o<=0;
wb_dat_o<=0;
wb_sel_o<=sel_default;
wb_we_o<=0;
wb_cyc_o<=0;
wb_stb_o<=0;
wb_cti_o<=cti_default;
wb_bte_o<=bte_default;
write_ack<=0;
read_ack<=0;
value_o <=0;
end
m_write_ready:
begin
wb_adr_o<=0;
wb_dat_o<=0;
wb_cyc_o<=0;
wb_stb_o<=0;
wb_we_o<=0;
end
m_read_ready:
begin
wb_adr_o<=0;
wb_dat_o<=0;
wb_cyc_o<=0;
wb_stb_o<=0;
wb_we_o<=0;
end
m_write_begin:
begin
wb_adr_o<=address_i;
wb_dat_o<=value_i;
wb_cyc_o<=1'b1;
wb_stb_o<=1'b1;
wb_we_o<=1'b1;
end
m_write_wait:
begin
wb_adr_o<=wb_adr_o;
wb_dat_o<=wb_dat_o;
wb_cyc_o<=wb_cyc_o;
wb_stb_o<=wb_stb_o;
wb_we_o<=wb_we_o;
end
m_write_done:
begin
wb_adr_o<=0;
wb_dat_o<=0;
wb_cyc_o<=0;
wb_stb_o<=0;
wb_we_o<=0;
write_ack<=1'b1;
end
m_read_begin:
begin
wb_adr_o<=address_i;
wb_dat_o<=0;
wb_cyc_o<=1'b1;
wb_stb_o<=1'b1;
wb_we_o<=0;
end
m_read_wait:
begin
wb_adr_o<=wb_adr_o;
wb_dat_o<=wb_dat_o;
wb_cyc_o<=wb_cyc_o;
wb_stb_o<=wb_stb_o;
wb_we_o <=0;
end
m_read_done:
begin
wb_adr_o<=0;
wb_dat_o<=0;
wb_cyc_o<=0;
wb_stb_o<=0;
wb_we_o<=0;
read_ack<=1'b1;
value_o<=wb_dat_i;
end
default:
begin
wb_adr_o<=0;
wb_dat_o<=0;
wb_sel_o<=sel_default;
wb_we_o<=0;
wb_cyc_o<=0;
wb_stb_o<=0;
wb_cti_o<=cti_default;
wb_bte_o<=bte_default;
write_ack<=0;
read_ack<=0;
value_o <=0;
end
endcase
end
endmodule

3》mycore.v

/*
*
* rill create 130618
* rillzhen@gmail.com
*/ module mycore
(
//===slave interface signals
wb_clk,
wb_rst, wbs_d_mycore_dat_o,
wbs_d_mycore_ack_o,
wbs_d_mycore_err_o,
wbs_d_mycore_rty_o, wbs_d_mycore_adr_i,
wbs_d_mycore_dat_i,
wbs_d_mycore_sel_i,
wbs_d_mycore_we_i,
wbs_d_mycore_cyc_i,
wbs_d_mycore_stb_i,
wbs_d_mycore_cti_i,
wbs_d_mycore_bte_i, //===master interface signals wbm_d_mycore_dat_i,
wbm_d_mycore_ack_i,
wbm_d_mycore_err_i,
wbm_d_mycore_rty_i, wbm_d_mycore_adr_o,
wbm_d_mycore_dat_o,
wbm_d_mycore_sel_o,
wbm_d_mycore_we_o,
wbm_d_mycore_cyc_o,
wbm_d_mycore_stb_o,
wbm_d_mycore_cti_o,
wbm_d_mycore_bte_o
);
input wb_clk;
input wb_rst;
output [31:0] wbs_d_mycore_dat_o;
output wbs_d_mycore_ack_o;
output wbs_d_mycore_err_o;
output wbs_d_mycore_rty_o; input [31:0] wbs_d_mycore_adr_i;
input [31:0] wbs_d_mycore_dat_i;
input [3:0] wbs_d_mycore_sel_i;
input wbs_d_mycore_we_i;
input wbs_d_mycore_cyc_i;
input wbs_d_mycore_stb_i;
input [2:0] wbs_d_mycore_cti_i;
input [1:0] wbs_d_mycore_bte_i; input [31:0] wbm_d_mycore_dat_i;
input wbm_d_mycore_ack_i;
input wbm_d_mycore_err_i;
input wbm_d_mycore_rty_i; output [31:0] wbm_d_mycore_adr_o;
output [31:0] wbm_d_mycore_dat_o;
output [3:0] wbm_d_mycore_sel_o;
output wbm_d_mycore_we_o;
output wbm_d_mycore_cyc_o;
output wbm_d_mycore_stb_o;
output [2:0] wbm_d_mycore_cti_o;
output [1:0] wbm_d_mycore_bte_o; wire [31:0] address;
wire [31:0] value;
wire write;
wire read;
wire read_ack;
wire write_ack;
wire [31:0] value_ack;
myslave myslave0
(
.wb_clk(wb_clk),
.wb_rst(wb_rst),
.wb_adr_i(wbs_d_mycore_adr_i),
.wb_dat_i(wbs_d_mycore_dat_i),
.wb_sel_i(wbs_d_mycore_sel_i),
.wb_we_i(wbs_d_mycore_we_i),
.wb_cyc_i(wbs_d_mycore_cyc_i),
.wb_stb_i(wbs_d_mycore_stb_i),
.wb_cti_i(wbs_d_mycore_cti_i),
.wb_bte_i(wbs_d_mycore_bte_i), .wb_dat_o(wbs_d_mycore_dat_o),
.wb_ack_o(wbs_d_mycore_ack_o),
.wb_err_o(wbs_d_mycore_err_o),
.wb_rty_o(wbs_d_mycore_rty_o),
.address_o(address),
.value_o(value),
.write_o(write),
.read_o(read),
.write_ack(write_ack),
.read_ack(read_ack),
.value_ack(value_ack)
);
mymaster mymaster0
(
.wb_clk (wb_clk),
.wb_rst (wb_rst), .wb_adr_o (wbm_d_mycore_adr_o),
.wb_dat_o (wbm_d_mycore_dat_o),
.wb_sel_o (wbm_d_mycore_sel_o),
.wb_we_o (wbm_d_mycore_we_o),
.wb_cyc_o (wbm_d_mycore_cyc_o),
.wb_stb_o (wbm_d_mycore_stb_o),
.wb_cti_o (wbm_d_mycore_cti_o),
.wb_bte_o (wbm_d_mycore_bte_o), .wb_dat_i (wbm_d_mycore_dat_i),
.wb_ack_i (wbm_d_mycore_ack_i),
.wb_err_i (wbm_d_mycore_err_i),
.wb_rty_i (wbm_d_mycore_rty_i), //internal signals
.write_i (write),
.read_i (read),
.address_i (address),
.value_i (value),
.write_ack (write_ack),
.read_ack (read_ack),
.value_o (value_ack)
);
endmodule /************** EOF ****************/

3,软件部分

1>介绍

为了测试虚实转换的正确性,编写ipcore的linux驱动是必须的,以实现之前介绍的验证步骤,软件部分的操作流程,前面已经介绍了。这里直接将代码贴在这里,一目了然。

细心的读者可能会发现,在给ipcore传数据的时候并没有做byteorder的转换(大小端的问题,之前反复提到过),这是因为之前对字节序的转换是驱动做的,这次是硬件做的(RTL里面增加了相应的逻辑,请仔细看硬件部分的代码便知),道理一样,不必疑惑。

2>代码实现

还跟之前的驱动一样,共三部分组成。

1》ip_mkg.c

/*
*
* rill mkg driver
*
*/
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h> /* get_user and put_user */
//#include <linux/clk.h>
//#include <linux/ioport.h>
#include <asm/io.h> /*ioremap*/
#include <linux/platform_device.h> /*cleanup_module*/
#include <linux/delay.h>
#include <asm-generic/io.h> #include "ip_mkg.h" void __iomem *g_mkg_mem_base = NULL;
void __iomem *g_mkg_core_base = NULL; static int device_open(struct inode *inode, struct file *file)
{
g_mkg_mem_base = ioremap(MKG_MEM_BASE,MKG_MEM_LEN);
g_mkg_core_base = ioremap (MKG_CORE_BASE, MKG_CORE_LEN); if(NULL == g_mkg_mem_base)
{
printk(KERN_ERR "mkg mem open ioremap error!\n");
return -1;
}
else
{
printk("mkg mem ioremap addr:%d!\n",(int)g_mkg_mem_base);
}
if(NULL == g_mkg_core_base)
{
printk(KERN_ERR "mkg core open ioremap error!\n");
return -1;
}
else
{
printk("mkg core ioremap addr:%d!\n",(int)g_mkg_core_base);
} return 0;
} static int device_release(struct inode *inode, struct file *file)
{
return 0;
} static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset)
{
/*int ret_val = 0; char * data = NULL; data = (char*)kmalloc(4, GFP_KERNEL);
if((ret_val = copy_from_user(new_regs, (struct reg_data*)ioctl_param, sizeof(struct reg_data))) != 0) ioread32(g_mkg_mem_base+length);
printk("============read:%d\n",);*/ return 1;
} static ssize_t device_write(struct file *filp, const char *buffer, size_t count, loff_t *offset)
{
//iowrite32(2,g_mkg_mem_base);
return 1;
} long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)
{
#if 0 int ret_val = 0;
unsigned int ret = 0;
struct reg_data *new_regs;
printk("ioctl======\n"); switch(ioctl_num)
{
case IOCTL_REG_SET:
{
new_regs = (struct reg_data*)kmalloc(sizeof(struct reg_data), GFP_KERNEL);
if((ret_val = copy_from_user(new_regs, (struct reg_data*)ioctl_param, sizeof(struct reg_data))) != 0)
{
kfree(new_regs);
printk(KERN_ERR " error copy line_datafrom user.\n");
return -1;
} //iowrite16(new_regs->value,g_mkg_mem_base+new_regs->addr);
kfree(new_regs);
}
break; case IOCTL_REG_GET:
{
new_regs = (struct reg_data*)kmalloc(sizeof(struct reg_data), GFP_KERNEL);
if((ret_val = copy_from_user(new_regs, (struct reg_data*)ioctl_param, sizeof(struct reg_data))) != 0)
{
kfree(new_regs);
printk(KERN_ERR " error copy line_datafrom user.\n");
return -1;
} //ret = ioread16(g_mkg_mem_base+new_regs->addr);
kfree(new_regs);
return ret;
}
break; }
#endif return -1;
} struct file_operations our_file_ops = {
.unlocked_ioctl = device_ioctl,
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release,
.owner = THIS_MODULE,
}; int ToBigEndian(int lit_End)
{
char * p=(char *)&lit_End; return (int)(p[0]<<24)+(int)(p[1]<<16)+(int)(p[2]<<8)+(int)(p[3]);
}
void test(void)
{ unsigned int * virt_adr;
unsigned int phy_adr;
int write_done=0,read_done=0,read_value=0;
unsigned int final_phy_adr;
char *p;
int read=0;
virt_adr=kmalloc(4,GFP_DMA);
if(!virt_adr)
printk("apply for kernel memory fails !\n"); phy_adr=virt_to_phys(virt_adr);
printk("virtual address !0x%x \n ",virt_adr);
printk("original physical address !0x%x \n",phy_adr); *virt_adr=0x6789bcdf;
final_phy_adr=phy_adr;
// final_phy_adr=0x98000040;
printk("final physical address !0x%x \n ",final_phy_adr);
// test begin
// write first number : final_phy_adr
printk("test begin \n write first number : final_phy_adr\n");
iowrite32(final_phy_adr,g_mkg_core_base+0x4);
printk("write address done !\n");
read=ioread32(g_mkg_core_base+0x4);
printk("write address : 0x%x \n",read);
iowrite32(0x3956abcd,g_mkg_core_base+0x8);
printk("write value done !\n");
read=ioread32(g_mkg_core_base+0x8);
printk("write value : 0x%x \n",read);
iowrite32(0x01000000,g_mkg_core_base+0x18);
printk("write command done !\n");
printk("write two number: final_phy_adr+4 \n");
// write two number: final_phy_adr+4
iowrite32(final_phy_adr+4,g_mkg_core_base+0x4);
printk("write address done !\n");
read=ioread32(g_mkg_core_base+0x4);
printk("write address : 0x%x \n",read);
iowrite32(0x3956abcd,g_mkg_core_base+0x8);
printk("write value done !\n");
read=ioread32(g_mkg_core_base+0x8);
printk("write value : 0x%x \n",read);
iowrite32(0x01000000,g_mkg_core_base+0x18);
printk("write command done !\n");
// write third number: final_phy_adr-4
printk("write third number: final_phy_adr-4 \n");
iowrite32(final_phy_adr-4,g_mkg_core_base+0x4);
printk("write address done !\n");
read=ioread32(g_mkg_core_base+0x4);
printk("write address : 0x%x \n",read);
iowrite32(0x3956abcd,g_mkg_core_base+0x8);
printk("write value done !\n");
read=ioread32(g_mkg_core_base+0x8);
printk("write value : 0x%x \n",read);
iowrite32(0x01000000,g_mkg_core_base+0x18);
printk("write command done !\n");
// write forth number: 0x98000040
printk("write forth number: 98000040 \n");
iowrite32(0x98000040,g_mkg_core_base+0x4);
printk("write address done !\n");
read=ioread32(g_mkg_core_base+0x4);
printk("write address : 0x%x \n",read);
iowrite32(0x3956abcd,g_mkg_core_base+0x8);
printk("write value done !\n");
read=ioread32(g_mkg_core_base+0x8);
printk("write value : 0x%x \n",read);
iowrite32(0x01000000,g_mkg_core_base+0x18);
printk("write command done !\n");
read=ioread32(g_mkg_core_base+0x18);
printk("write command : 0x%x \n",read);
write_done=ioread32(g_mkg_core_base+0x0c);
// read first number : final_phy_adr
printk("read first number : final_phy_adr\n");
iowrite32(final_phy_adr,g_mkg_core_base+0x4);
printk("read address done !\n");
read=ioread32(g_mkg_core_base+0x4);
printk("read address : 0x%x \n",read);
iowrite32(0x02000000,g_mkg_core_base+0x18);
printk("read commnad done !\n");
read=ioread32(g_mkg_core_base+0x18);
printk("read command : 0x%x \n",read);
read_done=ioread32(g_mkg_core_base+0x10);
read_value=ioread32(g_mkg_core_base+0x14);
printk("<write_done flag: 0x%x >\n",write_done);
printk("<read from or1200: 0x%x >\n",*virt_adr);
printk("<read_done flag: 0x%x >\n",read_done);
printk("<read_value flag: 0x%x >\n",read_value);
printk(" read second number : final_phy_adr+4\n");
// read second number : final_phy_adr+4
iowrite32(final_phy_adr+4,g_mkg_core_base+0x4);
printk("read address done !\n");
read=ioread32(g_mkg_core_base+0x4);
printk("read address : 0x%x \n",read);
iowrite32(0x02000000,g_mkg_core_base+0x18);
printk("read commnad done !\n");
read=ioread32(g_mkg_core_base+0x18);
printk("read command : 0x%x \n",read);
read_done=ioread32(g_mkg_core_base+0x10);
read_value=ioread32(g_mkg_core_base+0x14);
printk("<read_done flag: 0x%x >\n",read_done);
printk("<read_value flag: 0x%x >\n",read_value);
printk(" read third number : final_phy_adr-4\n");
// read third number : final_phy_adr-4
iowrite32(final_phy_adr-4,g_mkg_core_base+0x4);
printk("read address done !\n");
read=ioread32(g_mkg_core_base+0x4);
printk("read address : 0x%x \n",read);
iowrite32(0x02000000,g_mkg_core_base+0x18);
printk("read commnad done !\n");
read=ioread32(g_mkg_core_base+0x18);
printk("read command : 0x%x \n",read);
read_done=ioread32(g_mkg_core_base+0x10);
read_value=ioread32(g_mkg_core_base+0x14);
printk("<read_done flag: 0x%x >\n",read_done);
printk("<read_value flag: 0x%x >\n",read_value);
printk(" read forth number : 0x98000040\n");
// read forth number : 0x98000040
iowrite32(0x98000040,g_mkg_core_base+0x4);
printk("read address done !\n");
read=ioread32(g_mkg_core_base+0x4);
printk("read address : 0x%x \n",read);
iowrite32(0x02000000,g_mkg_core_base+0x18);
printk("read commnad done !\n");
read=ioread32(g_mkg_core_base+0x18);
printk("read command : 0x%x \n",read);
read_done=ioread32(g_mkg_core_base+0x10);
read_value=ioread32(g_mkg_core_base+0x14);
printk("<read_done flag: 0x%x >\n",read_done);
printk("<read_value flag: 0x%x >\n",read_value); } int init_module()
{
int ret_val;
int ret;
int ret2;
void __iomem *ret_from_request;
void __iomem *ret_from_request2; //=== Allocate character device
ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &our_file_ops);
if (ret_val < 0)
{
printk(KERN_ALERT " device %s failed(%d)\n", DEVICE_NAME, ret_val);
return ret_val;
} ret = check_mem_region(MKG_MEM_BASE, MKG_MEM_LEN);
if (ret < 0)
{
printk(KERN_ERR "mkg check_mem_region bussy error!\n");
return -1;
} ret_from_request = request_mem_region(MKG_MEM_BASE, MKG_MEM_LEN, "ip_mkg"); ret2 = check_mem_region(MKG_CORE_BASE, MKG_CORE_LEN);
if (ret2 < 0)
{
printk(KERN_ERR "mkg check_mem_region bussy error!\n");
return -1;
} ret_from_request2 = request_mem_region(MKG_CORE_BASE, MKG_CORE_LEN, "ip_mkg"); //===ioremap mkg registers g_mkg_mem_base = ioremap(MKG_MEM_BASE,MKG_MEM_LEN);
if(NULL == g_mkg_mem_base)
{
printk(KERN_ERR "mkg mem ioremap error!\n");
return -1;
}
else
{
;//printk("mkg ioremap addr:%d!\n",(unsigned int)g_mkg_mem_base);
} g_mkg_core_base = ioremap(MKG_CORE_BASE,MKG_CORE_LEN);
if(NULL == g_mkg_core_base)
{
printk(KERN_ERR "mkg core ioremap error!\n");
return -1;
}
else
{
;//printk("mkg ioremap addr:%d!\n",(unsigned int)g_mkg_mem_base);
} printk("mkg module init done!\n"); test(); return 0;
} void cleanup_module()
{
release_mem_region(MKG_MEM_BASE, MKG_MEM_LEN);
release_mem_region(MKG_CORE_BASE,MKG_CORE_LEN);
unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
} MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rill zhen:rill_zhen@126.com");

2》ip_mkg.h

#ifndef __IP_MKG_H__
#define __IP_MKG_H__ #define MAJOR_NUM 102
#define DEVICE_NAME "ip_mkg"
#define MKG_MEM_BASE 0x98000000
#define MKG_MEM_LEN 3072
#define MKG_CORE_BASE 0x97000000
#define MKG_CORE_LEN 128
#define IOCTL_REG_SET 0
#define IOCTL_REG_GET 1 struct reg_data
{
unsigned short addr;
int value;
}; #endif

3》makefile

请参考之前的写法,要编译的文件不同而已。

4,验证

1>将修改后的ORPSoC的工程进行综合

2>编译驱动生成ko文件,在板子上进行测试验证

3>具体操作步骤,前面的blog中有详细介绍,请参考:

http://blog.csdn.net/rill_zhen/article/details/8849149

http://blog.csdn.net/rill_zhen/article/details/8700937

4>结果

因为截屏的话,一屏显示不完整,故只将打印输出信息保存,如下:

可以看出,软件(使用虚拟地址)和硬件(使用物理地址)的访存操作为同一地址。

Please press Enter to activate this console.
# mkdir nfs
# mount -t nfs -o nolock 192.168.1.101:/home/openrisc/nfs nfs
# cd nfs
# insmod ip_mkg.ko
mkg module init done!
virtual address !0xc1526010
original physical address !0x1526010
final physical address !0x1526010
test begin
write first number : final_phy_adr
write address done !
write address : 0x1526010
write value done !
write value : 0x3956abcd
write command done !
write two number: final_phy_adr+4
write address done !
write address : 0x1526014
write value done !
write value : 0x3956abcd
write command done !
write third number: final_phy_adr-4
write address done !
write address : 0x152600c
write value done !
write value : 0x3956abcd
write command done !
write forth number: 98000040
write address done !
write address : 0x98000040
write value done !
write value : 0x3956abcd
write command done !
write command : 0x0
read first number : final_phy_adr
read address done !
read address : 0x1526010
read commnad done !
read command : 0x0
<write_done flag: 0x0 >
<read from or1200: 0xcdab5639 >
<read_done flag: 0x1000000 >
<read_value flag: 0xcdab5639 >
read second number : final_phy_adr+4
read address done !
read address : 0x1526014
read commnad done !
read command : 0x0
<read_done flag: 0x1000000 >
<read_value flag: 0xcdab5639 >
read third number : final_phy_adr-4
read address done !
read address : 0x152600c
read commnad done !
read command : 0x0
<read_done flag: 0x1000000 >
<read_value flag: 0xcdab5639 >
read forth number : 0x98000040
read address done !
read address : 0x98000040
read commnad done !
read command : 0x0
<read_done flag: 0x1000000 >
<read_value flag: 0xcdab5639 >
#

5,小结

虚实地址转换的问题解决了,中断的问题也解决了(请参考http://blog.csdn.net/rill_zhen/article/details/8894856),那么设计一个完整的具有DMA功能的ipcore,问题就不大了。

OpenRisc-31-关于在设计具有DMA功能的ipcore时的虚实地址转换问题的分析与解决的更多相关文章

  1. 安装SQL Server 2012过程中出现“启用windows功能NetFx3时出错”(错误原因、详细分析及解决方法)以及在Windows Server2012上安装.NET Framework 3.5的详细分析及安装过程

           问题:在服务器(操作系统为Windows server 2012)上安装SQL Server 2012的过程中,安装停留在下图所示的界面上,显示”正在启用操作系统功能NetFx3”随后出 ...

  2. 审核流(2)流程设计-SNF.WorkFlow功能使用说明--SNF快速开发平台3.1

    流程设计 图形化的流程设计,更方便.直观 1.打开“流程设计“程序,如上.点击”新建“如下: 2.红色部分为必填项,审批对象是选择要审批的程序菜单,单据名称是在审核流流转时用于提示的单据名称,还要选择 ...

  3. [置顶] STM32的ADC1采集多条通道,可以不使用DMA功能吗?

    类似的问题 为什么我采集5条通道的电压,而采集到的值却都是第一条的呢? 我什么时候需要使用DMA功能? Ⅰ关于ADC的一些知识 STM32的ADC是一种12位逐次逼近型的模拟数字转换器.它有多达18条 ...

  4. 什么是需求Bug、设计Bug、功能bug?

    首先什么是需求Bug.设计Bug.功能bug? 需求Bug,指由于客户需求描述不清晰或错误.需求收集人员自身原因及需求本身模糊难于分析.获取等原因,导致客户需求获取不准确,后期产品不能满足客户.用户的 ...

  5. Java 开源办公开发平台 O2OA V5.4.0 发布 | 设计元素搜索功能上线

    O2OA V5.4.0版本此次更新的设计元素搜索功能,可以让用户在海量的脚本.页面.表单.视图等信息中迅速锁定有价值的信息,以便提高用户获取信息的效率.拥有此搜索功能后,在开发过程中,可以加速定位脚本 ...

  6. Web API核查表:设计、测试、发布API时需思考的43件事[转]

    Web API核查表:设计.测试.发布API时需思考的43件事   当设计.测试或发布一个新的Web API时,你是在一个原有的复杂系统上构建新的系统.那么至少,你也要建立在HTTP上,而HTTP则是 ...

  7. 个人永久性免费-Excel催化剂功能第68波-父子结构表转换之父子关系BOM表拆分篇

    Excel中制造业行业中,有一个非常刚需的需求是对BOM(成品物料清单)的拆解,一般系统导出的BOM表,是经过压缩处理的,由父子表结构的方式存储数据.对某些有能力使用SAP等专业ERP软件的工厂来说, ...

  8. 个人永久性免费-Excel催化剂功能第67波-父子结构表转换添加辅助信息之子父关系篇

    Excel作为一款数据领域的万物互联工具,连接一切外部的多种多样的数据源.将数据带到Excel的环境中,再进行数据处理.转换.统计分析等工作,是众多表哥表姐们每天都在经历的事情.能最快速将其他来源数据 ...

  9. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(五)——实现注册功能

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

随机推荐

  1. CDLinux环境下WiFi密码破解

    > 准备好所需软件以及上篇教程中使用Fbinstool制作的可启动U盘 2 > 解压CDLinux-0.9-spring-0412.iso到U盘的根目录  如图 3 > 打开fbin ...

  2. iOS Dev (67) 单例的实现

    iOS Dev (67) 单例的实现 博客:http://blog.csdn.net/prevention 作者:大锐哥 摘自:Learn iPhone and iPad cocos2d Game D ...

  3. [置顶] js综合应用:表格的四则运算

    在做调查问卷的过程中,遇到一个表格的统计问题,算是需要些js方面的综合知识,所以记录下来. 在上次完成了基本的求和的基础上,添加了基本的加减乘除四则运算. 基本需求简化后如下: 对应的htm了为: & ...

  4. 正则RegEXp

    JavaScript RegExp 对象 RegExp 对象 RegExp 对象表示正则表达式,它是对字符串执行模式匹配的强大工具. 直接量语法 /pattern/attributes 创建 RegE ...

  5. SQL Server(SSIS package) call .net DLL

    There are two method to call .net DLL in SQLSERVER. The first one is to use the sql clr but it has a ...

  6. mysql 中的 IF 和 IFNULL 用法

    IFNULL(expr1,expr2) 如果expr1不是NULL,IFNULL()返回expr1,否则它返回expr2.IFNULL()返回一个数字或字符串值,取决于它被使用的上下文环境. IF(S ...

  7. FreeCodeCamp:Title Case a Sentence

    要求: 确保字符串的每个单词首字母都大写,其余部分小写. 像'the'和'of'这样的连接符同理. 结果: titleCase("I'm a little tea pot") 应该 ...

  8. python实现单向链表

    #Definition for singly-linked list. class ListNode(object): def __init__(self, x): self.val = x self ...

  9. Python学习之路——字符处理(二)

    一.set集合: set是一个无序且不重复的元素集合 建立一个集合: x = set([1, 'tom', 2, 3, 4]) print(type(x)) print(x) 以上实例运行后反回结果结 ...

  10. Java学习之开篇—个人随想

    现在大三上学期了,家里希望考研,不然觉得我这学校不好找工作,我自己觉得工作还是靠自己,学校就像给人第一眼感觉那样,虽然重要但也只会吸引HR多看两眼,真正留得住HR的还是要有拿的出手的技能. 当初凭着对 ...