You are on page 1of 22

Microcontroller and Embedded systems

Tutorials on:
Using the AVR Studio 6 Simulator and Debugger
Input/output Ports
First we have to discuss about I/O ports. Generally AVR microcontrollers have four I/O ports named as
PORTA, PORTB, PORTC, PORTD up to PORTG (ATMEGA128). Take example as ATMEGA8 or
ATMEGA 16 or ATMEGA32 microcontrollers, these are any having four I/O ports and each port having
8 I/O lines. These lines are bi-directional means we can use these I/O lines either input or output. In
addition to each this pin has some of other functions like ADC, timers, interrupts, serial communication
pins and other pins. To perform any operation with general purpose I/O (GPIO) pins there is a need to
configure three registers. Those registers named as DDRx, PORTx, PINx (here x indicates the name of
the register A or B or C or D).

Each registers of these three registers are 8-bit registers means generally each port has 8 pins as like each
register has 8-bits and each pin refers on bit of register. If we want to configure any pin of the port we can
configure the corresponding bits of all three registers. In this article I am taking example as ATMEGA128
microcontroller. Now consider pins 35-42 of the microcontroller, if we want to configure these 8-pins,
there is a need of configure corresponding three registers of 8-bits. Here explaining clearly, in
ATMEGA128 pin 35-42 refers PORTC. So if we want to configure PORTC, we need to configure DDRC,
PORTC and PINC registers

These 8-bits are divided into two 4-bit groups and named as lower nibbles upper nibbles. 0-3 bits are
called as lower nibbles and 4-7 bits are called as upper nibbles.

Configuring the PORT:


If we want to configure one port; there is a need to configure corresponding three registers of the port. So
now we are configuring the PORTC, so we need to configure DDRC, PORTC and PINC registers as
described below:
DDRx register:
The name of the register is Data Direction Register. The name only indicates complete use of the
register that is data direction. There are only two directions. Those are controller to module and module to
controller. If data direction is from module to controller that is input, if data is passing from controller to
module that is output. So the two directions are input direction and output direction

This register is used to assign the pin of the port as either input direction or output direction. In
this register the port and pin indicated as DDRxn, here x indicates the port name and n
indicates the pin number. For example pin 38 refers to 4th pin of PORTC is defined as DDRC4.
Generally these GPIO pins are digital I/O pins that mean these are having only two logics as
logic0 and logic1. Same like these DDR also. If DDRxn is written as logic one, the pin is
configured as output pin. If DDRxn is written as logic zero, the pin is configured as input pin.
Up to here we are discussing as logic 0 and logic 1, but how to know what is logic 0 and what is
logic 1, how both are differs. Generally most of the microcontrollers drives the 5V, and before
setting the pin either input or output there is 5V of potential at each GPIO pin of controller.
Microcontrollers have some threshold voltage levels. The threshold level is indicated as half of
the driving voltage. If the driving voltage of controller is 5V, the threshold voltage of the
controller is 2.5V. So the controller knows that if voltage level is below the threshold level, it
sense as logic zero and above the threshold level it sense as logic one.
So in this sense logic zero means DDRxn configured as input pin and logic one means DDRxn
configured as output pin. If pin is configured as input, the internal pull-up resistors will be on. If
we want to turn-off the pull-up resistors, the pin has to be configured as output.
DDRx register

Example
To configure some bits of PORTC as inputs and some bits as outputs where configure 0,2,4,6
pins as inputs and 1,3,5,7 pins as outputs.
Solution
Generally the register initial value is zero means register bits are configured to input. So change
require bits to logic one to change as output.
Generally we are using shift operation to assign value to bit of register. Take bit0 of DDRC, the
initial value of the bit is zero. If we want to change the bit to one, just we can use simple shift
operation as 1<<DDRC0. If we want to change remaining bits, that is also same but OR
operation is performed between the bits. Now in our example the code is as follows:
DDRC = (1<<DDRC1) | (1<<DDRC3) | (1<<DDRC5) | (1<<DDRC7);
The above line indicates that setting 1,3,5,7 pins of PORTC as outputs and setting 0,2,4,6 pins of
PORTC as inputs.
There are so many ways to perform this operation mentioned below.
DDRC = (1<<1) | (1<<3) | (1<<5) | (1<<7);
Or
Or

DDRC = 0xAA;
DDRC = 0b10101010;

These are the several ways to setting directions of the PORTC.


PORTx register:
PORTx register is used to control the voltage on the hardware pin. As same like DDRx register,
this PORTx register is also having 8-bits. If bits of the PORTx are written as logic one, the port
is driven to high means 5V voltage having at the pin. If bits of the PORTx are written as logic
zero, the port is driven to low means 0V voltage having at the pin.

This register is very useful for setting output pins either low or high. DDRx register set some bits
as input bits and some as output bits. The PORTx register is very useful to set the output bits as
either high or low.

This register declaration is similar to the DDRx register, the only change is name of the register.
From the above example, let us set some of output pins as low and some of output pins as high.
Here we are setting 1, 5 pins are high and 3, 7 pins are low.
PORTD = (1<<PORTD1) | (1<<PORTD5);
Or PORTD = (1<<1) | (1<<5);
Or PORTD = 0b00100010;
Or PORTD = 0x22;

