新浪博客

MicroBlaze中断编程——以PS/2键盘输入为例

2012-07-23 11:00阅读:
转:http://www.eefocus.com/yq000cn/blog/2012-03/201498_5978e.html
在最近的工程中,需要用到PS/2键盘和鼠标作为控制输入,所以在网上找了一些相关的资料,内容很丰富,看来已经有很多人做过了这方面的编程。本篇Blog算是实践总结,为以后的开发积累一些基础知识。
MicroBlaze支持重启(reset),中断( interrupt), 暂停(break)和异常( exception)。这里粗略的介绍:
  • reset
    当 外部按键发出reset信号或者XMD通过MDM(MicroBlaze Debug module)发出reset信号,这些信号都会被proc_sys_reset模块接收,然后该模块产生一个16周期长的高电平信号至 MicroBlaze的MB_RESET管脚。MicroBlaze响应reset, PC 寄存器指向0x0地址,依照向量表中代码执行。
  • exception
    异常是MicroBlaze对内部运行发生错误的情况发做出的响应,这些情况包括:非法指令,指令和数据总线错误和未对齐的访问(unaligned access)。如除0操作,非法操作码异常,数据总线异常等。
  • break
    break 分为software break和hardware break。hardware break,这时MDM模块的输出端口Ext_BRK和Ext_NM_BRK跟MicroBlaze对应的输入端口相连。一旦break响应,暂停返回地址(break return address)自动装入R16寄存器中。而software break通过brkbrki指令来完成。
  • interrupt
    MicroBlaze 只
