Файл: Beginers introduction to the Assebly Language of ATMEL-AVR Microprocessors (Gerhard Schmidt,2004, англ).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.06.2025
Просмотров: 596
Скачиваний: 1
Avr-Asm-Tutorial |
5 |
http://www.avr-asm-tutorial.net |
Tools for AVR assembly programing
This section provides informations about the necessary tools that are used to program AVRs with the STK200 board. Programming with the STK500 is very different and shown in more detail in the Studio section. Note that the older software for the STK200 is not supported any more.
Four basic programs are necessary for assembly programming. These tools are:
•the editor,
•the assembler program,
•the chip programing interface, and
•the simulator.
The necessary software tools are ©ATMEL and available on the webpage of ATMEL for download. The screenshots here are ©ATMEL. It should be mentioned that there are different versions of the software and some of the screenshots are subject to change with the used version. Some windows or menues look different in different versions. The basic functions are mainly unchanged. Refer to the programer's handbook, this page just provides an overview for the beginner's first steps and is not written for the assembly programing expert.
The editor
Assembler programs are written with a editor. The editor just has to be able to create and edit ASCII text files. So, basically, any simple editor does it. I recommend the use of a more advanced editor, either WAVRASM©ATMEL or the editor written by Tan Silliksaar (screenshot see below).
An assembly program written with WAVRASM© goes like this. Just install WAVRASM© and start the program:
Now we type in our directives and assembly commands in the WAVRASM editor window, together with some comments (starting with ;). That should look like this:
Now store the program text, named to something.asm into a dedicated directory, using the file menue. The assembly program is complete now.
If you like editing a little more in a sophisticated manner you can use the excellent editor written by Tan Silliksaar. This editor tools is designed for AVRs and available for free from Tan's webpage. In this editor our program looks like this:
Avr-Asm-Tutorial |
6 |
http://www.avr-asm-tutorial.net |
The editor recognizes commands automatically and uses different colors (syntax highlighting) to signal user constants and typing errors in those commands (in black). Storing the code in an .asm file provides nearly the same text file.
The assembler
Now we have to translate this code to a machine-oriented form well understood by the AVR chip. Doing this is called assembling, which means collecting the right command words. If you use WAVRASM© just click assemble on the menue. The result is shown here:
The assembler reports the complete translation with no errors. If errors occur these are notified. Assembling resulted in one word of code which resulted from the command we used. Assembling our single asm-text file now has produced four other files (not all apply here).
The first of these four new files, TEST.EEP, holds the content that should be written to the EEPROM of the AVR. This is not very interesting in our case, because we didn't program any content for the EEPROM. The assembler has therefore deleted this file when he completed the assembly run.
The second file, TEST.HEX, is more relevant because this file holds the commands later programmed into the AVR chip. This file looks like this.
The hex numbers are written in a special ASCII form, together with adress informations and a checksum for each line. This form is called Intel-hex-format, and it is very old. The form is well understood by the programing
software.
The third file, TEST.OBJ, will be introduced later, this file is needed to simulate an AVR. Its format is hexadecimal and defined by ATMEL. Using a hex-editor its content looks like this. Attention: This file format is
not compatible with the programer software, don't use this file to program the AVR (a very common error when starting).
The fourth file, TEST.LST, is a text file. Display its content with a simple editor. The following results.
The program with all its adresses, comands and error messages are displayed in a readable form. You will need that file in some cases to debug errors.
Avr-Asm-Tutorial |
7 |
http://www.avr-asm-tutorial.net |
Programming the chips
To program our hex code to the AVR ATMEL has written the ISP software package. (Not that this software is not supported and distributed any more.) We start the ISP software and load the hex file that we just generated (applying menue item LOAD PROGRAM). That looks like this:
Applying menue item PROGRAM will burn our code in the chip's program store. There are a number of preconditions necessary for this step (the correct parallel port has to be selected, the programming adapter must be connected, the chip must be on board the adapter, the power supply must be on, etc.).
Besides the ATMEL-ISP and the programming boards other programming boards or adapters could be used, together with the
appropriate programming software. Some of these alternatives are available on the internet.
Simulation in the studio
In some cases self-written assembly code, even assembled without errors, does not exactly do what it should do when burned into the chip. Testing the software on the chip could be complicated, esp. if you have a minimum hardware and no opportunity to display interim results or debugging signals. In these cases the studio from ATMEL provides ideal opportunities for debugging. Testing the software or parts of it is possible, the program could be tested step-by-step displaying results.
The studio is started and looks like this.
First we open a file (menue item FILE OPEN). We demonstrate this using the tutorial file test1.asm, because there are some more commands and action that in our single-command program above.
Open the file TEST1.OBJ that results by assembling TEST1.asm. You are asked which options you like to use (if not, you can change these using the menue item SIMULATOR OPTIONS). The following options will be selected:
In the device selection section we select the desired chip type. The correct frequency should be selected if you like to simulate correct timings.
In order to view the content of some registers and what the processor's status is we select VIEW PROCESSOR and REGISTERS. The display should now look like this.
Avr-Asm-Tutorial |
8 |
http://www.avr-asm-tutorial.net |
The processor window displays all values like the command counter, the flags and the timing information (here: 1 MHz clock). The stop watch can be used to measure the necessary time for going through routines etc.
Now we start the program execution. We use the single step opportunity (TRACE INTO or F11). Using GO would result in continous exection and not much would be seen due to the high speed of simulation. After the first executed step the processor window should look like this.
The program counter is at step 1, the cycle counter at 2 (RJMP needed two cycles). At 1 MHz clock two microseconds have been wasted, the flags and pointer registers are not changed. The source text window displays a pointer on the next command that will be executed.
Pressing F11 again executes the next command, register mp (=R16) will be set to 0xFF. Now the register window should highlite this change.
Register R16's new value is displayed in red letters. We can change the value of a register at any time to test what happens then.
Now step 3 is executed, output to the direction register of Port B. To display this we open a new I/O view window and select Port B. The display should look like this.
The Data Direction
Register in the I/O-view window of Port B now shows the new value. The values could be changed manually, if desired, pin by pin.
The next two steps are simulated using F11. They are not displayed here. Setting the output ports to one with the command LDI
mp,0xFF and OUT PORTB,mp results in the following picture in the I/O view. Now the output port bits are all one, the I/O view shows this.
That is our short trip through the simulator software world. The simulator is capable to much more, so it should be applied extensively in cases of design errors. Visit the different menue items, there is much more than showed here.
Avr-Asm-Tutorial |
9 |
http://www.avr-asm-tutorial.net |
Register
What is a register?
Registers are special storages with 8 bits capacity and they look like this:
Bit 7 |
Bit 6 |
Bit 5 |
Bit 4 |
Bit 3 |
Bit 2 |
Bit 1 |
Bit 0 |
Note the numeration of these bits: the least significant bit starts with zero (20 = 1).
A register can either store numbers from 0 to 255 (positive number, no negative values), or numbers from -128 to +127 (whole number with a sign bit in bit 7), or a value representing an ASCII-coded character (e.g. 'A'), or just eight single bits that do not have something to do with each other (e.g. for eight single flags used to signal eight different yes/no decisions).
The special character of registers, compared to other storage sites, is that
•they can be used directly in assembler commands,
•operations with their content require only a single command word,
•they are connected directly to the central processing unit called the accumulator,
•they are source and target for calculations.
There are 32 registers in an AVR. They are originally named R0 to R31, but you can choose to name them to more meaningful names using an assembler directive. An example:
.DEF MyPreferredRegister = R16
Assembler directives always start with a dot in column 1 of the text. Instructions do NEVER start in column 1, they are always preceeded by a Tabor blank character!
Note that assembler directives like this are only meaningful for the assembler but do not produce any code that is executable in the AVR target chip. Instead of using the register name R16 we can now use our own name MyPreferredRegister, if we want to use R16 within a command. So we write a little bit more text each time we use this register, but we have an association what might be the content of this register.
Using the command line
LDI |
MyPreferredRegister, 150 |
which means: load the number 150 immediately to the register R16, LoaD Immediate. This loads a fixed value or a constant to that register. Following the assembly or translation of this code the program storage written to the AVR chip looks like this:
000000 E906
The load command code as well as the target register (R16) as well as the value of the constant (150) is part of the hex value E906, even if you don't see this directly. Don't be afraid: you don't have to remember this coding because the assembler knows how to translate all this to yield E906.
Within one command two different registers can play a role. The easiest command of this type is the copy command MOV. It copies the content of one register to another register. Like this:
.DEF MyPreferredRegister = R16
.DEF AnotherRegister = R15
LDI MyPreferredRegister, 150
MOV AnotherRegister, MyPreferredRegister
The first two lines of this monster program are directives that define the new names of the registers R16 and R15 for the assembler. Again, these lines do not produce any code for the AVR. The command lines with LDI and MOV produce code:
000000 E906
000001 2F01
The commands write 150 into register R16 and copy its content to the target register R15. IMPORTANT NOTE:
The first register is always the target register where the result is written to!
(This is unfortunately different from what one expects or from how we speak. It is a simple convention that was once defined that way to confuse the beginners learning assembler. That is why assembler is that complicated.)
Avr-Asm-Tutorial |
10 |
http://www.avr-asm-tutorial.net |
Different registers
The beginner might want to write the above commands like this:
.DEF AnotherRegister = R15
LDI AnotherRegister, 150
And: you lost. Only the registers from R16 to R31 load a constant immediately with the LDI command, R0 to R15 don't do that. This restriction is not very fine, but could not be avoided during construction of the command set for the AVRs.
There is one exception from that rule: setting a register to Zero. This command
CLR MyPreferredRegister
is valid for all registers.
Besides the LDI command you will find this register class restriction with the following additional commands:
•ANDI Rx,K ; Bit-And of register Rx with a constant value K,
•CBR Rx,M ; Clear all bits in register Rx that are set to one within the constant mask value M,
•CPI Rx,K ; Compare the content of the register Rx with a constant value K,
•SBCI Rx,K ; Subtract the constant K and the current value of the carry flag from the content of register Rx and store the result in register Rx,
•SBR Rx,M ; Set all bits in register Rx to one, that are one in the constant mask M,
•SER Rx ; Set all bits in register Rx to one (equal to LDI Rx,255),
•SUBI Rx,K ; Subtract the constant K from the content of register Rx and store the result in register Rx.
In all these commands the register must be between R16 and R31! If you plan to use these commands you should select one of these registers for that operation. It is easier to program. This is an additional reason why you should use the directive to define a register's name, because you can easier change the registers location afterwards.
Pointerregister
A very special extra role is defined for the register pairs R26:R27, R28:R29 and R30:R31. The role is so important that these pairs have extra names in AVR assembler: X, Y and Z. These pairs are 16-bit pointer registers, able to point to adresses with max. 16-bit into SRAM locations (X, Y or Z) or into locations in program memory (Z).
The lower byte of the 16-bit-adress is located in the lower register, the higher byte in the upper register. Both parts have their own names, e.g. the higher byte of Z is named ZH (=R31), the lower Byte is ZL (=R30). These names are defined in the standard header file for the chips. Dividing these 16-bit-pointer- names into two different bytes is done like follows:
.EQU Adress = RAMEND ; RAMEND is the highest 16-bit adress in SRAM LDI YH,HIGH(Adress) ; Set the MSB
LDI YL,LOW(Adress) ; Set the LSB
Accesses via pointers are programmed with specially designed commands. Read access is named LD (LoaD), write access named ST (STore), e.g. with the X-pointer:
Pointer |
Sequence |
Examples |
X |
Read/Write from adress X, don't change the pointer |
LD R1,X or ST X,R1 |
X+ |
Read/Write from/to adress X and increment the pointer afterwards by |
LD R1,X+ or ST X+,R1 |
one |
||
-X |
Decrement the pointer by one and read/write from/to the new adress |
LD R1,-X or ST -X,R1 |
afterwards |
||
Similiarly you can use Y and Z for that purpose.
There is only one command for the read access to the program storage. It is defined for the pointer pair Z and it is named LPM (Load from Program Memory). The command copies the byte at adress Z in the program memory to the register R0. As the program memory is organised word-wise (one command on one adress consists of 16 bits or two bytes or one word) the least significant bit selects the lower or higher byte (0=lower byte, 1= higher byte). Because of this the original adress must be multiplied by 2 and access is limited to 15-bit or 32 kB program memory. Like this: