Lab1 Appendix.pdf

52
Lab 1 Appendix (20152016-1) 1 APPENDIX A FOR LABORATORY 1 SHEET The ATmega32 Architecture A.1. Importance of of knowledge of CPU Architecture CPU Architecture is needed by Assembly Language programmer to create effectively the codes of the program. To write the program, knowledge of the instruction set list is need to select what instruction to use. Instructions can be categorise by the function of the operation which are of different syntaxes for each different valid addressing mode of each category. To use instructions, knowledge of valid CPU registers, memory map of available memory devices and Input/Output (peripherals device) registers, the valid addressing modes of each instruction that provide transfer of data between CPU registers, I/O registers and memory locations is needed. Some instruction requires implicit registers (not specified in instruction) and there are specific rule in using them, e.g. the MUL, BRxx, PUSH, POP, CALL and ROL instructions. To write functioning program, knowledge on CPU architecture is needed so that flow of program and access of data (from valid locations) are correctly implemented such that the locations and data size and sequence executions are validly implemented. ATmega32 and ATmega32A have the same architecture. Figure A.1: ATmega32 Built-up Architecture Memory Specifications A.2. The AVR architecture (including Atmega32) has three main (block) memory spaces, the Data Memory and the Program Memory space. In addition, some most AVR (including the ATmega32) has an EEPROM Memory for data storage. All three memory spaces are separated from each other and each are addressed linearly (address is in incremental sequence). In this laboratory we are using only with the Data Memory and the Program Memory space in programs. PROGRAM Flash ROM Ports OSC CPU Timers Other Peripherals Program Bus Data Bus RAM I/O PINS EEPROM Interrupt Unit ALU PC: Instruction dec.

Transcript of Lab1 Appendix.pdf

Lab 1 Appendix (20152016-1) 1

APPENDIX A FOR LABORATORY 1 SHEET

The ATmega32 Architecture A.1.

Importance of of knowledge of CPU Architecture

CPU Architecture is needed by Assembly Language programmer to create effectively the codes

of the program.

To write the program, knowledge of the instruction set list is need to select what

instruction to use. Instructions can be categorise by the function of the operation which

are of different syntaxes for each different valid addressing mode of each category.

To use instructions, knowledge of valid CPU registers, memory map of available memory

devices and Input/Output (peripherals device) registers, the valid addressing modes of

each instruction that provide transfer of data between CPU registers, I/O registers and

memory locations is needed. Some instruction requires implicit registers (not specified in

instruction) and there are specific rule in using them, e.g. the MUL, BRxx, PUSH, POP,

CALL and ROL instructions.

To write functioning program, knowledge on CPU architecture is needed so that flow of

program and access of data (from valid locations) are correctly implemented such that the

locations and data size and sequence executions are validly implemented. ATmega32 and

ATmega32A have the same architecture.

Figure A.1: ATmega32 Built-up Architecture

Memory Specifications A.2.

The AVR architecture (including Atmega32) has three main (block) memory spaces, the Data

Memory and the Program Memory space. In addition, some most AVR (including the ATmega32)

has an EEPROM Memory for data storage. All three memory spaces are separated from each

other and each are addressed linearly (address is in incremental sequence). In this

laboratory we are using only with the Data Memory and the Program Memory space in

programs.

PROGRAM

Flash ROM

PortsOSC

CPU

Timers

Other

Peripherals

Program

Bus

Data

Bus

RAM

I/O

PINS

EEPROM

Interrupt

Unit

ALU

PC:

Instruction dec.

Lab 1 Appendix (20152016-1) 2

Memory Map

The memory map of a microcontroller is a diagram which gives the size, type and layout of

the memories that are available in the microcontroller. The information use to construct

the memory map is extracted from the datasheet of the microcontroller.

The diagram below gives the memory map for three (3) blocks of memory spaces of

the ATMega32.

Figure A.3: ATmega32 (ATmega32A) Memory map

Program Memory A.3.

The Atmega32 contains 32K (32768) bytes of On-chip In-System Reprogrammable Flash memory

for program storage. For software security, the Flash Program memory space is divided into

two sections, Boot Program section and Application Program section. The figure below

illustrates the Flash Memory.

a. Instruction in Program Memory

The Atmega32 instructions are 16 wide: when accessed by the CPU (using Program

Counter) to address instruction, the Flash is organized as 16K x 16. Each addressed

hold 2 bytes of data. The two bytes of each address are arranged in “little endian”

order.

b. Data in Program Memory

The Flash memory can also be used to store data (thus is non-volatile – data not lost

when power is removed).

When accessed by the CPU (using Pointer Register Z), the Flash is organized as 32K x

8. Each addressed hold 1 bytes of data. So the absolute address to accessed byte size

data is calculated by multiplying 2 with the physical Flash memory address: the lower

byte of the word is the added with 1 (odd address).

Lab 1 Appendix (20152016-1) 3

Figure A.3: Addressing 16 bit data and 8 bit data of the Program Memory.

In this lab we will not access the Boot Program (Flash) section.

Program will be stored in the Application Program section (which is physically a flash

RAM) and data can be stored Program memory Space (Flash RAM) and Data memory Space (which

is physically a Static RAM or SRAM).

In real application the address location 0x00 to 0x29 should be reserved for interrupt

vector table as shown below.

High Byte Low Byte

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0

$0000 Byte 0 Byte 1 $0000 Byte 0

$0001 Byte 2 Byte 3 $0001 Byte 1

$0002 Byte 4 Byte 5 $0002 Byte 2

$0003 Byte 3

$0004 Byte 4

$0005 Byte 5

$0006

$3FFE Byte 32764 Byte 32765

$3FFF Byte 32766 Byte 32767

$7FFC Byte 32764

$7FFD Byte 32765

$7FFE Byte 32767

$7FFF Byte 32766

Addressing 16 bit Data Addressing 8 bit Data

Address of 8-bi t data = Address of 16-

bit data * 2 or Shi ft left va lue of

address or (addr <<1). The high byte

wi l l take the even address (+0) and the

high byte wi l l take the odd address

(+1)

Only LPM and SPM instructions can be used used to access the program

memory

Lab 1 Appendix (20152016-1) 4

Table A.2

However program can be written on the vector table area, if its respective subsequent

interrupt is not used (depending on application). Vector 1 is definitely at the initial

instruction upon a RESET event. Address for vector 1 (a.k.a. RESET vector) is the initial

value loaded into PC upon RESET. Reset is invoked on any of the following event: External

Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset.

In this laboratory 1 and 2 RESET can be simulated as Power-on Reset (when “Build and Run”

is executed in the Editor mode of the AVR Studio) or External Pin (when “Debug|Reset” menu

is selected in the Debug Mode of the AVR Studio)

The following are typical application of program setup for RESET when no other interrupt

are used but we still want to reserve the vector table but completely use the rest of

program memory

.include “m32adef.inc”

.CSEG ;Start of Program Segment in Flash Memory

jmp start ;Reset Handler

.org 0x2a ;Set location counter to address $002A (for Atmega32)

;to skip the interrupt vectors table

start:

ldi r20,high(RAMEND); Set Stack Pointer to top of RAM

out sph,r20

ldi r20,low(RAMEND)

out spl,r20

Lab 1 Appendix (20152016-1) 5

Data (SRAM) Memory Space A.4.

Figure A.4 (1)

Figure A.4 (2)

There are three types of registers mapped in the Data (SRAM) Memory Space.

General Purpose Registers (GPR)

Standard I/O Registers

General Purpose RAM (Data Address Space)

The first of the SRAM is reserved for General Purpose Registers in the ATmega32. These registers are connected to the ALU (Arithmetic Logic Unit) and are used to manipulate data. The registers are labelled R0 – R31. The Register is divided into two group call Lower Registers and Upper Registers.

$0000

$0001

$0020

General

purpose

RAM

(SRAM)

R0

R1

R2

$001F

$005F

R31

...

TWBR

TWSR

SPH

SREG

...

General

Purpose

Registers

Standard I/O

Registers

$00

$01

$3E

$3F

$0060

...

...

Data Address

Space

I/O Address

...

8 bit

$FFFF

Lab 1 Appendix (20152016-1) 6

General Purpose Registers (GPR) Mappings A.5.

The GPRs and I/O Registers are mapped sequentially from address $0000 to address $005F in the Data Memory which is the RAM memory space. The mapping of each respective register is as in shown Figure A.4 (2).

The lower 16 registers, R0 – R15, work just the rest of the registers with the exception

of loading immediate data. These registers have access to the full range of the Data

Memory, ALU, and additional peripherals.

The upper 16 registers, R16 – R31, have additional capabilities. They have access to

immediate data using the LDI instruction. These registers will be the ones that get the

most use throughout your program. To move data into or out of these registers, the various

different Load and Store instructions are needed. All arithmetic instructions work on

these registers.

