LAB 4 The Mini DSO and Advanced Debugging

Lab 4

Mini DSO and Advanced Debugging

In this lab you will lean about the sophisticated debugging tools of HEW4 by finding and repairing bugs in a miniature digital scope sample program.

  1. The DSO Lab

Lab Description

The Mini DSO code creates a miniature digital scope using the top line of the 2 X 8 LCD which is on the Starter Kit . The first part of the lab will run this LCD in a demo mode which displays a sine wave on the screen that sweeps through different frequencies. The Red LED will blink each time a sweep is completed. We will run the program to show some basic debug features

The second part of the lab switches the LCD DSO to monitor and display the voltage on the analog input pot. In this section of the lab the code should perform the following items

  1. The DSO samples the analog potentiometer at 3 different rates: 1, 10 or 100 mSec per sample. The sampling rate can be changed by pushing S1 (the button under the Red LED). The current sampling rate is displayed on the LCD.
  2. The AD converter is running in repeat mode, so it will continuously be sampling the analog potentiometer
  3. The sampling rate is set by the TA2 timer. One sample is captured each time the timer underflows. The sampling is done in the timer interrupt service routine.
  4. The green LED blinks each time one complete sweep is captured (40 samples across the display)

The code for the second portion of the lab has some problems in it. We will use some of the powerful debugging features of the tools to find and correct these bugs.

In the lab text items in all CAPS are screens items or buttons in HEW. Bold items refer to program variables or settings

  1. Running the DSO Demo

1 Verify the RTA-FoUSB and SKP is connected and the yellow LED on the RTA-FoUSB is blinking about once per second.

2 Launch HEW4 and select “Browse to another project workspace”.

3 OPEN the DSO Workspace located in

C: \Renesas\SKP16C26A\Sample_Code\dso_lab\dso_lab.hws

NOTES:

□ This project was configured for an SKP16C/26A and has been told not to bring up the INIT window (no need).

□ This project was configured to automatically download the dso_lab.x30 file when it connects to the target. (So you do not have to select “Debug-Download Modules-> Download All Modules” after you connect to the target!

□ If a HEW session is exited (and saved) while it is connected to a target, it will attempt to reconnect when you re-open the project. (This is why the workspace attempts to connect to the target when you open it.)

□ You may want to notice that before you download the code into the target, the X30 file is empty in the middle . After you download the X30 file it has a down pointing arrow in it .

4 Main.c should be open in the editor/debug window. If not, open it by double-clicking on it in the project window.

5 Click the RESET GO icon to run the program (or push F5)

6 You should see a sine wave scrolling along the top line of the LCD and the text “Mini DSO” on the second line

7 We now want to place a breakpoint in the routine “SineDisplay”. One way to find this routine would be to scroll through main and find it. We will use one of the features of HEW to find the routine.

8 Click the NAVIGATION TAB at the bottom of the project panel. Scroll to the bottom of the list and find the “SineDisplay” entry. (Note: There are two primary sections within the Navigation Tab: C Defines and C Functions. Entries are grouped into these two categories.)

9 Double click on the SineDisplay entry and it will open the main.c module in the editor window and place the cursor at the beginning of the function.

  1. The SineDisplay function is the code that calculates the sine wave and calls the display driver routine to display it. In the second “for loop” in the function you see the define DISP_WIDTH_PIXELS. If we wanted to know what this value is we could search all the modules or again use the navigation pane to quickly find the information.
  1. In the C Defines section of the navigation pane find the value DISP_WIDTH_PIXELS. Double clicking on that entry will open the module where that value is defined, which is skp_lcd.h. It shows that the value is 5 times the number of characters, or on our LCD, 40.
  1. You can now close the skp_lcd.h window by clicking the lower CLOSE button in the upper right corner
  1. Set a breakpoint at the line LCD_Display_FB(LCD_LINE1);. in the SineDisplay function by double clicking in the breakpoint gutter. Once the program reaches the breakpoint you will see that the display stops scrolling and the cursor arrow is in the breakpoint
  1. If we wanted to know the value of the float “f” (line 103) we could open a C Watch window. However, we can also check it by just placing the cursor over the variable in the program. Place the cursor over any of the f’s in line 97. A pop-up window will appear which shows the value of the variable “f”.
  1. Hit GO a few times and check the value of “f” after the program stops at the breakpoint
  1. One other powerful feature of the HEW debug environment is the mixed mode view. Click the View Mixed Mode button in the upper left corner of the debug/editor window. Notice that the assembly code is shown along with the C source. There is also a disassembly mode available.

  1. Hit the Step Over button,or F10, a few times while in the View Mixed Mode View and you will see that the steps occur at the Assembly instruction level.
  2. Change back to the View Source Mode.
  3. Now RUN (F5) the code and it should stop again at our breakpoint on line 106. If you hit the STEP OVER button,or F10, a few times now, you will see that these steps occur at the C Source instruction level.

This is the end of part 1 of this Lab

  1. Debugging the Real Time Display code

We will now modify the code that was run in the first part of this lab to build the real time display code that was described in the beginning of the lab

1 Use the Navigation Tool to find where “DEMO” is defined and go to this code.

2 Change the line “#define DEMO 1” to “#define DEMO 0”

3 Build the program, it should build with no errors.

4 When asked if you would like to download the .x30 module, click <Yes>.

5 Run the program (F5).

6 Though we should see the green LED blinking and some display in the top line of the LCD all you will see is the “1 mS” text on the second line. Though the build occurred with no errors there are a few bugs in the program.

Debug Problem 1

Since the description of the code indicates that everything is interrupt driven the first step we will take is to check if the interrupt service routine (ISR) is working

  1. Set a Breakpoint in the ISR_TimerA2 function at the line:

adValue = {unsigned char} (ado/128);

  1. You will see that the ISR is never getting executed since we never reach the breakpoint. A few things that could cause this
  2. the global interrupt enable flag is not set (I bit in the flag register)
  3. the timer is not counting
  4. the timer interrupt is not enabled.
  1. The first cause is easy to check. Open a register window by clicking the register button and STOP the program. The register window shows the status of all the internal registers and also shows the status of all the bits in the Flag register. Notice that the “I” flag (Interrupt Enable Flag) is set which means that interrupts are enabled.
  1. Next we will check if the timer is actually running. We will use the RAM monitor to check if the free-running timer is running. Rather than look up the actual address of the timer in the data sheet we will use the address labels to make things faster
  1. Click GO to start the program running
  2. Open the RAM Monitor by clicking the RAM Monitor button
  1. Click the Base Icon in the RAM Monitor window and set the Start Address at 0, which is the beginning of the SFR area (The SFR area is the location of all the peripheral registers). Click OK
  1. Right click in the RAM monitor window
  1. In the pop up dialog box select “address”
  1. In the Display Address dialog box click the label symbol.
  1. Type a “t” to get to the beginning of those variables and scroll down until you find ta2. Click OK in the Select Address and Display Address dialog boxes
  1. You will now see the ta2 label and the value is changing, each time it changes it is shown in red. We can tell from this that the timer is running

You can change the number of columns displayed per row by right clicking in the window, selecting column and changing the number

  1. Change the base of the RAM monitor back to 400 by clicking the base icon and setting the start address to 400
  2. Close the RAM Monitor Window
  1. The next thing to determine is if the timer interrupt is enabled and if the timer has requested an interrupt. On the M16C each peripheral has its own interrupt vector and control register. We will want to look at the ta2ic (timer A2 interrupt control register) to determine the status. We could do this in the RAM monitor window but we may not know what each bit means. Instead we will use a C Watch window.
  1. Open a C Watch window by clicking the C Watch button
  1. Stop the program

.

  1. Select the FILE LOCAL tab in the C WATCH window, you will notice all the SFR registers are listed. Scroll down to ta2ic_addr (you may need to adjust the width of the NAME column)
  1. Double Click the + next to the word union on the line ta2ic_addr and the window will expand.
  2. Double Click the + next to the word (struct) and you will see the individual bits in the register.

From this display we can see that the ir (interrupt request bit ) is a high, indicating that the interrupt has been requested. We can also see from ilv12 – ilv10 that the priority level of this interrupt is 3 (a peripheral interrupt is enabled anytime it has a priority other than 0).

We could have also done this using the IO Window

  1. Close the C Watch Window.
  1. Since we now have determined that the interrupt is being requested and interrupts are enabled the only thing left is that the interrupt vector is not correct. Though the Interrupt was properly declared and the function exists we have to set up the interrupt vector table. This can be done automatically by the compiler but in many sample programs it is manually set in the sect30 file.
  1. Open the sect30_26askp.inc file, scroll down near the bottom of the file and you will see a Variable Vector section.
  2. Now go down to the line which has Timer A2 in it.
  3. Notice the dummy_int vector is declared and the actual ISR_TimerA2 lines are commented out

.lword dummy_int ; TIMER A2 (for user) (vector 23)

; .glb _ISR_TimerA2

; .lword _ISR_TimerA2

  1. Modify the code so that the dummy_int is commented out and the correct interrupt routine is now declared as shown below

; .lword dummy_int ; TIMER A2 (for user) (vector 23)

.glb _ISR_TimerA2

.lword _ISR_TimerA2

  1. Build the project
  2. When asked if you would like to download the load module, click <Yes>.
  3. Run the updated Program.
  1. The program should now have a line displayed on the top row of the LCD. Vary the analog potentiometer and you should see the line go up and down.
  1. Now we will look at one of the variables in Real Time
  2. Open or go to the C Watch window
  3. Select the global tab and you will see the adValue. (You may have to resize the space given to the name.)
  4. Click the RAM Monitor button in the C Watch window to enable the real time update function.
  5. Rotate the Pot on the Starter Kit.
  6. You should see the adValue change as you rotate the pot.

If the value in the C Watch window is not updating. Open the RAM monitor window and change the base address to 400h (the start of RAM on all M16C devices). For the C Watch window to update in Real Time the RAM monitor area must overlap the variables that are being watched.

--- Though this may have taken some time in the lab environment you should see that the powerful debugging interface allowed us to check many things without having to constantly refer to data sheets to find absolute addresses. The real time capability also allow checking variables or peripheral registers “on- the-fly” to determine if they are operating.

Debug Problem 2

Most things are working now, however, pushing S1 (switch furthest to the left) should change the sample rate and that is not working. Let’s find that problem.

  1. In the main.c file find the lines

“if (!S1) //changes the timebase between sample when S1 pressed

{
timebase = (timebase * 10);

if (timebase = 1000)

set a breakpoint on the line if “timebase = (timebase * 10);”

  1. In the C Watch window, select the Global tab
  1. Press S1 and the program should stop at the break
  1. Check the value of “timebase” by placing your cursor over it or looking at the C watch window. The value should be 1.
  1. Step the program using the STEP IN button (or F11).
  2. “timebase” is now 10. (Which matches the code.)
  1. Step again and we should compare the current value of “timebase” to 1000. Notice that when you step “timebase” got set to 1000. Rather than checking to see if the value was 1000, the code actually set the value to 1000.
  1. Modify the code to read
    “if (timebase = = 1000)”
  1. Rebuild the code and Run it. We will now check the comparison again.
  1. Stop the program and find the line.

if (!S1) (

timebase = (timebase * 10);

  1. Click on the on the line “timebase = (timebase * 10);” to set the cursor at that point
  1. Right click in the editor window and in the dialog box select “Set PC Here”. Notice that the yellow PC pointer arrow is now at that line. This is an easy way to run code from a certain line without having to set or move existing breakpoints or, in this case, physically change the state of S1.
  1. Step the program while monitoring the variable “timebase” in the C Watch window and you will see that the comparison works properly now
  2. Run the code.
  3. Press S1 and see the effect of the different time bases.

This is the end of the lab, you should now have code that works and if you have time, change the compiler optimization and see how it affects code size.

27 July 20051 of 11Rev. 3.0