首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

OpenRisc-11-平添ip core到ORPSoC并编写它的linux driver,然后run helloworld

2013-03-25 
OpenRisc-11-添加ip core到ORPSoC并编写它的linux driver,然后run helloworld引言我觉得ORPSoC的关键在于‘

OpenRisc-11-添加ip core到ORPSoC并编写它的linux driver,然后run helloworld

引言

我觉得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 registersg_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);}MODULE_LICENSE("GPL");MODULE_AUTHOR("Rill zhen:rillzhen@gmail.com");


 

 

2》ip_mkg.h,需要注意的是ip core的基地址是在写verilog HDL时指定的。

 

#ifndef __IP_MKG_H__#define __IP_MKG_H__#define MAJOR_NUM102#define DEVICE_NAME"ip_mkg"#define MKG_MEM_BASE 0x10000001#define MKG_MEM_LEN32#define IOCTL_REG_SET 0#define IOCTL_REG_GET 1struct reg_data {unsigned short addr;int value;};#endif


 

 

3》Makefile

 

# 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 cleanelse    # called from kernel build system: just declare what our modules are    obj-m := ip_mkg.oendif


 

 

11.3 遇到的问题

1》当在执行make时会遇到如下警告:__ioremap undefined。

OpenRisc-11-平添ip core到ORPSoC并编写它的linux driver,然后run helloworld

2》在板子上insmod时会遇到如下error:unknown symbol __ioremap。

 

OpenRisc-11-平添ip core到ORPSoC并编写它的linux driver,然后run helloworld

11.4 解决方法

在arch/openrisc/mm/ioremap.c中添加如下代码:并重新编译kernel。

 

#include <linux/module.h>EXPORT_SYMBOL(__ioremap);


 

 

 

 

 

11.5 小结

实验步骤

 

0》virtualbox虚拟机unbuntu上安装nfs服务

0.0>确保virtualbox能上网

0.1> apt-get install nfs-kernel-server

0.2>创建nfs共享目录:mkdir /home/openrisc/nfs

0.3>vim /etc/exports,添加如下内容

/home/openrisc/nfs  *(rw,sync)

0.4>重启nfs服务

sudo /etc/init.d/nfs-kernel-server restart

 

1》修改arch/openrisc/mm/ioremap.c

2》cd /home/openrisc/soc-design/linux

3》make ARCH=openrisc defconfig;make生成vmlinux

4》cd 到ip_mkg下,make生成ip_mkg.ko模块文件

5》参考如下链接,在FPGA板子上运行linux(刚刚生成的vmlinux文件)

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

6》配置virtualbox的ip

sudo ifconfig eth8 192.168.1.101 broadcast 192.168.1.255

7》配置PC机的ip为192.168.1.102

8》板子起来后默认的ip为192.168.1.100,如果不是,则需要配置为同一网段。确保板子能ping通virtualbox

9》板子上执行mkdir nfs,创建本地nfs共享目录

10》挂载NFS:mount -t nfs -o nolock 192.168.1.101:/home/openrisc/nfs /nfs

11》在virtualbox里将ip_mkg.ko copy到nfs共享目录

12》板子上cd nfs

13》执行insmod ip_mkg.ko加载模块,可以通过lsmod检查一下

14》创建设备节点:mknod /dev/ip_mkg c 102 0

15》测试:cat /dev/ip_mkg,看到如下结果:

 

OpenRisc-11-平添ip core到ORPSoC并编写它的linux driver,然后run helloworld

 

 

16》运行helloworld

16.1>编写hello.c

#include <stdio.h>void main(){printf("rill helloworld!\n");}


16.2>编译: or2-linux-gcc hello.c -o hello

16.3>copy到板子上:cp hello /home/openrisc/nfs

16.4>在板子上cd到/nfs,然后ls可以看到刚copy来的hello文件,最后运行:./hello,可以看到输出:

 

OpenRisc-11-平添ip core到ORPSoC并编写它的linux driver,然后run helloworld

 

 

17》最后放一首歌,庆祝一下:

OpenRisc-11-平添ip core到ORPSoC并编写它的linux driver,然后run helloworld

梦醒时分
词曲:李宗盛
演唱:陈淑桦

你说你爱了不该爱的人
你的心中满是伤痕
你说你犯了不该犯的错
心中满是悔恨
你说你尝尽了生活的苦
找不到可以相信的人
你说你感到万分沮丧
甚至开始怀疑人生

早知道伤心总是难免的
你又何苦一往情深
因为爱情总是难舍难分
何必在意那一点点温存
要知道伤心总是难免的
在每一个梦醒时分
有些事情你现在不必问
有些人你永远不必等

你说你爱了不该爱的人
你的心中满是伤痕
你说你犯了不该犯的错
心中满是悔恨
你说你尝尽了生活的苦
找不到可以相信的人
你说你感到万分沮丧
甚至开始怀疑人生

早知道伤心总是难免的
你又何苦一往情深
因为爱情总是难舍难分
何必在意那一点点温存
要知道伤心总是难免的
在每一个梦醒时分
有些事情你现在不必问
有些人你永远不必等

早知道伤心总是难免的
你又何苦一往情深
因为爱情总是难舍难分
何必在意那一点点温存
要知道伤心总是难免的
在每一个梦醒时分
有些事情你现在不必问
有些人你永远不必等 

热点排行