In normal case, to access these registers you use Register Direct Addressing mode (Section

A.6(b) though you can use Data Memory Addressing Mode(Section A.6(c)

a. I/O Registers Location

The Special I/O registers I/O address (under “I/O”) are mapped in the Data Address Space (under “Mem”) as follows:

Figure A.5 (a)

Lab 1 Appendix (20152016-1) 7

b. I/O Registers

These are Special Function Registers are registers in the ATmega32 that either control or monitor the various components of the chip. Most of the Special Function Registers have

read/write capabilities; check the datasheet for the ATmega32 for more details. These

register reside in the ATmega32 I/O Memory and as such, require the IN and OUT

instructions to read and write to these registers.

The ATmega32 is equipped with 4 Digital I/O Ports labelled Port A through Port D. Each

port has its own unique capabilities such as External RAM Addressing, PWMs, Timers, and

Counters. Unfortunately, this document will only cover the basics that are common with

each port. Digital I/O register will be used in Laboratory 2 thus explained more in

Laboratory 2.

In normal case, to access these registers you use Register Direct Addressing mode (Section

A.6(d) though you can use Data Memory Addressing Mode(Section A.6(c).

c. Internal SRAM (Data Memory)

The memory space is addressed from 0x60 to 0x085f. To access these memory spaces you must

use any of the five different addressing modes for the data memory cover: Direct, Indirect

with Displacement, Indirect, Indirect with Pre-decrement, Indirect with Post-increment. In

the General Purpose Register file, registers R26 to R31 feature the indirect addressing

pointer registers (X, Y, and Z).

To access Data memory locations, you must use Data Memory Addressing Mode(Section A.6(c).

Processor registers A.6.

In addition to these 32 general-purpose registers, the CPU has a few special-purpose

registers:

PC: 16-bit program counter

SP: 16-bit stack pointer

SREG: 8-bit status register

X, Y, and Z pointer registers: 8-bit segment registers that are prepended to 16-

bit addresses.

a. Program Counter

The Program Counter (PC) is a register that is apart of all central processing unit (CPU) or microprocessor. All microcontrollers contains a microprocessor and thus has a program counter. The purpose of the program counter is to hold/store (to point to) the address of the next instruction to be executed by the microcontroller's microprocessor.

The PC is automatically incremented to hold/store (to point to) the address of the

next instruction after execution of the current instruction.

When the program begins, the PC must contain the address of the first instruction in

the program which is the RESET event.

When a RESET event occurs The content of the reset vector is loaded into PC. A JMP

instruction at the reset vector address can be set to jump the bootloader program

starts.

Program instructions are stored in consecutive program memory locations. To jump

elsewhere in the program, Program Flow Control (branch/jump/call/return) instruction

is used.

Note: These are jump instructions that can modify the PC (e.g., the PC must change

when calling or returning from some other routine).

The CPU clock determines the execution time of instructions which a series of

execution can be calculated to generate a required delay.

Lab 1 Appendix (20152016-1) 8

b. The AVR Stack Pointer

The AVR ATmega32 stack pointer (SP) consist of two I/O register SPL (Stack Pointer Low) and SPH (Stack Pointer High). The size of the stack pointer depends on the amount of the ATmega32 data memory. The stack pointer is 16-bits wide but is accessed through

the two register, SPH:SPL. Stack Pointer points to the location where the next data

can be stored in the CPU stack. CALL, RCALL, PUSH and POP instructions uses and modify

the Stack Pointer when executed.

Figure A.5 (b)

c. Status Register (SREG)

The Status Register or SREG contains the important information about the ALU such as the

Carry Bit, Overflow Bit, and Zero Bit. These bits are set and cleared during ALU

instructions. This register becomes extremely useful during branching operations. The

following table details the bit assignments within the SREG.

Figure A.5 (c)

Status Register are:

Is 8 bits wide.

Contains information associated with the results of the most recent ALU operation.

Carry flag (C) set if CY from most signficant bit (MSB) or a borrow occur

on subtracts.

Often used when adding numbers that are larger than 8 bits. Here we

need to use an add with carry instruction (ADC) to add the next most significant byte.

Zero flag (Z) set if result is zero.

BREQ instruction says branch if zero flag is set. BRNE instruction says branch if zero flag is not set.

Lab 1 Appendix (20152016-1) 9

Negative flag (N) set if MSB is one. A copy of the most significant bit of

an arithmetic result.

Arithmetic instructions change the flags

Data transfer instructions do not change the flag.

The instruction set documentation identifies which flags each

instruction may modify.

Overflow flag (V) set if 2's complement overflow occurs.

An overflow occurs if you get the wrong sign for your result, e.g.,

6410 + 6410 = -12810 (010000002 + 010000002 = 100000002). Note: whenever the carry into the MSB and the carry out don't

match, we have an overflow.

Sign bit (S) s = N EXOR V, and shows the true sign of a comparison.

Half carry flag (H) is set when carry occurs from b3 to b4. Used with binary coded decimal (BCD) arithemtic. This is an

internal carry from additions.

T Bit copy. Special bit load and bit store instructions use this

bit.

I Interrupt flag. Set when interrupts are enabled.

d. The Pointer Registers: X, Y and Z-Registers

The last six of the General Purpose Registers have additional functionality. They serve as the pointers for indirect addressing. The ATmega32 has a 16-bit addressing scheme that requires two registers for the address alone. The AVR RISC structure supports this scheme with the X, Y, and Z-Registers. These registers are the last six General Purpose Registers (R26-R31). The following table details the register assignments:

Figure A.5 (d)

Addressing Modes A.7.

An addressing mode specifies how to determine/calculate the effective memory address of an

operand by using information held in registers and/or constants contained within an

instruction or elsewhere.

Instruction formats are of 3 types:

Implicit: No operand specified in the instruction, but the instruction execute a

defined function on one or more of a defined GPRs, Pointer Registers, CPU register or

Memory location.

E.g. NOP and RET

Single Operand: E.g. INC R0

Two operand: “LDI R16,0x20”, “STS 0x200,R0” and “MOV R0,R20”.

Lab 1 Appendix (20152016-1) 10

Operand can be of a constant or variable.

There are four types of variables that can be declared as operand: GPRs, I/O registers,

Data SRAM (GPRs, I/O registers and Data Memory are mapped in here too) and program Memory.

Each of these devices are accessed by each specific individual mode. As for GPRs and I/O

registers, though the have the own individual mode, the can be accessed by using the Data

Memory Addressing mode because they are mapped in the Data Memory space.

Addressing mode define the operand of the instruction (Refer section A.7) and for each

operand, there is a specific instruction that that is defined to use each of these

individual modes. All addressing mode is instruction specific which can be identified by

their operands specification in the Instruction Set Summary (Section A.7)

a. Immediate Addressing Mode

The Immediate addressing mode is only valid as source operand (mandatory) only and is

a constant. The destination operand must be of any the upper 16 GPRs (R16 thru R31).

E.g “LDI R16,0x30” or “CPI R31,3”

Where:

Source is an 8 bit constant that taken as the data.

Immediate addressing mode can be identified by the operands “Rd,K” and “Rdl,K”.

b. GPRs Addressing mode

There are two modes:

(a) Register Direct or Single Register Rd (Single operand or Implicit Operand

Instructions)

E.g. “INC R0”

Single Register addressing mode can be identified by the operands “Rd”.

(b) Register Direct, Two Registers Rd and Rr (Two Operand Instructions)

E.g. “MOV R0,R16”

Register addressing mode can be identified by the operands “Rd,R”.

c. Data Memory Addressing Modes

There five different addressing modes for the data memory:

1. Direct or Data Direct

Direct addressing mode can be identified by the operands “Rd,k” or “k,Rr” which

are used in instruction “LDS” and “STS” respectively.

“k” is taken as the absolute address where data can be taken from (for “LDS Rd,k”

instruction), or written to (for “STS k,Rr” instruction).

2. Indirect

Indirect addressing mode can be identified by the operands “Rd,X”, “Rd,Y”, “Rd,Z”,

“X,Rr”, “Y,Rr” or “Z,Rr” which are used either in instruction “LD” and “ST” only.

X, Y and Z are pointer registers

The content of the specified pointer register in the instruction is taken as the

address where data can be taken from (for “LD” instruction), or written to (for

“STD” instruction).

3. Indirect with Displacement

Indirect with Displacement addressing mode can be identified by the operands

“Rd,X+q”, “Rd,Y+q”, “Rd,Z+q”, “X+q,Rr”, “Y+q,Rr” or “Z+q,Rr” which are used either

in instruction “LDD” and “STD” only. X, Y and Z are pointer registers

Lab 1 Appendix (20152016-1) 11

The content of the specified pointer register in the instruction after being added

with q, is taken as the address where data can be taken from (for “LDD”

instruction), or written to (for “STD” instruction).

4. Indirect with Pre-decrement

Indirect with Pre-decrement addressing mode can be identified by the operands “-

X,Rr”, “-Y,Rr” or “-Z,Rr” which are used either in instruction “ST” only. X, Y and

Z are pointer registers

The content of the specified pointer register in the instruction after being

decremented by 1, is taken as the address where data taken from Rr can be written

to (for “ST” instruction).

5. Indirect with Post-increment.

Indirect with Post-increment addressing mode can be identified by the operands

“Rd,X+”, “Rd,Y+” or “Rd,Z+” which are used either in instruction “LD” only. X, Y

and Z are pointer registers

The content of the specified pointer register in the instruction is taken as the

address where data can be taken from (for “LD” instruction) to be written to Rd.

After the transfer the pointer register will be incremented by 1.

In the Register File, registers R26 to R31 feature the indirect Addressing Pointer

Registers.

The direct addressing reaches the entire data space.

The Indirect with Displacement mode reaches 63 address locations from the base

address given by the X, Y or Z register.

All instructions that use Data Memory Addressing Modes take two operands and one

of the operand must be a GPR.

When using indirect addressing modes with pre-decrement and post-increment, the

address registers X, Y, and Z are decremented or incremented by the execution of

the instruction.

The 32 general purpose working registers, 64 I/O Registers, and the 2048 bytes of

internal data SRAM in the ATmega32 are all accessible through all these addressing

modes

d. I/O Memory Addressing Modes

The I/O locations are accessed by the IN and OUT instructions, transferring data

between the 32 general purpose working registers and the I/O space.

I/O Registers within the address range $00 - $1F are directly bit accessible using the

SBI and CBI instructions. These addresses are Equates to labels in m32def.inc. The

valid names are given in Figure A.4(3).

In these registers, the value of single bits can be checked by using the SBIS and SBIC

instructions. Refer to the Instruction Set section for more details.

When using the I/O specific commands IN and OUT, the I/O addresses $00 - $3F must be

used.

When addressing I/O Registers as data space using LD and ST instructions, $20 must be

added to these addresses.

All instructions that uses I/O Memory Addressing Modes takes two operands, and one of

the operand must be a Register Direct Addressing Modes.

e. Program Memory Addressing mode

There are three modes:

(a) Program Memory Constant Addressing using the LPM and SPM Instructions

(b) Program Memory with Post-increment using the LPM Z+ Instruction

Lab 1 Appendix (20152016-1) 12

f. Direct Program Addressing Mode

The operand in JMP and CALL instruction is Direct Program Addressing. E.g. JMP k and

CALL k.

PC k

g. Indirect Program Addressing Mode

The implicit operands in IJMP and ICALL Indirect Program Addressing. These instruction

have no operands.

The source operand is the Z register and the destination operand is the PC (Program

Counter).

PC Z

h. Relative Program Addressing Mode

The operand in RJMP and RCALL instruction is Relative Program Addressing.

E.g. BRNE k, RJMP k, and RCALL k

There is only one operand which is the source operand and is a 12-bit constant. The

destination operand is implicit and it is the PC (Program Counter).

PC PC + 1 + k

AVR Instructions SET A.8.

Instructions of a processor when executed determine what task the processor should do. A

group of instructions which is arranged to perform a certain algorithm becomes a useful

program. Instruction must be written according to its format following its hardware design

which is specified in the processors in the instruction set reference manual. The

references for the AVR 8-bit microcontroller is in file “Atmel AVR 8-bit Instruction Set

manual 2014.pdf” (but refer to “Atmega32 Reference manual.pdf” pp 329 – 331 for list of

instruction supported on ATmega32/ATmega32A), which is categorised as below:

1. Arithmetic and Logic Operation Instructions

2. Data Transfer Instructions

3. Bit and Bit Test manipulation Instructions

4. Branch instructions a.k.a. Program Flow Control Instructions

Lab 1 Appendix (20152016-1) 13

a. Arithmetic and Logic Operation Instructions

Instruction from this category allows 8-bit arithmetic or logic operation on a GPR

(the destination operand). Instructions are specific for source operand which can be

either Immediate (a constant) or Register Direct. Result from instruction in this

category is stored in Status Register (either of the H, S, C, V and Z flag) can be

used by the conditional Branch Instruction to determine the flow of a program.

Table A8(a): Arithmetic and Logic Operation Instructions

b. Data Transfer Instructions

Except for LDI Instruction, instruction from this category allows transfer of 8-bit

data between GPRs and Data Memory, I/O Memory or Program Memory. If data need to me

transferred between Data Memory, I/O Memory or Program Memory, a GPR has to be used as

the intermediate storage to implement the transfer.

Lab 1 Appendix (20152016-1) 14

Table A8(b): Data Transfer Instructions

Lab 1 Appendix (20152016-1) 15

c. Bit and Bit Test manipulation Instructions

Instruction from this category allows specified bits of an 8-bit Number on a GPR or

the Status Register (the destination operand) to be changed or tested. Result from

instruction in this category is stored in Status Register (either of the H, S, C, V

and Z flag) can be used by the conditional Branch Instruction to determine the flow of

a program.

Table A8(b): Bit and Bit Test manipulation Instructions

Lab 1 Appendix (20152016-1) 16

d. Branch instructions (Program Flow Control Instructions)

Instruction from this category when executed, changes the Program Counter, either

conditional or unconditional thus allowing a program to executes with a decision

whether to jump or not. By using proper decision making in the codes, structured

block (IF, IF-Then-Else, While Loop, Do-While loop, For Loop, Repeat Loop and Switch-

Case) can be implemented.

Table A8(d): Branch instructions (Program Flow Control Instructions)

Lab 1 Appendix (20152016-1) 17

e. Instruction Format

The Instruction format of an ATmega32 microcontroller is specified in Instruction Set

Summary (refer Section A.7). The Instruction must have an Opword specified from the

Instruction Set’s Mnemonics and may be followed with one of the following operand

specification depending on the Opword:

1) No Operand (Example Instruction’s Opword Mnemonics: NOP, CLC)

2) One Operand (Example Instruction’s Opword Mnemonics: CLR R0, INC R1, JMP here)

Depending on the instruction the operand may be the:

a. The destination

b. The source and destination operand.

c. Source to an implicit destination

3) Two Operand (Example Instruction’s Opword Mnemonics: MOV, LDI, STS)

The valid source and destination operand is determined from the Instruction’s Opword

specified in Instruction Set Summary (refer Section A.7)

In this Laboratory, we will not use all but only some basic instruction which will be

used to help us understand a few of the Addressing Modes for the ATmega32

microcontroller.

Lab 1 Appendix (20152016-1) 18

Basic Assembler Directive A.9.

The Assembler supports a number of directives. The directives are not translated directly

into opcodes. Instead, they are used to adjust the location of the program in memory,

define macros, or initialize memory and so on.

Assembler-Directives control the assembler, they don't create any own code. The leading

dot must be in column 1 of the line. An overview of the basic directives is given in the

following table.

Table A9(d): Basic Assembler Directive

Segment Directive Description

Header

.DEVICE Defines the type of the target processor and the applicable set of instructions (illegal instructions for that type trigger an error message, syntax: .DEVICE AT90S8515)

.DEF Defines a synonym for a register (e.g. .DEF MyReg = R16)

.EQU Defines a symbol and sets its value (later changes of this value remain possible, syntax: .EQU test = 1234567, internal storage of the value is 4-byte- Integer)

.SET Fixes the value of a symbole (later redefinition is not possible)

.INCLUDE Includes a file and assembles its content, just like its content would be part of the calling file (typical e.g. including the header file for device ATmega32: .INCLUDE "m32Adefdef.inc")

Code

.CSEG Start of the code segment. All valid declaration using “.DB” and “.DW” only that follows is assembled to the code segment and will be stored the program memory space(Flash Memory).

.DB

Inserts one or more constant bytes in the code segment (could be numbers from 0..255, an ASCII-character like 'c', a string like 'abcde' or a combination like 1,2,3,'abc'. The number of inserted bytes must be even, otherwise an additional zero byte will be inserted by the assembler.)

.DW Insert a binary word in the code segment (e.g. produces a table within the code)

.LISTMAC Macros will be listed in the .LST-file. (Default is that macros are not listed)

.MACRO Beginning of a macro (no code will be produced, call of the macro later produces code, syntax: .MACRO macroname parameters, calling by: macroname parameters)

.ENDMACRO End of the macro

EEPROM

.ESEG Assemble to the EEPROM-segment (the code produced will go to the EEPROM section, the code produces an .EEP-file)

.DB Inserts one or more constant bytes in the EEPROM segment (could be numbers from 0..255, an ASCII-character like 'c', a string like 'abcde' or a combination like 1,2,3,'abc'.)

.DW Inserts a binary word to the EEPROM segment (the lower byte goes to the next adress, the higher byte follows on the incremented address)

SRAM

.DSEG

Assemble to the data segment (here only .BYTE directives and labels are valid, during assembly only the labels are used). All valid declaration that follows is assembled to the data segment and will be stored the DATA memory space(SRAM)

.BYTE Reserves one or more bytes space in the data segment (only used to produce correct labels, does not insert any values!)

Everywhere

.ORG Defines the address within the respective segment, where the assembler assembles to (e.g. .ORG 0x0000)

.LIST Switches the listing to the .LST-file on (the assembled code will be listet in a readable text file .LST)

.NOLIST Switches the output to the .LST-file off, suppresses listing.

.INCLUDE Inserts the content of another source code file, as if its content would be part of the source file (typical e.g. including the header file: .INCLUDE "C:\avrtools\appnotes\8515def.inc")

.EXIT End of the assembler-source code (stops the assembling process)

Lab 1 Appendix (20152016-1) 19

Refer to http://www.atmel.com/Images/doc1022.pdf or file “AVR Assembler User Guide.pdf” for examples.

Assembly Language A.10.

An assembly language is a low-level programming language for computers, microprocessors,

microcontrollers, and other programmable devices. It implements a symbolic representation

of the machine codes and other constants needed to program a given CPU architecture. This

representation is usually defined by the hardware manufacturer, and is based on mnemonics

that symbolize processing steps (instructions), processor registers, memory locations, and

other language features. An assembly language is thus specific to certain physical (or

virtual) computer architecture.

An assembler converts each assembly language statement into the corresponding machine-

language statement. Assembly language is an alphanumeric representation of machine code.

Below is an example of a AVR assembly code written in assembly language. Each line of the

code is an instruction telling the microcontroller to carry out a task.

ADD R16, R17 ; Add value in R16 to value in R17

DEC R17 ; Minus 1 from the value contained in R17

MOV R18, R16 ; Copy the value in R16 to R18

END: JMP END ; Jump to the label END

The instructions used in writing programs in assembly language are not general but

specific to the microcontroller. Each company provides a set of instructions for there

microcontrollers. AVR 8-bits microcontrollers have a common instruction set.

Refer to file “Atmel AVR 8-bit Instruction Set manual 2014”, the datasheet for complete

reference on AVR 8-bits microcontrollers.

Please note that not all instructions are available to all microcontrollers. The set

available to each AVR microcontroller is given in the specific device datasheet. For

ATmega32/ATmega32A valid instructions are given between pp 329-331

The Editor A.11.

Assembler programs are written with an editor. The editor just has to be able to create

and edit ASCII text files.

Some features of the editor are that it can detect errors (usually syntax errors):

● Errors, that the assembler later detects, are reported along with the line number

in the text file. Line numbers is useful for reference when discussing your code with

someone else.

● Typing errors are largely reduced, if those errors are marked with colours. It is

a nice feature of an editor to highlight the components of a line in different colours.

The AVR Studio 6 is integrated with an editor that recognizes instructions automatically

and uses different colours (syntax highlighting) to signal user constants and typing

errors in those instructions (in black). Storing the code in an .asm file provides nearly

the same text file; colours are not stored in the file.

Assembler & Source Files A.12.

The Assembler works on source files containing instruction mnemonics, labels and

directives. The instruction mnemonics and the directives often take operands.

Code lines should be limited to 120 characters.

Lab 1 Appendix (20152016-1) 20

Every input line can be preceded by a label, which is an alphanumeric string terminated by

a colon. Labels are used as targets for jump and branch instructions and as variable names

in Program memory and RAM.

An input line may take one of the four following forms:

1. [label:] directive [operands] [Comment]

2. [label:] instruction [operands] [Comment]

3. Comment

4. Empty line

A comment has the following form:

; [Text]

Items placed in braces are optional. The text between the comment-delimiter (;) and the

end of line (EOL) is ignored by the Assembler. Labels, instructions and directives are

described in detail in the following sections.

Good Practice to Organize Code A.13.

When writing AVR assembly programs it is a good practice to organize code in four columns

as shown in the code below. This has the benefit of your program being easier to

read/debug by you and others.

;Col_1 Col_2 Col_3 Col_4

ADD R16, R17 ; Add value in R16 to value in R17

DEC R17 ; Minus 1 from the value contained in R17

MOV R18, R16 ; Copy the value in R16 to R18

END: JMP END ; Jump to the label END

Column 1 (Col_1) is used for labels. Labels are basically markers use by the programmer when indicating to the microcontroller to jump to a specific location in the code.

Column 2 (Col_2) is used for the microcontroller instructions.

Column 3 (Col_3) is used for arguments operated on by the instruction in column 2.

Column 4 (Col_4) is used for comments. Note here that a semi-colon ";" is put in front of each comments. That is the semi-colon indicate that the statement that follows it in the

same line is a comment.

Note: There are no restrictions with respect to column placement of labels, directives,

comments or instructions.

Comments A.14.

A comment starts with a semicolon, double slash or enclosed by the “\*” and the *\

character. All that follows behind on the same line will be ignored by the assembler. If

you need to write a comment over multiple lines, start each line with a semicolon. So each

assembler program may start like this:

\*

Prog.asm, Program to do for this Lab 1

Written by Zuraimi bin Yahya, last change: 9.9.2012

*\

Put comments around all parts of the program, be it a complete subroutine or a table.

Within the comment mention the special nature of the routine, pre-conditions necessary to

call or run the routine. Also mention the results of the subroutine in case you later will

Lab 1 Appendix (20152016-1) 21

have to find errors or to extend the routine later. Single line comments are defined by

adding a semicolon or double slash behind the comments on the line. Like this:

;Comments using semi-colon

LDI R16,0x0A ;Here something is loaded

//Comments using double slash

MOV R17,R16 //and copied somewhere else

The Assembler A.15.

The AVR Studio 6 IDE A.16.

Atmel Studio 6 is a software development environment developed by Atmel. It is meant to replace AVR Studio 5 going forward providing a single development platform for Atmel's 8-bits, 32-bits and ARM Cortex-M families of AVR microcontrollers.

Some Features of Atmel Studio 6

- It is a full software development environment with an editor, simulator, programmer,

etc.

- It comes with its own integrated C compiler the AVR GNU C Compiler (GCC). As such you do

not need a third party C compiler.

- It provides a single environment to develop programs for both the 8-bits, 32-bits and

ARM Cortex-M AVR series of microcontrollers.

- It also integrates fully QTouch studio.

- Provides support for several programmers including the STK500, AVR Dragon, etc

To Create a Project before typing an assembly language A.17.

Install AVR Studio 6 before continuing the following steps.

Step A1: To create a assembly project first start Atmel Studio 6 by going to the start

menu on your PC select Atmel AVR Tools then Atmel Studio 6. See the splash

screen for Atmel Studio 6, as shown figure below, this indicates that Atmel

Studio 6 is starting up. Just wait for a moment.

After Atmel Studio 6 starts the Atmel Studio 6 Start Page will appear as shown in the

figure below.

EDITOR

PROGRAM

ASSEMBLER

PROGRAM

DOWNLOAD TO

AVR ’s FLASH

DOWNLOAD TO

AVR’s EEPROM

myfile.asm

myfile.objmyfile.eep myfile.hex myfile.map myfile.lst

Lab 1 Appendix (20152016-1) 22

Lab 1 Appendix (20152016-1) 23

Step A2: Click on New Project pointed to by the green arrow in the diagram above to start

a new project. The following window will appear.

Lab 1 Appendix (20152016-1) 24

Step A3: To create a new assembly project select C from the panel to the left pointed to

by the green arrow. Also type the file Name and Location pointed to by the green

arrows at the bottom of the window. The following window will then appear. I n

this example the projeck name is “Lab1Pre”.

Lab 1 Appendix (20152016-1) 25

Step A4: The window above is the device selection screen for Atmel Studio 6. Scroll down

and select the microcontroller you will be using. The following window will then

appear.

This is the Atmel Studio 6 editor where you type your assembly program. The editor starts

your assembly program for you by providing you with the structure (in comment field) shown

in the editor of the figure above. You may optionally delete (or edit) the structure.

Step A5: Write the program given in Figure A.17(A5), on the Atmel Studio 6 editor.

Explanations on the program are given in the comments fields). Please do not cut

and paste. Its is objectively targetted that by reading then writing back the

program line by line (and referring to A.6 thru A.15, the writer will develope:

1) The experience on typing a program.

2) The good practice to organize code.

