在实现内核程序(driver)和硬件(ipcore)的memory共享时,需要解决的主要问题是如何将用kmalloc()函数获得的内核逻辑地址转换成物理地址,以供硬件(ipcore)使用,最终实现DMA操作。
内核空间的程序(driver)和ipcore的memory的共享问题已经解决,请参考:
http://blog.csdn.net/rill_zhen/article/details/9121009
这时,如果用户空间的程序(AP)想向ipcore传递数据,可以在内核空间的driver部分的read/write函数的实现时通过copy_from_user和copy_to_user两个函数与用户空间程序实现数据交换,然后通过上面的方式,再与ipcore实现数据交换。
这样做可以实现AP和ipcore的数据交换,并且在数据量比较小时队系统的影响也不大。但是,如果AP和ipcore交换的数据较大时,就会严重影响系统性能。甚至,如果不用DMA,后果就更严重。
本小节就解决这个问题。
为了更清晰的说明在AP和ipcore间的数据交换的具体过程,我假设了三种方式:
1》AP和kernel通过copy_from_user和copy_to_user两个函数实现数据交换。
2》kernel和ipcore之间通过io_read32/io_write32两个函数实现数据交换。
3》CPU需要进行2次数据拷贝。
1》AP和kernel通过copy_from_user和copy_to_user两个函数实现数据交换。
2》kernel和ipcore之间通过virtual_to_physical()函数将内核空间的地址转换成物理地址,然后ipcore通过DMA的方式实现数据交换。
3》CPU需要进行1次数据拷贝。
1》AP和kernel通过mmap()函数将ipcore的物理地址(也可以是内核空间的逻辑地址)映射到用户空间。
如果是内核空间的逻辑地址(ipcore和内核共享SDRAM):不带显存的显卡采用的就是这种方式(framebuffer)。
2.1》kernel和ipcore之间通过virtual_to_physical()函数将内核空间的地址转换成物理地址,然后ipcore通过DMA的方式实现数据交换。
如果是ipcore的地址(ipcore有local RAM,不与内核共享SDRAM):带显存的显卡采用的就是这种方式(framebuffer)
2.2》kernel和ipcore之间通过virtual_to_physical()函数将内核空间的地址转换成物理地址,然后ipcore通过可以直接访问本地数据的方式实现数据交换。
3》CPU需要进行0次数据拷贝,即CPU不进行数据拷贝,可以完全从大量数据拷贝工作中解脱出来。
注:上述3中方式均不考虑最初的那次数据拷贝(从文件(disk)到内存(SDRAM))。
采用方式a的情况:
http://blog.csdn.net/rill_zhen/article/details/8722664
采用方式b的情况:
http://blog.csdn.net/rill_zhen/article/details/8849149
而本小节就是采用方式c中ipcore有local RAM,不与内核共享SDRAM的情况。
采为了更直观的表示上述三种情况,我做了如下对比图:
为了实现上面所述的方式c2的情况,软件部分的工作如下:
1》在驱动层实现mmap函数,将mkg_slave的地址空间映射给用户(主要调用io_remap_pfn_range()函数实现将ipcore的物理地址映射到用户空间)
2》在用户层调用mmap()获得对应的虚拟地址3》用户程序直接操作这个虚拟地址,就可以实现直接操作my_ram这个ipcore
将之前驱动部分的工作(调用io_read32()/io_write32())交给用户层来做,如果ipcore工作良好,则说明这个方式是成功的。
具体信息请参考之前其他blog中的driver的内容。
3个文件:ip_mkg.c,ip_mkg.h,makefile
/* * * 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; } void device_vma_open (struct vm_area_struct * vma) { printk("ip_mkg vma open ,virt 0x%x, phy 0x%x\n",vma->vm_start,vma->vm_pgoff<<PAGE_SHIFT); } void device_vma_close(struct vm_area_struct * vma) { printk("ip_mkg vma close \n"); } static struct vm_operations_struct device_remap_vm_ops = { .open = device_vma_open, .close = device_vma_close, }; static int device_mmap (struct file * filp,struct vm_area_struct * vma) { unsigned long off; unsigned long start; if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { printk("vm_pgoff is wrong !\n"); return -EINVAL; } start=0x97000000; start &= PAGE_MASK; printk("start is 0x%x \n",start); off=vma->vm_pgoff<<PAGE_SHIFT; off+=start; printk("off is 0x%x \n",off); vma->vm_pgoff=off>>PAGE_SHIFT; vma->vm_flags |=VM_IO | VM_RESERVED; vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); printk(" vm_start: 0x%x ,off : 0x%x \n ",vma->vm_start,off>>PAGE_SHIFT); if(io_remap_pfn_range(vma,vma->vm_start,off >> PAGE_SHIFT,vma->vm_end-vma->vm_start,vma->vm_page_prot)) { printk("remap_pfn_range error \n"); return - EAGAIN; } printk("remap success \n"); // vma->vm_ops = & device_remap_vm_ops; // device_vma_open( vma); return 0; } struct file_operations our_file_ops = { .unlocked_ioctl = device_ioctl, .read = device_read, .write = device_write, .open = device_open, .release = device_release, .mmap = device_mmap, .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) { /* int write_data[256]={ 0x69016901, 0x8b014401, 0xa7011a01, 0xbd01ee00, 0xcd01bf00, 0xd7018f00, 0xdb015e00, 0xd8012e00, 0xcf010000, 0xc101d403, 0xad01ab03, 0x94018603, 0x78016503, 0x58014803, 0x35013203, 0x11012003, 0xec001403, 0xc7000e03, 0xa3000c03, 0x80001003, 0x5f001903, 0x42002503, 0x28003603, 0x12004803, 0x00005e03, 0xf3037403, 0xe9038b03, 0xe403a303, 0xe303b903, 0xe603ce03, 0xec03e203, 0xf503f203, 0x00000000, 0x0d000a00, 0x1c001200, 0x2b001700, 0x3a001800, 0x49001600, 0x56001100, 0x62000900, 0x6c000000, 0x7400f503, 0x7900e803, 0x7c00db03, 0x7b00cd03, 0x7800c003, 0x7300b303, 0x6b00a803, 0x61009f03, 0x56009703, 0x4a009203, 0x3c008f03, 0x2f008e03, 0x21009003, 0x15009503, 0x09009c03, 0x0000a403, 0xf803af03, 0xf203ba03, 0xef03c603, 0xee03d303, 0xef03e003, 0xf303ec03, 0xf903f703, 0x00000000, 0x09000700, 0x14000d00, 0x20001100, 0x2d001200, 0x3a001100, 0x46000e00, 0x52000800, 0x5c000000, 0x6400f703, 0x6b00eb03, 0x7000df03, 0x7200d103, 0x7100c403, 0x6e00b603, 0x6900aa03, 0x61009f03, 0x58009503, 0x4d008d03, 0x40008803, 0x33008503, 0x25008403, 0x18008703, 0x0b008c03, 0x00009403, 0xf7039e03, 0xef03aa03, 0xea03b703, 0xe803c603, 0xe903d503, 0xee03e403, 0xf603f303, 0x00000000, 0x0e000b00, 0x1e001400, 0x32001a00, 0x47001d00, 0x5d001c00, 0x75001700, 0x8c000d00, 0xa2000000, 0xb800ee03, 0xcb00d803, 0xdb00be03, 0xe700a103, 0xf0008003, 0xf4005d03, 0xf2003903, 0xec001403, 0xe000ef02, 0xcf00cb02, 0xb800a802, 0x9b008802, 0x7a006c02, 0x55005302, 0x2c003f02, 0x00003102, 0xd2032802, 0xa2032502, 0x71032902, 0x41033302, 0x12034302, 0xe6025902, 0xbc027502, 0x97029702, 0x7502bc02, 0x5902e602, 0x43021203, 0x33024103, 0x29027103, 0x2502a203, 0x2802d203, 0x31020000, 0x3f022c00, 0x53025500, 0x6c027a00, 0x88029b00, 0xa802b800, 0xcb02cf00, 0xef02e000, 0x1403ec00, 0x3903f200, 0x5d03f400, 0x8003f000, 0xa103e700, 0xbe03db00, 0xd803cb00, 0xee03b800, 0x0000a200, 0x0d008c00, 0x17007500, 0x1c005d00, 0x1d004700, 0x1a003200, 0x14001e00, 0x0b000e00, 0x00000000, 0xf303f603, 0xe403ee03, 0xd503e903, 0xc603e803, 0xb703ea03, 0xaa03ef03, 0x9e03f703, 0x94030000, 0x8c030b00, 0x87031800, 0x84032500, 0x85033300, 0x88034000, 0x8d034d00, 0x95035800, 0x9f036100, 0xaa036900, 0xb6036e00, 0xc4037100, 0xd1037200, 0xdf037000, 0xeb036b00, 0xf7036400, 0x00005c00, 0x08005200, 0x0e004600, 0x11003a00, 0x12002d00, 0x11002000, 0x0d001400, 0x07000900, 0x00000000, 0xf703f903, 0xec03f303, 0xe003ef03, 0xd303ee03, 0xc603ef03, 0xba03f203, 0xaf03f803, 0xa4030000, 0x9c030900, 0x95031500, 0x90032100, 0x8e032f00, 0x8f033c00, 0x92034a00, 0x97035600, 0x9f036100, 0xa8036b00, 0xb3037300, 0xc0037800, 0xcd037b00, 0xdb037c00, 0xe8037900, 0xf5037400, 0x00006c00, 0x09006200, 0x11005600, 0x16004900, 0x18003a00, 0x17002b00, 0x12001c00, 0x0a000d00, 0x00000000, 0xf203f503, 0xe203ec03, 0xce03e603, 0xb903e303, 0xa303e403, 0x8b03e903, 0x7403f303, 0x5e030000, 0x48031200, 0x36032800, 0x25034200, 0x19035f00, 0x10038000, 0x0c03a300, 0x0e03c700, 0x1403ec00, 0x20031101, 0x32033501, 0x48035801, 0x65037801, 0x86039401, 0xab03ad01, 0xd403c101, 0x0000cf01, 0x2e00d801, 0x5e00db01, 0x8f00d701, 0xbf00cd01, 0xee00bd01, 0x1a01a701, 0x44018b01 }; int read_rslt[256]; int loop1= 0; int loop2= 0; int loop3= 0; int loop4= 0; int loop5= 0; int temp= 0; printk("<----ip_mkg test start---->\n"); for(loop1=0;loop1<256;loop1++) read_rslt[loop1]=0x98766789; printk("<----the initialization of result --->\n"); for(loop2=0;loop2<256;loop2++) { iowrite32(write_data[loop2],g_mkg_mem_base+(loop2*4)); } printk("<----write orignal data --->\n"); iowrite32(0x01000000,g_mkg_core_base+0x4); printk("<---write control data --->\n"); */ 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); /* p=(char *)&phy_adr; final_phy_adr=(unsigned int)(p[3]<<24); printk("final physical address !0x%x \n ",final_phy_adr); final_phy_adr=final_phy_adr+(unsigned int)(p[2]<<16); printk("final physical address !0x%x \n ",final_phy_adr); final_phy_adr=final_phy_adr+(unsigned int)(p[1]<<8); printk("final physical address !0x%x \n ",final_phy_adr); final_phy_adr=final_phy_adr+(unsigned int)(p[0]); printk("final physical address !0x%x \n ",final_phy_adr); */ // final_phy_adr= (int)(p[0]<<24)+(int)(p[1]<<16)+(int)(p[2]<<8)+(int)(p[3]); /* *virt_adr=0x6789abcd; iowrite32(final_phy_adr,g_mkg_core_base+0x4); printk("read address done !\n"); iowrite32(0x02000000,g_mkg_core_base+0x18); printk("read commnad done !\n"); 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); */ *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); /* iowrite32(0x40000098,g_mkg_core_base+0x4); printk("write address done !\n"); iowrite32(0x1234abcd,g_mkg_core_base+0x8); printk("write value done !\n"); iowrite32(0x01000000,g_mkg_core_base+0x18); printk("write command done !\n"); iowrite32(0x40000098,g_mkg_core_base+0x4); printk("read address done !\n"); iowrite32(0x02000000,g_mkg_core_base+0x18); printk("read commnad done !\n"); write_done=ioread32(g_mkg_core_base+0x0c); 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_done flag: 0x%x >\n",read_done); printk("<read_value flag: 0x%x >\n",read_value); */ //printk("<----write control data: 0x01000000 end value:0x%x ---->\n",ioread32(g_mkg_core_base+4)); // iowrite32(0x03000000,g_mkg_core_base+0x8); // printk("<----write control data: 0x03000000 end value:0x%x---->\n",ioread32(g_mkg_core_base+8)); // mdelay(100); // mdelay(100); // mdelay(100); // mdelay(100); // printk("<----delay ends ---->\n"); // temp=ioread32(g_mkg_core_base); // printk("<-------my core status:0x%x--->\n",temp); /* while(1) { temp=ioread32(g_mkg_mem_base+0x804); if(temp==0x10101010) break; printk("<-------my core status:0x%x--->\n",temp); mdelay(1); } printk("<----waiting ends ---->\n"); mdelay(100); printk("<----delay ends ---->\n"); for(loop3=0;loop3<256;loop3++) { read_rslt[loop3]=ioread32(g_mkg_mem_base+0x00000400+(loop3*4)); } printk("<----read rslt from ram ---->\n"); temp=ioread32(g_mkg_mem_base+0x00000800); printk("<-------my clock cnt:0x%x--->\n",temp); for(loop4=0;loop4<256;loop4++) { printk("====mem read addr==0x%x==mem value:0x%x==\n",loop4,read_rslt[loop4]); } */ /* for(loop2=0;loop2<256;loop2++) { temp=ioread32(temp_addr); printk("====mem read addr==0x%x==mem value:0x%x==\n",temp_addr,temp); temp_addr=temp_addr+4; } udelay(1000); printk("<----ip_mkg read initial value ends---->\n"); temp_addr=g_mkg_mem_base; for(loop=0;loop<256;loop++) { iowrite32(loop,temp_addr); printk("====mem write addr==0x%x==mem value:0x%x==\n",temp_addr,loop); temp_addr=temp_addr+4; } udelay(1000); printk("<----ip_mkg write end---->\n\n\n"); temp_addr=g_mkg_mem_base; for(loop1=0;loop1<256;loop1++) { temp=ioread32(temp_addr); printk("====mem read addr==0x%x==mem value:0x%x==\n",temp_addr,temp); temp_addr=temp_addr+4; } printk("<----ip_mkg test end---->\n"); #endif int loop = 0; unsigned int phy_addr1 = 0; unsigned int phy_addr2 = 0; int * virtual_addr1 = NULL; int * virtual_addr2 = NULL; printk("<----ip_mkg test start---->\n"); //=====ip_mkg reg test======================================================== #if 1 printk("reg test start==\n"); iowrite32(0x11223344,g_mkg_mem_base); iowrite32(0x00000097,g_mkg_mem_base+0x10); iowrite32(0x03000000,g_mkg_mem_base+4); printk("reg test start1==\n"); printk("reg test start2==\n"); printk("reg test start3==\n"); for(loop=0;loop<7;loop++) printk("====reg addr==0x%x==reg value:0x%x==\n",loop*4,ioread32(g_mkg_mem_base+4*loop)); #endif //========================================================================= //============mem write test #if 0 printk("mem write test start==\n"); iowrite32(0x97000004,g_mkg_mem_base); iowrite32(0x2,g_mkg_mem_base+0xc); printk("======reg:c value:0x%x==\n",ioread32(g_mkg_mem_base+0xc)); printk("======reg:14 value:0x%x==\n",ioread32(g_mkg_mem_base+0x14)); printk("======reg:18 value:0x%x==\n",ioread32(g_mkg_mem_base+0x18)); printk("======reg:1c value:0x%x==\n",ioread32(g_mkg_mem_base+0x1c)); printk("======reg:20 value:0x%x==\n",ioread32(g_mkg_mem_base+0x20)); printk("======reg:24 value:0x%x==\n",ioread32(g_mkg_mem_base+0x24)); for(loop = 0;loop<10;loop++) printk("wait=write=\n"); printk("wait=write=\n"); iowrite32(0x1,g_mkg_mem_base+0xc); printk("======reg:c value:0x%x==\n",ioread32(g_mkg_mem_base+0xc)); for(loop = 0;loop<10;loop++) printk("wait=read=\n"); printk("wait=read=\n"); printk("======reg:10 value:0x%x==\n",ioread32(g_mkg_mem_base+0x10)); printk("======reg:c value:0x%x==\n\n",ioread32(g_mkg_mem_base+0xc)); #endif //============mem read test #if 0 printk("mem read test start==\n"); virtual_addr1 = (int *)kmalloc(sizeof(int), GFP_KERNEL); virtual_addr2 = (int *)kmalloc(sizeof(int), GFP_KERNEL); *virtual_addr1 = 0x55; *virtual_addr2 = 0x66; phy_addr1 = virt_to_phys(virtual_addr1); phy_addr2 = virt_to_phys(virtual_addr2); printk("virtual addr1:0x%x==phy addr1:0x%x==\n",(int)virtual_addr1,phy_addr1); printk("virtual addr2:0x%x==phy addr2:0x%x==\n",(int)virtual_addr2,phy_addr2); iowrite32(phy_addr1,g_mkg_mem_base); iowrite32(0x1,g_mkg_mem_base+0xc); printk("wait=read=\n"); printk("======reg:0 value:0x%x==\n",ioread32(g_mkg_mem_base)); printk("======reg:c value:0x%x==\n",ioread32(g_mkg_mem_base+0xc)); printk("====phy addr1==0x%x==ram value:0x%x==\n",phy_addr1,ioread32(g_mkg_mem_base+0x10)); printk("======reg:c value:0x%x==\n\n",ioread32(g_mkg_mem_base+0xc)); iowrite32(phy_addr2,g_mkg_mem_base); iowrite32(0x1,g_mkg_mem_base+0xc); printk("wait=2=\n"); printk("======reg:0 value:0x%x==\n",ioread32(g_mkg_mem_base)); printk("======reg:c value:0x%x==\n",ioread32(g_mkg_mem_base+0xc)); printk("====phy addr2==0x%x==ram value:0x%x==\n",phy_addr2,ioread32(g_mkg_mem_base+0x10)); printk("======reg:c value:0x%x==\n\n",ioread32(g_mkg_mem_base+0xc)); kfree(virtual_addr1); kfree(virtual_addr2); #endif printk("<----ip_mkg test end---->\n"); */ } 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:[email protected]");
#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 1024 #define MKG_CORE_BASE 0x97000000 #define MKG_CORE_LEN 1024 #define IOCTL_REG_SET 0 #define IOCTL_REG_GET 1 struct reg_data { unsigned short addr; int value; }; #endif
# To build modules outside of the kernel tree, we run "make" # in the kernel source tree; the Makefile these then includes this # Makefile once again. # This conditional selects whether we are being included from the # kernel Makefile or not. ifeq ($(KERNELRELEASE),) # Assume the source tree is where the running kernel was built # You should set KERNELDIR in the environment if it's elsewhere KERNELDIR ?= /home/openrisc/soc-design/linux # The current directory is passed to sub-makes as argument PWD := $(shell pwd) modules: make -C $(KERNELDIR) M=$(PWD) modules ARCH=openrisc CROSS_COMPILE=or32-linux- modules_install: make -C $(KERNELDIR) M=$(PWD) modules_install ARCH=openrisc CROSS_COMPILE=or32-linux- clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers .PHONY: modules modules_install clean else # called from kernel build system: just declare what our modules are obj-m := ip_mkg.o endif
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/types.h> int main() { int mkg_fd=0; mkg_fd=open("/dev/ip_mkg",O_RDWR); char * mkg_p=0; if(!mkg_fd) { printf("Error: cant open ip_mkg device.\n"); exit(1); } printf("The ip_mkg device is open now .\n"); mkg_p=(char *)mmap(0,sizeof(int)*256,PROT_READ | PROT_WRITE,MAP_SHARED,mkg_fd,0); if((int)mkg_p ==-1) { printf("Error: fail to map device to memory .\n"); exit(4); } printf("Map succuss!\n"); printf("mkg_p is 0x%x \n",mkg_p); *((unsigned int *)(mkg_p+0x4))=0x98000040; printf("write address! 0x%x !\n",*((unsigned int *)(mkg_p+0x4))); *((unsigned int *)(mkg_p+0x8))=0x6789bcdf; printf("write value ! 0x%x !\n",*((unsigned int *)(mkg_p+0x8))); *((unsigned int *)(mkg_p+0x18))=0x00000001; printf("write command ! 0x%x ~\n",*((unsigned int *)(mkg_p+0x18))); *((unsigned int *)(mkg_p+0x4))=0x98000040; printf("read address! 0x%x !\n",*((unsigned int *)(mkg_p+0x4))); *((unsigned int * )(mkg_p+0x18))=0x00000002; printf("read command ! 0x%x ~\n",*((unsigned int *)(mkg_p+0x18))); printf(" read done flag ! 0x%x \n",*((unsigned int *)(mkg_p+0x10))); printf(" read value ! 0x%x \n", *((unsigned int *)(mkg_p+0x14))); printf("write done flag ! 0x%x \n",*((unsigned int *)(mkg_p+0xc))); munmap(mkg_p,sizeof(int)*256); close(mkg_fd); return 0; }
硬件部分和之前的内容差异不大,详细信息请参考之前的内容,为了保持小节的独立性,这里直接贴出完整rtl:mycore.v,mymaster.v,myslave.v,myram.v:
/* * rill create 2013-06-25 * [email protected] */ 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 ****************/
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
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 default_code =32'h4875_efad; 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; reg [31:0] write_ack_done; always @(posedge wb_clk) if(wb_rst) write_ack_done<=0; else if(write_ack) write_ack_done<=32'h1; else if(write_o) write_ack_done<=0; 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_dat_o<=err_code; wb_dat_o<=default_code; 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_dat_o<=err_code; wb_dat_o<=default_code; 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_dat_o<=err_code; wb_dat_o<=default_code; 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_dat_o<=err_code; wb_dat_o<=default_code; 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]}; wb_dat_o<=value_reg; // wb_dat_o<={value_reg[7:0],value_reg[15:8],value_reg[23:16],wb_adr_i[7:0]}; else if(wb_adr_i[7:0] == write_done_adr) // wb_dat_o<={write_done,23'b0,wb_adr_i[7:0]}; wb_dat_o<=write_ack_done; // wb_dat_o<={write_done,23'b0,wb_adr_i[7:0]}; else if(wb_adr_i[7:0] == read_done_adr) wb_dat_o<={read_done,31'b0}; // wb_dat_o<={read_done,23'b0,wb_adr_i[7:0]}; 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]}; wb_dat_o<=address_reg; //wb_dat_o<={address_reg[7:0],address_reg[15:8],address_reg[23:16],wb_adr_i[7:0]}; else if(wb_adr_i[7:0] == wr_adr) wb_dat_o<=wr_reg; // wb_dat_o<={wr_reg[23:0],wb_adr_i[7:0]}; else if(wb_adr_i[7:0] == value_adr) wb_dat_o<=value_i_reg; //wb_dat_o<={value_i_reg[31:8],wb_adr_i[7:0]}; else // wb_dat_o<=wb_adr_i; wb_dat_o<=err_code; 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_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]}; address_reg<=wb_dat_i; 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; wb_dat_o<=err_code; 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; wb_dat_o<=err_code; 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; wb_dat_o<=err_code; 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; wb_dat_o<=err_code; 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<=default_code; // wb_dat_o<=0; wb_ack_o<=0; end endcase end endmodule
module myram ( 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 ); 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; parameter myram_adr =32'h9800_0040; parameter err_code =32'h1234_3456; parameter ram_idle = 4'b0001; parameter ram_read = 4'b0010; parameter ram_write = 4'b0100; reg [3:0] state, next_state; reg [31:0] value; assign wb_err_o = 0 ; assign wb_rty_o = 0; always @(posedge wb_clk) if(wb_rst) state <= ram_idle; else state <= next_state; always @(*) case(state) ram_idle: begin if(wb_stb_i && wb_cyc_i && wb_we_i && (wb_adr_i == myram_adr)) next_state = ram_write; else if (wb_stb_i && wb_cyc_i && !wb_we_i && (wb_adr_i == myram_adr)) next_state = ram_read; else next_state = ram_idle; end ram_write: begin next_state = ram_idle; end ram_read: begin next_state = ram_idle; end default: begin next_state = ram_idle; end endcase always @ (posedge wb_clk) if(wb_rst) begin wb_ack_o <=0; wb_dat_o <=0; value <=err_code; end else begin case(next_state) ram_idle: begin wb_ack_o<=0; wb_dat_o<=0; end ram_write: begin wb_ack_o<=1'b1; wb_dat_o<=0; value<=wb_dat_i; end ram_read: begin wb_ack_o<=1'b1; wb_dat_o<=value; end default: begin wb_ack_o <= 0; wb_dat_o <= 0; value <= err_code; end endcase end endmodule
经过上述的分析和实现,在进行综合,烧板,起linux,insmod,mknod,./a.out之后,就可以看到验证结果了,如下图,可以看出,AP层程序可以直接控制ipcore:
注:在AP层编写程序时,不存在大小端转换的问题,所以本小节的所有代码(包括硬件/软件)中,均没有大小端转换的内容,这是与之前内容的最大不同。
本小节实现了用户程序直接访问ipcore的地址空间,减少了CPU的数据搬运操作,可有效提供系统的性能。
enjoy!