Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: WinAVR и переменные
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Serg79
Как разместить глобальную переменную по определенному адресу в памяти, при использовании WinAVR.
Например:
Код
/*
* Нужно разместить по адресу 0x0110
*/
char flag;

Как мне это сделать?
Сергей Борщ
Цитата(Serg79 @ Sep 27 2006, 10:21) *
Как разместить глобальную переменную по определенному адресу в памяти, при использовании WinAVR.
Например:
Код
/*
* Нужно разместить по адресу 0x0110
*/
char flag;

Как мне это сделать?
Посмотреть в заголовочных файлах из комплекта компилятора как там по абсолютным адресам размещаются переменные портов, таймеров и другой периферии.
Serg79
Народ, не ужели ни кто не знает как это сделать.
Для регистров это так:
Код
register uint8_t flag __asm__ ("r18");

а для памяти как?

Может кто знает как это в IAR-е делается?

Цитата(Сергей Борщ @ Sep 27 2006, 12:30) *
Цитата(Serg79 @ Sep 27 2006, 10:21) *

Как разместить глобальную переменную по определенному адресу в памяти, при использовании WinAVR.
Например:
Код
/*
* Нужно разместить по адресу 0x0110
*/
char flag;

Как мне это сделать?
Посмотреть в заголовочных файлах из комплекта компилятора как там по абсолютным адресам размещаются переменные портов, таймеров и другой периферии.

Походу так не прокатит, там вот что написанно:
Код
#define SREG      _SFR_IO8(0x3F)

хоть они и находяться в как бы в общей памяти но они все таки _SFR_.
Но я сейчас попробую.
Serg79
Цитата(Сергей Борщ @ Sep 27 2006, 12:30) *
Цитата(Serg79 @ Sep 27 2006, 10:21) *

Как разместить глобальную переменную по определенному адресу в памяти, при использовании WinAVR.
Например:
Код
/*
* Нужно разместить по адресу 0x0110
*/
char flag;

Как мне это сделать?
Посмотреть в заголовочных файлах из комплекта компилятора как там по абсолютным адресам размещаются переменные портов, таймеров и другой периферии.

Нет, так точно не прокатит. Вот что там есть:
Код
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
#define _MMIO_WORD(mem_addr) (*(volatile uint16_t *)(mem_addr))

#define _SFR_MEM8(mem_addr) _MMIO_BYTE(mem_addr)
#define _SFR_MEM16(mem_addr) _MMIO_WORD(mem_addr)

Данные макросы просто грамотно формируют указатель на соответствуюфий адрес. И данный диапозон адресов не используется компилятором под глобальные переменные.
А мне именно надо разместить переменную по адресу начинающемуся с 0x0100.
otrog
Для IAR-а делал так:
Код
#define r_mode  (* (char *) 0x8000) /* Declare a memory mapped I/O address*/

Попробуйте так:
Код
#define flag  (* (char *) 0x0110) /* Declare a memory mapped I/O address*/
Serg79
Цитата(otrog @ Sep 27 2006, 13:10) *
Для IAR-а делал так:
Код
#define r_mode  (* (char *) 0x8000) /* Declare a memory mapped I/O address*/

Попробуйте так:
Код
#define flag  (* (char *) 0x0110) /* Declare a memory mapped I/O address*/

Это то же самое что и
Код
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))

Это просто тычек пальцем в память по определенному адресу, а откуда я знаю что компилятор разместил по этому адресу. Там может быть как глобальная так и статическая переменная, а может и ни чего не быть.

А мне надо имеено зарезервировать участок памяти определенного размера и по определенному адрессу. И что бы компилятор не использовал больше этот диапозон памяти под свои нужды.

Может кто знает как сдвинуть ".data" секцию вниз на пример на 8 байтов. Что бы скажем она уже начиналась не с адреса 0х0100 а с 0х0108.
Serg79
Представляете, в отстойном CodeVision это можно сделать:
Код
Global variables can be stored at specific SRAM locations at design-time using the @ operator.
Example:

/* the integer variable "a" is stored
   in SRAM at address 80h */
int a @0x80;

/* the structure "alfa" is stored
   in SRAM at address 90h */
struct x {
         int a;
         char c;
         } alfa @0x90;

А в WinAVR нельзя. Я в шоке. wacko.gif

Вы мне скажите, это хоть в IAR можно проделать?
IgorKossak
Цитата(Serg79 @ Sep 27 2006, 14:06) *
Вы мне скажите, это хоть в IAR можно проделать?

Легко!
Равно как и любую секцию расположить как угодно.
otrog
Цитата(Serg79 @ Sep 27 2006, 15:06) *
Вы мне скажите, это хоть в IAR можно проделать?

Вот так:
Код
__no_init int a @0x80;
Tiro
Ну прочтите же, наконец, документацию!

excl.gif Перемещаем .data

WinAVR 20060421, avr-libc-user-manual-1.4.4.pdf

8.7.2 The .data Section
This section contains static data which was defined in your code. Things like the fol-
lowing would end up in .data:

Код
char err_str [] = "Your program has died a horrible death!";
struct point pt= { 1, 1 };


It is possible to tell the linker the SRAM address of the beginning of the .data section.
This is accomplished by adding -Wl,-Tdata,addr to the avr-gcc command
used to the link your program. Not that addr must be offset by adding 0x800000
the to real SRAM address so that the linker knows that the address is in the SRAM
memory space. Thus, if you want the .data section to start at 0x1100, pass 0x801100
at the address to the linker.

excl.gif Для того, чтобы привязать переменную к абсолютному адресу, можно назначить ей уникальное имя секции при помощи указания атрибута. Способ указания атрибутов переменных рассмотрен в gcc.pdf, раздел 5.32 Specifying Attributes of Variables.

Вот пример :

Код
int my_glob_var __attribute__ (( section ("my_glob_var") ));


excl.gif Как переместить секцию, написано в разделе 8.10.3 файла avr-libc-user-manual-1.4.4.pdf
Если линковка выполняется из avr-gcc, а не прямым вызовом avr-ld, то в командной строке (или в строке Makefile, где вызывается avr-gcc, надо написать -Wl,--section-start=.my_glob_var=0x801234
aesok
Цитата(Serg79 @ Sep 27 2006, 11:21) *
Как разместить глобальную переменную по определенному адресу в памяти, при использовании WinAVR.


А зачем вам это нужно? Язык 'C ' как раз и был придуман для того чтобы избавить програмиста от ручного распределения переменных в памяти и переложить это на компилятор и линкер. Если вам нужно узнать по какому адресу компилятор расположил переменную - для этого сущесвуют указатели.

В WinAVR можно размещать переменые по абсолютным адресам:

1) Вы можете указать начало сегмента данных с адреса отличного от начала RAM, с помощью опции ликера -Tdata 0x8ххххх, и компилятор будет размещать переменые начиная с этого адреса.

2) Можоно создать свой сегмент, задать ему начальный адрес, и расположить ваши переменые в нем.


Анатолий.
Harvester
Цитата(Serg79 @ Sep 27 2006, 13:53) *
Цитата(otrog @ Sep 27 2006, 13:10) *

Для IAR-а делал так:
Код
#define r_mode  (* (char *) 0x8000) /* Declare a memory mapped I/O address*/

Попробуйте так:
Код
#define flag  (* (char *) 0x0110) /* Declare a memory mapped I/O address*/

Это то же самое что и
Код
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))

...

А мне надо имеено зарезервировать участок памяти определенного размера и по определенному адрессу. И что бы компилятор не использовал больше этот диапозон памяти под свои нужды.

Может кто знает как сдвинуть ".data" секцию вниз на пример на 8 байтов. Что бы скажем она уже начиналась не с адреса 0х0100 а с 0х0108.

