Download Lab5 - Cristinel Ababei
Transcript
Lab 5: Debugging and More on Interrupts COEN-4720 Embedded Systems Cristinel Ababei and Nathan Zimmerman Dept. of Electrical and Computer Engineering, Marquette University 1. Objective The objective of this lab is to learn about the different features of the debugger of uVision. We’ll also reemphasize some aspects about interrupts. 2. uVision Debuger The ARM CoreSight technology [1] integrated into the ARM Cortex-M processor-based devices provides powerful debug and trace capabilities. It enables run-control to start and stop programs, breakpoints, memory access, and Flash programming. Features like PC sampling, data trace, exceptions including interrupts, and instrumentation trace are available in most devices. Devices integrate instruction trace using ETM, ETB, or MTB to enable analysis of the program execution. Refer to [1] for a complete overview of the debug and trace capabilities. MDK contains the μVision Debugger that connects to various Debug/Trace adapters, and allows you to program the Flash memory. It supports traditional features like simple and complex breakpoints, watch windows, and execution control. Using trace, additional features like event/exception viewers, logic analyzer, execution profiler, and code coverage are supported. The μVision Debugger is completely integrated into the μVision IDE. It provides many features, including the following [2]: --Disassembly of the code on C/C++ source- or assembly-level with program execution in various stepping modes and various view modes, like assembler, text, or mixed mode --Multiple breakpoint options including access and complex breakpoints --Review and modify memory, variable, and register values --List the program call tree including stack variables --Review the status of on-chip microcontroller peripherals --Debugging commands or C-like scripting functions --Code Coverage statistics for safety-critical application testing --Various analyzing tools to view statistics, record values of variables and peripheral I/O signals, and to display them on a time axis --Instruction Trace capabilities to view the history of executed instructions The μVision Debugger offers two operating modes: 1) Simulator Mode - configures the μVision Debugger as a software-only product that accurately simulates target systems including instructions and most on-chip peripherals (serial port, external I/O, timers, and interrupts; peripheral simulation capabilities vary depending on the device you have selected.). In this mode, you can test your application code before any hardware is available. It gives you serious benefits for rapid development of reliable embedded software. 2) Target Mode - connects the μVision Debugger to real hardware. Several target drivers are available that interface to a: -ULINK JTAG/OCDS Adapter that connects to on-chip debugging systems -Monitor that may be integrated with user hardware or that is available on many evaluation boards 1 -Emulator that connects to the microcontroller pins of the target hardware -In-System Debugger that is part of the user application program and provides basic test functions -ULINKPro Adapter a high-speed debug and trace unit connecting to on-chip debugging systems via JTAG/SWD/SWV, and offering Cortex-M3ETM Instruction Trace capabilities Debug Menu The Debug Menu of uVision IDE includes commands that start and stop a debug session, reset the CPU, run and halt the program, and single-step in high-level and assembly code. In addition, commands are available to manage breakpoints, view RTOS Kernel information, and invoke execution profiling. You can modify the memory map and manage debugger functions and settings. Note: In this lab we’ll only study the Simulator Mode of the debugger. Among the different ways of debugging the actual hardware target, one could use JTAG interface based debugging options. One such example include the use of the Keil ULINK2 Debug Adapter [3], which connects the PC’s USB port to the target system (via JTAG, SWD, or OCDS) and allows us to program and debug embedded programs on target hardware; with a JTAG speed up to 10MHz. The LandTiger 2.0 has a JTAG connector, and if you get your own ULINK2 Debug Adapter (you can also borrow one from your instructor), you are encouraged to study more debugging features on your own. If you do that, first, please read the Chapter titled “Debug Applications” from the uVision IDE Getting Started Guide [4]; this guide was included as file 7_mdk5_getting_started_YOU_SHOULD_READ_IT.pdf in the files archive of lab#2. This is optional for this lab. 3. Example1 – Blinky Revisited The files necessary for this example are located in example1/ folder as part of the downloadable archive for this lab. As mentioned earlier, the μVision Debugger can be configured as a Simulator or as a Target Debugger. In this example, we’ll use the Simulator. Go to the Debug tab of the Options for Target dialog to switch between the two debug modes and to configure each mode. Configure to Use Simulator. Before running the simulation, replace the following two lines inside blinky1.c: delay( 1 << 24 ); with: delay( 1 << 14 ); This is to make the blinking of P1.29 faster inside the simulator; otherwise, we’d need to wait too long to actually see the corresponding bit turning 1 or 0. Simulation Debug Use all the provided files under example1/ to create a new uVision project and Build it. 1. Click Debug menu option and select Start/Stop Debug Session. A warning about the fact that this is an evaluation version shows up; click OK. 2. Then, a new window appears where we can see the simulation of the program. 3. This window has several different supportive panels/sub-windows where we can monitor changes during the simulation. The left hand side panel, Registers, provides information regarding the Registers of LPC17xx with which we are working. 4. Again, click on the Debug menu option and select Run. The code starts simulating. 5. It is good practice that before going ahead with the actual hardware implementation to perform a debug/simulation session to make sure that our program behaves according to the design requirements. 2 6. 7. 8. 9. In our example, we use PORT2. Go to Peripherals menu option then select GPIO Fast Interface followed by Port 2. You should get the window that shows P2.1 blinking. Stop the simulation: Debug->Stop or hit the Stop icon from the Toolbar. Breakpoints 1. Let’s set two breakpoints on lines: LPC_GPIO2->FIOPIN |= 1 << 1; // make P2.1 high LPC_GPIO2->FIOPIN &= ~( 1 << 1 ); // make P2.1 low inside blinky1.c. To set a breakpoint, right-click on each of these lines, on the left margin of the panel that displays this file and then select Insert/Remove Breakpoint. 2. Go to Peripherals menu option then select GPIO Fast Interface followed by Port 2. 3. Debug->Run. Notice that the simulation starts and runs till the first breakpoint where it stops. Notice that P2.1 is 0. To continue the simulation click the icon “Step (F11)” once. What happens? P2.1 is turned 1 and we stepped with the simulation to the next instruction inside our program. 4. Step (F11) again more times. Observe what happens each time. While stepping inside the delay() function, observe the value of local variable “i” inside the panel labeled Call Stack + Locals on the bottom right side of the uVision IDE. Notice how “i” is incremented. To get out from within the delay() function click the icon “Step out (Ctrl-F11)”. 5. Once you get a hang of it, stop the simulation. Logic Analyzer The debugger includes a logic analyzer which allows us to study the relative timing of various signals and variable changes. It’s activated using the button in the debugger. Note that you can only use the logic analyzer when you’re running in the simulator, not on the board. The logic analyzer is mostly self-explanatory. Use the Setup button to add channels. You can use symbolic names such as FIO1PIN to determine what registers or variables to watch, and you can specify a mask value (which is ANDed with the contents of the register or variable) and a right shift value (which is applied after the AND operation). You can view the result as a numeric value (“analog”) or as a bit value. At any point you can stop the updating of the screen (and/or stop the simulation itself), and change the resolution to zoom in or out. You can also scroll forward and backward in time using the scrollbar below the logic analyzer window. There are also “prev” and “next” buttons to move quickly from one transition to another. 1. Open the Logic Analyzer by clicking the icon Analysis Windows->Logic Analyzer 2. Click Setup… in the new window of the logic analyzer. Then, click New (Insert) icon and type FIO2PIN. Type in 0x00000002 as “And Mask” and select Bit as the Display Type. 3. Go to Peripherals menu option then select GPIO Fast Interface followed by Port 2 to show the GPIO2 Fast Interface. 4. Run simulation and observe how the signal changes inside the Logic Analyzer window. 4. More on Interrupts The LPC1768 microprocessor can have many sources of interrupts. All the internal peripherals are capable of generating interrupts. The specific conditions that produce interrupts can be set individually for each peripheral. The individual interrupts can be enabled or disabled using a set of registers (think of memory locations in the “memory space”). 3 Selected GPIO pins can also be set to generate interrupts. For instance, the push-button marked INT0 on the LandTiger 2.0 board is connected to pin P2.10 of the LPC1768 microprocessor (see page 6 of the schematic diagram, provided as file 0_HY_LandTiger_SCH.pdf in the archive of lab#2). This pin can be a source of external interrupts to the MCU. The table below shows different functionalities that can be assigned to P2.10 pin (based on the information in the user manual, page 119). If you plan to use P2.10 as GPIO, then you should also enable this source of interrupt as described in section 9.5.6 of the LPC17xx user manual. Note that you can set the P2.10 pin to be sensitive to either the rising edge or the falling edge. More information on clearing the interrupt pending bit can be found in table 123 in section 9.5.6.10, page 147 of the user manual. To write an interrupt handler in C we need to describe/create a function with an appropriate name and it will automatically be used (it will be called automatically via the pointers stored inside the vector table). The name of this function consists of the prefix from the table below plus the keyword “Handler” appended to it (e.g., TIMER0_IRQHandler). --------------------------------------------------------------------------------------Int# Prefix Description --------------------------------------------------------------------------------------0 WDT_IRQ Watchdog timer 1 TIMER0_IRQ Timer 0 2 TIMER1_IRQ Timer 1 3 TIMER2_IRQ Timer 2 4 TIMER3_IRQ Timer 3 5 UART0_IRQ UART 0 6 UART1_IRQ UART 1 7 UART2_IRQ UART 2 8 UART3_IRQ UART 3 9 PWM1_IRQ PWM 1 (not used on MCB1700) 10 I2C0_IRQ I2C 0 (not used on MCB1700) 11 I2C1_IRQ I2C 1 (not used on MCB1700) 12 I2C2_IRQ I2C 2 (not used on MCB1700) 13 SPI_IRQ SPI (used for communicating with LCD display) 14 SSP0_IRQ SSP 0 (not used on MCB1700) 15 SSP1_IRQ SSP 1 (not used on MCB1700) 16 PLL0_IRQ PLL 0 (interrupts not used by our labs) 17 RTC_IRQ Real-time clock 18 EINT0_IRQ External interrupt 0 19 EINT1_IRQ External interrupt 1 (not used on MCB1700) 20 EINT2_IRQ External interrupt 2 (not used on MCB1700) 21 EINT3_IRQ External interrupt 3 (not used on MCB1700) & GPIO interrupt 22 ADC_IRQ ADC end of conversion 23 BOD_IRQ Brown-out detected (not used) 4 24 USB_IRQ USB 25 CAN_IRQ CAN 26 DMA_IRQ DMA 27 I2S_IRQ I2S (not used on MCB1700) 28 ENET_IRQ Ethernet 29 RIT_IRQ Repetitive-interrupt timer 30 MCPWM_IRQ Motor control PWM 31 QEI_IRQ Quadrature encoder 32 PLL1_IRQ USB phase-locked loop 33 USBActivity_IRQ USB activity 34 CANActivity_IRQ CAN activity --------------------------------------------------------------------------------------- A particular peripheral can generate its interrupts for a variety of reasons, which are configured within that peripheral. For example, timers can be configured to generate interrupts either on match or on capture. The priorities of the interrupts can be set individually. See sections 6.5.11 to 6.5.19 of the user manual for details. A set of functions is available for enabling and disabling specific interrupts, setting their priority, and controlling their pending status (find them inside core_cm3.h file, which is the so called CMSIS Cortex-M3 Core Peripheral Access Layer Header File): void NVIC_EnableIRQ(IRQn_Type IRQn) void NVIC_DisableIRQ(IRQn_Type IRQn) void NVIC_SetPriority(IRQn_Type IRQn, int32_t priority) uint32_t NVIC_GetPriority(IRQn_Type IRQn) void NVIC_SetPendingIRQ(IRQn_Type IRQn) void NVIC_ClearPendingIRQ(IRQn_Type IRQn) IRQn_Type NVIC_GetPendingIRQ(IRQn_Type IRQn) The IRQn names are just the prefix from the table above with an “n” appended (e.g., TIME0_IRQn). We can also enable or disable interrupts altogether using __disable_irq() and __enable_irq(). We can also trigger any interrupt in software (inside our C programs) by writing the interrupt number to the NVIC->STIR register (values up to 111 are permitted). We must clear interrupt conditions in the interrupt handler. This is done in different ways, depending on what caused the interrupt. For example, if we have INT0 configured to generate an interrupt, you would clear it by setting the low-order bit of the LPC_SC>EXTINT register. For detailed descriptions of all interrupts, you should read Chapter 6 of the NXP LPC17xxx User Manual. 5. Example2 – Blink LED using Timer 0 Interrupt The files necessary for this example are located in example2/ folder as part of the downloadable archive for this lab. Use all the provided files to create a new uVision project and then Build and Flash->Download it. Observe operation and comment. Please read the source code to understand how it works; it contains lots of comments. 5 6. Example 3 – Drawing circles on the 240x320 pixels LCD display of the LandTiger 2.0 board You are given two versions of this example: Version 1 files are located in lab5_circles1 and Version 2 files are located in lab5_circles2. Both versions do the same thing: plot randomly sized circles at random locations and of random colors on the 240x320 LCD display of the board. Create two different uVision projects for each version of this example. Build and download each of the projects. Observe their operation. You should observe a simplified (in that circles are not filled) operation as shown in Fig.1. Figure 1 Drawing filled circles on the LCD display of the LandTiger 2.0 board. Read and compare the source code from main_circles1.c and main_circles2.c. Which version do you think is better and why? Is there anything that you would change to make this example more efficient? 7. Lab Assignment You must implement required programming assignment and also answer the questions. Description of your programming solutions as well as answers to the questions below must be included in the lab report. a) Lab5 programming assignment 1. Write a program that uses the LCD screen to display a smiley face in the center of the screen. In your program, you should use the Timer 0 Interrupt to trigger the change of color for the smiley face every other second or so. The smiley face’s color should alternate between yellow and red. The size of the face should be approximately the size of a dime. The background can be any other color different from yellow and red. Hint: Start with modifying any of the projects from Example 3 above. This example has already functions for drawing empty circles and lines. I have included 6 already place holders for functions that you would need to describe/write (inside GLCD.c and GLCD.h). Then, you also need only to implement the logic of the main program by changing the main() function. The Timer 0 interrupt is already set up in the Example 3. 2. Demonstrate to the TA setting a breakpoint and viewing the value of a variable. 3. Use Timer 0 as well to measure the time it took to draw your smiley face. Read the count register before and after your draw command. Display the time it took to draw your smiley face in milliseconds on the LCD. b) Lab 5 questions 1. Using a debugger and breakpoints is incredibly useful for tracking down problems. However, breakpoints freeze a programs execution which can be problematic for some type of programs. Give an example of a real world embedded c program in which using breakpoints would not be practical/safe. Give an alternative solution to using break points. 2. What was the frames per second (FPS) of the smiley face that you drew? How would you improve the FPS? 3. Assume the LandTiger display has a resolution of 320 by 240 pixels. Assume display uses 16 bit color. Assume the display is connected with an 8 bit bus. Assume our processor clock speed is at maximum. Assume our processor can write 8 bits in 1 clock cycle. Optimistically, what would be the maximum FPS that our processor could achieve on the screen? Would this be fast enough to display a movie that appears in real time to the human eye? 8. Credits and references [1] ARM CoreSight technology; http://www2.keil.com/coresight/ [2] uVision IDE and Debugger; http://www.keil.com/uvision/debug.asp [3] Keil ULINK2 Debug Adapter (costs about $150 if purchased from ARM or about $20 if purchased elsewhere); --http://www.keil.com/ulink2/ --http://www.hotmcu.com/ulink2-debug-adapter-with-usb-interface-p-9.html?cPath=3_25 --http://www.amazon.com/ULINK2-Emulator-Original-FirmwareSupport/dp/B00MFY27QO/ref=sr_1_fkmr0_3?ie=UTF8&qid=1407427505&sr=8-3fkmr0&keywords=ULINK2+Debug+Adapter [4] Keil ARM, Getting Started, Creating Applications with μVision; http://www2.keil.com/docs/default-source/default-document-library/mdk5-getting-started.pdf?sfvrsn=0 7