支持一个外部中断源(连接于Interrupt 端口),所以需要多个中断输入的话,就得添加中断控制器(xps_intc)了。只有当机器状态寄存器(Machine Status Register,MSR)中的中断使能位(interrupt enable)置'1',MicroBlaze才能响应中断。MicroBlaze响应中断,PC指向中断向量(地址:0x10),R14存储了中断返回地址。注:具体细节问题,请见参考1。
MicroBlaze中断编程——以PS/2键盘输入为例
注:该表格来自于MicroBlaze参考手册,见参考1
下面具体介绍如何对MicroBlaze进行中断编程。
  1. 中断信号的物理连接
    system.mhs文件定义了物理硬件的相关信息,包括总线架构、外围设备、处理器、系统内部信号互连和地址空间等。所以这里就通过MHS定义文件给出关于中断信号互连的信息。
    当然MicroBlaze的中断输入,可以配置成电平触发或者边沿触发,在配置MicroBlaze的GUI或者在MicroBlaze.mpd中通过设置 C_INTERRUPT_IS_EDGEC_EDGE_IS_POSITIVE来完成对中断的触发的配置
    BEGIN microblaze
    . . .
    PORT MB_RESET = mb_reset
    PORT Interrupt = Interrupt
    END


    BEGIN xps_uartlite
    . . .
    PORT Interrupt = RS232_Uart_1_Interrupt
    END

    BEGIN xps_intc
    . . .
    PORT Irq = Interrupt
    PORT Intr = RS232_Uart_1_Interrupt&plb_ps2_controller_0_IP2INTC_Irpt
    END

    BEGIN plb_ps2_controller
    . . .
    PORT IP2INTC_Irpt = plb_ps2_controller_0_IP2INTC_Irpt
    PORT mouse_clk = plb_ps2_controller_0_mouse_clk
    PORT mouse_data = plb_ps2_controller_0_mouse_data
    PORT key_clk = plb_ps2_controller_0_key_clk
    PORT key_data = plb_ps2_controller_0_key_data
    END


  2. EDK提供的驱动以及相关函数的介绍
    void microblaze_enable_interrupts(void)
    该函数使MicroBlaze可以响应中断,即MSR中的“interrupt enable”位置’1’;
    void microblaze_disable_interrupts(void)
    该函数使MicroBlaze不能响应中断,即MSR中的“interrupt enable”位置 ’0’;
    这几个函数都定义包含在$EDK_project/microblaze_0/include/mb_interface.h
    头文件中

    XIntc_Initialize(&InterruptController, (Xuint16)INTC_DEVICE_ID);
    该函数用于初始化中断控制器,主要包括初始化XIntc的结构体,初始化向量列表,以及所有中断源输入禁用,中断输出禁用。
    int XIntc_Connect(XIntc * InstancePtr, u8 Id,
    XInterruptHandler Handler, void *CallBackRef)
    中断源的标示和相关中断处理程序的连接。
    XIntc_Start(XIntcInstancePtr, XIN_REAL_MODE);
    该函数使得中断控制器输出的中断信号启用。XIN_REAL_MODE 意思是只允许硬件中断(hardware interrupt)
    void XIntc_Enable(XIntc * InstancePtr, u8 Id)
    该函数使得对应ID的中断源输入启用
    这几个函数定义在$EDK_project/microblaze_0/libsrc/intc_v1_11_a/src/xintc.c
    需要包含的头文件:xintc.h
  3. C语言编程实例

    #include
    #include
    #include 'xparameters.h'
    #include 'xutil.h'
    #include 'xintc.h'
    #include 'plb_ps2_controller.h'
    #include 'mb_interface.h'
    #define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
    int init_input(void);
    XStatus SetUpInterruptSystem(XIntc *XIntcInstancePtr);
    static XIntc InterruptController;
    void PS2_InterruptHandler(void *CallbackRef)
    {
    u32 mouse_state, keybd_state, flags;
    Xuint32 baseaddr = (Xuint32) XPAR_PLB_PS2_CONTROLLER_0_BASEADDR;

    keybd_state = ((u32 *)baseaddr)[0];
    mouse_state = ((u32 *)baseaddr)[1];
    flags = PLB_PS2_CONTROLLER_mReadReg(baseaddr, PLB_PS2_CONTROLLER_INTR_IPISR_OFFSET);
    if (flags & EVENT_FROM_MOUSE)

    handle_mouse_event(mouse_state);
    if (flags & EVENT_FROM_KEYBD)

    handle_keybd_event(keybd_state);

    PLB_PS2_CONTROLLER_mWriteReg(baseaddr, PLB_PS2_CONTROLLER_INTR_IPISR_OFFSET, flags);
    }
    XStatus init_input(void)
    {
    XStatus Status;
    Xuint32 baseaddr = (Xuint32) XPAR_PLB_PS2_CONTROLLER_0_BASEADDR;

    PLB_PS2_CONTROLLER_mWriteReg(baseaddr, PLB_PS2_CONTROLLER_INTR_DIER_OFFSET, 0);
    PLB_PS2_CONTROLLER_mWriteReg(baseaddr, PLB_PS2_CONTROLLER_INTR_DGIER_OFFSET, 0xFFFFFFFF);
    PLB_PS2_CONTROLLER_mWriteReg(baseaddr, PLB_PS2_CONTROLLER_INTR_IPIER_OFFSET, 0xFFFFFFFF);
    PLB_PS2_CONTROLLER_mWriteReg(baseaddr, PLB_PS2_CONTROLLER_INTR_IPISR_OFFSET, 0);

    Status = XIntc_Initialize(&InterruptController, (Xuint16)INTC_DEVICE_ID);
    if (Status != XST_SUCCESS)
    { return XST_FAILURE; }
    Status = XIntc_SelfTest(&InterruptController);
    if (Status != XST_SUCCESS)
    { return XST_FAILURE; }

    Status = XIntc_Connect(XIntcInstancePtr, XPAR_XPS_INTC_0_PLB_PS2_CONTROLLER_0_IP2INTC_IRPT_INTR,
    (XInterruptHandler)PS2_InterruptHandler,
    (void *)0);
    if (Status != XST_SUCCESS)
    { return XST_FAILURE;}

    Status = XIntc_Start(XIntcInstancePtr, XIN_REAL_MODE);
    if (Status != XST_SUCCESS)
    {
    return XST_FAILURE;
    }

    XIntc_Enable(XIntcInstancePtr, XPAR_XPS_INTC_0_PLB_PS2_CONTROLLER_0_IP2INTC_IRPT_INTR);

    microblaze_enable_interrupts();
    return XST_SUCCESS;
    }
    int main(void){

    init_input();

    while(1);
    return 1;
    }
  4. 汇编代码详解
    使用mb-objdump工具对实例进行了反汇编,想看看到底是个什么情况
    Disassembly of section .vectors.reset:
    00000000 <_start>:
    0: b0009000 imm -28672
    4: b8080000 brai 0 #main()程序起始地址是0x90000000
    Disassembly of section .vectors.sw_exception:
    00000008 <_vector_sw_exception>:
    8: b0009000 imm -28672
    c: b8080438 brai 1080
    Disassembly of section .vectors.interrupt:
    00000010 <_vector_interrupt>:
    10: b0009000 imm -28672
    14: b8080474 brai 1140 #中断处理程序起始地址是0x90000474
    Disassembly of section .vectors.hw_exception:
    00000020 <_vector_hw_exception>:
    20: b0009000 imm -28672
    24: b8080450 brai 1104
    90000474 <__interrupt_handler>: #中断处理程序起始地址和汇编代码
    90000474: 3021ffb0 addik r1, r1, -80
    90000478: f9e10000 swi r15, r1, 0
    9000047c: f8610020 swi r3, r1, 32
    90000480: f8810024 swi r4, r1, 36
    90000484: f8a10028 swi r5, r1, 40
    90000488: f8c1002c swi r6, r1, 44
    9000048c: f8e10030 swi r7, r1, 48
    90000490: f9010034 swi r8, r1, 52
    90000494: f9210038 swi r9, r1, 56
    90000498: f941003c swi r10, r1, 60
    9000049c: f9610040 swi r11, r1, 64
    900004a0: f9810044 swi r12, r1, 68
    900004a4: fa210048 swi r17, r1, 72
  5. 总结
    主要描述了MicroBlaze的中断的基本原理,以及编程。
参考文献:
  1. MicroBlaze Processor Reference Guide
    http://www.xilinx.com/support/documentation/sw_manuals/mb_ref_guide.pdf
  2. Using and Creating Interrupt-based Systems
    http://www.xilinx.com/support/documentation/application_notes/xapp778.pdf
  3. Embedded System Tools Reference Manual
    http://www.xilinx.com/support/documentation/sw_manuals/edk10_est_rm.pdf
  4. Process System Reset Module
    http://www.xilinx.com/support/documentation/ip_documentation/processor_sys_reset.pdf

我的更多文章

下载客户端阅读体验更佳

APP专享