3) The knowledge on the assembler directive used and their argument(s).

4) The knowledge on how assembler directive declare locations for writing program

and data in Program memory of the ATmega32 architecture.

5) The knowledge on how assembler directive declare locations for locations for

variable in Data memory of the ATmega32 architecture.

6) The knowledge on how the instructions and their operand(s) are written.

7) The knowledge on function of addressing modes for each instruction: where data

is taken (source) and where data is stored (destination).

Do not copy the comments as-is given in Figure A.17(A5). You are required to

develop your own original comments which can be done as you progressively type out

and understand the sequence of instructions.

/* * Lab1Pre.asm * * Created: 9/8/2015 8:28:38 PM * Author: DELL5110 */ /* Note that hexadecimal number can represented with either the prefix "0x" or "$" It is a good practice to just use either "0x" or "$" but in this lab both is used for demonstration purpose. Note also how comments is declared

Lab 1 Appendix (20152016-1) 26

*/ /* The ATmega32A is a functionally identical, drop-in replacement for the ATmega32. All devices are subject to the same qualification process and same set of production tests, but as the manufacturing process is not the same. Some electrical characteristics differ. In this lab ATmega32 device will be used. */ .include "m32Adef.inc" //Register/Bit Definitions for the ATmega32A /* By including this file "m32Adef.inc" in the assembly program file, all I/O register names and I/O register bit names appearing in the data book can be used. In addition, the six registers forming the three data pointers X, Y and Z have been assigned names XL - ZH. Highest RAM address for Internal SRAM (RAMEND) is also defined ($085F). */ .equ ten = 10 .cseg //Declare Program (Flash) Memory Space .org 0x0 reset: jmp start //RESET vector at address 0x0000 /* When RESET event is invoked, PC <-- 0000. The CPU will execute instruction at pointed by PC. In normal procedure we will force PC to be set to the location of the bootup codes by using the "jmp start" instruction which effectively causes to jump to the address 0x2A. 0x2A is the address in Program memory just after the interrupt vector table of the ATmega32. We can omit this "jmp main" (and straight away continue with the bootup codes) if we are not going to use any interrupt in the program (which are unlikely in normal application of a CPU or microcontroller). */ //Address 0x0002 to 0x002f is reserved for Interrupt vector table .org 0xA /*In this lab1 since we are not going to use interrupt, we are using the vector table area for our program starting at address 0xA*/ start: /* Boot up codes starts here where STACK, I/O control registers and any other global variables used in the operation of the CPU, is initiallised. */ /* Process No: 1. Initialise stack ponter at highest (end) of Data Memory (SRAM). Effectively, SP <-- 0x85F (value of RAMEND which is defined in "m32A.inc") */ ldi R16,low(RAMEND) //r16 <-- (using Immediate addressing mode) out SPL,R16 //SPH <-- R16 (using I/O addressing mode) /*R16 (one of the upper GPRs) is used as the intermediate variable to hold low byte of value RAMEND before being stored to SPL*/ ldi r16,high(RAMEND)//R16 <-- high byte of value RAMEND out SPH,R16 //SPH <-- R16 /*Finally SP<--RAMEND after sequential executions of the four instructions*/ /* Process No: 2. Now we are going to initialise num1 with value $2F*/ ldi r17,$2a //r17 <-- $2a using Immediate addressing mode sts num1,r17 //num1 <--r17 using direct addressing modes /*R17 (one of the upper GPRs) is used as the intermediate variable to hold value $2a before being stored to num1 (absolute address is $60) Finally num1<-- $2a after sequential executions of the two instructions*/ /* Process No: 3. Now we are going to copy data in num1 into temp1*/ lds r17,num1 //r18 <-- num1 using Direct addressing mode sts temp1,r17 //num1 <--r18 using direct addressing modes /*R18 (one of the upper GPRs) is used as the intermediate variable to hold value from num1 before being stored to temp1 (absolute address is $120)' Finally temp1 <-- num1 after sequential executions of the

