OpenRisc-31-关于在设计具有DMA功能的ipcore时的虚实地址转换问题的分析与解决
引言
之前,我们在讨论基于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时的虚实地址转换问题的分析与解决的更多相关文章
- 安装SQL Server 2012过程中出现“启用windows功能NetFx3时出错”(错误原因、详细分析及解决方法)以及在Windows Server2012上安装.NET Framework 3.5的详细分析及安装过程
问题:在服务器(操作系统为Windows server 2012)上安装SQL Server 2012的过程中,安装停留在下图所示的界面上,显示”正在启用操作系统功能NetFx3”随后出 ...
- 审核流(2)流程设计-SNF.WorkFlow功能使用说明--SNF快速开发平台3.1
流程设计 图形化的流程设计,更方便.直观 1.打开“流程设计“程序,如上.点击”新建“如下: 2.红色部分为必填项,审批对象是选择要审批的程序菜单,单据名称是在审核流流转时用于提示的单据名称,还要选择 ...
- [置顶]
STM32的ADC1采集多条通道,可以不使用DMA功能吗?
类似的问题 为什么我采集5条通道的电压,而采集到的值却都是第一条的呢? 我什么时候需要使用DMA功能? Ⅰ关于ADC的一些知识 STM32的ADC是一种12位逐次逼近型的模拟数字转换器.它有多达18条 ...
- 什么是需求Bug、设计Bug、功能bug?
首先什么是需求Bug.设计Bug.功能bug? 需求Bug,指由于客户需求描述不清晰或错误.需求收集人员自身原因及需求本身模糊难于分析.获取等原因,导致客户需求获取不准确,后期产品不能满足客户.用户的 ...
- Java 开源办公开发平台 O2OA V5.4.0 发布 | 设计元素搜索功能上线
O2OA V5.4.0版本此次更新的设计元素搜索功能,可以让用户在海量的脚本.页面.表单.视图等信息中迅速锁定有价值的信息,以便提高用户获取信息的效率.拥有此搜索功能后,在开发过程中,可以加速定位脚本 ...
- Web API核查表:设计、测试、发布API时需思考的43件事[转]
Web API核查表:设计.测试.发布API时需思考的43件事 当设计.测试或发布一个新的Web API时,你是在一个原有的复杂系统上构建新的系统.那么至少,你也要建立在HTTP上,而HTTP则是 ...
- 个人永久性免费-Excel催化剂功能第68波-父子结构表转换之父子关系BOM表拆分篇
Excel中制造业行业中,有一个非常刚需的需求是对BOM(成品物料清单)的拆解,一般系统导出的BOM表,是经过压缩处理的,由父子表结构的方式存储数据.对某些有能力使用SAP等专业ERP软件的工厂来说, ...
- 个人永久性免费-Excel催化剂功能第67波-父子结构表转换添加辅助信息之子父关系篇
Excel作为一款数据领域的万物互联工具,连接一切外部的多种多样的数据源.将数据带到Excel的环境中,再进行数据处理.转换.统计分析等工作,是众多表哥表姐们每天都在经历的事情.能最快速将其他来源数据 ...
- 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(五)——实现注册功能
使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...
随机推荐
- PHP第一章学习——了解PHP(上)
计划开启PHP学习教程,情况如下: 1.采用教程35章48个视频文件 2.时间4月29日-5月6日 共计8天 3.具体划分每天学习章节数不少于5个,预留5-6号时间为五一假期出玩情况 4.要求认真学习 ...
- 偶然碰到的Win7 64位下CHM 的问题解决
最近下了几个沪江资料,都是chm格式的,但是在win7 64位下,都显示不了里面的音频和视频flash之类的控件,虽然可以通过源文件的方式打开视频文件,但是很麻烦. 网上似乎碰到的人也不是很多, ...
- windows下使用python googleprotobuf
首先下载:protobuf-2.5.0.tar.gz 和protoc-2.5.0-win32.zip.两者的版本要对应: 将下载的google protobuf解压,会看到一个python目录,Win ...
- js 获取星期
var week; if (new Date().getDay() == 0) week = "星期日"; if (new Date() ...
- HttpContext的解释意义
在.ashx中,我们HttpContext这个词,到底是什么意思?下面给大家说说 HttpContext 类:封装有关个别 HTTP 请求的所有 HTTP 特定的信息. 在处理请求执行链的各个阶段中, ...
- KMP算法的一个C++实现
本文参考阮一峰老师的KMP算法,重点是“部分匹配表”的建立.算法可参考 http://kb.cnblogs.com/page/176818/ . /* * kmp.cpp * Author: Qian ...
- linux: telnet
问题: telnet: connect to address 192.168.1.103: Connection refused 总结:{ 1. 需要开启telnet服务, /etc/xinetd.d ...
- 第一节 UPC 码
UPC码(Universal Product Code)是最早大规模应用的条码,其特性是一种长度固定.连续性的条码,目前主要在美国和加拿大使用,由於其应用范围广泛,故又被称万用条码. UPC码仅可用来 ...
- android自定义控件 onMeasure() 测量尺寸
上次讲的自定义控件刷新点屏幕的任意地方都会刷新,而且在xml里自定义控件下面放一个textview的话,这个TextView是显示不出来的,不只这个,以前的几个自定义控件都是 为什么呢?今天来讲下on ...
- Phalcon框架中的另类使用
不像传统的PHP框架,假设框架想被还有一个框架使用仅仅能通过rpc或是引入文件等的方式.Phalcon能够在其他框架中直接使用.这是因为Phalcon是以扩展的形式存在的,在server载入时会直接载 ...