/avr-assembly-examples

Tutorials/examples/practice using assembly language for the Atmel AVR microcontrollers.

Primary LanguageAssemblyMIT LicenseMIT

AVR Assembly: Project Intent

This project consists of notes and examples that I worked on while learning AVR assembly language programming for the first time.

Most or all of the examples assume use of the atmega168p. I haven't used any headers for constants (which forces me to really understand where these values come from) so these programs will require adaptation to use with other AVR chips. The mods required should be minor, though.

I've used a breadboard set up as per the example on page 56 of Make: AVR Programming by Elliot Williams.

Development Board

Notes on AVR Assembly Setup

Setting Up Avra Assembler

Download the source code for avra from Github:

git@github.com:Ro5bert/avra.git

To build avra from scratch:

# cd into the root directory and run:
make

Check Programmer Connection

To check the device/programmer are working, run the command below (adjust for your programmer and chip):

avrdude -c usbasp -p m168

-c	programmer type
-p	AVR part/device

If you call avrdude -c without the part, it will give you a list of available AVR device strings to choose from.

Note, my chips that look like m168p read as m168. Shrug?

Check Fuse Settings

You can check the fuse settings like:

avrdude -c usbasp -v -p m168

I noticed that it won't output information about the fuses if it thinks that the chip is wrong, however.

Building

To build using avra is trivial:

avra filename.asm

Flashing the Chip

avrdude -c usbasp -p m168 -U flash:w:hello.hex

You may also want to set the bitrate:

-b 57600

Obviously, change these settings however it makes sense for your particular setup.

A Note on Power

I noticed that the AVR chips can be a bit sensitive about VCC while being programmed, and that power via USB / programmer isn't always reliable. If something isn't working, try using a real power supply.

I/O Registers

AVR I/O registers are 64 bytes in data memory just after the 32 general working registers (0x20 - 0x5F). They include the PORT, PIN, and DDR registers that control the m/c's pins.

Note that the Status Register (SREG) is one of the I/O registers.

AVR assembly language has instructions just for dealing with the I/O registers:

in In from I/O location out Out from I/O location cbi Clear a bit in an I/O register (first 32 registers) sbi Set a bit in an I/O register (first 32 registers) sbic Skip if bit in I/O register is 0 sbis Skip if bit in I/O register is 1

cbi and sbi only work with the first 32 I/O registers. All PORT, PIN and DDR registers are in the first 32 memory locations. c/sbi are useful for setting output to pins.

cbi and sbi use a pin number and not a mask, so you can only set one pin at a time. in/out may be more efficient.

sbis/sbic can skip the next instruction based on a bit in an I/O register, so you can use this to check the state of a pin.

Examples:

in	r15, DDRB	; load DDRB to r15
out	DDRB, r0	; load r0 to DDRB

I/O Addresses

There are Data Memory addresses, and there are I/O addresses. I/O addresses are mapped to data memory addresses, in order to be able to more efficiently access (some) I/O addresses.

Data memory address 0x20 maps to I/O 0x00.

You can see how this is useful: by renumbering the I/O addresses, it allows access to the first 32 in 5 bits.

Extended I/O Addresses

Extended I/O and SRAM allow for direct access using the lds and sts instructions. Because these addresses are out of the range of the first 32 I/O registers, we can't use in or out with them. sts/lds work with the general purpose registers and up to 64K of memory. Prefer to use these with r16-r31, it's more efficient.

References

AVR Instruction Notes

(Random and incomplete)

ldi rd, imm

Loads an 8-bit number (0-255) into an upper half register (16-31)

out rd, r

Copies a number from a working register to an I/O register.

rjmp label

Jumps to the label. The label cannot be more than 204 instructions away. This is a "relative" jump.