Lab 1 Appendix (20152016-1) 27

two instructions */ /* Process No: 4. Now we are going to do the calculation of sum = num1 + temp1 + 5 */ lds r0,num1 ;r0 <-- num1 lds r1,temp1 ;r1 <-- temp1 add r0,r1 ;r0 <-- r0 + r1 ldi r16,5 ;r16 <-- 5 add r0,r16 ;r0 < r0 + r1 sts sum,r0 ;sum <-- r0 ;Effectively sum <-- num1 + temp1 + 5 ($59) /* Process No: 5. Now we are going to initialise pointer Register Y with address of numbers3*/ ldi YL,low(numbers3) //YL <-- low byte of address of numbers3 ldi YH,high(numbers3) //YH <-- high byte of address of numbers3 //effectively Y <-- address of numbers3 /* Process No: 6. Now we are going to store value $53 at address pointed by X (value in X)*/ ldi r16,$53 //r16 <-- $53 using R16 as intermediate (one of valid GPR) st Y,r16 //(Y) <-- R16 Using Register Indirect addressing mode /* Process No: 7. Now we are going to store value $35 at address which is 16 byte after (displaced +vely) address of numbers3*/ ldi r16,$35 //r16 <-- $35 using R16 as intermediate (one of valid GPR) std Y+3,r16 //(Y+3) <-- R16 Using Register Indirect with displacement //addressing mode /* Process No: 8. Now we are going to initialise value: $10, $11, $12, $13 and $14 in sequence in the array pointed by numbers3 (i.e address $80, $81, $82, $83 and $84) consecutively by using address register indirect with post increment method X register must be initialise to point to the first address of array numbers3 Consecutively using Register Indirect with post increment mode and r20 is pre-updated (initially r20<--$10 but subsequently r20 incremented) the operation: (X) <-- r20, X <-- X + 1 is executed 4 times */ /*we will need to initialise pointer Register X with address of numbers3*/ ldi XL,low(numbers3) //XL <-- low byte of address of numbers3 ldi XH,high(numbers3) //XH <-- high byte of address of numbers3 //effectively X <-- address of numbers3 /*Now in four consecutively phase: with r20 pre-updated, X <-- r20, x<--x+1 (initially r20<--$10, subsequently r20 incremented)*/ ldi r20,ten //r20 <-- $10: (r20 initialised value $10) st X+,r20 //(X) <-- r20, X <-- X + 1: (effectively [$080] <-- $10, X <-- $081) inc r20 //r20 <-- r20 +1: (effectively r20 <-- $11) st X+,r20 //(X) <-- r20, X <-- X + 1: (effectively [$081] <-- $11, X <-- $082) inc r20 //r20 <-- r20 +1: (effectively r20 <-- $12) st X+,r20 //(X) <-- r20, X <-- X + 1: (effectively [$082] <-- $12, X <-- $083) inc r20 //r20 <-- r20 +1: (effectively r20 <-- $13) st X+,r20 //(X) <-- r20, X <-- X + 1: (effectively [$083] <-- $13, X <-- $084) inc r20 //r20 <-- r20 +1: (effectively r20 <-- $14) st X+,r20 //(X) <-- r20, X <-- X + 1: (effectively [$084] <-- $14, X <-- $085) /* Process No: 9. Now we are going to copy in sequentialy, the string of 1 byte data in address numbers2+0 ($80), numbers2+1 ($81),numbers2+2 ($82) and numbers2+3 ($83) to array pointed by numbers3+3 in REVERSE ORDER (address $67, $66, $65, $64) Effectively sequentially, the following will happen: (numbers3+3) <-- ($numbers2) (numbers3+2) <-- ($numbers2+1) (numbers3+1) <-- ($numbers2+2) (numbers3) <-- ($numbers2+3) */ /*Initially we are going to initialise pointer Register X with address of numbers2 */ ldi XL,low(numbers2+4) //XL <-- low byte of address of numbers2 + 4 ($68)