Review Process for Developing Embedded Software


To develop software for an embedded system
Create source file (on Host)
Type in C code (on Host)
Compile/Assemble: translate into machine code (on Host)
Link: combine all object files and libraries, resolve all symbols (on Host)
Locate: assign memory addresses to code and data (on Host)
Download: copy executable image into Target processor memory (only if you have target
device)
Execute: reset Target processor
The following tutorial covers the steps needed to program AVRs in Windows using Atmel
Studio and a USB AVR Programmer. Atmel Studio is a free integrated development
environment (IDE) provided by Atmel. In this tutorial, we will write a simple program to blink
an LED connected to pin PORTD1 of an AVR. If you want to program an AVR that does not
have an LED connected to pin PORTD1, the code in this tutorial can be modified.
You will need to:

Download and install Atmel Studio by following the instructions on Atmels website. If
you use Windows Vista, you should download Atmel Studio 6.2, because that is latest
version that supports Windows Vista. This tutorial was written for Atmel Studio 7.0 and
Atmel Studio 6.2.
Install the USB AVR Programmers drivers on your computer.
If you are using Atmel Studio 6 or older, you might need to add an XML file to Atmel
Studio to make it support the AVR you wish to program.
After you have completed these prerequisites, you can create a new Atmel Studio project:

1. Open Atmel Studio and click New Project. In the New Project dialog, select GCC C
Executable Project for the template. Enter the project name and location. In this tutorial,
we will name our project BlinkLED and put it in the C:\ directory, but you can
choose a different name and location if you would like. Uncheck the Create directory
for solution box to simplify the directory structure of your project. Click OK.

The New Project dialog of Atmel Studio 6.


2. In the Device Selection window, select the device name of your specific AVR. Click OK
to create the project.

The Device Selection dialog of Atmel Studio 6.

3. Remove the template code that was automatically placed in BlinkLED.c and replace it
with the code below:

4. Click the Build Solution button on the toolbar (or press F7) to compile the code.

Expected Output from build execution(if there is no error in your code)

Building a project with Atmel Studio 6.

(This following part concerns you only in case you have hardware/Target
device)
Downloading and Executing Your Program
Once a program has been successfully compiled, linked, and located, it must be moved to the
target platform
Download the binary image to the embedded system
-Executable binary image is transferred and loaded into a memory device on target board
-Can be loaded into ROM via a device programmer, which burns a chip that is then re-inserted
into the embedded system.
-Your program will then execute when you reset the
processor, or apply power to the embedded system
Debugging Embedded Software
Now that the software has been downloaded to the target processor, how do we know if it is
working?
Run-time errors are not as obvious
-Most embedded systems do not have a screen
-When a program fails, usually causes the processor to crash or lock-up
Logic errors
If program runs, is it performing the correct steps?
Debugging Tools

Debugging with Simulators


A debugger or debugging tool is a computer program that is used to test and debug other
programs. The code to be examined might alternatively be running on an instruction set
simulator
When the program crashes, the debugger shows the actual position in the original code if it is a
source-level debugger. If it is a low-level debugger or a machine-language debugger it shows
that line in the program.
Simulator is host-based program that simulates functionality and instruction set of target
processor
- Front-end has text or GUI-based windows for source code, register contents, etc
- Valuable during early stages of development
- Disadvantage: only simulates processor, not peripherals
Debugging with Remote Debuggers(Only in case you have hardware/Target
device ))
- Remote Debuggers used to monitor/control embedded SW
-Used to download, execute and debug embedded software over communications link (e.g., serial
port)
- Front-end has text or GUI-based windows for source code, register contents, etc
- Backend provides low-level control of target processor, runs on target processor and
communicates to front-end over comm-link
- Debugger and software being debugged are executing on two different computer systems
- Supports higher level of interaction between host and target
Allows start/restart/kill, and stepping through program
Software breakpoints (stop execution if instruction X is fetched)

Read/write registers or data at specified address


- Disadvantage: Requires target processor to run more than final software package
Debugging with In-Circuit Emulators((This

part concerns you only in case you have

hardware/Target)

In-Circuit Emulators (ICE)


-Take the place of (i.e., emulates) target processor
- Contains copy of target processor, plus RAM, ROM, and its own embedded software
- Allows you to examine state of processor while program is running
- Uses Remote debugger for human interface
-Has more capability than target processor
Supports software and hardware breakpoints (stop execution on memory and I/O read/write,
interrupts)
Real-time tracing
Stores information about each processor cycle that is executed
Allows you to see what order things happened
Disadvantage: Expensive!

(This part concerns you only in case you have hardware)


5. Make sure your USB AVR programmer is connected to your computer via its USB A to
mini-B cable and then select Add target from the Tools menu. Select STK500 as the
tool. Select the COM port that has been assigned to the programmers programming port,
and click Apply. If you are not sure which COM port to select, look in the Device
Manager under the Ports (COM & LPT) list. This step can be skipped if you have done
it before.

The Add target dialog box in Atmel Studio 6.


6. Click the Device Programming button on the toolbar. You can also select Device
Programming from the Tools menu.

7. This will bring up the Device Programming dialog. For the Tool, select the STK500 that
you added earlier. Select the same device you selected earlier. If your device is not in the
list, you might need to add it to the list by following the instructions. For the Interface,
select ISP. Click Apply.

Selecting a programmer, device, and interface in the Device Programming dialog of Atmel
Studio 6.
If you got an error that says Unable to connect to tool STK500 and you see an error message in
the Output pane in the main window that says The signature of the attached tool is AVRISP_2,

which is unexpected. then you need to upgrade your programmers firmware to version 1.07 or
later
If you have not done so already, connect the programmer to the target device using the 6-pin ISP
cable. Make sure the cable is oriented so that pin 1 on the connector lines up with pin 1 on your
target device, and that the target device is powered on. You can test the connection by clicking
the Read button next to the Device Signature box. This sends a command to the target AVR
asking for its signature. If everything works correctly, you should see a number in hex notation
appear in the Device Signature box. If you get an error about the signature being wrong, you
might have selected the wrong device. If you get a warning that says Read voltage is outside
selected devices operating range then double check to make sure that your device is powered
and that you have upgraded the programmer to firmware version 1.07 or later.

Reading the device signature of an AVR in Atmel Studio 6.


9. Now it is time to program your target device. Select the Memories section on the left.
The Flash box should contain the path to the ELF file that was generated when you built
your program. If it does not, you can browse for this using the button to the right of
the text box. If you navigate to your projects folder, you should find it as
Debug\<project name>.elf. Click the Program button in the Flash box.

The Memories section of the Device Programming dialog in Atmel Studio 6.


As your USB AVR Programmer programs the AVR, you should see all three LEDs flicker and
you should see the following text appear at the bottom of the window:
Erasing device... OK
Programming Flash...OK
Verifying Flash...OK

If there were no problems, the LED connected to PORTD1 of your AVR should now be
flashing!

Debugging the code using Simulator


Since you are now aware of creating and building your project using AVR Studio 6, the
following step is to know how to debug and simulate your code using the AVR Simulator.
The AVR Studio 6 Simulator has the following features:

It supports software emulation of any real AVR device without actually connecting it.
It gives access to all the peripherals of the real MCU but no external devices.

So if you want to give external signals, you need to do it yourself, either by manually
updating the registers.

Let us consider the following code as an example to explain the functionality of the AVR
Simulator.
1
2
3
4
5
6
7
8
9
10
11
12

#include <avr/io.h>
int main(void)
{
uint8_t counter;
DDRB = 0xFF;
while(1)
{
counter++;
// insert breakpoint here <----PORTB = counter;
}
}

Now, click on the Debug menu and then click on Start Debugging and Break. If
initially no debugger is chosen, AVR Studio 6 will ask you to choose a Debug Tool.
AVR Simulator is always an option there. Choose it and click OK.

Debug Tool

fter this, debugging starts and halts in the beginning of main(). You can see a yellow
arrow mark determining the current executing line.
Let us place a breakpoint in the main and start execution. Highlight the variable counter
in counter++, right click it, go to Breakpoint and then click on Insert Breakpoint.

Insert Breakpoint

Now press the play button (F5) or click on Continue from the Debug menu to run to the
breakpoint.
Now look at the affected registers in the I/O view. If you dont have the I/O View open,
you can select it from the Debug toolbar or from the Debug windows menu.

I/O View

All the peripheral features are mentioned over here. We can monitor any changes from
the software and also manipulate the values to provide input.
Now, since the counter changes the value of PORTB, scroll down in the I/O View and
click on PORTB.

Choose PORTB in I/O View

Upon clicking PORTB, you can see the three registers assigned for PORTB operations,
PINB, DDRB and PORTB. You can also view their current values.
A solid block represents 1 whereas a blank block represents 0.
Since it the beginning of main(), we defined DDRB = 0xFF, all the blocks are filled. You
can also look at its value there.
Now, press the play button. The loop iterates once and stops at the breakpoint. You can
see that values of PINB and PORTB have changed to 0x01. This is because after one
iteration, counter = 1.
(You can use Reset and Restart to move to the starting point of debugging)

Debug in Progress (1)

The red block indicates that there has been a change in the value of the bit. If its a solid
red block, a change has been there from 0 to 1. If its just a red outline, its the other way
round.(from 1 to 0)
Once again click on play. You will be able to see the following sequences.

Debug in Progress (2)

Debug in Progress (3)

Debug in Progress (4)

Now, if you want to change some other registers (apart from the ones changed by the
code), simply click on the corresponding register and change its value.
Say for example you want to change the value of DDRD. Click on PORTD and then give
any value you want. You can also click on the corresponding bits to toggle the values.

Making External Changes


So now we are done with the basics of AVR Studio 6. There are more advanced features of
debugging in AVR Studio 6 which includes In-System Debugging which is a kind of runtime
debugging unlike the software emulation that we learnt here. However, we are not interested in
discussing these concepts here as it is possible only with AVR Programmers (special tools for
downloading code into target device).

You might also like