OpenRisc-26-openrisc interruption Experiment

Source: Internet
Author: User

Introduction

An interrupt (abnormal) system is an important part of the computer architecture and the most complex part.

Many peripherals now provide interrupt processing mechanisms to reduce the CPU usage time.

This section uses a simple example to describe how to use the interrupt mechanism of openrisc.

1. Features

This section implements a wishbone slave module (mycore), which receives commands from its corresponding Linux driver and generates an interruption signal.

The Linux driver registers the interrupt handler and records the number of interruptions.

In this experiment, an interruption is triggered when the module is loaded (insmod ip_mkg.ko. An interruption is triggered when the program read is tested.

View the results in the code, and view the results through CAT/proc/STAT.

2. Or interrupt resource analysis part 1 hardware



1. the following code shows that:

The maximum number of external disconnections supported by or is 31. Only (2 ~ 31) available.

 

2. The following Code shows that:

Currently, the disconnection in use is: 2 ~ 23.

3. the following comprehensive results show that:

Actually used: 2, 4, 6, 14, 15, 16, 20, 21. A total of 8. The details are as follows:


SDC: 3.


USB: 2.


UART: 1.


Simple_spi: 1 root.


ETH: 1 root.

 

2.2 Software

The following Linux kernel code shows that:


Or contains 32. (Does not match the hardware ).

2.3 The disconnection duration used in this experiment is 24.

3. The lab content is 3.1 RTL Encoding

1> mycore. v

 

 

/*** rill create 2013-05-07**/`include "orpsoc-defines.v"module mycore(     intr_o,//interrupt outputwb_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);output  reg intr_o;input [addr_width-1: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           wb_clk;input           wb_rst;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;//external parametersparameter addr_width = 32;parameter mycore_adr = 0;//local regsreg [addr_width-1:0] num_1;reg [addr_width-1:0] num_2;reg [addr_width-1:0] sum;parameter s_idle = 3'b000;parameter s_read = 3'b001;parameter s_write = 3'b010;reg [2:0] state = s_idle;//irq statusparameter irq_idle = 3'b000;parameter irq_action = 3'b001;reg [2:0] irq_state = irq_idle;reg [7:0] irq_done;//irq flagassign wb_err_o=0;assign wb_rty_o=0;always @(*)//sum processbeginsum = num_1 + num_2;endalways @(posedge wb_clk)//interrupt processbeginif(wb_rst)beginintr_o <= 1'b0;endelsebegincase (irq_state)irq_idle:beginintr_o <= 1'b0;if( (32'd1 == num_1) && (irq_done == 8'd0) )beginirq_state <= irq_action;irq_done <= 8'd1;endelse if( (32'd2 == num_1) && (irq_done == 8'd1) )beginirq_state <= irq_action;irq_done <= 8'd2;endelse if( (32'd3 == num_1) && (irq_done == 8'd2) )beginirq_state <= irq_action;irq_done <= 8'd3;endelse if( (32'd4 == num_1) && (irq_done == 8'd3) )beginirq_state <= irq_action;irq_done <= 8'd4;endelsebeginirq_state <= irq_idle;endendirq_action:beginintr_o <= 1'b1;irq_state <= irq_idle;enddefault:beginirq_state <= irq_idle;intr_o <= 1'b0;endendcaseendendalways @(posedge wb_clk)//wishbone interfacebeginif(wb_rst)beginstate <= s_idle;endelsebegincase(state)s_idle:beginwb_dat_o <= 1'b0;wb_ack_o <= 1'b0;if(wb_stb_i && wb_cyc_i && wb_we_i)beginstate <= s_write;endelse if(wb_stb_i && wb_cyc_i && !wb_we_i)beginstate <= s_read;endelsebeginstate <= s_idle;endends_write:beginif(wb_adr_i == {mycore_adr,24'h000000})beginnum_1 <= wb_dat_i;wb_ack_o <= 1'b1;endelse if(wb_adr_i == {mycore_adr,24'h000004})beginnum_2 <= wb_dat_i;wb_ack_o <= 1'b1;endelse begin//wb_ack_o=1'b0;endstate <= s_idle;end  s_read:beginif(wb_adr_i=={mycore_adr,24'h000000})beginwb_dat_o <= num_1;wb_ack_o <= 1'b1;endelse if(wb_adr_i=={mycore_adr,24'h000004})beginwb_dat_o <= num_2;wb_ack_o <= 1'b1;endelse if(wb_adr_i=={mycore_adr,24'h000008})beginwb_dat_o <= sum;wb_ack_o <= 1'b1;endelse beginwb_dat_o=0;wb_ack_o <= 1'b1;endstate <= s_idle;enddefault:beginstate <= s_idle;endendcaseendendendmodule/************** EOF ****************/

 


2> examples: orpsoc_top.v

 

3.2 RTL synthesis

For example, there is one more broken line: 9 in total.

3.3 Linux driver Encoding

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 <asm-generic/io.h>#include "ip_mkg.h"#include <linux/interrupt.h>volatile int g_irq_test_counter = 0;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("kernel:mkg open ok!\n");}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",);*/iowrite32(0x02000000,g_mkg_mem_base);printk("request_irq ==2==!\n");printk("mkg g_irq_test_counter:%d!\n",(int)g_irq_test_counter);printk("kernel:mkg g_irq_test_counter:%d!\n",(int)g_irq_test_counter);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,};static irqreturn_t ip_mkg_irq(int irq, void *dev){g_irq_test_counter = g_irq_test_counter+1;return IRQ_HANDLED;}void test(void){int err = 0;int loop = 0;printk("request_irq...\n");err = request_irq(MKG_IRQ_INDEX,ip_mkg_irq,0,"ip_mkg",NULL);if(err){printk("request_irq error!\n");}else{printk("request_irq ok!\n");}#if 1printk("reg test start==\n");iowrite32(0x11223344,g_mkg_mem_base);iowrite32(0x11223344,g_mkg_mem_base+0x4);for(loop=0;loop<3;loop++)printk("====reg addr==0x%x==reg value:0x%x==\n",loop*4,ioread32(g_mkg_mem_base+4*loop));#endifiowrite32(0x01000000,g_mkg_mem_base);printk("request_irq ==1==!\n");printk("mkg g_irq_test_counter:%d!\n",(int)g_irq_test_counter);/*iowrite32(0x02000000,g_mkg_mem_base);printk("request_irq ==2==!\n");printk("mkg g_irq_test_counter:%d!\n",(int)g_irq_test_counter);iowrite32(0x03000000,g_mkg_mem_base);printk("request_irq ==3==!\n");printk("mkg g_irq_test_counter:%d!\n",(int)g_irq_test_counter);*/printk("<----ip_mkg test end---->\n"); }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",(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);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 0x97000000#define MKG_MEM_LEN32#define MKG_IRQ_INDEX24#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

3.4 application layer encoding

1> mkg_test.c

 

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int main(){int fd = 0;int read_data = 0;char buffer[10] = {0};fd =open("/dev/ip_mkg",O_RDWR);if(0 == fd){printf("file /dev/ip_mkg open error!\n");return 0;}else{printf("file open ok!\n\n\n");}read(fd,buffer,1);close(fd);return 0;}

 

 

4. Experiment steps

1> RTL encoding and Synthesis


2> compile the driver in Linux


3> compile and test the application


4> FPGA board Verification


For detailed operation steps, see:

Http://blog.csdn.net/rill_zhen/article/details/8700937


5> note that you must create a device node (mknod/dev/ip_mkg C 102 0) before running the test program)

5. Experiment results

1> code printing results, such:


2> CAT/proc/STAT

 

3> it can be seen that the driver sends two commands to mycore, mycore also produces two interruptions, and the interrupt handler also executes two.

 

4> reverse verification: In addition to displaying that the experiment is correct on the front, verification can also be performed on the back to show that the experiment is correct.

1. Inject the code sent by the command before testing, without interruption.

2. Modify the registration interrupt number to 25, and test again without interruption.

5> note:


1. If the interrupt command is sent continuously (as commented out in the driver), only one interrupt may occur.

2. After an interrupt command is sent, the following printed information may not be updated immediately (that is, the counter is still 0 ).

6. Summary

Through the above steps, we will have a better understanding of the use of the external interrupt of openrisc.

This provides an additional working mechanism for SoC Development, which can be polling or interrupted.

Enjoy!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.