Lab 1 Appendix (20152016-1) 28

ldi XH,high(numbers2+4) //XH <-- high byte of address of numbers2 + 4 ($00) //effectively X <-- address of numbers2 + 4 ($0068) /*Then we are going to initialise pointer Register Y with $54 (end address of source array)*/ ldi YL,low(numbers3) //YL <-- low byte of $00 ldi YH,high(numbers3) //YH <-- high byte of $01 //effectively Y <-- $050 ld r16,Y+ //R16 <-- (Y), Y<--Y+1: Effectively (r16 <-- ($80), Y<--$81 st -X,r16 //X <-- X-1, X <-- R16: Effectively (X<-- 67, ($67)<-- R16 //Overall effectively: ($67) <-- ($80), Y <--$81 X <-- $66 ld r16,Y+ //R16 <-- (Y), Y<--Y+1: Effectively (r16 <-- ($81), Y<--$82 st -X,r16 //X <-- X-1, X <-- R16: Effectively (X<-- 66, ($66)<-- R16 //Overall effectively: ($66) <-- ($81), Y <--$82 X <-- $65 ld r16,Y+ //R16 <-- (Y), Y<--Y+1: Effectively (r16 <-- ($82), Y<--$83 st -X,r16 //X <-- X-1, X <-- R16: Effectively (X<-- 65, ($65)<-- R16 //Overall effectively: ($65) <-- ($82), Y <--$83 X <-- $64 ld r16,Y+ //R16 <-- (Y), Y<--Y+1: Effectively (r16 <-- ($83), Y<--$84 st -X,r16 //X <-- X-1, X <-- R16: Effectively (X<-- 64, ($64)<-- R16 //Overall effectively: ($64) <-- ($83), Y <--$84 X <-- $63 /* Process No: 10. Now we are going to read 4 successives byte of data array from numbers1 in Program Memory to array numbers4 in data memory */ ldi ZH,high(numbers1<<1);ZH <-- high byte of absolute byte address of numbers1 ($200) ldi ZL,low(numbers1<<1) ;ZL <-- low byte of absolute byte address of numbers1 ldi YH,high(numbers4) ;YH <-- high byte of absolute byte address of numbers4 ldi YL,low(numbers4) ;YL <-- low byte of absolute byte address of numbers4 ldi r17,4 ;Set repeat loop = 4 repeat: lpm r18,Z+ ;R18 <-- (Z),Z <-- Z+1 st Y+,r18 ;Y <-- R18, Y <-- Y+1 dec r17 ;R17 <-- R17-1 brne repeat ;Repeat until (R17==0) /* Process No: 11. Program does an infinite loop (halt at location "here") as it continuously executes "rjmp here" */ here: rjmp here .org $50 //Address to start at 0x100 in Program Memory SS_table: .db $3f,$06,$5b,$4f,$66,$6d,$7d, $03, $7f, $6f //SS_table declared at address $100 numbers1: .db 0x10, 0x1,0x12,0x3,0x14,0x15,0x6,0x7,0x18,0x9 //numbers1 declared at address $10A .dseg //Data Memory(Flash) Space (by default at address start $60) num1: .byte 1 ;num1 declared as 1 byte storage by default at address $60 num2: .byte 1 ;num2 declared as 1 byte storage at next address=0x61 data1: .byte 1 ;data1 declared as 1 byte storage at next address=0x62 data2: .byte 1 ;data2 declared as 1 byte storage at next address=0x63 numbers2: ; .byte 7 ;numbers2 declared at address $64 as a 7 byte array storage endofnumbers2: .byte 1 .org 0x80 //Address to start at 0x100 numbers3: .byte 6 ;numbers2 declared as a 6 byte array storage numbers4: .byte $10 ;numbers2 declared as a 16 byte array storage at address 0x110 temp1: .byte 1 ;temp1 will be declared at address 0x96 temp2: .byte 1 ;temp1 will be declared at address 0x97 sum: .byte 1 ;temp1 will be declared at address 0x98

