|
WinAVR и переменные |
|
|
Guest_Serg79_*
|
Sep 27 2006, 07:21
|
Guests

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

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Serg79 @ Sep 27 2006, 10:21)  Как разместить глобальную переменную по определенному адресу в памяти, при использовании WinAVR. Например: Код /* * Нужно разместить по адресу 0x0110 */ char flag; Как мне это сделать? Посмотреть в заголовочных файлах из комплекта компилятора как там по абсолютным адресам размещаются переменные портов, таймеров и другой периферии.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
Guest_Serg79_*
|
Sep 27 2006, 08:36
|
Guests

|
Народ, не ужели ни кто не знает как это сделать. Для регистров это так: Код 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_. Но я сейчас попробую.
|
|
|
|
Guest_Serg79_*
|
Sep 27 2006, 08:59
|
Guests

|
Цитата(Сергей Борщ @ 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.
|
|
|
|
|
Sep 27 2006, 09:10
|
Местный
  
Группа: Свой
Сообщений: 232
Регистрация: 22-02-06
Из: Воронеж
Пользователь №: 14 589

|
Для IAR-а делал так: Код #define r_mode (* (char *) 0x8000) /* Declare a memory mapped I/O address*/ Попробуйте так: Код #define flag (* (char *) 0x0110) /* Declare a memory mapped I/O address*/
--------------------
Истина рождается в спорах; но когда страсти кипят, истина испаряется.
|
|
|
|
Guest_Serg79_*
|
Sep 27 2006, 09:53
|
Guests

|
Цитата(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 - Sep 27 2006, 09:54
|
|
|
|
Guest_Serg79_*
|
Sep 27 2006, 11:06
|
Guests

|
Представляете, в отстойном 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 нельзя. Я в шоке.  Вы мне скажите, это хоть в IAR можно проделать?
|
|
|
|
|
Sep 27 2006, 11:27
|
Местный
  
Группа: Свой
Сообщений: 232
Регистрация: 22-02-06
Из: Воронеж
Пользователь №: 14 589

|
Цитата(Serg79 @ Sep 27 2006, 15:06)  Вы мне скажите, это хоть в IAR можно проделать? Вот так: Код __no_init int a @0x80;
--------------------
Истина рождается в спорах; но когда страсти кипят, истина испаряется.
|
|
|
|
|
Sep 27 2006, 11:32
|
Знающий
   
Группа: Свой
Сообщений: 781
Регистрация: 3-10-04
Из: Санкт-Петербург
Пользователь №: 768

|
Ну прочтите же, наконец, документацию!  Перемещаем .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.  Для того, чтобы привязать переменную к абсолютному адресу, можно назначить ей уникальное имя секции при помощи указания атрибута. Способ указания атрибутов переменных рассмотрен в gcc.pdf, раздел 5.32 Specifying Attributes of Variables. Вот пример : Код int my_glob_var __attribute__ (( section ("my_glob_var") ));  Как переместить секцию, написано в разделе 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
|
|
|
|
|
Sep 27 2006, 11:37
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(Serg79 @ Sep 27 2006, 11:21)  Как разместить глобальную переменную по определенному адресу в памяти, при использовании WinAVR. А зачем вам это нужно? Язык 'C ' как раз и был придуман для того чтобы избавить програмиста от ручного распределения переменных в памяти и переложить это на компилятор и линкер. Если вам нужно узнать по какому адресу компилятор расположил переменную - для этого сущесвуют указатели. В WinAVR можно размещать переменые по абсолютным адресам: 1) Вы можете указать начало сегмента данных с адреса отличного от начала RAM, с помощью опции ликера -Tdata 0x8ххххх, и компилятор будет размещать переменые начиная с этого адреса. 2) Можоно создать свой сегмент, задать ему начальный адрес, и расположить ваши переменые в нем. Анатолий.
Сообщение отредактировал aesok - Sep 27 2006, 11:39
|
|
|
|
|
Sep 27 2006, 11:47
|
Местный
  
Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846

|
Цитата(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-е
--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
|
|
|
|
|
Sep 29 2006, 06:50
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Цитата(defunct @ Sep 29 2006, 02:50)  Цитата(aesok @ Sep 27 2006, 14:37)  Язык 'C ' как раз и был придуман для того чтобы избавить програмиста от ручного распределения переменных в памяти и переложить это на компилятор и линкер.
Когда используется шина внешней памяти и по некоторым фиксированным адресам располагаются регистры внешних I/O устройств, то без ручного распределения просто нельзя обойтись... Ручного распределения действительно не избежать. То ли это будет назначение адресов в каком-нибудь выделенном сегменте, то ли определение переменных каждую в свой сегмент. В любом случае линкеру (или программисту) работы прибавится. Что же касается высокоуровневости языка С, то когда речь идёт о встроенных системах, то абсолютного абстрагирования от аппаратуры и её особенностей как правило не избежать. Об этом уже очень много писали. Главное здесь, чтобы все подобные особенности были определены единожды (hal, bsp, называйте это как хотите) и доступны через заголовочные файлы. В этом случае никакого противоречия с С нет.
|
|
|
|
|
Sep 29 2006, 07:12
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(defunct @ Sep 29 2006, 03:50)  Цитата(aesok @ Sep 27 2006, 14:37)  Язык 'C ' как раз и был придуман для того чтобы избавить програмиста от ручного распределения переменных в памяти и переложить это на компилятор и линкер.
Когда используется шина внешней памяти и по некоторым фиксированным адресам располагаются регистры внешних I/O устройств, то без ручного распределения просто нельзя обойтись... ДА, полностью с Вами согласен. Но вопрос был не про проты ввода/вывода, а про голобальную переменую в памяти. Порграмист в 'C' должен указывать сегмент в котором должна находиться переменая (data, EEPROM, ROM), а выбором ареса где будет нахадиться переменая в этом сегменте должен заниматься компилятор. Анатолий.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|