以添加一个串口设备的中断处理函数为例,简单介绍Simulator仿真中断的调试实现过程。 ► 一、建立工程 创建一个新工程叫project1,并向其中添加Interrupt.c和utilities.c文件,均可在IARARM的安装文件tutor下找到。Interrupt.c是一个进行中断处理的C语言源文件,其中中断处理函数从串行口接收寄存器(RBRTHR)读取数据,然后输出其值。主程序允许中断并在等待中断过程中开始输出点号‘.’。 Interrupt.c源文件见附件 在工作区中选择项目文件夹project1—Debug,然后选择Project-Options菜单项,在弹出的读话框中对Linker等都使用默认配置。 ► 二、设置仿真环境 C-SPY中断系统基于一个周期计数器,在产生一个中断之前,用户可以指定该周期数。仿真UART输入,需要从文本文件InputData.txt中读取数据,其中包括Fibonacci数列,在UART接收寄存器UARTRBRTHR上设置一个‘直接读取断点’,然后将其连接到一个用户定义的宏函数Access(),该宏函数即可从文本文件中读取Fibonacci数列。无论何时产生中断,中断服务程序都要读取UARTRBRTHR寄存器,继而触发断点,执行Access()宏函数并将Fibonacci数列导入UART接收寄存器。‘直接读取断点’将在处理器读取UARTRBRTHR寄存器前触发中断,从而使宏函数 Access()得以运行,并将通过指令直接读入的数据存入寄存器中。 以下是模拟器实现串口中断仿真的步骤 1. 编写C-SPY宏文件 用户可以在启动C-SPY 时注册自定义文件,并自动执行该文件中的宏函数。本例采用 C-SPY宏文件SetupSimple.mac, 也可在IARARM的安装文件tutor下找到。 __var _fileHandle; execUserSetup() { __message "execUserSetup() called\n"; // Open the text file for ASCII reading // Put in the appropriate path to the InputData.txt file _fileHandle = __openFile( "$TOOLKIT_DIR$\\tutor\\InputData.txt", "r" ); if( !_fileHandle ) { __message "could not open file" ; } } Access() { __message "Access() called\n"; // In this tutorial we read the fib values from a file __var _fibValue; if( 0 == __readFile( _fileHandle, &_fibValue ) ) { UARTRBRTHR = _fibValue; } else { __message "error reading value from file"; } __message "UARTRBR = 0x", _fibValue:%X,"\n"; } execUserReset() { __message "execUserReset() called\n"; if( _fileHandle ) { __resetFile( _fileHandle ); } } execUserExit() { __message "execUserExit() called\n"; __closeFile( _fileHandle ); } 宏文件中首先定义了一个宏函数exeUserSetup(),它将在启动C-SPY并完成应用程序下载到目标系统之后自动运行,用来创建仿真环境。然后定义一个Access()宏函数,它将从InputData.txt文件中读取Fibonacci数列,并将这些数值分配给接收寄存器地址。用户需要将Access()宏函数连接到一个‘立即读取断点’。 2. 设置C-SPY选项 在工作区窗口选择文件夹project1—Debug,然后选择Project-Options菜单项,在弹出对话框的选择Category 列表框中选择Debugger项,在Setup 选项卡的Driver下拉列表框中选择Simulator,并选择Run to 复选框,并通过浏览按钮确认宏文件SetupSimple.mac的存放路径。C-SPY中断系统需要部分中断定义,这些定义在设备描述文件中提供,在Device description file选项区域内选择Override defaut复选框,并通过浏览按钮确认合适的设备描述文件,如下图1所示。设置完成后执行Project菜单中的Make命令,编译并链接项目。 3. 启动C-SPY模拟器 选择project—Debug菜单项,启动IAR C-SPY调试器进入模拟器模拟调试状态,运行project1项目,并使Interrupt.c出现在源代码窗口中。然后检查Debug log(调试日志)窗口,确认已经加载SetupSimple.mac宏文件,并且execUserSetup宏函数也已被调用。 ![]() 图1 4. 设置中断仿真 指定一个中断,使它循环2000次后模拟一次中断。选择Simulator-Interrupts菜单项,弹出如图2所示对话框, 在其中单击New按钮,弹出图3对话框。按以下内容对其中断进行设置。 Interrup : 填入IRQ用于指定所采用的中断。 Description:这里IAR软件会自动填好相应的内容使仿真器能够正确模拟中断,用户在使用时请不要修改。 ![]() 图2 ![]() 图3 First activation:填入4000,其是指定首次激活中断的时间,当周期计数器达到指定值时中断被激活。 Repeat interval:填入2000,其是中断的重复间隔,以时钟周期为单位。 Hold time:选择Infinite,功能是保持时间。 Probability%:填入100,功能是指定产生中断的可能性,100%表示将按指定的频率产生中断,采用其他百分数将按随机频率产生中断。在运行过程中,C-SPY处于等待状态,直到循环计数器超过激活时间而产生依次中断,每循环2000次重复产生中断。 5. 设置立即断点 采用定义一个宏函数并将其链接到一个立即断点的方法,可以用宏函数来模拟硬件设备,如本例使用的UART串行口。立即断点不会中断程序运行,而仅仅是使程序临时挂起以便检查是否UART输入是用一个设置在UARTRBRTHR地址上的立即读取断点,与宏文件中已定义的Access()宏函数相链接来模拟实现的。 选择View—Breakpoint菜单项打开中断窗口,右击该窗口,在弹出的快捷菜单中选择New Breakpoint—Immediate项,打开如图4所示的对话框。 ![]() 在该对话框中输入如图4中的参数: Break at:填入UARTRBRTHR,其用于接收缓冲器地址 Access Type:填入Read,说明断点类型(Read or Write) Action:Access(),用于链接到断点的宏 在执行过程中,当C-SPY在UARTRBRTHR地址上检测到一个读取访问时,会暂时挂起仿真进程而执行Access()宏函数,从InputData.txt文件中读取数值,并将其写入UARTRBRTHR,C-SPY在读取UARTRBRTHR接收缓冲器的值后将恢复仿真进程。 ► 三、运行仿真中断 单步运行程序到While()循环处暂停,等待输入。在Interrupt.c源代码窗口中找到irqHandler()函数,并在“++callCount;”语句行设置一个断点。全速运行程序,到达断点时程序将暂停,Terminal I/O对话框将显示Fibonacci数列,如图5。 ![]() C-SPY提供了2个系统宏函数__setSimBreak和__orderInterrupt,可在设置宏函数execUserSetup()中调用,用于自动设置断点和中断定义,避免用户进行手动配置。为此可以采用宏文件SetupAdvanced.mac取代前面的SetupSimple.mac.这样在C-SPY启动时将自动设置断点,完成中断定义,用户还不必手动在Interrupts和Breakpoints对话框中进行输入。注意,在加载SetupAdvanced.mac宏文件之前,应该先去除以前定义的断点和中断。 SetupAdvanced.mac宏文件源程序见后。 Interrupt.c源文件如下: #pragma language=extended #include <stdio.h> #include <inarm.h> #include <arm_interrupt.h> #include <ioml674001.h> #include "Utilities.h" const unsigned int RESET_VEC_ADDR = 0x0; __irq __arm void irqHandler(void); /* * Function: install_handler * * Input: vector - interrupt vector location * function - address to function * * Returns: old contents of vector * * Description: * installs the function 'function' at the vector address 'vector'. * A branch instruction to the function will be placed at the vector * address, the old contents at the vector location will be returned * by install_handler and can be used to chain another handler. */ static unsigned int install_handler(unsigned int *vector, unsigned int function) { unsigned int vec, old_vec, vectoraddr; old_vec = *vector; vectoraddr = 4*(vector-resetvec) + RESET_VEC_ADDR; vec = ((function - vectoraddr - 8) >> 2); vec |= 0xea000000; /* add opcode for B instruction */ *vector = vec; old_vec &= ~0xea000000; old_vec = ( old_vec << 2 ) + vectoraddr + 8; return(old_vec); } /* * Inputs: None. * Outputs: UART setup registers are modified. * Returns: Nothing. * Description: This routine initialises the UART on the ML674001. */ static void InitUart(void) { UARTFCRIIR_bit.FCR0 = 0; // Unbuffered operation UARTLCR_bit.LCR10 = 3; // 8-bit character UARTLCR_bit.LCR2 = 0; // 1 stop bit UARTLCR_bit.LCR3 = 0; // No parity UARTLCR_bit.LCR7 = 1; // Enable access to UARTDLL/DLH UARTDLL = 0xD7; // 9600 baud at 33MHz CCLK UARTDLM = 0x00; UARTLCR_bit.LCR7 = 0; // Enable access to UARTRBR/THR UARTIER_bit.IER0 = 1; // Enable received data available // interrupt. ILC1_bit.ILR9 = 4; // Set UART interrupt priority // level } // The showstopper int callCount = 0; // to have something to do, while waiting for interrupts static void do_foreground_process( void ) { putchar('.'); } // IRQ handler __irq __arm void irqHandler(void) { unsigned int fib; // We only use UART receive interrupts, so we // do not need to check the interrupt source. // read fib value from UART receive buffer fib = UARTRBRTHR; put_fib(fib); // increment the show stopper ++callCount; // Clear current interrupt level CILCL = 0; } // Main program for Interrupt simulation tutorial. // Prints the Fibonacci numbers. void main( void ) { // initalize the UART and fibonacci numbers init_fib(); InitUart(); // install irqHandler function at vector irqvec install_handler(irqvec, (unsigned int)irqHandler); __enable_interrupt(); /* now loop 'forever', taking input when interrupted */ while (callCount < MAX_FIB) { do_foreground_process(); } } SetupAdvanced.mac宏文件源程序如下: _var _fileHandle; __var _interruptID; __var _breakID; execUserSetup() { __message "execUserSetup() called\n"; // Call the simulation setup SimulationSetup (); } execUserReset() { __message "execUserReset() called\n"; if( _fileHandle ) { __resetFile( _fileHandle ); } } execUserExit() { __message "execUserExit() called\n"; // Call the Simulation shutdown SimulationShutdown(); } SimulationSetup() { // Open the text file for ASCII reading // Put in the appropriate path to the InputData.txt file _fileHandle = __openFile( "$TOOLKIT_DIR$\\tutor\\InputData.txt", "r" ); if( !_fileHandle ) { __message "could not open file" ; } _interruptID = __orderInterrupt( "IRQ", 4000, 2000, 0, 0, 0, 100 ); if( -1 == _interruptID ) { __message "ERROR: syntax error in interrupt description"; } // Set up the immediate breakpoint _breakID = __setSimBreak( "UARTRBRTHR", "R", "Access()" ); } Access() { __message "Access() called\n"; // In this tutorial we read the fib values from a file __var _fibValue; if( 0 == __readFile( _fileHandle, &_fibValue ) ) { UARTRBRTHR = _fibValue; } else { __message "error reading value from file"; } __message "UARTRBR = 0x", _fibValue:%X,"\n"; } SimulationShutdown() { __cancelInterrupt( _interruptID ); __clearBreak( _breakID ); __closeFile( _fileHandle ); } |
IAR仿真中断的调试实现 ——简单介绍Simulator仿真中断的调试实现过程
最新推荐文章于 2024-06-10 06:30:00 发布