Lab 1 Appendix (20152016-1) 29

Figure A.17(A5)

Step A6: Closing/Opening an Existing Project.

Whenever it need be, you can always edit existing project that has been created and closed

and close. How to do this can be self-learned.

Debugging A.18.

Debugging is a process of finding logical errors in a program. However though you can use

this process to achieve the objective stated in Step A5.

There are no fixed steps on debugging a program. The concept is that we need to know where

and what caused the bug so that we can do the correct rectification on the program.

Conceptually, to find the bug, we need to know what the input to the program is, and/or

what the output is, and/or whether logically (in decision instruction) it is doing as what

it should be. So to do this we may use one of the following methods:

1. Single Step by Step, using Step Over or Step Into operation.

2. Set breakpoint(s) at location where we want to inspect the input or output of

the program. Then we run (or simulate) until the program reach the breakpoint.

3. Step Over an instruction or function (or procedure) and inspect the input or

output of the program’s instruction or function (or procedure).

4. Step Into the function (or procedure) and inspect the input or output of the

program’s function (or procedure).

5. Note: Step Over an instruction is the same operation as Step Into the

instruction.

Step A7: Selecting Target of Program when to Debug

Atmel Studio 6 allows the target to be selected. If no external target is connected, by

default AVR simulator will be selected. To make/confirm selection select ProjectLab1Pre

Properties.... You can click “Selected debugger/programmer” select available target.

Lab 1 Appendix (20152016-1) 30

a. Starting and Ending a Debug Session in Atmel Studio 6

To start a debug session and halt press Alt+F5 or choose Debug→Start Debugging and

Break from the menu, alternatively, press the toolbar button as illustrated below:

Lab 1 Appendix (20152016-1) 31

To Continuer a debug session (when in Break) and keep executing press F5 or press the

toolbar button with the continue symbol or choose Debug→Continue from the menu as

illustrated below:

To end the debug session use the Stop Debugging button or keyboard shortcut Shift+F5.

b. What is a Break.

The Break is a situation in debug session when execution of instruction is halted. PC

(Program Counter) will hold (pointing) to the next instruction the CPU will execute.

c. Debug control

Several commands are available for controlling the debugger. They are available from

both the Debug menu and several toolbars. The Atmel Studio Integrated Development

Environment (IDE) has two major operating modes: design mode and debug mode. Design

mode is when you are editing the source code project, while debug mode is when you

debug your project. The IDE adapts to modes, and menus an toolbars changes.

Note

Some debug commands are available in design mode, some in debug mode.

In design mode, the available debug commands are those that will start the debug

session, e.g. Start Debugging and Break, Start Debugging, Start without Debugging.

In debug mode, you will find commands like Break All, Step Out and Reset.

Figure A.18(c) shows the pull down menu of the debugging command when the Debug menu

is selected while in Debug Mode:

Figure A.18(c)

Lab 1 Appendix (20152016-1) 32

The following are explanation on some of the commands.

Start Debugging and Break

Starts the debugger, and breaks the execution on the first statement of the program (RESET vector).

Start Debugging

Starts the debugger, and runs the program. In debug mode and stopped, it resumes execution.

Start Without Debugging

Programs the project without starting debugging. For details, see Debug: Start without debugging.

Break All

Halts (breaks) the debugger. Normally we select this when we want to break a running program.

Stop Debugging

Stops and terminates the debug session, and returns to design mode.

Restart

Restarts the debugger and reloads the program.

Reset

Resets the program to the first statement

Step Into

Executes one instruction. When in disassembly level, one assembly level instruction is executed, otherwise one source level instruction is executed.

Step Over

Similar to Step Into, Step Over executes one instruction. However, if the instruction contains a function call/subroutine call, the function/subroutine is executed as well. If a user breakpoint is encountered during Step Over, execution is halted.

Step Out

Continue execution until the current function has completed. If a user breakpoint is encountered during Step Over, execution is halted. If a Step Out command is issued when the program is on the top level, the program will continue executing until it reaches a breakpoint or it is stopped by the user.

Quick Watch and Watches

Adds a Quick Watch for the variable or expression under the cursor.

Toggle Breakpoint

Toggle the breakpoint status for the instruction where the cursor is placed. Note that this function is only available when the source window or disassembly window is the active view.

New Breakpoint

Create a new breakpoint at the location of the cursor.

A breakpoint tells the debugger to temporarily suspend execution of a program when a specific condition takes place, e.g. when a certain instruction is about to be executed.

Breakpoints provide a powerful tool that enables you to suspend execution where and when you need to. Rather than stepping through your code line by line or instruction by instruction, you can allow

Lab 1 Appendix (20152016-1) 33

your program to run until it hits a breakpoint, and then start to debug. This speeds up the debugging process.

Disable All Breakpoints

This function clears all set program breakpoints, including breakpoints which have been disabled.

d. Breakpoint glyphs (icon)

The source windows and the Disassembly window show breakpoint locations by displaying

symbols called glyphs in the left margin. The following table describes these glyphs.

If you rest the mouse on a breakpoint glyph, a breakpoint tip appears with more

information. This information is especially useful for error and warning breakpoints.

Icon Description

Normal breakpoint. The solid glyph indicates that the breakpoint is enabled. The hollow glyph indicates that it is disabled.

Advanced breakpoint. Active/disabled. The + sign indicates that the breakpoint has at least one advanced feature (such as condition, hit count, or filter) attached to it.

Breakpoint error. The X indicates that the breakpoint could not be set because of an error condition.

Breakpoint warning. The exclamation mark indicates that a breakpoint could not be set because of a temporary condition. Usually, this means that the code at the breakpoint or tracepoint location has not been loaded. It can also be seen if you attach to a process and the symbols for that process are not loaded. When the code or symbols are loaded, the breakpoint will be enabled and the glyph will change.

e. Applying Debugging as a learning aid tool.

By using debugging technique you can:

1. Visualise the architecture of the ATmega32A by using Processor View, Memory Views

and I/O Views to identify the physical components in the processor.

2. You can note the relationship between each view. For instance the data in R27:R26

represent the data in X pointer register (refer Figure A.5 (d)). Try changing R26:R25 and you will find that X will also change.

3. By single stepping (Step Over or Step Into) an instruction you can find out or

confirm your understanding on the execution of the program i.e. the changes of

Registers or Memory Location as defined in the Instruction Set Reference, the

location of data taken from or send to as defined by the addressing modes of the

instruction.

4. By Stepping Into a subroutine call (CALL or RCALL instruction), you can find out

or confirm your understanding on the execution of the Instruction, i.e. the

changes of PC and STACK and trace (single step) into the subroutine.

5. By Stepping Over a subroutine call (CALL or RCALL instruction), you can find out

or confirm that your understanding on the execution of the whole subroutine

without getting into the subroutine.

6. You can simulate condition before you execute an instruction by setting contents

the register or memory location that is used by the instruction before executing

it so that you can visualise/confirm the effect of the register or memory location

data in towards the execution of the instruction.

7. By tracing through a program you can confirm/examine the program flow of a program

and you can visualise/confirm that PC (Program Counter) directs the flow of the

Lab 1 Appendix (20152016-1) 34

program. So you can see how Program Flow Instructions (Branch Instructions)

