ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.06.2025
Просмотров: 2218
Скачиваний: 0
CodeVisionAVR
3.17 Using an External Startup File
In every program the CodeVisionAVR C compiler automatically generates a code sequence to make the following initializations immediately after the AVR chip reset:
1.interrupt vector jump table
2.global interrupt disable
3.EEPROM access disable
4.Watchdog Timer disable
5.external SRAM access and wait state enable if necessary
6.clear registers R2 … R14
7.clear the SRAM
8.initialize the global variables located in SRAM
9.initialize the Data Stack Pointer register Y
10.initialize the Stack Pointer register SP
11.initialize the UBRR register if necessary
The automatic generation of code sequences 2 to 8 can be disabled by checking the Code Generation|Use an External Startup Initialization File check box in the Project|Configure|C Compiler|Code Generation dialog window. The C compiler will then include, in the generated .asm file, the code sequences from an external file that must be named STARTUP.ASM . This file must be located in the directory where your main C source file resides.
You can write your own STARTUP.ASM file to customize or add some features to your program. The code sequences from this file will be immediately executed after the chip reset.
A basic STARTUP.ASM file is supplied with the compiler distribution and is located in the ..\BIN directory.
Here's the content of this file:
;CodeVisionAVR C Compiler
;(C) 1998-2007 Pavel Haiduc, HP InfoTech s.r.l. ;EXAMPLE STARTUP FILE FOR CodeVisionAVR V1.24.1 OR LATER
.EQU __CLEAR_START=0X60 |
;START ADDRESS OF SRAM AREA TO CLEAR |
|
;SET THIS ADDRESS TO 0X100 FOR THE |
||
;ATmega128 OR ATmega64 CHIPS |
||
.EQU __CLEAR_SIZE=256 |
;SIZE OF SRAM AREA TO CLEAR IN BYTES |
|
CLI |
;DISABLE INTERRUPTS |
|
CLR |
R30 |
|
OUT |
EECR,R30 ;DISABLE EEPROM ACCESS |
|
;DISABLE THE WATCHDOG
LDI R31,0x18
OUT WDTCR,R31
OUT WDTCR,R30
OUT MCUCR,R30 ;MCUCR=0, NO EXTERNAL SRAM ACCESS
;CLEAR R2-R14
LDI |
R24,13 |
LDI |
R26,2 |
CLR |
R27 |
__CLEAR_REG: |
|
ST |
X+,R30 |
DEC |
R24 |
BRNE |
__CLEAR_REG |
© 1998-2007 HP InfoTech S.R.L. |
Page 101 |
CodeVisionAVR
;CLEAR SRAM
LDI R24,LOW(__CLEAR_SIZE) LDI R25,HIGH(__CLEAR_SIZE) LDI R26,LOW(__CLEAR_START) LDI R27,HIGH(__CLEAR_START)
__CLEAR_SRAM: ST X+,R30 SBIW R24,1
BRNE __CLEAR_SRAM
;GLOBAL |
VARIABLES INITIALIZATION |
LDI |
R30,LOW(__GLOBAL_INI_TBL*2) |
LDI |
R31,HIGH(__GLOBAL_INI_TBL*2) |
__GLOBAL_INI_NEXT: |
|
LPM |
R30,1 |
ADIW |
|
MOV |
R24,R0 |
LPM |
R30,1 |
ADIW |
|
MOV |
R25,R0 |
SBIW |
R24,0 |
BREQ __GLOBAL_INI_END |
|
LPM |
R30,1 |
ADIW |
|
MOV |
R26,R0 |
LPM |
R30,1 |
ADIW |
|
MOV |
R27,R0 |
LPM |
R30,1 |
ADIW |
|
MOV |
R1,R0 |
LPM |
R30,1 |
ADIW |
|
MOV |
R22,R30 |
MOV |
R23,R31 |
MOV |
R31,R0 |
MOV |
R30,R1 |
__GLOBAL_INI_LOOP: |
|
LPM |
R30,1 |
ADIW |
|
ST |
X+,R0 |
SBIW |
R24,1 |
BRNE |
__GLOBAL_INI_LOOP |
MOV |
R30,R22 |
MOV |
R31,R23 |
RJMP __GLOBAL_INI_NEXT __GLOBAL_INI_END:
The __CLEAR_START and __CLEAR_SIZE constants can be changed to specify which area of SRAM to clear at program initialization.
The __GLOBAL_INI_TBL label must be located at the start of a table containing the information necessary to initialize the global variables located in SRAM. This table is automatically generated by the compiler.
© 1998-2007 HP InfoTech S.R.L. |
Page 102 |
CodeVisionAVR
3.18 Including Assembly Language in Your Program
You can include assembly language anywhere in your program using the #asm and #endasm directives.
Example:
void delay(unsigned char i) { while (i--) {
/* Assembly language code sequence */ #asm
nop nop #endasm
};
}
Inline assembly may also be used.
Example:
#asm("sei") /* enable interrupts */
The registers R0, R1, R22, R23, R24, R25, R26, R27, R30 and R31 can be freely used in assembly routines.
However when using them in an interrupt service routine the programmer must save, respectively restore, them on entry, respectively on exit, of this routine.
© 1998-2007 HP InfoTech S.R.L. |
Page 103 |
CodeVisionAVR
3.18.1 Calling Assembly Functions from C
The following example shows how to access functions written in assembly language from a C program:
//function in assembler declaration
//this function will return a+b+c
#pragma warn- // this will prevent warnings int sum_abc(int a, int b, unsigned char c) { #asm
ldd |
r30,y+3 |
;R30=LSB a |
ldd |
r31,y+4 |
;R31=MSB a |
ldd |
r26,y+1 |
;R26=LSB b |
ldd |
r27,y+2 |
;R27=MSB b |
add |
r30,r26 ;(R31,R30)=a+b |
|
adc |
r31,r27 |
;R26=c |
ld |
r26,y |
|
clr |
r27 |
;promote unsigned char c to int |
add |
r30,r26 ;(R31,R30)=(R31,R30)+c |
|
adc |
r31,r27 |
|
#endasm
}
#pragma warn+ // enable warnings
void main(void) { int r;
// now we call the function and store the result in r r=sum_abc(2,4,6);
}
The compiler passes function parameters using the Data Stack.
First it pushes the integer parameter a, then b, and finally the unsigned char parameter c.
On every push the Y register pair decrements by the size of the parameter (4 for long int, 2 for int, 1 for char).
For multiple byte parameters the MSB is pushed first. As it is seen the Data Stack grows downward.
After all the functions parameters were pushed on the Data Stack, the Y register points to the last parameter c, so the function can read its value in R26 using the instruction: ld r26,y.
The b parameter was pushed before c, so it is at a higher address in the Data Stack. The function will read it using: ldd r27,y+2 (MSB) and ldd r26,y+1 (LSB).
The MSB was pushed first, so it is at a higher address.
The a parameter was pushed before b, so it is at a higher address in the Data Stack. The function will read it using: ldd r31,y+4 (MSB) and ldd r30,y+3 (LSB).
The functions return their values in the registers (from LSB to MSB):
•R30 for char and unsigned char
•R30, R31 for int and unsigned int
•R30, R31, R22, R23 for long and unsigned long.
So our function must return its result in the R30, R31 registers.
After the return from the function the compiler automatically generates code to reclaim the Data Stack space used by the function parameters.
The #pragma warn- compiler directive will prevent the compiler from generating a warning that the function does not return a value.
This is needed because the compiler does not know what it is done in the assembler portion of the function.
© 1998-2007 HP InfoTech S.R.L. |
Page 104 |