MicroBlaze使用_char* malloc

2022-11-03 15:33:13 浏览数 (2)

转自http://blog.163.com/gcs_gcs/blog/static/17448606620121193113914/

在最近的工程中,需要用到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操作,非法操作码异常,数据总线异常等。

breakbreak分为software break和hardware

break。hardware

break,这时MDM模块的输出端口Ext_BRK和Ext_NM_BRK跟MicroBlaze对应的输入端口相连。一旦break响应,暂停返回地址(break

return address)自动装入R16寄存器中。而software

break通过brk和brki指令来完成。

interruptMicroBlaze只支持一个外部中断源(连接于Interrupt

端口),所以需要多个中断输入的话,就得添加中断控制器(xps_intc)了。只有当机器状态寄存器(Machine Status

Register,MSR)中的中断使能位(interrupt

enable)置’1’,MicroBlaze才能响应中断。MicroBlaze响应中断,PC指向中断向量(地址:0x10),R14存储了中断返回地址。

注:具体细节问题,请见参考1。

注:该表格来自于MicroBlaze参考手册,见参考1

下面具体介绍如何对MicroBlaze进行中断编程。

中断信号的物理连接system.mhs文件定义了物理硬件的相关信息,包括总线架构、外围设备、处理器、系统内部信号互连和地址空间等。所以这里就通过MHS定义文件给出关于中断信号互连的信息。 当然MicroBlaze的中断输入,可以配置成电平触发或者边沿触发,在配置MicroBlaze的GUI或者在MicroBlaze.mpd中通过设置 C_INTERRUPT_IS_EDGE ,C_EDGE_IS_POSITIVE来完成对中断的触发的配置。

BEGIN

microblaze . .

.PORT MB_RESET =

mb_reset PORT Interrupt =

InterruptEND

BEGIN xps_uartlite . .

. PORT Interrupt =

RS232_Uart_1_InterruptEND

BEGIN

xps_intc . . . PORT Irq =

Interrupt PORT

Intr =

RS232_Uart_1_Interrupt&plb_ps2_controller_0_IP2INTC_IrptEND

BEGIN

plb_ps2_controller . . . PORT IP2INTC_Irpt =

plb_ps2_controller_0_IP2INTC_IrptPORT 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

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

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; }

汇编代码详解使用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

总结 主要描述了MicroBlaze的中断的基本原理,以及编程。

参考文献:

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/201093.html原文链接:https://javaforall.cn

0 人点赞