changes the PC in accordance to the Instruction Set reference.

8. You can use Breakpoints to force the program to stop at the any of the Breakpoints

the program will pass through.

9. By using Breakpoints you can execute your program such that it skip a sequence of

code that you do not want to trace and stop at the instruction that you want to

begin you single stepping. This will help you overcome repeating tracing that code

that you have confirmed not needed (to save time and energy doing the tedious

stepping over) especially after you restart the program to test the working of the

program after making changes on code.

Note: Select Debug Stop Debugging to clear all registers and Memory contents to

avoid confusion of old data contents during previous debugging process.

10. Certain instruction can only be executed in the program is running so you cannot

use single step method. By setting breakpoints at the instruction you can stop the

program when the certain event occurs. From that breakpoint you can trace the

program if needed. These event can occur from interrupts INT0, INT1 , INT2, ADC or

Timers or input from switches that is check by conditional branch instructions.

11. When you are debugging a program that reads data from Digital I/O ports, you can

simulate the input by setting the revenant PINxn bit before you trace or run the

program. By doing this you can check the flow of the program that check the status

of the input.

Lab 1 Appendix (20152016-1) 35

Viewing the Disassembly of the ATmega32 Program A.19.

Step A8: To view the disassembly Display, in Debug mode Select

DebugWindowsDisassembler which will open Disassembler window Tab as shown in

Figure A.19(A7). The Disassembly window is only available when debugging.

The disassembly window shows your program code disassembled. Program execution and AVR

instructions can be followed in this view. By right clicking inside the Disassembly window

you will be able to set breakpoints, run to the position of the cursor or go to the source

code. You cannot modify the source code from the Disassembly window.

Figure A.19(A8): Disassbler View

In addition to assembly instructions, the Disassembly window can show the following optional information: 1. The next instruction to be execute. Identified in box with circle #1

2. Memory address where each instruction is located. For native applications, this is the actual memory address. Identify labels address from the respective instruction. Identified in box with circle #2

3. Code bytes byte representations of the actual machine. Identified in box with circle #3

4. Source code from which the assembly code derives. Identified in box with circle #4.

5. Symbol names for the memory addresses. Identified in box with circle #5.

6. Original source code instruction. Not Shown in Figure.

3

2

4

4

4

4 3

1

Lab 1 Appendix (20152016-1) 36

Editing values and bits in break mode A.20.

When the project is in debug break mode, any value can be changed by clicking the value

field and writing a new value. Some values and bits cannot be modified as they are read-

only, and some bits may be write-only. See the documentation for each device for more

information. When a bit or value is set, it is immediately read back from the device,

ensuring that the I/O View only displays actual values from the device. If a new value is

set, but the I/O view does not update as expected, the register might be write-only or

simply not accessible.

When a register has changed since last time it was displayed, it will indicate so with a

red coloured value and bits in the display. If a bit has been set since last time, it will

be solid red. If it has been cleared it will simply have a red border. This feature can be

toggled on or off in the toolbar.

Viewing the ATmega32 Processor’s Registers A.21.

Step A9: Select Debug→Windows→Processor View. The processor view offers a simulated or

direct view of the current target device MPU or MCU. In you can see a partial

list of the simulated device's ATxmega32/ATmega32A registers.

Figure A.21(A9): Processor View window

Lab 1 Appendix (20152016-1) 37

The program counter shows the address of the instruction being executed.

The stack pointer shows the application's current stack pointer value.

The X, Y and Z registers are temporary pointers that can be used in indirect passing or

retrieving arguments or objects to and from functions. Cycle counter counts the cycles elapsed from the simulation’s start.

Status register or SREG shows the currently set flags.

Further on you will be able to toggle a setting for displaying the flag names.

The stop watch field allows you to make rudimentary profiling of your application. It is influenced

by the frequency set in Frequency field, which defines target MCU/MPU frequency, in case when

the prototyping board is connected.

Each register can be displayed in hexadecimal, decimal, octal and binary (flag) format by right-

clicking and choosing Display in binary, etc., or Display in... . Each field can also be modified, as

shown in the below image. If a field is a status or flags register, composed of a number of the

one-bit flags, you can toggle individual flags by clicking on them -

The processor view is only active in the debug mode.

Viewing the ATmega32 Memory Space A.22.

The memory view gives you an outline of the memory.

It is possible to select among the attached memories to see all the segments by switching

between them in a Segment drop-down menu on top of the memory view, you can also specify

the starting address for the memory view window in the Address form field on top of the

memory view.

In order to specify the address you can use either a normal hexadecimal entry or an

expression: See the section called “Expression formatting”. The Columns drop-down menu allows

to specify how many byte-aligned memory columns you wish to see at one time, most often

that should be left at Auto setting, but if you have to manually check a fixed-length type

values and you know how many words or bytes those values occupy, you could align the

memory view so that each row will correspond to a desired number of values.

a. Viewing Instruction data in Program Memory

Step A10: Select Debug WindowsMemory viewWindow 1, or Ctrl+Alt+M+n where n is the

memory's number (1).

Figure A.22 (a): Memory 1 window with “prog Flash” (Program memory), address start at 0x00

and Auto column selected.

Lab 1 Appendix (20152016-1) 38

This is the machine code which is also displayed in a different format shown in

display in Figure A.19(A7-1). Inspect address 0x0000 and 0x000A the similarity and

difference between the two displays.

b. Viewing .DB data in Program Memory

Step A11: Now change the setting such that address = 0x0050 * 2 = 0x00A0 (Refer Section

A.3 Figure A.3). This is the Address of SS_table declared in program memory of

program “Lab1pre”.

Also set Columns : 2. The display will be in Figure A.19(A7-2).

Figure A.22(b): Location and contents of SS_table declared in Program Memory of

program “Lab1pre” using “.DB” assembler directive.

You will see the physical address of the “.DB” assembler directive in Program

Memory and the content of the memory locations from the .DB declarations.

Using Watch window to determine address of label (address may be used as A.23. variables)

Step A12: Select Debug WindowsWatch.

Figure A.23(A12): Example of Watch window for some of the variable from Lab1Pre project.

1. The identifier under the “Name” are valid labels declared in the program being

debug that have to be entered manually.

2. Watch window can be used to determine value of labels declared in the program

3. Using this value as address in memory window, you can watch content of the label

(as variable) by watching the address.

Debugging the program Using Single Step A.24.

In Debug mode There are two commands to single step through the code. These are "Step

Over" <F10> and "Step Into" <F11>. The difference between these commands is

that <F10> does not trace into subroutines. Since our example does not contain any

subroutines, there is no difference between these commands in this example.

Lab 1 Appendix (20152016-1) 39

Step A13: Close “Lab1Pre” and reopen the project. You should be able to find the folder,

otherwise search for “Lab3pre.atsln. You should see the following display. If

there is no “Lab1Pre.asm” double-click the “Lab1Pre.asm” icon in the “Solution

Explorer” window.

Lab 1 Appendix (20152016-1) 40

Step A14: Make sure that the “Selected debugger/programmer” is on “Simulator”.

Step A15: Select “Start Debugging and Break” command and you will see the following

display. If the “Processor” window is not open, open it (Debug

Windowprocessor View)

Figure A24(A15): Debug and Processor View on ““Start Debugging and Break” command.

The yellow arrow will be pointing to the instruction “jmp start” addressed (pointed) by

Program Counter which is at 0x000000 which is the next instruction to be executed.

Lab 1 Appendix (20152016-1) 41

Single Step through your program A.25.

Step A16: Noting that PC is at address “0x00000A”, To Single Step over instruction “jmp

start” strike the [F10] key once):

Note that the word in red indicates the register that is affected from the

execution changes from the previous value. If the field is affected from the

execution but the result is the same value as before (no change), the colour of

the word in the fields will be black (as if the register is not affected from

the instruction – so be careful not to assume so).

This command will cause the simulation to execute the instruction “jmp start”

pointed by Program Counter and stop at the next instruction which in this case

will be “ldi R16,low(RAMEND)” at address 0x000A shown by the yellow arrow. The

Program Counter will be updated to point at the next instruction which is 0x000A

which is also the address of “start”.

Figure A25(A16-1): Display after single-stepping instruction at address 0x000000

(execution of “jmp start”)

Referring to the instruction “JMP” in page 82 the in the file “AVR-Instruction-Set

2002.pdf” as shown below, the PC take the value of the operand that is “start” and the is

no changes in the SREG.

To check the Status Register, you will need to view the Processor window. Grey colour text in

the boxed (eg. C for Carry bit) represent that that the bit is 0. A black font colour

represents that that the bit is 1 (not shown right now).

Lab 1 Appendix (20152016-1) 42

Figure A25(A16-2): JMP instruction ” in page 82 the in the file “AVR-Instruction-Set 2002.pdf”

Lab 1 Appendix (20152016-1) 43

Step A17: Single step again over instruction “ldi R16,low(RAMEND)” and inspect content of

R16 and SREG (Status Register).

