日期:2014-05-16 浏览次数:20766 次
引言
我觉得ORPSoC的关键在于‘P’,即programmable。SoC的有优势就在于只要是满足总线interface的ip,可以实现plug & work。
所以一旦完成前面的工作之后,添加属于自己的ip core到ORPSoC的wishbone总线上,并编写它对应的驱动就成为非常关键的一步。
本小节就做一个简单的例子,来说明需要完成的工作步骤及其中遇到的问题和对应的解决方法。
11.1 编写wishbone为interface的ip core(ip_mkg)
1》这一步请参考:
http://blog.csdn.net/rill_zhen/article/details/8659788
2》将其中的my_slave_module链接到ORPSoC的wishbone上。
11.2 编写linux下的driver module
代码及makefile如下:
1》ip_mkg.c
/* * * rill mkg driver * */ #include <linux/vmalloc.h> #include <linux/slab.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 "ip_mkg.h" void __iomem *g_mkg_mem_base = NULL; static int device_open(struct inode *inode, struct file *file) { g_mkg_mem_base = ioremap(MKG_MEM_BASE,MKG_MEM_LEN); if(NULL == g_mkg_mem_base) { printk(KERN_ERR "mkg open ioremap error!\n"); return -1; } else { printk("mkg ioremap addr:%d!\n",(int)g_mkg_mem_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) { return 0; } static ssize_t device_write(struct file *filp, const char *buffer, size_t count, loff_t *offset) { return 0; } long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { int ret_val = 0; unsigned int ret = 0; struct reg_data *new_regs; 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; } 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 init_module() { int ret_val; int ret; void __iomem *ret_from_request; //=== 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"); //===ioremap mkg registers g_mkg_mem_base = ioremap(MKG_MEM_BASE,MKG_MEM_LEN); if(NULL == g_mkg_mem_base) { printk(KERN_ERR "mkg ioremap error!\n"); return -1; } else { ;//printk("mkg ioremap addr:%d!\n",g_mkg_mem_base); } printk("mkg module init done!\n"); return 0; } void cleanup_module() { release_mem_region(MKG_MEM_BASE, MKG_MEM_LEN); unregister_chrdev(MAJOR_NUM, DEVICE_NAME); }