ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.06.2025
Просмотров: 2212
Скачиваний: 0
CodeVisionAVR
3.7.7 Global Variables Memory Map File
During compilation the C compiler generates a Global Variables Memory Map File, in which are specified the SRAM address location, register allocation and size of the global variables used by the program.
This file has the .map extension and can be viewed using the menu File|Open command or by pressing the Open button on the toolbar.
Structure and union members are listed individually along with their corresponding address and size. This file is useful during program debugging using the AVR Studio debugger.
3.8 Defining Data Types
User defined data types are declared using the typedef reserved keyword.
The syntax is:
typedef [<storage modifier>] <type definition> <identifier>;
The symbol name <identifier> is assigned to <type definition>.
Examples:
/* type definitions */ typedef unsigned char byte; typedef eeprom struct {
int a; char b[5];
} eeprom_struct_type;
/* variable declaration */ byte alfa;
eeprom eeprom_struct_type struct1;
© 1998-2007 HP InfoTech S.R.L. |
Page 86 |
CodeVisionAVR
3.9 Type Conversions
In an expression, if the two operands of a binary operator are of different types, then the compiler will convert one of the operands into the type of the other.
The compiler uses the following rules:
If either of the operands is of type float then the other operand is converted to the same type.
If either of the operands is of type long int or unsigned long int then the other operand is converted to the same type.
Otherwise, if either of the operands is of type int or unsigned int then the other operand is converted to the same type.
Thus char type or unsigned char type gets the lowest priority.
Using casting you can change these rules.
Example:
void main(void) { int a, c;
long b;
/* The long integer variable b will be treated here as an integer */ c=a+(int) b;
}
It is important to note that if the Project|Configure|C Compiler|Code Generation|Promote char to int option isn't checked or the #pragma promotechar+ isn't used, the char, respectively unsigned char, type operands are not automatically promoted to int , respectively unsigned int, as in compilers targeted for 16 or 32 bit CPUs.
This helps writing more size and speed efficient code for an 8 bit CPU like the AVR. To prevent overflow on 8 bit addition or multiplication, casting may be required. The compiler issues warnings in these situations.
Example:
void main(void) { unsigned char a=30; unsigned char b=128; unsigned int c;
/* This will generate an incorrect result, because the multiplication is done on 8 bits producing an 8 bit result, which overflows. Only after the multiplication, the 8 bit result is promoted to unsigned int */
c=a*b;
/* Here casting forces the multiplication to be done on 16 bits, producing an 16 bit result, without overflow */
c=(unsigned int) a*b;
}
© 1998-2007 HP InfoTech S.R.L. |
Page 87 |
CodeVisionAVR
The compiler behaves differently for the following operators:
+= -= *= /= %= &= |= ^= <<= >>=
For these operators, the result is to be written back onto the left-hand side operand (which must be a variable). So the compiler will always convert the right hand side operand into the type of left-hand side operand.
3.10 Operators
The compiler supports the following operators:
+-
*/
%++
--=
==~
!!=
<>
<= >=
&&&
| ||
^?
<<>>
-= |
+= |
/= |
%= |
&= |
*= |
^= |
|= |
>>= |
<<= |
© 1998-2007 HP InfoTech S.R.L. |
Page 88 |
CodeVisionAVR
3.11 Functions
You may use function prototypes to declare a function.
These declarations include information about the function parameters. Example:
int alfa(char par1, int par2, long par3);
The actual function definition may be written somewhere else as:
int alfa(char par1, int par2, long par3) { /* Write some statements here */
}
The old Kernighan & Ritchie style of writing function definitions is not supported. Function parameters are passed through the Data Stack.
Function values are returned in registers R30, R31, R22 and R23 (from LSB to MSB).
© 1998-2007 HP InfoTech S.R.L. |
Page 89 |
CodeVisionAVR
3.12 Pointers
Due to the Harvard architecture of the AVR microcontroller, with separate address spaces for data (SRAM), program (FLASH) and EEPROM memory, the compiler implements three types of pointers. The syntax for pointer declaration is:
[<type storage modifier>] type * [<pointer storage modifier>] [* [<pointer storage modifier>] ...] pointer_name;
or
type [<type storage modifier>] * [<pointer storage modifier>] [* [<pointer storage modifier>] ...] pointer_name;
where type can be any data type.
Variables placed in SRAM are accessed using normal pointers.
For accessing constants placed in FLASH memory, the flash type storage modifier is used. For accessing variables placed in EEPROM, the eeprom type storage modifier is used. Although the pointers may point to different memory areas, they are by default stored in SRAM. Example:
/* Pointer to a char string placed in SRAM */ char *ptr_to_ram=”This string is placed in SRAM”;
/* Pointer to a char string placed in FLASH */
flash char *ptr_to_flash1=”This string is placed in FLASH”; char flash *ptr_to_flash2=”This string is also placed in FLASH”;
/* Pointer to a char string placed in EEPROM */
eeprom char *ptr_to_eeprom1="This string is placed in EEPROM"; char eeprom *ptr_to_eeprom2="This string is also placed in EEPROM";
In order to store the pointer itself in other memory areas, like FLASH or EEPROM, the flash or eeprom pointer storage modifiers must be used as in the examples below:
/* Pointer stored in FLASH to a char string placed in SRAM */ char * flash flash_ptr_to_ram=”This string is placed in SRAM”;
/* Pointer stored in FLASH to a char string placed in FLASH */
flash char * flash flash_ptr_to_flash=”This string is placed in FLASH”;
/* Pointer stored in FLASH to a char string placed in EEPROM */
eeprom char * flash eeprom_ptr_to_eeprom="This string is placed in EEPROM";
/* Pointer stored in EEPROM to a char string placed in SRAM */ char * eeprom eeprom_ptr_to_ram=”This string is placed in SRAM”;
/* Pointer stored in EEPROM to a char string placed in FLASH */
flash char * eeprom eeprom_ptr_to_flash=”This string is placed in FLASH”;
/* Pointer stored in EEPROM to a char string placed in EEPROM */ eeprom char * eeprom eeprom_ptr_to_eeprom="This string is placed in EEPROM";
© 1998-2007 HP InfoTech S.R.L. |
Page 90 |
CodeVisionAVR
In order to improve the code efficiency several memory models are implemented.
The TINY memory model uses 8 bits for storing pointers to the variables placed in SRAM. In this memory model you can only have access to the first 256 bytes of SRAM.
The SMALL memory model uses 16 bits for storing pointers the variables placed in SRAM. In this memory model you can have access to 65536 bytes of SRAM.
In both TINY and SMALL memory models pointers to the FLASH memory area use 16 bits.
Because in these memory models pointers to the FLASH memory are 16 bits wide, the total size of the constant arrays and literal char strings is limited to 64K.
However the total size of the program can be the full amount of FLASH.
In order to remove the above mentioned limitation, there are available two additional memory models:
MEDIUM and LARGE.
The MEDIUM memory model is similar to the SMALL memory model, except it uses pointers to constants in FLASH that are 32 bits wide. The pointers to functions are however 16 bit wide because they hold the word address of the function, so 16 bits are enough to address a function located in all 128kbytes of FLASH.
The MEDIUM memory model can be used only for chips with 128kbytes of FLASH.
The LARGE memory model is similar to the SMALL memory model, except it uses pointers to the FLASH memory area that are 32 bits wide.
The LARGE memory model can be used for chips with 256kbytes or more of FLASH.
In all memory models pointers to the EEPROM memory area are 16 bit wide.
Pointers can be grouped in arrays, which can have up to 8 dimensions.
Example:
/* Declare and initialize a global array of pointers to strings placed in SRAM */
char *strings[3]={"One","Two","Three"};
/* Declare and initialize a global array of pointers to strings placed in FLASH
The pointer array itself is also stored in FLASH */
flash char * flash messages[3]={"Message 1","Message 2","Message 3"};
/* Declare some strings in EEPROM */ eeprom char m1[]="aaaa";
eeprom char m2[]="bbbb";
void main(void) {
/* Declare a local array of pointers to the strings placed in EEPROM You must note that although the strings are located in EEPROM, the pointer array itself is located in SRAM */
char eeprom *pp[2];
/* and initialize the array */ pp[0]=m1;
pp[1]=m2;
}
© 1998-2007 HP InfoTech S.R.L. |
Page 91 |
CodeVisionAVR
Pointers to functions always access the FLASH memory area. There is no need to use the flash keyword for these types of pointers.
Example:
/* Declare a function */ int sum(int a, int b) { return a+b;
}
/* Declare and initialize a global pointer to the function sum */ int (*sum_ptr) (int a, int b)=sum;
void main(void) { int i;
/* Call the function sum using the pointer */ i=(*sum_ptr) (1,2);
}
© 1998-2007 HP InfoTech S.R.L. |
Page 92 |