This command will cause the simulation to execute the instruction “ldi R16,low(RAMEND)” and stop at the next instruction which in this case will be “out SPL,R16” at address 0x000B shown by the yellow arrow. The Program Counter will be updated to point at the next instruction which is 0x000B. R16 will be loaded with 0x5F. Red color on the word denotes that the value has changed

Figure A25(A17): Display after single-stepping instruction at address 0x00000A (execution

of “ldi R16,low(RAMEND”) “out SPL,R16”.

Lab 1 Appendix (20152016-1) 44

Step A18: Single step again and inspect content of R16 and SREG (Status Register).

This command will cause the simulation to execute the instruction “out SPL,R16”

pointed by Program Counter and stop at the next instruction which in this case

will be “ldi R16,high(RAMEND)” at address 0x000C shown by the yellow arrow. The

Program Counter will be updated to point at the next instruction which is 0x000C

which is also the address of “ldi R16,high(RAMEND)”.

Do the single stepping until the instruction “rjmp here”.

If you want to check the memory location, you may check using the memory window (refer

Section A.22).

Using Breakpoint A.26.

Breakpoints are a method of halting execution flow. By adding a breakpoint in the assembly

code we can run the program at full speed, and it will be stopped at the line with the

breakpoint. By now you have noticed that you have to press<F11> three times to go through

the loop once. We will add a breakpoint at the by placing the cursor on the instruction in

the source view window and press <F9> (or the "Toggle Breakpoint" in the "Debug" menu ). A

red circle will appear in the left margin of the source view window as shown. By

pressing <F5> or "Run" from the "Debug" menu the program will start running and break

(stop) at the instruction with the breakpoint.

There may be situations where we have single stepped through far in the program but you

may need to reverse a few steps back to review a result. We will need to Stop Debugging

and start over sequential single stepping again until we reach the instruction we want to

review which can be unnecessarily tedious.

The best method to overcome this is to set a breakpoint at the instruction we want to

stop, RUN the program so that it will stop at the breakpoint it meets. Then you may single

step through from there.

To set a breakpoint, click on any row to put the cursor on the line of the instruction

where you want to break (stop) as show below (in this example “ldi r20,ten” ). Do not

select the whole line. Then press F9.

Lab 1 Appendix (20152016-1) 45

You will see a red dot on the side of the instruction as shown in the following display.

You may set another (or many) breakpoint(s) that we need so that we may CONTINUE running

the program until it meets the next breakpoint.

You may remove any breakpoint by pressing F9 or clicking the Toggle Breakpoint icon. To

remove all breakpoint, select Debug|Remove all Breakpoints or click the Remove all

Breakpoints icon.

Stopping Debug A.27.

Step A19: Stop Debugging by selecting the menu Debug| Stop Debugging.

Calculating Execution Time A.28.

a. Calculating Execution Time for Sequential Code

To determine the execution time (ET) for a piece of AVR assembly code you will need

the following information:

The clock frequency of the AVR microcontroller the code is running on.

The information sheet that tells the number of cycle each instruction requires to execute.

Refer to “Instruction Set Summary.pdf” under the “#Clock Note” column or “AVR-

Instruction-Set.pdf” on the “Cycles” title. Respective example are shown below:

In snippet of “Instruction Set Summary.pdf” shown below:

For single execution time instruction

As highlighted in the red boxes, LDI takes 1 clock cycle to execute

Lab 1 Appendix (20152016-1) 46

For 2 conditional execution time instruction:

As highlighted in the red boxes, BRCC take 1 clock cycle if condition is FALSE and 2

clock cycle if condition is TRUE.

Once you have the above information follow the steps below to calculate the execution

time:

Steps to calculate ET (Execution time)

1. Determine the period of the microcontroller clock using the equation:

Period (T) = 1/Frequency(f)

2. Determine the total number of cycle (C) to execute the piece of AVR assembly

code given. This is done by determining the number of cycle for each

instruction to execute in the code and adding them. The number of cycle each

instruction takes to execute is found in the datasheet for the microcontroller.

See AVR Instruction Set Summary.

3. Calculate the execution time (ET) for the piece of assembly code using the

following equation:

ET = T * C

Lab 1 Appendix (20152016-1) 47

Example 1

Calculate the execution time for the following piece of assembly code given that

the code will be running on an Atmel AVR 8-bit micro-controller being clocked by a

4MHz oscillator.

LDI R16, 0xFF

LDI R17, 0xEE

ADD R17, R16

MOV R20, R17

Solution

Step 1 - Determine the Period (T)

T = 1/f = 1/4*106 = 0.250µs

Step 2 - Determine Total Number of Cycles for execution (C)

; Instruction # cycles to execute

LDI R16, 0xFF ; 1

LDI R17, 0xEE ; 1

ADD R17, R16 ; 1

MOV R20, R17 ; 1

; _______________________________________________________

; Total # of cycles for execution (C) = 4

Step 3 - Calculate Execution Time (ET) using information from steps 1 & 2

ET = C * T = 4 * 0.250 = 1µs

Lab 1 Appendix (20152016-1) 48

b. Calculating Execution Time for Code with Single Loop

Example 2

Calculate the execution time for the following piece of AVR assembly code given

that the code will be running on an Atmel AVR 8-bit micro-controller being clocked

by a 1 MHz oscillator.

LDI R16, 5

Again: DEC R16

NOP

BRNE Again

NOP

NOP

Solution

Step 1 - Determine the Period (T)

T = 1/f = 1/106 = 1 µs

Step 2 - Determine Total Number of Cycles for execution (C)

; Instruction # cycles to execute

LDI R16, 5 ; 1

Again: DEC R16 ;-----|

NOP ; | A

BRNE Again ;-----|

NOP ; 1

NOP ; 1

;

_______________________________________________________

; Total # of cycles for execution (C) = 3 + A

The total number of cycles for the execution of the code is given as (3 + A). In calculating the total number of cycles for execution, in this case, it must be

taken into consideration that the block of code labeled A is executed more than

once because it forms a loop.

What is done here is that we look at the block of code which construct the loop as

a single instruction for which we will determine the number of cycle for execution

next.

Calculating the number of cycles for block A

; Instruction # cycles to execute

Again: DEC R16 ;-----| 1

NOP ; | 1

BRNE Again ;-----| 2

; _______________________________________________________

; Total # of cycles for execution of A = 5*(1+1+2) - 1

In this code the loop is controlled by the value in R16 which is 5. So the code in

block A is done 5 times. This result in C = 3 + A = 3 + [5(1+1+2) -1] = 22cycles.

One important point to note here is that the BRNE instruction takes 2 cycle to

execute when it is true and 1 cycle when the condition is false. So for the 5

times the BRNE instruction is executed 1 time the condition is false which is why

we subtract 1.

Step 3 - Calculate Execution Time (ET) using information from steps 1 & 2

ET = C * T = 22 * 1 = 22 µs

Lab 1 Appendix (20152016-1) 49

c. Verifying the Calculated Execution Time

Step 1: Open AtmelStudio and create a new AVR assembly project.

The entire code in the Atmel Studio editor should be similar to that below:

/* * DelaywithLoop.asm * * Created: 1/8/2015 11:33:08 PM * Author: DELL5110 */ .org 0 reset: jmp boot .org 0x2a boot: ; Instruction # cycles to execute LDI R16, 5 ; 1 Again: DEC R16 ;-----|2 NOP ; |1 A = 5*(1+1+2)-1 = 22 BRNE Again ;-----|1 NOP ; 1 NOP ; 1 ; _______________________________________________________ ; Total # of cycles for execution (C) = 3 + A shell: RJMP shell

Step 1: Go to the “Debug” menu in the Atmel Studio and select “Start Debugging and

Break”. You should get a screen looking like the one below:

Lab 1 Appendix (20152016-1) 50

Atmel Studio is now in simulation mode notice the yellow arrow, which indicates

the microcontroller is about to execute this line of code.

Also notice the 'Processor' window pane to the left, which indicates the value of

the Cycle Counter, Frequency, Stop Watch, etc. At this point the Cycle Counter and

Stop Watch is at 0, indicating that no instruction as been executed. The Frequency

for this simulation is set to 1 MHz.

Step 2: Single Step to label “boot” and you will get the following display:

Note that Cycle Counter = 3 and Stopwatch = 3.

Step 3: Position the cursor at the beginning of the line “shell: RJMP shell”. Then

go to the Debug menu and select Run to Cursor.

The simulator will now execute all the instruction up to where the cursor

is located. You should now see an update 'Processor' window pane showing the number of cycles that has passed to execute up to this point in the code, given by Cycle Counter.

We are interested in the Stop Watch value which gives the time taken to execute the instructions up to this point in the code which is 25 cycles or

25 µSec. That is the Execution Time for from instruction at “boot” to instruction at “shell” = 25-3 = 22 cycle or 22 µSec. This is equal to what

we have calculated previously.

Lab 1 Appendix (20152016-1) 51

Lab 1 Appendix (20152016-1) 52