Вообще-то этим занимается не компилятор а компоновщик (linker). Соответственно все эти секции настраиваются в файле .xcl. А затем дефайном на зарезервированный участок.
Код
#define my_sect 0x....
....

char *ptr = (char *)my_sect;



Кстати, вот фрагмент такого файла (для нестандартной mega103):
Код
-D_..X_INTVEC_SIZE=60   /* 24 Interrupt vectors * 4 bytes each */
-D_..X_FLASH_TEND=FF    /* End of tiny flash memory */
-D_..X_FLASH_NEND=FFFF  /* End of near flash memory */
-D_..X_FLASH_END=1FFFF  /* End of flash memory */
/* Internal data memory */
-D_..X_SRAM_BASE=da00     /* Start of ram memory */
-D_..X_SRAM_TEND=daFF     /* End of tiny ram memory */

-D_..X_SRAM_END=dfff     /* End of ram memory */
/* Internal EEPROM */
-D_..X_EEPROM_END=FFF   /* End of eeprom memory */

За счет этих строк компилятор использует ОЗУ, начиная с адреса 0xda00. А вот строки из программы:
включаемый файл:
Код
//memory definition
#define mem_endP0In             0xc000
#define mem_endP0Out             0xc010

программа:
Код
volatile usb_ctrlrequest_t *usb_ctrl_req;
...
usb_ctrl_req=(usb_ctrlrequest_t *)mem_endP0In;

PS. На конкретные значения адресов не удивляйтесь, это не реальный контроллер, а ядро в ASIC-е
defunct
Цитата(aesok @ Sep 27 2006, 14:37) *
Язык 'C ' как раз и был придуман для того чтобы избавить програмиста от ручного распределения переменных в памяти и переложить это на компилятор и линкер.

Когда используется шина внешней памяти и по некоторым фиксированным адресам располагаются регистры внешних I/O устройств, то без ручного распределения просто нельзя обойтись...
IgorKossak
Цитата(defunct @ Sep 29 2006, 02:50) *
Цитата(aesok @ Sep 27 2006, 14:37) *

Язык 'C ' как раз и был придуман для того чтобы избавить програмиста от ручного распределения переменных в памяти и переложить это на компилятор и линкер.

Когда используется шина внешней памяти и по некоторым фиксированным адресам располагаются регистры внешних I/O устройств, то без ручного распределения просто нельзя обойтись...

Ручного распределения действительно не избежать. То ли это будет назначение адресов в каком-нибудь выделенном сегменте, то ли определение переменных каждую в свой сегмент.
В любом случае линкеру (или программисту) работы прибавится.
Что же касается высокоуровневости языка С, то когда речь идёт о встроенных системах, то абсолютного абстрагирования от аппаратуры и её особенностей как правило не избежать. Об этом уже очень много писали.
Главное здесь, чтобы все подобные особенности были определены единожды (hal, bsp, называйте это как хотите) и доступны через заголовочные файлы. В этом случае никакого противоречия с С нет.
aesok
Цитата(defunct @ Sep 29 2006, 03:50) *
Цитата(aesok @ Sep 27 2006, 14:37) *

Язык 'C ' как раз и был придуман для того чтобы избавить програмиста от ручного распределения переменных в памяти и переложить это на компилятор и линкер.

Когда используется шина внешней памяти и по некоторым фиксированным адресам располагаются регистры внешних I/O устройств, то без ручного распределения просто нельзя обойтись...


ДА, полностью с Вами согласен. Но вопрос был не про проты ввода/вывода, а про голобальную переменую в памяти. Порграмист в 'C' должен указывать сегмент в котором должна находиться переменая (data, EEPROM, ROM), а выбором ареса где будет нахадиться переменая в этом сегменте должен заниматься компилятор.


Анатолий.
AVR_Amator
По WinAVR есть очень любопытные сайты
http://avr.h15.ru
http://[banned]
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.