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

来源:互联网 发布:最终幻想14 知乎 编辑:程序博客网 时间:2024/04/30 13:23

引言

之前,我们在讨论基于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;parameteraddress_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;parameterwrite_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;parameters_write=9'b000010000;parameters_read_pause=9'b000100000;parameters_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;regread_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;elsestate<=next_state;always @(*)begincase(state)s_idle:beginif(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;elsenext_state=s_idle;ends_write_done:beginnext_state=s_idle;ends_read_done:beginnext_state=s_idle;ends_write:beginnext_state=s_write_pause1;ends_write_pause1:beginnext_state=s_write_pause2;ends_read:beginnext_state=s_read_pause;ends_read_pause:beginnext_state=s_idle;ends_write_pause2:beginnext_state=s_write_pause3;ends_write_pause3:beginnext_state=s_idle;enddefault:beginnext_state=s_idle;endendcase end always @(posedge wb_clk) if(wb_rst)beginaddress_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;endelsebegincase(next_state)s_idle:beginaddress_o<=0;value_o<=0;write_o<=0;read_o<=0;wb_dat_o<=0;wb_ack_o<=0; ends_read_done:beginaddress_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;ends_write_done:beginaddress_o<=0;value_o<=0;write_o<=0;read_o<=0;wb_dat_o<=0;wb_ack_o<=0;  write_done<=1'b1;ends_read:beginif(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;elsewb_dat_o<=wb_adr_i;   wb_ack_o<=0;address_o<=0;value_o<=0;write_o<=0;read_o<=0;ends_read_pause:beginwb_dat_o<=wb_dat_o;wb_ack_o<=1'b1;address_o<=0;value_o<=0;write_o<=0;read_o<=0;ends_write:beginif(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;ends_write_pause1:beginif(wr_reg == read_command)beginread_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;endelse if(wr_reg == write_command)beginwrite_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;endelsebeginwrite_o<=0;read_o<=0;//wb_ack_o<=1'b1;//wb_dat_o<=0;address_o<=0;value_o<=0;endends_write_pause2:beginif(wr_reg == read_command)beginread_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;endelse if(wr_reg == write_command)beginwrite_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;endelsebeginwrite_o<=0;read_o<=0;//wb_ack_o<=1'b1;//wb_dat_o<=0;address_o<=0;value_o<=0;endends_write_pause3:begin  if(wr_reg == read_command)  beginread_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)  beginwrite_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;endelsebeginwrite_o<=0;read_o<=0;wb_ack_o<=1'b1;wb_dat_o<=0;address_o<=0;value_o<=0;endenddefault:beginaddress_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;endendcaseendendmodule    

  
 


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 interfaceinputwb_clk;inputwb_rst;inputwb_ack_i; inputwb_err_i; inputwb_rty_i;input[31:0]wb_dat_i;outputreg [31:0]wb_adr_o;outputreg [31:0]wb_dat_o;outputreg wb_cyc_o; outputregwb_stb_o;outputreg [3:0]wb_sel_o;outputreg wb_we_o;outputreg [2:0]wb_cti_o;outputreg [1:0]wb_bte_o;inputwrite_i;inputread_i;input [31:0]address_i;input [31:0]value_i;outputreg [31:0]value_o;output reg write_ack;outputreg read_ack;parameterm_idle=9'b000000001;parameter   m_write_ready=  9'b010000000;parameterm_read_ready=9'b100000000;parameterm_write_begin=9'b000000010;parameterm_write_wait=9'b000000100;parameterm_write_done=9'b000001000;parameterm_read_begin=9'b000010000;parameterm_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;elsestate<=next_state;always @(*)case(state)m_idle:beginif(write_i)next_state=m_write_ready;else if(read_i)next_state=m_read_ready;else next_state=m_idle;endm_write_ready:beginnext_state=m_write_begin;endm_read_ready:beginnext_state=m_read_begin;endm_write_begin:beginnext_state=m_write_wait;endm_write_wait:beginif(wb_ack_i)next_state=m_write_done;elsenext_state=m_write_wait;endm_write_done:beginnext_state=m_idle;endm_read_begin:beginnext_state=m_read_wait;endm_read_wait:beginif(wb_ack_i)next_state=m_read_done;elsenext_state=m_read_wait;endm_read_done:beginnext_state=m_idle;enddefault:beginnext_state=m_idle;endendcasealways @ (posedge wb_clk)if(wb_rst)beginwb_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;endelsebegincase(next_state)m_idle:beginwb_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;endm_write_ready:beginwb_adr_o<=0;wb_dat_o<=0;wb_cyc_o<=0;wb_stb_o<=0;wb_we_o<=0;endm_read_ready:beginwb_adr_o<=0;wb_dat_o<=0;wb_cyc_o<=0;wb_stb_o<=0;wb_we_o<=0; endm_write_begin:beginwb_adr_o<=address_i;wb_dat_o<=value_i;wb_cyc_o<=1'b1;wb_stb_o<=1'b1;wb_we_o<=1'b1;endm_write_wait:beginwb_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;endm_write_done:beginwb_adr_o<=0;wb_dat_o<=0;wb_cyc_o<=0;wb_stb_o<=0;wb_we_o<=0;write_ack<=1'b1;endm_read_begin:beginwb_adr_o<=address_i;wb_dat_o<=0;wb_cyc_o<=1'b1;wb_stb_o<=1'b1;wb_we_o<=0;endm_read_wait:beginwb_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;endm_read_done:beginwb_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;enddefault:beginwb_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;endendcaseendendmodule




3》mycore.v


/*** rill create 130618* rillzhen@gmail.com*/module mycore(   //===slave interface signalswb_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 signalswbm_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;outputwbs_d_mycore_ack_o;outputwbs_d_mycore_err_o;outputwbs_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;inputwbs_d_mycore_we_i;inputwbs_d_mycore_cyc_i;inputwbs_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;inputwbm_d_mycore_ack_i;inputwbm_d_mycore_err_i;inputwbm_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;outputwbm_d_mycore_we_o;outputwbm_d_mycore_cyc_o;outputwbm_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;wirewrite;wireread;wireread_ack;wirewrite_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+4iowrite32(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 registersg_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_NUM102#define DEVICE_NAME"ip_mkg"#define MKG_MEM_BASE 0x98000000#define MKG_MEM_LEN3072#define MKG_CORE_BASE 0x97000000#define MKG_CORE_LEN 128#define IOCTL_REG_SET 0#define IOCTL_REG_GET 1struct 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_adrwrite 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_adrread 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+4read 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-4read address done !read address : 0x152600c read commnad done !read command : 0x0 <read_done  flag: 0x1000000   ><read_value flag: 0xcdab5639   > read forth number: 0x98000040read 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,问题就不大了。




原创粉丝点击